summaryrefslogtreecommitdiff
path: root/sc/source
diff options
context:
space:
mode:
authorJens-Heiner Rechtien <hr@openoffice.org>2009-01-06 13:57:48 +0000
committerJens-Heiner Rechtien <hr@openoffice.org>2009-01-06 13:57:48 +0000
commit4453678f4d07a65e548a04b6fa2655b66274514d (patch)
tree0f9787ba9adaea1aa46b3354481b2e4e6e8d42c7 /sc/source
parent6c0208067b950fec47d8a2679e0daa79fc78a2c0 (diff)
CWS-TOOLING: integrate CWS odff05
2008-12-11 04:17:37 +0100 er r265237 : #i94555# AppendIntToken for GAMMADIST, Excel needs 4 parameters; also use AppendIntToken instead of AppendNumToken for POISSON 2008-12-11 04:04:27 +0100 er r265236 : #i96837# make cumulative parameter of POISSON optional; patch from <lvyue> with slight modifications 2008-12-11 03:35:03 +0100 er r265235 : #i96835# make base parameter of LOG() optional also in UI; patch from <lvyue> 2008-12-11 03:15:30 +0100 er r265234 : #i94555# patch from <regina>, ODFF: Add GAMMA, CHISQDIST, CHISQINV. Make the 'cumulative' parameter of GAMMADIST optional. Adapt the domain of CHIDIST to allow negative x. Remove the constraint "degrees of freedom < 1.0E5" from CHIDIST and CHIINV. Plus a mechanism to write the now optional parameter of GAMMADIST to PODF and ODFF if omitted, for backwards compatibility. 2008-12-10 18:14:16 +0100 er r265214 : DBG_... need semicolon 2008-12-05 00:49:55 +0100 er r264881 : WaE unxlngi6: declaration of 'pFuncInfo' shadows a previous local 2008-12-05 00:26:05 +0100 er r264879 : #i91547# BETADIST with optional density/cumulative parameter and much better precision; patch from <regina> 2008-12-04 22:51:40 +0100 er r264877 : #i91602# add expm1() and log1p() replacements; based on a patch from <regina> 2008-12-01 16:07:35 +0100 dr r264614 : #i93789# import of EUROCONVERT from XLSX/XLSB 2008-11-28 13:15:01 +0100 dr r264543 : #i93789# new sheet function EUROCONVERT + XLS import/export, patch contributed by lvyue 2008-11-26 14:54:23 +0100 er r264397 : CWS-TOOLING: rebase CWS odff05 to trunk@264325 (milestone: DEV300:m36) 2008-11-20 14:23:33 +0100 er r264053 : CWS-TOOLING: rebase CWS odff05 to trunk@263288 (milestone: DEV300:m35) 2008-11-19 18:07:43 +0100 er r264012 : merged from trunk 2008-11-19 17:51:36 +0100 er r264011 : migrate CWS odff05 to SVN
Diffstat (limited to 'sc/source')
-rw-r--r--sc/source/core/data/validat.cxx4
-rw-r--r--sc/source/core/inc/interpre.hxx13
-rw-r--r--sc/source/core/inc/jumpmatrix.hxx56
-rw-r--r--sc/source/core/src/compiler.src19
-rw-r--r--sc/source/core/tool/compiler.cxx8
-rw-r--r--sc/source/core/tool/interpr1.cxx171
-rw-r--r--sc/source/core/tool/interpr2.cxx113
-rw-r--r--sc/source/core/tool/interpr3.cxx480
-rw-r--r--sc/source/core/tool/interpr4.cxx6
-rw-r--r--sc/source/core/tool/interpr5.cxx107
-rw-r--r--sc/source/core/tool/parclass.cxx3
-rw-r--r--sc/source/core/tool/scmatrix.cxx130
-rw-r--r--sc/source/core/tool/token.cxx153
-rw-r--r--sc/source/filter/excel/excform8.cxx6
-rw-r--r--sc/source/filter/excel/tokstack.cxx5
-rw-r--r--sc/source/filter/excel/xeformula.cxx33
-rw-r--r--sc/source/filter/excel/xehelper.cxx4
-rw-r--r--sc/source/filter/excel/xelink.cxx89
-rw-r--r--sc/source/filter/excel/xilink.cxx16
-rw-r--r--sc/source/filter/excel/xlformula.cxx3
-rw-r--r--sc/source/filter/inc/xelink.hxx4
-rw-r--r--sc/source/filter/inc/xilink.hxx7
-rw-r--r--sc/source/filter/inc/xllink.hxx3
-rw-r--r--sc/source/filter/xml/XMLExportDDELinks.cxx4
-rw-r--r--sc/source/ui/src/scfuncs.src143
25 files changed, 1235 insertions, 345 deletions
diff --git a/sc/source/core/data/validat.cxx b/sc/source/core/data/validat.cxx
index 8aa84645d8c8..b3e88a05239b 100644
--- a/sc/source/core/data/validat.cxx
+++ b/sc/source/core/data/validat.cxx
@@ -7,7 +7,7 @@
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: validat.cxx,v $
- * $Revision: 1.25 $
+ * $Revision: 1.24.110.2 $
*
* This file is part of OpenOffice.org.
*
@@ -711,7 +711,7 @@ bool ScValidationData::GetSelectionFromFormula( TypedScStrCollection* pStrings,
const ScMatrixValue* pMatVal = pValues->Get( nCol, nRow, nMatValType);
// strings and empties
- if( NULL == pMatVal || ScMatrix::IsStringType( nMatValType ) )
+ if( NULL == pMatVal || ScMatrix::IsNonValueType( nMatValType ) )
{
if( NULL != pMatVal )
aValStr = pMatVal->GetString();
diff --git a/sc/source/core/inc/interpre.hxx b/sc/source/core/inc/interpre.hxx
index c1bd2c29bc48..3cce11685e54 100644
--- a/sc/source/core/inc/interpre.hxx
+++ b/sc/source/core/inc/interpre.hxx
@@ -106,6 +106,7 @@ class ScInterpreter
friend class ScTDistFunction;
friend class ScFDistFunction;
friend class ScChiDistFunction;
+ friend class ScChiSqDistFunction;
public:
DECL_FIXEDMEMPOOL_NEWDEL( ScInterpreter )
@@ -560,6 +561,7 @@ void ScDde();
void ScBase();
void ScDecimal();
void ScConvert();
+void ScEuroConvert();
//----------------------- Finanzfunktionen ------------------------------------
void ScNPV();
@@ -642,17 +644,21 @@ double phi(double x);
double taylor(double* pPolynom, USHORT nMax, double x);
double gauss(double x);
double gaussinv(double x);
-double GetBetaDist(double x, double alpha, double beta);
+double GetBetaDist(double x, double alpha, double beta); //cumulative distribution function
+double GetBetaDistPDF(double fX, double fA, double fB); //probability density function)
double GetChiDist(double fChi, double fDF); // for LEGACY.CHIDIST, returns right tail
double GetChiSqDistCDF(double fX, double fDF); // for CHISQDIST, returns left tail
+double GetChiSqDistPDF(double fX, double fDF); // probability density function
double GetFDist(double x, double fF1, double fF2);
double GetTDist(double T, double fDF);
double Fakultaet(double x);
double BinomKoeff(double n, double k);
double GetGamma(double x);
double GetLogGamma(double x);
+double GetBeta(double fAlpha, double fBeta);
+double GetLogBeta(double fAlpha, double fBeta);
void ScLogGamma();
-void ScGamma(); // ready for ODF 1.2 GAMMA
+void ScGamma();
void ScPhi();
void ScGauss();
void ScStdNormDist();
@@ -676,7 +682,8 @@ void ScLogNormInv();
void ScTDist();
void ScFDist();
void ScChiDist(); // for LEGACY.CHIDIST, returns right tail
-// TODO: void ScChiSqDist;
+void ScChiSqDist(); // returns left tail or density
+void ScChiSqInv(); //invers to CHISQDIST
void ScWeibull();
void ScBetaDist();
void ScFInv();
diff --git a/sc/source/core/inc/jumpmatrix.hxx b/sc/source/core/inc/jumpmatrix.hxx
index bce78c6500e2..34893187009c 100644
--- a/sc/source/core/inc/jumpmatrix.hxx
+++ b/sc/source/core/inc/jumpmatrix.hxx
@@ -7,7 +7,7 @@
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: jumpmatrix.hxx,v $
- * $Revision: 1.6 $
+ * $Revision: 1.6.148.1 $
*
* This file is part of OpenOffice.org.
*
@@ -73,6 +73,8 @@ class ScJumpMatrix
SCSIZE nRows;
SCSIZE nCurCol;
SCSIZE nCurRow;
+ SCSIZE nResMatCols;
+ SCSIZE nResMatRows;
bool bStarted;
// not implemented, prevent usage
@@ -88,6 +90,8 @@ public:
, nRows( nRowsP )
, nCurCol( 0 )
, nCurRow( 0 )
+ , nResMatCols( nColsP )
+ , nResMatRows( nRowsP )
, bStarted( false )
{
// Initialize result matrix in case of
@@ -128,6 +132,21 @@ public:
short& rStart, short& rNext,
short& rStop ) const
{
+ if (nCols == 1 && nRows == 1)
+ {
+ nCol = 0;
+ nRow = 0;
+ }
+ else if (nCols == 1 && nRow < nRows)
+ nCol = 0;
+ else if (nRows == 1 && nCol < nCols)
+ nRow = 0;
+ else if (nCols <= nCol || nRows <= nRow)
+ {
+ DBG_ERROR("ScJumpMatrix::GetJump: dimension error");
+ nCol = 0;
+ nRow = 0;
+ }
pJump[ (ULONG)nCol * nRows + nRow ].
GetJump( rBool, rStart, rNext, rStop);
}
@@ -160,14 +179,45 @@ public:
}
else
{
- if ( ++nCurRow >= nRows )
+ if ( ++nCurRow >= nResMatRows )
{
nCurRow = 0;
++nCurCol;
}
}
GetPos( rCol, rRow );
- return nCurCol < nCols;
+ return nCurCol < nResMatCols;
+ }
+ void GetResMatDimensions( SCSIZE& rCols, SCSIZE& rRows )
+ {
+ rCols = nResMatCols;
+ rRows = nResMatRows;
+ }
+ void SetNewResMat( SCSIZE nNewCols, SCSIZE nNewRows )
+ {
+ if ( nNewCols > nResMatCols || nNewRows > nResMatRows )
+ {
+ pMat = pMat->CloneAndExtend( nNewCols, nNewRows );
+ if ( nResMatCols < nNewCols )
+ {
+ pMat->FillDouble( CreateDoubleError(
+ NOTAVAILABLE), nResMatCols, 0, nNewCols-1,
+ nResMatRows-1);
+ }
+ if ( nResMatRows < nNewRows )
+ {
+ pMat->FillDouble( CreateDoubleError(
+ NOTAVAILABLE), 0, nResMatRows, nNewCols-1,
+ nNewRows-1);
+ }
+ if ( nRows == 1 && nCurCol != 0 )
+ {
+ nCurCol = 0;
+ nCurRow = nResMatRows - 1;
+ }
+ nResMatCols = nNewCols;
+ nResMatRows = nNewRows;
+ }
}
};
diff --git a/sc/source/core/src/compiler.src b/sc/source/core/src/compiler.src
index e72a63a52506..1c953ec8f981 100644
--- a/sc/source/core/src/compiler.src
+++ b/sc/source/core/src/compiler.src
@@ -1179,6 +1179,19 @@ Resource RID_SC_FUNCTION_NAMES
{
Text [ en-US ] = "NUMBERVALUE" ;
};
+ String SC_OPCODE_GAMMA
+ {
+ Text [ en-US ] = "GAMMA" ;
+ };
+ String SC_OPCODE_CHISQ_DIST
+ {
+ Text [ en-US ] = "CHISQDIST" ;
+ };
+ String SC_OPCODE_CHISQ_INV
+ {
+ Text [ en-US ] = "CHISQINV" ;
+ };
+
/* BEGIN defined ERROR.TYPE() values. */
/* ERROR.TYPE( #NULL! ) == 1 */
String SC_OPCODE_ERROR_NULL
@@ -1529,6 +1542,9 @@ Resource RID_SC_FUNCTION_NAMES_ENGLISH
String SC_OPCODE_GET_PIVOT_DATA { Text = "GETPIVOTDATA" ; };
String SC_OPCODE_EUROCONVERT { Text = "EUROCONVERT" ; };
String SC_OPCODE_NUMBERVALUE { Text = "NUMBERVALUE" ; };
+ String SC_OPCODE_GAMMA { Text = "GAMMA" ; };
+ String SC_OPCODE_CHISQ_DIST { Text = "CHISQDIST" ; };
+ String SC_OPCODE_CHISQ_INV { Text = "CHISQINV" ;};
/* BEGIN defined ERROR.TYPE() values. */
String SC_OPCODE_ERROR_NULL { Text = "#NULL!" ; };
String SC_OPCODE_ERROR_DIVZERO { Text = "#DIV/0!" ; };
@@ -1850,6 +1866,9 @@ Resource RID_SC_FUNCTION_NAMES_ENGLISH_ODFF
String SC_OPCODE_GET_PIVOT_DATA { Text = "GETPIVOTDATA" ; };
String SC_OPCODE_EUROCONVERT { Text = "EUROCONVERT" ; };
String SC_OPCODE_NUMBERVALUE { Text = "NUMBERVALUE" ; };
+ String SC_OPCODE_GAMMA { Text = "GAMMA" ; };
+ String SC_OPCODE_CHISQ_DIST { Text = "CHISQDIST" ;};
+ String SC_OPCODE_CHISQ_INV { Text = "CHISQINV" ;};
/* BEGIN defined ERROR.TYPE() values. */
String SC_OPCODE_ERROR_NULL { Text = "#NULL!" ; };
String SC_OPCODE_ERROR_DIVZERO { Text = "#DIV/0!" ; };
diff --git a/sc/source/core/tool/compiler.cxx b/sc/source/core/tool/compiler.cxx
index 16f51a015667..e9b583ec7783 100644
--- a/sc/source/core/tool/compiler.cxx
+++ b/sc/source/core/tool/compiler.cxx
@@ -6725,11 +6725,13 @@ void ScCompiler::CreateStringFromTokenArray( rtl::OUStringBuffer& rBuffer )
return;
ScTokenArray* pSaveArr = pArr;
- if (ScGrammar::isPODF( meGrammar))
+ bool bODFF = ScGrammar::isODFF( meGrammar);
+ if (bODFF || ScGrammar::isPODF( meGrammar))
{
// Scan token array for missing args and re-write if present.
- if (pArr->NeedsPofRewrite())
- pArr = pArr->RewriteMissingToPof();
+ ScMissingConvention aConv( bODFF);
+ if (pArr->NeedsPofRewrite( aConv))
+ pArr = pArr->RewriteMissingToPof( aConv);
}
// At least one character per token, plus some are references, some are
diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx
index 242dc0662d8e..f1ab1da94432 100644
--- a/sc/source/core/tool/interpr1.cxx
+++ b/sc/source/core/tool/interpr1.cxx
@@ -7,7 +7,7 @@
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: interpr1.cxx,v $
- * $Revision: 1.61 $
+ * $Revision: 1.60.54.5 $
*
* This file is part of OpenOffice.org.
*
@@ -129,8 +129,11 @@ void ScInterpreter::ScIfJump()
}
else
{
+ // Treat empty and empty path as 0, but string
+ // as error.
+ bIsValue = !ScMatrix::IsRealStringType( nType);
bTrue = false;
- fVal = 0.0;
+ fVal = (bIsValue ? 0.0 : CreateDoubleError( errNoValue));
}
if ( bTrue )
{ // TRUE
@@ -309,6 +312,37 @@ void ScInterpreter::ScChoseJump()
}
+void lcl_AdjustJumpMatrix( ScJumpMatrix* pJumpM, ScMatrixRef& pResMat, SCSIZE nParmCols, SCSIZE nParmRows )
+{
+ SCSIZE nJumpCols, nJumpRows;
+ SCSIZE nResCols, nResRows;
+ SCSIZE nAdjustCols, nAdjustRows;
+ pJumpM->GetDimensions( nJumpCols, nJumpRows );
+ pJumpM->GetResMatDimensions( nResCols, nResRows );
+ if (( nJumpCols == 1 && nParmCols > nResCols ) ||
+ ( nJumpRows == 1 && nParmRows > nResRows ))
+ {
+ if ( nJumpCols == 1 && nJumpRows == 1 )
+ {
+ nAdjustCols = nParmCols > nResCols ? nParmCols : nResCols;
+ nAdjustRows = nParmRows > nResRows ? nParmRows : nResRows;
+ }
+ else if ( nJumpCols == 1 )
+ {
+ nAdjustCols = nParmCols;
+ nAdjustRows = nResRows;
+ }
+ else
+ {
+ nAdjustCols = nResCols;
+ nAdjustRows = nParmRows;
+ }
+ pJumpM->SetNewResMat( nAdjustCols, nAdjustRows );
+ pResMat = pJumpM->GetResultMatrix();
+ }
+}
+
+
bool ScInterpreter::JumpMatrix( short nStackLevel )
{
pJumpMatrix = pStack[sp-nStackLevel]->GetJumpMatrix();
@@ -404,52 +438,69 @@ bool ScInterpreter::JumpMatrix( short nStackLevel )
double fVal;
ScRange aRange;
PopDoubleRef( aRange );
- ScAddress& rAdr = aRange.aStart;
- ULONG nCol = (ULONG)rAdr.Col() + nC;
- ULONG nRow = (ULONG)rAdr.Row() + nR;
if ( nGlobalError )
{
fVal = CreateDoubleError( nGlobalError );
nGlobalError = 0;
pResMat->PutDouble( fVal, nC, nR );
}
- else if ( nCol > static_cast<ULONG>(aRange.aEnd.Col()) ||
- nRow > static_cast<ULONG>(aRange.aEnd.Row()))
- {
- fVal = CreateDoubleError( errNoValue );
- pResMat->PutDouble( fVal, nC, nR );
- }
else
{
- rAdr.SetCol( static_cast<SCCOL>(nCol) );
- rAdr.SetRow( static_cast<SCROW>(nRow) );
- ScBaseCell* pCell = GetCell( rAdr );
- if (HasCellEmptyData( pCell))
- pResMat->PutEmpty( nC, nR );
- else if (HasCellValueData( pCell))
+ // Do not modify the original range because we use it
+ // to adjust the size of the result matrix if necessary.
+ ScAddress aAdr( aRange.aStart);
+ ULONG nCol = (ULONG)aAdr.Col() + nC;
+ ULONG nRow = (ULONG)aAdr.Row() + nR;
+ if ((nCol > static_cast<ULONG>(aRange.aEnd.Col()) &&
+ aRange.aEnd.Col() != aRange.aStart.Col())
+ || (nRow > static_cast<ULONG>(aRange.aEnd.Row()) &&
+ aRange.aEnd.Row() != aRange.aStart.Row()))
{
- double fCellVal = GetCellValue( rAdr, pCell);
- if ( nGlobalError )
- {
- fCellVal = CreateDoubleError(
- nGlobalError);
- nGlobalError = 0;
- }
- pResMat->PutDouble( fCellVal, nC, nR );
+ fVal = CreateDoubleError( NOTAVAILABLE );
+ pResMat->PutDouble( fVal, nC, nR );
}
else
{
- String aStr;
- GetCellString( aStr, pCell );
- if ( nGlobalError )
+ // Replicate column and/or row of a vector if it is
+ // one. Note that this could be a range reference
+ // that in fact consists of only one cell, e.g. A1:A1
+ if (aRange.aEnd.Col() == aRange.aStart.Col())
+ nCol = aRange.aStart.Col();
+ if (aRange.aEnd.Row() == aRange.aStart.Row())
+ nRow = aRange.aStart.Row();
+ aAdr.SetCol( static_cast<SCCOL>(nCol) );
+ aAdr.SetRow( static_cast<SCROW>(nRow) );
+ ScBaseCell* pCell = GetCell( aAdr );
+ if (HasCellEmptyData( pCell))
+ pResMat->PutEmpty( nC, nR );
+ else if (HasCellValueData( pCell))
{
- pResMat->PutDouble( CreateDoubleError(
- nGlobalError), nC, nR);
- nGlobalError = 0;
+ double fCellVal = GetCellValue( aAdr, pCell);
+ if ( nGlobalError )
+ {
+ fCellVal = CreateDoubleError(
+ nGlobalError);
+ nGlobalError = 0;
+ }
+ pResMat->PutDouble( fCellVal, nC, nR );
}
else
- pResMat->PutString( aStr, nC, nR );
+ {
+ String aStr;
+ GetCellString( aStr, pCell );
+ if ( nGlobalError )
+ {
+ pResMat->PutDouble( CreateDoubleError(
+ nGlobalError), nC, nR);
+ nGlobalError = 0;
+ }
+ else
+ pResMat->PutString( aStr, nC, nR );
+ }
}
+ SCSIZE nParmCols = aRange.aEnd.Col() - aRange.aStart.Col() + 1;
+ SCSIZE nParmRows = aRange.aEnd.Row() - aRange.aStart.Row() + 1;
+ lcl_AdjustJumpMatrix( pJumpMatrix, pResMat, nParmCols, nParmRows );
}
}
break;
@@ -472,9 +523,10 @@ bool ScInterpreter::JumpMatrix( short nStackLevel )
{
SCSIZE nCols, nRows;
pMat->GetDimensions( nCols, nRows );
- if ( nCols <= nC || nRows <= nR )
+ if ((nCols <= nC && nCols != 1) ||
+ (nRows <= nR && nRows != 1))
{
- fVal = CreateDoubleError( errNoValue );
+ fVal = CreateDoubleError( NOTAVAILABLE );
pResMat->PutDouble( fVal, nC, nR );
}
else
@@ -492,6 +544,7 @@ bool ScInterpreter::JumpMatrix( short nStackLevel )
pResMat->PutString( rStr, nC, nR );
}
}
+ lcl_AdjustJumpMatrix( pJumpMatrix, pResMat, nCols, nRows );
}
}
break;
@@ -775,7 +828,9 @@ ScMatrixRef ScInterpreter::CompareMat()
{
for ( SCSIZE k=0; k<nR; k++ )
{
- if ( j < nC0 && j < nC1 && k < nR0 && k < nR1 )
+ SCSIZE nCol = j, nRow = k;
+ if ( pMat[0]->ValidColRowOrReplicated( nCol, nRow ) &&
+ pMat[1]->ValidColRowOrReplicated( nCol, nRow ))
{
for ( short i=1; i>=0; i-- )
{
@@ -3963,6 +4018,16 @@ static void lcl_GetLastMatch( SCSIZE& rIndex, const ScMatrix& rMat,
nVal == rMat.GetDouble(rIndex+1))
++rIndex;
}
+ //! Order of IsEmptyPath, IsEmpty, IsString is significant!
+ else if (rMat.IsEmptyPath(rIndex))
+ {
+ if (bReverse)
+ while (rIndex > 0 && rMat.IsEmptyPath(rIndex-1))
+ --rIndex;
+ else
+ while (rIndex < nMatCount-1 && rMat.IsEmptyPath(rIndex+1))
+ ++rIndex;
+ }
else if (rMat.IsEmpty(rIndex))
{
if (bReverse)
@@ -3984,14 +4049,9 @@ static void lcl_GetLastMatch( SCSIZE& rIndex, const ScMatrix& rMat,
aStr == rMat.GetString(rIndex+1))
++rIndex;
}
- else if (rMat.IsEmptyPath(rIndex))
+ else
{
- if (bReverse)
- while (rIndex > 0 && rMat.IsEmptyPath(rIndex-1))
- --rIndex;
- else
- while (rIndex < nMatCount-1 && rMat.IsEmptyPath(rIndex+1))
- ++rIndex;
+ DBG_ERRORFILE("lcl_GetLastMatch: unhandled matrix type");
}
}
@@ -4097,7 +4157,7 @@ void ScInterpreter::ScMatch()
{
ScMatValType nType = GetDoubleOrStringFromMatrix(
rEntry.nVal, *rEntry.pStr);
- rEntry.bQueryByString = ScMatrix::IsStringType( nType);
+ rEntry.bQueryByString = ScMatrix::IsNonValueType( nType);
}
break;
default:
@@ -4353,7 +4413,7 @@ void ScInterpreter::ScCountIf()
{
ScMatValType nType = GetDoubleOrStringFromMatrix( fVal,
rString);
- bIsString = ScMatrix::IsStringType( nType);
+ bIsString = ScMatrix::IsNonValueType( nType);
}
break;
case svString:
@@ -4540,7 +4600,7 @@ void ScInterpreter::ScSumIf()
{
ScMatValType nType = GetDoubleOrStringFromMatrix( fVal,
rString);
- bIsString = ScMatrix::IsStringType( nType);
+ bIsString = ScMatrix::IsNonValueType( nType);
}
break;
default:
@@ -4848,7 +4908,7 @@ void ScInterpreter::ScLookup()
{
ScMatValType nType = GetDoubleOrStringFromMatrix( rEntry.nVal,
*rEntry.pStr);
- rEntry.bQueryByString = ScMatrix::IsStringType(nType);
+ rEntry.bQueryByString = ScMatrix::IsNonValueType(nType);
}
break;
default:
@@ -5237,7 +5297,7 @@ void ScInterpreter::ScHLookup()
{
ScMatValType nType = GetDoubleOrStringFromMatrix(
rEntry.nVal, *rEntry.pStr);
- rEntry.bQueryByString = ScMatrix::IsStringType( nType);
+ rEntry.bQueryByString = ScMatrix::IsNonValueType( nType);
}
break;
default:
@@ -5489,7 +5549,7 @@ void ScInterpreter::ScVLookup()
{
ScMatValType nType = GetDoubleOrStringFromMatrix(
rEntry.nVal, *rEntry.pStr);
- rEntry.bQueryByString = ScMatrix::IsStringType( nType);
+ rEntry.bQueryByString = ScMatrix::IsNonValueType( nType);
}
break;
default:
@@ -6064,18 +6124,27 @@ void ScInterpreter::ScIndirect()
BYTE nParamCount = GetByte();
if ( MustHaveParamCount( nParamCount, 1, 2 ) )
{
+ bool bTryXlA1 = true; // whether to try XL_A1 style as well.
ScAddress::Convention eConv = ScAddress::CONV_OOO;
if (nParamCount == 2 && 0.0 == ::rtl::math::approxFloor( GetDouble()))
+ {
eConv = ScAddress::CONV_XL_R1C1;
+ bTryXlA1 = false;
+ }
const ScAddress::Details aDetails( eConv, aPos );
+ const ScAddress::Details aDetailsXlA1( ScAddress::CONV_XL_A1, aPos );
SCTAB nTab = aPos.Tab();
String sRefStr( GetString() );
ScRefAddress aRefAd, aRefAd2;
- if ( ConvertDoubleRef( pDok, sRefStr, nTab, aRefAd, aRefAd2, aDetails ) )
+ if ( ConvertDoubleRef( pDok, sRefStr, nTab, aRefAd, aRefAd2, aDetails) ||
+ (bTryXlA1 && ConvertDoubleRef( pDok, sRefStr, nTab, aRefAd,
+ aRefAd2, aDetailsXlA1)))
PushDoubleRef( aRefAd.Col(), aRefAd.Row(), aRefAd.Tab(),
- aRefAd2.Col(), aRefAd2.Row(), aRefAd2.Tab() );
- else if ( ConvertSingleRef ( pDok, sRefStr, nTab, aRefAd, aDetails ) )
+ aRefAd2.Col(), aRefAd2.Row(), aRefAd2.Tab() );
+ else if ( ConvertSingleRef ( pDok, sRefStr, nTab, aRefAd, aDetails) ||
+ (bTryXlA1 && ConvertSingleRef ( pDok, sRefStr, nTab, aRefAd,
+ aDetailsXlA1)))
PushSingleRef( aRefAd.Col(), aRefAd.Row(), aRefAd.Tab() );
else
{
diff --git a/sc/source/core/tool/interpr2.cxx b/sc/source/core/tool/interpr2.cxx
index 20a7a6070071..26e41b0df46f 100644
--- a/sc/source/core/tool/interpr2.cxx
+++ b/sc/source/core/tool/interpr2.cxx
@@ -7,7 +7,7 @@
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: interpr2.cxx,v $
- * $Revision: 1.38 $
+ * $Revision: 1.37.100.3 $
*
* This file is part of OpenOffice.org.
*
@@ -172,7 +172,7 @@ void ScInterpreter::ScGetDateValue()
{
short eType = pFormatter->GetType(nFIndex);
if (eType == NUMBERFORMAT_DATE || eType == NUMBERFORMAT_DATETIME)
- PushDouble(fVal);
+ PushDouble(::rtl::math::approxFloor(fVal));
else
PushIllegalArgument();
}
@@ -391,7 +391,11 @@ void ScInterpreter::ScGetTimeValue()
{
short eType = pFormatter->GetType(nFIndex);
if (eType == NUMBERFORMAT_TIME || eType == NUMBERFORMAT_DATETIME)
- PushDouble(fVal);
+ {
+ double fDateVal = rtl::math::approxFloor(fVal);
+ double fTimeVal = fVal - fDateVal;
+ PushDouble(fTimeVal);
+ }
else
PushIllegalArgument();
}
@@ -1551,7 +1555,7 @@ void ScInterpreter::ScBackSolver()
const USHORT nMaxIter = 100;
const double fEps = 1E-10;
- const double fDelta = 1E-3;
+ const double fDelta = 1E-6;
double fBestX, fXPrev;
double fBestF, fFPrev;
@@ -1672,7 +1676,9 @@ void ScInterpreter::ScBackSolver()
}
}
- double nX = ::rtl::math::approxFloor((fBestX / fDelta) + 0.5) * fDelta;
+ // Try a nice rounded input value if possible.
+ const double fNiceDelta = (bDoneIteration && fabs(fBestX) >= 1e-3 ? 1e-3 : fDelta);
+ double nX = ::rtl::math::approxFloor((fBestX / fNiceDelta) + 0.5) * fNiceDelta;
if ( bDoneIteration )
{
@@ -2328,6 +2334,103 @@ void ScInterpreter::ScConvert()
}
+BOOL lclConvertMoney( const String& aSearchUnit, double& rfRate, int& rnDec )
+{
+ struct ConvertInfo
+ {
+ const sal_Char* pCurrText;
+ double fRate;
+ int nDec;
+ };
+ ConvertInfo aConvertTable[] = {
+ { "EUR", 1.0, 2 },
+ { "ATS", 13.7603, 2 },
+ { "BEF", 40.3399, 0 },
+ { "DEM", 1.95583, 2 },
+ { "ESP", 166.386, 0 },
+ { "FIM", 5.94573, 2 },
+ { "FRF", 6.55957, 2 },
+ { "IEP", 0.787564, 2 },
+ { "ITL", 1936.27, 0 },
+ { "LUF", 40.3399, 0 },
+ { "NLG", 2.20371, 2 },
+ { "PTE", 200.482, 2 },
+ { "GRD", 340.750, 2 },
+ { "SIT", 239.640, 2 },
+ { "MTL", 0.429300, 2 },
+ { "CYP", 0.585274, 2 }
+ };
+
+ const size_t nConversionCount = sizeof( aConvertTable ) / sizeof( aConvertTable[0] );
+ for ( size_t i = 0; i < nConversionCount; i++ )
+ if ( aSearchUnit.EqualsIgnoreCaseAscii( aConvertTable[i].pCurrText ) )
+ {
+ rfRate = aConvertTable[i].fRate;
+ rnDec = aConvertTable[i].nDec;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+void ScInterpreter::ScEuroConvert()
+{ //Value, FromUnit, ToUnit[, FullPrecision, [TriangulationPrecision]]
+ BYTE nParamCount = GetByte();
+ if ( MustHaveParamCount( nParamCount, 3, 5 ) )
+ {
+ double nPrecision = 0.0;
+ if ( nParamCount == 5 )
+ {
+ nPrecision = ::rtl::math::approxFloor(GetDouble());
+ if ( nPrecision < 3 )
+ {
+ PushIllegalArgument();
+ return;
+ }
+ }
+ BOOL bFullPrecision = FALSE;
+ if ( nParamCount >= 4 )
+ bFullPrecision = GetBool();
+ String aToUnit( GetString() );
+ String aFromUnit( GetString() );
+ double fVal = GetDouble();
+ if ( nGlobalError )
+ PushError( nGlobalError);
+ else
+ {
+ double fRes;
+ double fFromRate;
+ double fToRate;
+ int nFromDec;
+ int nToDec;
+ String aEur( RTL_CONSTASCII_USTRINGPARAM("EUR"));
+ if ( lclConvertMoney( aFromUnit, fFromRate, nFromDec )
+ && lclConvertMoney( aToUnit, fToRate, nToDec ) )
+ {
+ if ( aFromUnit.EqualsIgnoreCaseAscii( aToUnit ) )
+ fRes = fVal;
+ else
+ {
+ if ( aFromUnit.EqualsIgnoreCaseAscii( aEur ) )
+ fRes = fVal * fToRate;
+ else
+ {
+ double fIntermediate = fVal / fFromRate;
+ if ( nPrecision )
+ fIntermediate = ::rtl::math::round( fIntermediate,
+ (int) nPrecision );
+ fRes = fIntermediate * fToRate;
+ }
+ if ( !bFullPrecision )
+ fRes = ::rtl::math::round( fRes, nToDec );
+ }
+ PushDouble( fRes );
+ }
+ else
+ PushIllegalArgument();
+ }
+ }
+}
+
void ScInterpreter::ScRoman()
{ // Value [Mode]
BYTE nParamCount = GetByte();
diff --git a/sc/source/core/tool/interpr3.cxx b/sc/source/core/tool/interpr3.cxx
index a50f39e25e88..246632a4c2e4 100644
--- a/sc/source/core/tool/interpr3.cxx
+++ b/sc/source/core/tool/interpr3.cxx
@@ -61,6 +61,7 @@ using ::std::vector;
//#define PI 3.1415926535897932
const double ScInterpreter::fMaxGammaArgument = 171.624376956302; // found experimental
+const double fMachEps = ::std::numeric_limits<double>::epsilon();
//-----------------------------------------------------------------------------
@@ -649,85 +650,6 @@ double ScInterpreter::GetLogGamma(double fZ)
return lcl_GetLogGammaHelper(fZ+2) - log(fZ+1) - log(fZ);
}
-double ScInterpreter::GetBetaDist(double x, double alpha, double beta)
-{
- if (beta == 1.0)
- return pow(x, alpha);
- else if (alpha == 1.0)
- return 1.0 - pow(1.0-x,beta);
- double fEps = 1.0E-8;
- BOOL bReflect;
- double cf, fA, fB;
- if (x < (alpha+1.0)/(alpha+beta+1.0))
- {
- bReflect = FALSE;
- fA = alpha;
- fB = beta;
- }
- else
- {
- bReflect = TRUE;
- fA = beta;
- fB = alpha;
- x = 1.0 - x;
- }
- if (x < fEps)
- cf = 0.0;
- else
- {
- double a1, b1, a2, b2, fnorm, rm, apl2m, d2m, d2m1, cfnew;
- a1 = 1.0; b1 = 1.0;
- b2 = 1.0 - (fA+fB)*x/(fA+1.0);
- if (b2 == 0.0)
- {
- a2 = b2;
- fnorm = 1.0;
- cf = 1.0;
- }
- else
- {
- a2 = 1.0;
- fnorm = 1.0/b2;
- cf = a2*fnorm;
- }
- cfnew = 1.0;
- for (USHORT j = 1; j <= 100; j++)
- {
- rm = (double) j;
- apl2m = fA + 2.0*rm;
- d2m = rm*(fB-rm)*x/((apl2m-1.0)*apl2m);
- d2m1 = -(fA+rm)*(fA+fB+rm)*x/(apl2m*(apl2m+1.0));
- a1 = (a2+d2m*a1)*fnorm;
- b1 = (b2+d2m*b1)*fnorm;
- a2 = a1 + d2m1*a2*fnorm;
- b2 = b1 + d2m1*b2*fnorm;
- if (b2 != 0.0)
- {
- fnorm = 1.0/b2;
- cfnew = a2*fnorm;
- if (fabs(cf-cfnew)/cf < fEps)
- j = 101;
- else
- cf = cfnew;
- }
- }
- if (fB < fEps)
- b1 = 69; // ln(1.0E30)
- else
- b1 = GetLogGamma(fA)+GetLogGamma(fB)-GetLogGamma(fA+fB);
-
- // cf *= pow(x, fA)*pow(1.0-x,fB)/(fA*exp(b1));
- // #108995# The formula above has 0 as results for the terms too easily,
- // resulting in an error where the equivalent formula below still works:
- // (x can't be 0 or 1, this is handled above)
- cf *= exp( log(x)*fA + log(1.0-x)*fB - b1 ) / fA;
- }
- if (bReflect)
- return 1.0-cf;
- else
- return cf;
-}
-
double ScInterpreter::GetFDist(double x, double fF1, double fF2)
{
double arg = fF2/(fF2+fF1*x);
@@ -799,7 +721,68 @@ double ScInterpreter::GetChiSqDistCDF(double fX, double fDF)
return GetLowRegIGamma( fDF/2.0, fX/2.0);
}
-// for ODF 1.2 GAMMA
+double ScInterpreter::GetChiSqDistPDF(double fX, double fDF)
+{
+ // you must ensure fDF is positive integer
+ double fValue;
+ double fCount;
+ if (fX <= 0.0)
+ return 0.0; // see ODFF
+ if (fDF*fX > 1391000.0)
+ {
+ // intermediate invalid values, use log
+ fValue = exp((0.5*fDF - 1) * log(fX*0.5) - 0.5 * fX - log(2.0) - GetLogGamma(0.5*fDF));
+ }
+ else // fDF is small in most cases, we can iterate
+ {
+ if (fmod(fDF,2.0)<0.5)
+ {
+ // even
+ fValue = 0.5;
+ fCount = 2.0;
+ }
+ else
+ {
+ fValue = 1/sqrt(fX*2*F_PI);
+ fCount = 1.0;
+ }
+ while ( fCount < fDF)
+ {
+ fValue *= (fX / fCount);
+ fCount += 2.0;
+ }
+ if (fX>=1425.0) // underflow in e^(-x/2)
+ fValue = exp(log(fValue)-fX/2);
+ else
+ fValue *= exp(-fX/2);
+ }
+ return fValue;
+}
+
+void ScInterpreter::ScChiSqDist()
+{
+ BYTE nParamCount = GetByte();
+ if ( !MustHaveParamCount( nParamCount, 2, 3 ) )
+ return;
+ double fX;
+ bool bCumulative;
+ if (nParamCount == 3)
+ bCumulative = GetBool();
+ else
+ bCumulative = true;
+ double fDF = ::rtl::math::approxFloor(GetDouble());
+ if (fDF < 1.0)
+ PushIllegalArgument();
+ else
+ {
+ fX = GetDouble();
+ if (bCumulative)
+ PushDouble(GetChiSqDistCDF(fX,fDF));
+ else
+ PushDouble(GetChiSqDistPDF(fX,fDF));
+ }
+}
+
void ScInterpreter::ScGamma()
{
double x = GetDouble();
@@ -828,31 +811,296 @@ void ScInterpreter::ScLogGamma()
PushIllegalArgument();
}
+double ScInterpreter::GetBeta(double fAlpha, double fBeta)
+{
+ double fA;
+ double fB;
+ if (fAlpha > fBeta)
+ {
+ fA = fAlpha; fB = fBeta;
+ }
+ else
+ {
+ fA = fBeta; fB = fAlpha;
+ }
+ if (fA+fB < fMaxGammaArgument) // simple case
+ return GetGamma(fA)/GetGamma(fA+fB)*GetGamma(fB);
+ // need logarithm
+ // GetLogGamma is not accurate enough, back to Lanczos for all three
+ // GetGamma and arrange factors newly.
+ const double fg = 6.024680040776729583740234375; //see GetGamma
+ double fgm = fg - 0.5;
+ double fLanczos = lcl_getLanczosSum(fA);
+ fLanczos /= lcl_getLanczosSum(fA+fB);
+ fLanczos *= lcl_getLanczosSum(fB);
+ double fABgm = fA+fB+fgm;
+ fLanczos *= sqrt((fABgm/(fA+fgm))/(fB+fgm));
+ double fTempA = fB/(fA+fgm); // (fA+fgm)/fABgm = 1 / ( 1 + fB/(fA+fgm))
+ double fTempB = fA/(fB+fgm);
+ double fResult = exp(-fA * ::rtl::math::log1p(fTempA)
+ -fB * ::rtl::math::log1p(fTempB)-fgm);
+ fResult *= fLanczos;
+ return fResult;
+}
+
+// Same as GetBeta but with logarithm
+double ScInterpreter::GetLogBeta(double fAlpha, double fBeta)
+{
+ double fA;
+ double fB;
+ if (fAlpha > fBeta)
+ {
+ fA = fAlpha; fB = fBeta;
+ }
+ else
+ {
+ fA = fBeta; fB = fAlpha;
+ }
+ const double fg = 6.024680040776729583740234375; //see GetGamma
+ double fgm = fg - 0.5;
+ double fLanczos = lcl_getLanczosSum(fA);
+ fLanczos /= lcl_getLanczosSum(fA+fB);
+ fLanczos *= lcl_getLanczosSum(fB);
+ double fLogLanczos = log(fLanczos);
+ double fABgm = fA+fB+fgm;
+ fLogLanczos += 0.5*(log(fABgm)-log(fA+fgm)-log(fB+fgm));
+ double fTempA = fB/(fA+fgm); // (fA+fgm)/fABgm = 1 / ( 1 + fB/(fA+fgm))
+ double fTempB = fA/(fB+fgm);
+ double fResult = -fA * ::rtl::math::log1p(fTempA)
+ -fB * ::rtl::math::log1p(fTempB)-fgm;
+ fResult += fLogLanczos;
+ return fResult;
+}
+
+// beta distribution probability density function
+double ScInterpreter::GetBetaDistPDF(double fX, double fA, double fB)
+{
+ // special cases
+ if (fA == 1.0) // result b*(1-x)^(b-1)
+ {
+ if (fB == 1.0)
+ return 1.0;
+ if (fB == 2.0)
+ return -2.0*fX + 2.0;
+ if (fX == 1.0 && fB < 1.0)
+ {
+ SetError(errIllegalArgument);
+ return HUGE_VAL;
+ }
+ if (fX <= 0.01)
+ return fB + fB * ::rtl::math::expm1((fB-1.0) * ::rtl::math::log1p(-fX));
+ else
+ return fB * pow(0.5-fX+0.5,fB-1.0);
+ }
+ if (fB == 1.0) // result a*x^(a-1)
+ {
+ if (fA == 2.0)
+ return fA * fX;
+ if (fX == 0.0 && fA < 1.0)
+ {
+ SetError(errIllegalArgument);
+ return HUGE_VAL;
+ }
+ return fA * pow(fX,fA-1);
+ }
+ if (fX <= 0.0)
+ {
+ if (fA < 1.0 && fX == 0.0)
+ {
+ SetError(errIllegalArgument);
+ return HUGE_VAL;
+ }
+ else
+ return 0.0;
+ }
+ if (fX >= 1.0)
+ if (fB < 1.0 && fX == 1.0)
+ {
+ SetError(errIllegalArgument);
+ return HUGE_VAL;
+ }
+ else
+ return 0.0;
+
+ // normal cases; result x^(a-1)*(1-x)^(b-1)/Beta(a,b)
+ const double fLogDblMax = log( ::std::numeric_limits<double>::max());
+ const double fLogDblMin = log( ::std::numeric_limits<double>::min());
+ double fLogY = (fX < 0.1) ? ::rtl::math::log1p(-fX) : log(0.5-fX+0.5);
+ double fLogX = log(fX);
+ double fAm1 = fA-1.0;
+ double fBm1 = fB-1.0;
+ double fLogBeta = GetLogBeta(fA,fB);
+ // check whether parts over- or underflow
+ if ( fAm1 * fLogX < fLogDblMax && fAm1 * fLogX > fLogDblMin
+ && fBm1 * fLogY < fLogDblMax && fBm1* fLogY > fLogDblMin
+ && fLogBeta < fLogDblMax && fLogBeta > fLogDblMin )
+ return pow(fX,fA-1.0) * pow(0.5-fX+0.5,fB-1.0) / GetBeta(fA,fB);
+ else // need logarithm;
+ // might overflow as a whole, but seldom, not worth to pre-detect it
+ return exp((fA-1.0)*fLogX + (fB-1.0)* fLogY - fLogBeta);
+}
+
+
+/*
+ x^a * (1-x)^b
+ I_x(a,b) = ---------------- * result of ContFrac
+ a * Beta(a,b)
+*/
+double lcl_GetBetaHelperContFrac(double fX, double fA, double fB)
+{ // like old version
+ double a1, b1, a2, b2, fnorm, apl2m, d2m, d2m1, cfnew, cf;
+ a1 = 1.0; b1 = 1.0;
+ b2 = 1.0 - (fA+fB)/(fA+1.0)*fX;
+ if (b2 == 0.0)
+ {
+ a2 = 0.0;
+ fnorm = 1.0;
+ cf = 1.0;
+ }
+ else
+ {
+ a2 = 1.0;
+ fnorm = 1.0/b2;
+ cf = a2*fnorm;
+ }
+ cfnew = 1.0;
+ double rm = 1.0;
+
+ const double fMaxIter = 50000.0;
+ // loop security, normal cases converge in less than 100 iterations.
+ // FIXME: You will get so much iteratons for fX near mean,
+ // I do not know a better algorithm.
+ bool bfinished = false;
+ do
+ {
+ apl2m = fA + 2.0*rm;
+ d2m = rm*(fB-rm)*fX/((apl2m-1.0)*apl2m);
+ d2m1 = -(fA+rm)*(fA+fB+rm)*fX/(apl2m*(apl2m+1.0));
+ a1 = (a2+d2m*a1)*fnorm;
+ b1 = (b2+d2m*b1)*fnorm;
+ a2 = a1 + d2m1*a2*fnorm;
+ b2 = b1 + d2m1*b2*fnorm;
+ if (b2 != 0.0)
+ {
+ fnorm = 1.0/b2;
+ cfnew = a2*fnorm;
+ bfinished = (fabs(cf-cfnew) < fabs(cf)*fMachEps);
+ }
+ cf = cfnew;
+ rm += 1.0;
+ }
+ while (rm < fMaxIter && !bfinished);
+ return cf;
+}
+
+// cumulative distribution function, normalized
+double ScInterpreter::GetBetaDist(double fXin, double fAlpha, double fBeta)
+{
+// special cases
+ if (fXin <= 0.0) // values are valid, see spec
+ return 0.0;
+ if (fXin >= 1.0) // values are valid, see spec
+ return 1.0;
+ if (fBeta == 1.0)
+ return pow(fXin, fAlpha);
+ if (fAlpha == 1.0)
+ // 1.0 - pow(1.0-fX,fBeta) is not accurate enough
+ return -::rtl::math::expm1(fBeta * ::rtl::math::log1p(-fXin));
+ //FIXME: need special algorithm for fX near fP for large fA,fB
+ double fResult;
+ // I use always continued fraction, power series are neither
+ // faster nor more accurate.
+ double fY = (0.5-fXin)+0.5;
+ double flnY = ::rtl::math::log1p(-fXin);
+ double fX = fXin;
+ double flnX = log(fXin);
+ double fA = fAlpha;
+ double fB = fBeta;
+ bool bReflect = fXin > fAlpha/(fAlpha+fBeta);
+ if (bReflect)
+ {
+ fA = fBeta;
+ fB = fAlpha;
+ fX = fY;
+ fY = fXin;
+ flnX = flnY;
+ flnY = log(fXin);
+ }
+ fResult = lcl_GetBetaHelperContFrac(fX,fA,fB);
+ fResult = fResult/fA;
+ double fP = fA/(fA+fB);
+ double fQ = fB/(fA+fB);
+ double fTemp;
+ if (fA > 1.0 && fB > 1.0 && fP < 0.97 && fQ < 0.97) //found experimental
+ fTemp = GetBetaDistPDF(fX,fA,fB)*fX*fY;
+ else
+ fTemp = exp(fA*flnX + fB*flnY - GetLogBeta(fA,fB));
+ fResult *= fTemp;
+ if (bReflect)
+ fResult = 0.5 - fResult + 0.5;
+ if (fResult > 1.0) // ensure valid range
+ fResult = 1.0;
+ if (fResult < 0.0)
+ fResult = 0.0;
+ return fResult;
+}
void ScInterpreter::ScBetaDist()
{
BYTE nParamCount = GetByte();
- if ( !MustHaveParamCount( nParamCount, 3, 5 ) )
+ if ( !MustHaveParamCount( nParamCount, 3, 6 ) ) // expanded, see #i91547#
return;
- double fA, fB, alpha, beta, x;
- if (nParamCount == 5)
- fB = GetDouble();
+ double fLowerBound, fUpperBound;
+ double alpha, beta, x;
+ bool bIsCumulative;
+ if (nParamCount == 6)
+ bIsCumulative = GetBool();
else
- fB = 1.0;
+ bIsCumulative = true;
+ if (nParamCount >= 5)
+ fUpperBound = GetDouble();
+ else
+ fUpperBound = 1.0;
if (nParamCount >= 4)
- fA = GetDouble();
+ fLowerBound = GetDouble();
else
- fA = 0.0;
+ fLowerBound = 0.0;
beta = GetDouble();
alpha = GetDouble();
x = GetDouble();
- if (x < fA || x > fB || fA == fB || alpha <= 0.0 || beta <= 0.0)
+ double fScale = fUpperBound - fLowerBound;
+ if (fScale <= 0.0 || alpha <= 0.0 || beta <= 0.0)
{
PushIllegalArgument();
return;
}
- x = (x-fA)/(fB-fA); // Skalierung auf (0,1)
- PushDouble(GetBetaDist(x, alpha, beta));
+ if (bIsCumulative) // cumulative distribution function
+ {
+ // special cases
+ if (x < fLowerBound)
+ {
+ PushDouble(0.0); return; //see spec
+ }
+ if (x > fUpperBound)
+ {
+ PushDouble(1.0); return; //see spec
+ }
+ // normal cases
+ x = (x-fLowerBound)/fScale; // convert to standard form
+ PushDouble(GetBetaDist(x, alpha, beta));
+ return;
+ }
+ else // probability density function
+ {
+ if (x < fLowerBound || x > fUpperBound)
+ {
+ PushDouble(0.0);
+ return;
+ }
+ x = (x-fLowerBound)/fScale;
+ PushDouble(GetBetaDistPDF(x, alpha, beta)/fScale);
+ return;
+ }
}
void ScInterpreter::ScPhi()
@@ -1325,7 +1573,7 @@ void ScInterpreter::ScChiDist()
return;
double fDF = ::rtl::math::approxFloor(GetDouble());
double fChi = GetDouble();
- if (fDF < 1.0 || fDF >= 1.0E5 || fChi < 0.0 )
+ if (fDF < 1.0) // x<=0 returns 1, see ODFF 6.17.10
{
PushIllegalArgument();
return;
@@ -1359,9 +1607,10 @@ void ScInterpreter::ScWeibull()
void ScInterpreter::ScPoissonDist()
{
- if ( MustHaveParamCount( GetByte(), 3 ) )
+ BYTE nParamCount = GetByte();
+ if ( MustHaveParamCount( nParamCount, 2, 3 ) )
{
- double kum = GetDouble(); // 0 oder 1
+ double kum = (nParamCount == 3 ? GetDouble() : 1); // 0 oder 1
double lambda = GetDouble(); // Mittelwert
double x = ::rtl::math::approxFloor(GetDouble()); // x
if (lambda < 0.0 || x < 0.0)
@@ -1640,10 +1889,14 @@ void ScInterpreter::ScHypGeomDist()
void ScInterpreter::ScGammaDist()
{
- if ( !MustHaveParamCount( GetByte(), 4 ) )
+ BYTE nParamCount = GetByte();
+ if ( !MustHaveParamCount( nParamCount, 3, 4 ) )
return;
- double fCumulative = GetDouble(); // parameter type will change to bool
- bool bCumulative = (fCumulative == 1.0); // see ODFF
+ double bCumulative;
+ if (nParamCount == 4)
+ bCumulative = GetBool();
+ else
+ bCumulative = true;
double fBeta = GetDouble(); // scale
double fAlpha = GetDouble(); // shape
double fX = GetDouble(); // x
@@ -1873,7 +2126,7 @@ void ScInterpreter::ScChiInv()
return;
double fDF = ::rtl::math::approxFloor(GetDouble());
double fP = GetDouble();
- if (fDF < 1.0 || fDF >= 1.0E5 || fP <= 0.0 || fP > 1.0 )
+ if (fDF < 1.0 || fP <= 0.0 || fP > 1.0 )
{
PushIllegalArgument();
return;
@@ -1887,6 +2140,39 @@ void ScInterpreter::ScChiInv()
PushDouble(fVal);
}
+class ScChiSqDistFunction : public ScDistFunc
+{
+ ScInterpreter& rInt;
+ double fp, fDF;
+
+public:
+ ScChiSqDistFunction( ScInterpreter& rI, double fpVal, double fDFVal ) :
+ rInt(rI), fp(fpVal), fDF(fDFVal) {}
+
+ double GetValue( double x ) const { return fp - rInt.GetChiSqDistCDF(x, fDF); }
+};
+
+
+void ScInterpreter::ScChiSqInv()
+{
+ if ( !MustHaveParamCount( GetByte(), 2 ) )
+ return;
+ double fDF = ::rtl::math::approxFloor(GetDouble());
+ double fP = GetDouble();
+ if (fDF < 1.0 || fP < 0.0 || fP >= 1.0 )
+ {
+ PushIllegalArgument();
+ return;
+ }
+
+ bool bConvError;
+ ScChiSqDistFunction aFunc( *this, fP, fDF );
+ double fVal = lcl_IterateInverse( aFunc, fDF*0.5, fDF, bConvError );
+ if (bConvError)
+ SetError(errNoConvergence);
+ PushDouble(fVal);
+}
+
/***********************************************/
void ScInterpreter::ScConfidence()
diff --git a/sc/source/core/tool/interpr4.cxx b/sc/source/core/tool/interpr4.cxx
index 67eac357e302..4ef402815f9b 100644
--- a/sc/source/core/tool/interpr4.cxx
+++ b/sc/source/core/tool/interpr4.cxx
@@ -3650,6 +3650,7 @@ StackVar ScInterpreter::Interpret()
case ocTDist : ScTDist(); break;
case ocFDist : ScFDist(); break;
case ocChiDist : ScChiDist(); break;
+ case ocChiSqDist : ScChiSqDist(); break;
case ocStandard : ScStandard(); break;
case ocAveDev : ScAveDev(); break;
case ocDevSq : ScDevSq(); break;
@@ -3692,10 +3693,12 @@ StackVar ScInterpreter::Interpret()
case ocRKP : ScRKP(); break;
case ocForecast : ScForecast(); break;
case ocGammaLn : ScLogGamma(); break;
+ case ocGamma : ScGamma(); break;
case ocGammaDist : ScGammaDist(); break;
case ocGammaInv : ScGammaInv(); break;
case ocChiTest : ScChiTest(); break;
case ocChiInv : ScChiInv(); break;
+ case ocChiSqInv : ScChiSqInv(); break;
case ocTInv : ScTInv(); break;
case ocFInv : ScFInv(); break;
case ocLogInv : ScLogNormInv(); break;
@@ -3712,6 +3715,7 @@ StackVar ScInterpreter::Interpret()
case ocBase : ScBase(); break;
case ocDecimal : ScDecimal(); break;
case ocConvert : ScConvert(); break;
+ case ocEuroConvert : ScEuroConvert(); break;
case ocRoman : ScRoman(); break;
case ocArabic : ScArabic(); break;
case ocInfo : ScInfo(); break;
@@ -3887,7 +3891,7 @@ StackVar ScInterpreter::Interpret()
const ScMatrixValue* pMatVal = xMat->Get(0, 0, nMatValType);
if ( pMatVal )
{
- if (ScMatrix::IsStringType( nMatValType))
+ if (ScMatrix::IsNonValueType( nMatValType))
{
if ( xMat->IsEmptyPath( 0, 0))
{ // result of empty FALSE jump path
diff --git a/sc/source/core/tool/interpr5.cxx b/sc/source/core/tool/interpr5.cxx
index 72f1b070d02f..32be76431569 100644
--- a/sc/source/core/tool/interpr5.cxx
+++ b/sc/source/core/tool/interpr5.cxx
@@ -7,7 +7,7 @@
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: interpr5.cxx,v $
- * $Revision: 1.34 $
+ * $Revision: 1.33.36.3 $
*
* This file is part of OpenOffice.org.
*
@@ -520,7 +520,7 @@ void ScInterpreter::ScMatValue()
ScMatValType nMatValType;
const ScMatrixValue* pMatVal = pMat->Get( nC,
nR, nMatValType);
- if (ScMatrix::IsStringType( nMatValType))
+ if (ScMatrix::IsNonValueType( nMatValType))
PushString( pMatVal->GetString() );
else
PushDouble(pMatVal->fVal);
@@ -578,7 +578,7 @@ void ScInterpreter::ScMatValue()
ScMatValType nMatValType;
const ScMatrixValue* pMatVal = pMat->Get( nC, nR,
nMatValType);
- if (ScMatrix::IsStringType( nMatValType))
+ if (ScMatrix::IsNonValueType( nMatValType))
PushString( pMatVal->GetString() );
else
PushDouble(pMatVal->fVal);
@@ -1018,6 +1018,23 @@ void ScInterpreter::ScMatTrans()
}
}
+
+/** Minimum extent of one result matrix dimension.
+ For a row or column vector to be replicated the larger matrix dimension is
+ returned, else the smaller dimension.
+ */
+inline SCSIZE lcl_GetMinExtent( SCSIZE n1, SCSIZE n2 )
+{
+ if (n1 == 1)
+ return n2;
+ else if (n2 == 1)
+ return n1;
+ else if (n1 < n2)
+ return n1;
+ else
+ return n2;
+}
+
ScMatrixRef ScInterpreter::MatAdd(ScMatrix* pMat1, ScMatrix* pMat2)
{
SCSIZE nC1, nC2, nMinC;
@@ -1025,14 +1042,8 @@ ScMatrixRef ScInterpreter::MatAdd(ScMatrix* pMat1, ScMatrix* pMat2)
SCSIZE i, j;
pMat1->GetDimensions(nC1, nR1);
pMat2->GetDimensions(nC2, nR2);
- if (nC1 < nC2)
- nMinC = nC1;
- else
- nMinC = nC2;
- if (nR1 < nR2)
- nMinR = nR1;
- else
- nMinR = nR2;
+ nMinC = lcl_GetMinExtent( nC1, nC2);
+ nMinR = lcl_GetMinExtent( nR1, nR2);
ScMatrixRef xResMat = GetNewMat(nMinC, nMinR);
if (xResMat)
{
@@ -1060,14 +1071,8 @@ ScMatrixRef ScInterpreter::MatSub(ScMatrix* pMat1, ScMatrix* pMat2)
SCSIZE i, j;
pMat1->GetDimensions(nC1, nR1);
pMat2->GetDimensions(nC2, nR2);
- if (nC1 < nC2)
- nMinC = nC1;
- else
- nMinC = nC2;
- if (nR1 < nR2)
- nMinR = nR1;
- else
- nMinR = nR2;
+ nMinC = lcl_GetMinExtent( nC1, nC2);
+ nMinR = lcl_GetMinExtent( nR1, nR2);
ScMatrixRef xResMat = GetNewMat(nMinC, nMinR);
if (xResMat)
{
@@ -1095,14 +1100,8 @@ ScMatrixRef ScInterpreter::MatMul(ScMatrix* pMat1, ScMatrix* pMat2)
SCSIZE i, j;
pMat1->GetDimensions(nC1, nR1);
pMat2->GetDimensions(nC2, nR2);
- if (nC1 < nC2)
- nMinC = nC1;
- else
- nMinC = nC2;
- if (nR1 < nR2)
- nMinR = nR1;
- else
- nMinR = nR2;
+ nMinC = lcl_GetMinExtent( nC1, nC2);
+ nMinR = lcl_GetMinExtent( nR1, nR2);
ScMatrixRef xResMat = GetNewMat(nMinC, nMinR);
if (xResMat)
{
@@ -1130,14 +1129,8 @@ ScMatrixRef ScInterpreter::MatDiv(ScMatrix* pMat1, ScMatrix* pMat2)
SCSIZE i, j;
pMat1->GetDimensions(nC1, nR1);
pMat2->GetDimensions(nC2, nR2);
- if (nC1 < nC2)
- nMinC = nC1;
- else
- nMinC = nC2;
- if (nR1 < nR2)
- nMinR = nR1;
- else
- nMinR = nR2;
+ nMinC = lcl_GetMinExtent( nC1, nC2);
+ nMinR = lcl_GetMinExtent( nR1, nR2);
ScMatrixRef xResMat = GetNewMat(nMinC, nMinR);
if (xResMat)
{
@@ -1166,14 +1159,8 @@ ScMatrixRef ScInterpreter::MatPow(ScMatrix* pMat1, ScMatrix* pMat2)
SCSIZE i, j;
pMat1->GetDimensions(nC1, nR1);
pMat2->GetDimensions(nC2, nR2);
- if (nC1 < nC2)
- nMinC = nC1;
- else
- nMinC = nC2;
- if (nR1 < nR2)
- nMinR = nR1;
- else
- nMinR = nR2;
+ nMinC = lcl_GetMinExtent( nC1, nC2);
+ nMinR = lcl_GetMinExtent( nR1, nR2);
ScMatrixRef xResMat = GetNewMat(nMinC, nMinR);
if (xResMat)
{
@@ -1201,14 +1188,8 @@ ScMatrixRef ScInterpreter::MatConcat(ScMatrix* pMat1, ScMatrix* pMat2)
SCSIZE i, j;
pMat1->GetDimensions(nC1, nR1);
pMat2->GetDimensions(nC2, nR2);
- if (nC1 < nC2)
- nMinC = nC1;
- else
- nMinC = nC2;
- if (nR1 < nR2)
- nMinR = nR1;
- else
- nMinR = nR2;
+ nMinC = lcl_GetMinExtent( nC1, nC2);
+ nMinR = lcl_GetMinExtent( nR1, nR2);
ScMatrixRef xResMat = GetNewMat(nMinC, nMinR);
if (xResMat)
{
@@ -3679,26 +3660,28 @@ void ScInterpreter::ScMatRef()
const ScMatrix* pMat = pCell->GetMatrix();
if( pMat )
{
- SCSIZE nCl, nRw;
- pMat->GetDimensions( nCl, nRw );
+ SCSIZE nCols, nRows;
+ pMat->GetDimensions( nCols, nRows );
SCSIZE nC = static_cast<SCSIZE>(aPos.Col() - aAdr.Col());
SCSIZE nR = static_cast<SCSIZE>(aPos.Row() - aAdr.Row());
- if (nC < nCl && nR < nRw)
+ if ((nCols <= nC && nCols != 1) || (nRows <= nR && nRows != 1))
+ PushNA();
+ else
{
ScMatValType nMatValType;
const ScMatrixValue* pMatVal = pMat->Get( nC, nR, nMatValType);
- if (ScMatrix::IsStringType( nMatValType))
+ if (ScMatrix::IsNonValueType( nMatValType))
{
- if (ScMatrix::IsEmptyType( nMatValType))
- {
- // Not inherited (really?) and display as empty string, not 0.
- PushTempToken( new ScEmptyCellToken( false, true));
- }
- else if (ScMatrix::IsEmptyPathType( nMatValType))
+ if (ScMatrix::IsEmptyPathType( nMatValType))
{ // result of empty FALSE jump path
nFuncFmtType = NUMBERFORMAT_LOGICAL;
PushInt(0);
}
+ else if (ScMatrix::IsEmptyType( nMatValType))
+ {
+ // Not inherited (really?) and display as empty string, not 0.
+ PushTempToken( new ScEmptyCellToken( false, true));
+ }
else
PushString( pMatVal->GetString() );
}
@@ -3710,8 +3693,6 @@ void ScInterpreter::ScMatRef()
nFuncFmtIndex = nCurFmtIndex;
}
}
- else
- PushNA();
}
else
{
diff --git a/sc/source/core/tool/parclass.cxx b/sc/source/core/tool/parclass.cxx
index d31c4a8ce565..8e4d3e0b1272 100644
--- a/sc/source/core/tool/parclass.cxx
+++ b/sc/source/core/tool/parclass.cxx
@@ -7,7 +7,7 @@
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: parclass.cxx,v $
- * $Revision: 1.12 $
+ * $Revision: 1.12.148.1 $
*
* This file is part of OpenOffice.org.
*
@@ -149,6 +149,7 @@ const ScParameterClassification::RawData ScParameterClassification::pRawData[] =
{ ocN, {{ Reference }, false }},
{ ocNPV, {{ Value, Reference }, true }},
{ ocNeg, {{ Array }, false }},
+ { ocNegSub, {{ Array }, false }},
{ ocNot, {{ Array }, false }},
{ ocNotEqual, {{ Array, Array }, false }},
{ ocOffset, {{ Reference, Value, Value, Value, Value }, false }},
diff --git a/sc/source/core/tool/scmatrix.cxx b/sc/source/core/tool/scmatrix.cxx
index 014cbbb5c491..891ed6378022 100644
--- a/sc/source/core/tool/scmatrix.cxx
+++ b/sc/source/core/tool/scmatrix.cxx
@@ -7,7 +7,7 @@
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: scmatrix.cxx,v $
- * $Revision: 1.18 $
+ * $Revision: 1.17.136.3 $
*
* This file is part of OpenOffice.org.
*
@@ -79,6 +79,14 @@ ScMatrix* ScMatrix::Clone() const
return pScMat;
}
+ScMatrix* ScMatrix::CloneAndExtend( SCSIZE nNewCols, SCSIZE nNewRows ) const
+{
+ ScMatrix* pScMat = new ScMatrix( nNewCols, nNewRows);
+ MatCopy(*pScMat);
+ pScMat->SetErrorInterpreter( pErrorInterpreter);
+ return pScMat;
+}
+
void ScMatrix::SetErrorAtInterpreter( USHORT nError ) const
{
if ( pErrorInterpreter )
@@ -180,7 +188,7 @@ void ScMatrix::Store(SvStream& /* rStream */) const
for (SCSIZE i=0; i<nCount; i++)
{
BYTE nType = CELLTYPE_VALUE;
- if ( mnValType && IsStringType( mnValType[i]))
+ if ( mnValType && IsNonValueType( mnValType[i]))
{
if ( pMat[i].pS )
aMatStr = *pMat[i].pS;
@@ -208,7 +216,7 @@ void ScMatrix::ResetIsString()
{
for (SCSIZE i = 0; i < nCount; i++)
{
- if ( IsStringType( mnValType[i]))
+ if ( IsNonValueType( mnValType[i]))
delete pMat[i].pS;
}
}
@@ -225,7 +233,7 @@ void ScMatrix::DeleteIsString()
SCSIZE nCount = nColCount * nRowCount;
for ( SCSIZE i = 0; i < nCount; i++ )
{
- if (IsStringType( mnValType[i]))
+ if (IsNonValueType( mnValType[i]))
delete pMat[i].pS;
}
delete [] mnValType;
@@ -258,7 +266,7 @@ void ScMatrix::PutString(const String& rStr, SCSIZE nIndex)
{
if (mnValType == NULL)
ResetIsString();
- if ( IsStringType( mnValType[nIndex]) && pMat[nIndex].pS )
+ if ( IsNonValueType( mnValType[nIndex]) && pMat[nIndex].pS )
*(pMat[nIndex].pS) = rStr;
else
{
@@ -277,10 +285,10 @@ void ScMatrix::PutStringEntry( const String* pStr, BYTE bFlag, SCSIZE nIndex )
// the value with if (IsValueOrEmpty()) GetDouble(). Backup pS first.
String* pS = pMat[nIndex].pS;
pMat[nIndex].fVal = 0.0;
- // An EMPTY entry must not have a string pointer therefor.
+ // An EMPTY or EMPTYPATH entry must not have a string pointer therefor.
DBG_ASSERT( (((bFlag & SC_MATVAL_EMPTY) == SC_MATVAL_EMPTY) && !pStr) || TRUE,
- "ScMatrix::PutStringEntry: pStr passed though EMPTY entry");
- if ( IsStringType( mnValType[nIndex]) && pS )
+ "ScMatrix::PutStringEntry: pStr passed through EMPTY entry");
+ if ( IsNonValueType( mnValType[nIndex]) && pS )
{
if ((bFlag & SC_MATVAL_EMPTY) == SC_MATVAL_EMPTY)
delete pS, pS = NULL;
@@ -312,7 +320,7 @@ void ScMatrix::PutEmpty(SCSIZE nIndex)
{
if (mnValType == NULL)
ResetIsString();
- if ( IsStringType( mnValType[nIndex]) && pMat[nIndex].pS )
+ if ( IsNonValueType( mnValType[nIndex]) && pMat[nIndex].pS )
{
delete pMat[nIndex].pS;
}
@@ -339,7 +347,7 @@ void ScMatrix::PutEmptyPath(SCSIZE nIndex)
{
if (mnValType == NULL)
ResetIsString();
- if ( IsStringType( mnValType[nIndex]) && pMat[nIndex].pS )
+ if ( IsNonValueType( mnValType[nIndex]) && pMat[nIndex].pS )
{
delete pMat[nIndex].pS;
}
@@ -366,7 +374,7 @@ void ScMatrix::PutBoolean( bool bVal, SCSIZE nIndex)
{
if (mnValType == NULL)
ResetIsString();
- if ( IsStringType( mnValType[nIndex]) && pMat[nIndex].pS )
+ if ( IsNonValueType( mnValType[nIndex]) && pMat[nIndex].pS )
{
delete pMat[nIndex].pS;
mnNonValue--;
@@ -379,29 +387,29 @@ void ScMatrix::PutBoolean( bool bVal, SCSIZE nIndex)
USHORT ScMatrix::GetError( SCSIZE nC, SCSIZE nR) const
{
- if (ValidColRow( nC, nR))
+ if (ValidColRowOrReplicated( nC, nR ))
return GetError( CalcOffset( nC, nR) );
else
{
DBG_ERRORFILE("ScMatrix::GetError: dimension error");
- return 0; // TODO: do we want an error instead?
+ return errNoValue;
}
}
double ScMatrix::GetDouble(SCSIZE nC, SCSIZE nR) const
{
- if (ValidColRow( nC, nR))
+ if (ValidColRowOrReplicated( nC, nR ))
return GetDouble( CalcOffset( nC, nR) );
else
{
DBG_ERRORFILE("ScMatrix::GetDouble: dimension error");
- return 0.0;
+ return CreateDoubleError( errNoValue);
}
}
const String& ScMatrix::GetString(SCSIZE nC, SCSIZE nR) const
{
- if (ValidColRow( nC, nR))
+ if (ValidColRowOrReplicated( nC, nR ))
{
SCSIZE nIndex = CalcOffset( nC, nR);
if ( IsString( nIndex ) )
@@ -454,7 +462,7 @@ String ScMatrix::GetString( SvNumberFormatter& rFormatter, SCSIZE nIndex) const
String ScMatrix::GetString( SvNumberFormatter& rFormatter, SCSIZE nC, SCSIZE nR) const
{
- if (ValidColRow( nC, nR))
+ if (ValidColRowOrReplicated( nC, nR ))
{
SCSIZE nIndex = CalcOffset( nC, nR);
return GetString( rFormatter, nIndex);
@@ -469,7 +477,7 @@ String ScMatrix::GetString( SvNumberFormatter& rFormatter, SCSIZE nC, SCSIZE nR)
const ScMatrixValue* ScMatrix::Get(SCSIZE nC, SCSIZE nR, ScMatValType& nType) const
{
- if (ValidColRow( nC, nR))
+ if (ValidColRowOrReplicated( nC, nR ))
{
SCSIZE nIndex = CalcOffset( nC, nR);
if (mnValType)
@@ -488,11 +496,11 @@ const ScMatrixValue* ScMatrix::Get(SCSIZE nC, SCSIZE nR, ScMatValType& nType) co
void ScMatrix::MatCopy(ScMatrix& mRes) const
{
- if (nColCount != mRes.nColCount || nRowCount != mRes.nRowCount)
+ if (nColCount > mRes.nColCount || nRowCount > mRes.nRowCount)
{
DBG_ERRORFILE("ScMatrix::MatCopy: dimension error");
}
- else
+ else if ( nColCount == mRes.nColCount && nRowCount == mRes.nRowCount )
{
if (mnValType)
{
@@ -503,7 +511,7 @@ void ScMatrix::MatCopy(ScMatrix& mRes) const
SCSIZE nStart = i * nRowCount;
for (SCSIZE j = 0; j < nRowCount; j++)
{
- if (IsStringType( (nType = mnValType[nStart+j])))
+ if (IsNonValueType( (nType = mnValType[nStart+j])))
mRes.PutStringEntry( pMat[nStart+j].pS, nType, nStart+j );
else
{
@@ -521,6 +529,41 @@ void ScMatrix::MatCopy(ScMatrix& mRes) const
mRes.pMat[i].fVal = pMat[i].fVal;
}
}
+ else
+ {
+ // Copy this matrix to upper left rectangle of result matrix.
+ if (mnValType)
+ {
+ ScMatValType nType;
+ mRes.ResetIsString();
+ for (SCSIZE i = 0; i < nColCount; i++)
+ {
+ SCSIZE nStart = i * nRowCount;
+ SCSIZE nResStart = i * mRes.nRowCount;
+ for (SCSIZE j = 0; j < nRowCount; j++)
+ {
+ if (IsNonValueType( (nType = mnValType[nStart+j])))
+ mRes.PutStringEntry( pMat[nStart+j].pS, nType, nResStart+j );
+ else
+ {
+ mRes.pMat[nResStart+j].fVal = pMat[nStart+j].fVal;
+ mRes.mnValType[nResStart+j] = nType;
+ }
+ }
+ }
+ }
+ else
+ {
+ mRes.DeleteIsString();
+ for (SCSIZE i = 0; i < nColCount; i++)
+ {
+ SCSIZE nStart = i * nRowCount;
+ SCSIZE nResStart = i * mRes.nRowCount;
+ for (SCSIZE j = 0; j < nRowCount; j++)
+ mRes.pMat[nResStart+j].fVal = pMat[nStart+j].fVal;
+ }
+ }
+ }
}
void ScMatrix::MatTrans(ScMatrix& mRes) const
@@ -540,7 +583,7 @@ void ScMatrix::MatTrans(ScMatrix& mRes) const
SCSIZE nStart = i * nRowCount;
for ( SCSIZE j = 0; j < nRowCount; j++ )
{
- if (IsStringType( (nType = mnValType[nStart+j])))
+ if (IsNonValueType( (nType = mnValType[nStart+j])))
mRes.PutStringEntry( pMat[nStart+j].pS, nType, j*mRes.nRowCount+i );
else
{
@@ -565,6 +608,49 @@ void ScMatrix::MatTrans(ScMatrix& mRes) const
}
}
+void ScMatrix::MatCopyUpperLeft(ScMatrix& mRes) const
+{
+ if (nColCount < mRes.nColCount || nRowCount < mRes.nRowCount)
+ {
+ DBG_ERRORFILE("ScMatrix::MatCopyUpperLeft: dimension error");
+ }
+ else
+ {
+ if (mnValType)
+ {
+ ScMatValType nType;
+ mRes.ResetIsString();
+ for ( SCSIZE i = 0; i < mRes.nColCount; i++ )
+ {
+ SCSIZE nStart = i * nRowCount;
+ for ( SCSIZE j = 0; j < mRes.nRowCount; j++ )
+ {
+ if ( IsNonValueType( (nType = mnValType[nStart+j]) ))
+ mRes.PutStringEntry( pMat[nStart+j].pS, nType,
+ i*mRes.nRowCount+j );
+ else
+ {
+ mRes.pMat[i*mRes.nRowCount+j].fVal = pMat[nStart+j].fVal;
+ mRes.mnValType[i*mRes.nRowCount+j] = nType;
+ }
+ }
+ }
+ }
+ else
+ {
+ mRes.DeleteIsString();
+ for ( SCSIZE i = 0; i < mRes.nColCount; i++ )
+ {
+ SCSIZE nStart = i * nRowCount;
+ for ( SCSIZE j = 0; j < mRes.nRowCount; j++ )
+ {
+ mRes.pMat[i*mRes.nRowCount+j].fVal = pMat[nStart+j].fVal;
+ }
+ }
+ }
+ }
+}
+
void ScMatrix::FillDouble( double fVal, SCSIZE nC1, SCSIZE nR1, SCSIZE nC2, SCSIZE nR2 )
{
if (ValidColRow( nC1, nR1) && ValidColRow( nC2, nR2))
diff --git a/sc/source/core/tool/token.cxx b/sc/source/core/tool/token.cxx
index 31fdcdedb7e9..776831726fe6 100644
--- a/sc/source/core/tool/token.cxx
+++ b/sc/source/core/tool/token.cxx
@@ -2486,11 +2486,6 @@ void ScTokenArray::ReadjustRelative3DReferences( const ScAddress& rOldPos,
// --- POF (plain old formula) rewrite of a token array ---------------------
-/* TODO: When both POF OOoXML and ODFF are to be supported differently, the
- * ScMissingContext and ScTokenArray::*Pof* methods should go to a convention
- * on its own.
- */
-
#if 0
// static function can't be compiled if not used (warning)
//#if OSL_DEBUG_LEVEL > 0
@@ -2512,37 +2507,41 @@ class ScMissingContext
void Clear() { mpFunc = NULL; mnCurArg = 0; }
inline bool AddDefaultArg( ScTokenArray* pNewArr, int nArg, double f ) const;
- static inline bool IsRewriteNeeded( OpCode eOp );
bool AddMissingExternal( ScTokenArray* pNewArr ) const;
- bool AddMissing( ScTokenArray *pNewArr ) const;
- void AddMoreArgs( ScTokenArray *pNewArr ) const;
+ bool AddMissing( ScTokenArray *pNewArr, const ScMissingConvention & rConv ) const;
+ void AddMoreArgs( ScTokenArray *pNewArr, const ScMissingConvention & rConv ) const;
};
-inline bool ScMissingContext::AddDefaultArg( ScTokenArray* pNewArr, int nArg, double f ) const
-{
- if (mnCurArg == nArg)
- {
- pNewArr->AddDouble( f );
- return true;
- }
- return false;
-}
-
-inline bool ScMissingContext::IsRewriteNeeded( OpCode eOp )
+inline bool ScMissingConvention::isRewriteNeeded( OpCode eOp ) const
{
switch (eOp)
{
+ case ocGammaDist:
+ case ocPoissonDist:
+ return true;
case ocMissing:
case ocLog:
case ocAddress:
- return true;
+ return !isODFF(); // rewrite only for PODF
default:
return false;
}
}
+inline bool ScMissingContext::AddDefaultArg( ScTokenArray* pNewArr, int nArg, double f ) const
+{
+ if (mnCurArg == nArg)
+ {
+ pNewArr->AddDouble( f );
+ return true;
+ }
+ return false;
+}
+
bool ScMissingContext::AddMissingExternal( ScTokenArray *pNewArr ) const
{
+ // Only called for PODF, not ODFF. No need to distinguish.
+
const String &rName = mpFunc->GetExternal();
// initial (fast) check:
@@ -2563,79 +2562,105 @@ bool ScMissingContext::AddMissingExternal( ScTokenArray *pNewArr ) const
return false;
}
-bool ScMissingContext::AddMissing( ScTokenArray *pNewArr ) const
+bool ScMissingContext::AddMissing( ScTokenArray *pNewArr, const ScMissingConvention & rConv ) const
{
if ( !mpFunc )
return false;
bool bRet = false;
- switch ( mpFunc->GetOpCode() )
+ if (rConv.isODFF())
{
- case ocFixed:
- return AddDefaultArg( pNewArr, 1, 2.0 );
- //break;
- case ocBetaDist:
- case ocBetaInv:
- case ocRMZ: // PMT
- return AddDefaultArg( pNewArr, 3, 0.0 );
- //break;
- case ocZinsZ: // IPMT
- case ocKapz: // PPMT
- return AddDefaultArg( pNewArr, 4, 0.0 );
- //break;
- case ocBW: // PV
- case ocZW: // FV
- bRet |= AddDefaultArg( pNewArr, 2, 0.0 ); // pmt
- bRet |= AddDefaultArg( pNewArr, 3, 0.0 ); // [fp]v
- break;
- case ocZins: // RATE
- bRet |= AddDefaultArg( pNewArr, 1, 0.0 ); // pmt
- bRet |= AddDefaultArg( pNewArr, 3, 0.0 ); // fv
- bRet |= AddDefaultArg( pNewArr, 4, 0.0 ); // type
- break;
- case ocExternal:
- return AddMissingExternal( pNewArr );
- //break;
+ }
+ else
+ {
+ switch ( mpFunc->GetOpCode() )
+ {
+ case ocFixed:
+ return AddDefaultArg( pNewArr, 1, 2.0 );
+ //break;
+ case ocBetaDist:
+ case ocBetaInv:
+ case ocRMZ: // PMT
+ return AddDefaultArg( pNewArr, 3, 0.0 );
+ //break;
+ case ocZinsZ: // IPMT
+ case ocKapz: // PPMT
+ return AddDefaultArg( pNewArr, 4, 0.0 );
+ //break;
+ case ocBW: // PV
+ case ocZW: // FV
+ bRet |= AddDefaultArg( pNewArr, 2, 0.0 ); // pmt
+ bRet |= AddDefaultArg( pNewArr, 3, 0.0 ); // [fp]v
+ break;
+ case ocZins: // RATE
+ bRet |= AddDefaultArg( pNewArr, 1, 0.0 ); // pmt
+ bRet |= AddDefaultArg( pNewArr, 3, 0.0 ); // fv
+ bRet |= AddDefaultArg( pNewArr, 4, 0.0 ); // type
+ break;
+ case ocExternal:
+ return AddMissingExternal( pNewArr );
+ //break;
- // --- more complex cases ---
+ // --- more complex cases ---
- case ocOffset:
- // FIXME: rather tough.
- // if arg 3 (height) ommitted, export arg1 (rows)
- break;
- default:
- break;
+ case ocOffset:
+ // FIXME: rather tough.
+ // if arg 3 (height) ommitted, export arg1 (rows)
+ break;
+ default:
+ break;
+ }
}
return bRet;
}
-void ScMissingContext::AddMoreArgs( ScTokenArray *pNewArr ) const
+void ScMissingContext::AddMoreArgs( ScTokenArray *pNewArr, const ScMissingConvention & rConv ) const
{
if ( !mpFunc )
return;
- // Log
- if ( mpFunc->GetOpCode() == ocLog && mnCurArg < 1 )
+ switch (mpFunc->GetOpCode())
{
- pNewArr->AddOpCode( ocSep );
- pNewArr->AddDouble( 10.0 );
+ case ocGammaDist:
+ if (mnCurArg == 2)
+ {
+ pNewArr->AddOpCode( ocSep );
+ pNewArr->AddDouble( 1.0 ); // 4th, Cumulative=TRUE()
+ }
+ break;
+ case ocPoissonDist:
+ if (mnCurArg == 1)
+ {
+ pNewArr->AddOpCode( ocSep );
+ pNewArr->AddDouble( 1.0 ); // 3rd, Cumulative=TRUE()
+ }
+ break;
+ case ocLog:
+ if ( !rConv.isODFF() && mnCurArg == 0 )
+ {
+ pNewArr->AddOpCode( ocSep );
+ pNewArr->AddDouble( 10.0 ); // 2nd, basis 10
+ }
+ break;
+ default:
+ break;
}
}
-bool ScTokenArray::NeedsPofRewrite()
+bool ScTokenArray::NeedsPofRewrite( const ScMissingConvention & rConv )
{
for ( ScToken *pCur = First(); pCur; pCur = Next() )
{
- if (ScMissingContext::IsRewriteNeeded( pCur->GetOpCode()))
+ if (rConv.isRewriteNeeded( pCur->GetOpCode()))
return true;
}
return false;
}
-ScTokenArray * ScTokenArray::RewriteMissingToPof()
+ScTokenArray * ScTokenArray::RewriteMissingToPof( const ScMissingConvention & rConv )
{
const size_t nAlloc = 256;
ScMissingContext aCtx[ nAlloc ];
@@ -2683,7 +2708,7 @@ ScTokenArray * ScTokenArray::RewriteMissingToPof()
pOcas[ nOcas++ ] = nFn; // entering ADDRESS()
break;
case ocClose:
- pCtx[ nFn ].AddMoreArgs( pNewArr );
+ pCtx[ nFn ].AddMoreArgs( pNewArr, rConv );
DBG_ASSERT( nFn > 0, "ScTokenArray::RewriteMissingToPof: underflow");
if (nOcas > 0 && pOcas[ nOcas-1 ] == nFn)
--nOcas; // leaving ADDRESS()
@@ -2701,7 +2726,7 @@ ScTokenArray * ScTokenArray::RewriteMissingToPof()
break;
case ocMissing:
if (bAdd)
- bAdd = !pCtx[ nFn ].AddMissing( pNewArr );
+ bAdd = !pCtx[ nFn ].AddMissing( pNewArr, rConv );
break;
default:
break;
diff --git a/sc/source/filter/excel/excform8.cxx b/sc/source/filter/excel/excform8.cxx
index d59618ef35ac..47fbd506099c 100644
--- a/sc/source/filter/excel/excform8.cxx
+++ b/sc/source/filter/excel/excform8.cxx
@@ -680,6 +680,12 @@ ConvErr ExcelToSc8::Convert( const ScTokenArray*& rpTokArray, XclImpStream& aIn,
}
break;
+ case xlExtEuroConvert:
+ {
+ aStack << aPool.Store( ocEuroConvert, String() );
+ }
+ break;
+
default: // OLE link
{
aPool << ocBad;
diff --git a/sc/source/filter/excel/tokstack.cxx b/sc/source/filter/excel/tokstack.cxx
index 78c29e079354..c6cff9bbce78 100644
--- a/sc/source/filter/excel/tokstack.cxx
+++ b/sc/source/filter/excel/tokstack.cxx
@@ -374,8 +374,13 @@ void TokenPool::GetElement( const UINT16 nId )
EXTCONT* p = ( n < nP_Ext )? ppP_Ext[ n ] : NULL;
if( p )
+ {
+ if( p->eId == ocEuroConvert )
+ pScToken->AddOpCode( p->eId );
+ else
pScToken->AddExternal( p->aText, p->eId );
}
+ }
break;
case T_Nlf:
{
diff --git a/sc/source/filter/excel/xeformula.cxx b/sc/source/filter/excel/xeformula.cxx
index cc2e7c519cd0..6fc5f782df8e 100644
--- a/sc/source/filter/excel/xeformula.cxx
+++ b/sc/source/filter/excel/xeformula.cxx
@@ -399,6 +399,7 @@ private:
void AppendNameXToken( sal_uInt16 nExtSheet, sal_uInt16 nExtName, sal_uInt8 nExpClass, sal_uInt8 nSpaces = 0 );
void AppendMacroCallToken( const XclExpExtFuncData& rExtFuncData, sal_uInt8 nExpClass, sal_uInt8 nSpaces = 0 );
void AppendAddInFuncToken( const XclExpExtFuncData& rExtFuncData, sal_uInt8 nExpClass, sal_uInt8 nSpaces = 0 );
+ void AppendEuroToolFuncToken( const XclExpExtFuncData& rExtFuncData, sal_uInt8 nExpClass, sal_uInt8 nSpaces = 0 );
void AppendParenToken( sal_uInt8 nOpenSpaces = 0, sal_uInt8 nCloseSpaces = 0 );
void AppendJumpToken( XclExpFuncData& rFuncData, sal_uInt8 nAttrType );
@@ -1723,6 +1724,9 @@ void XclExpFmlaCompImpl::AppendDefaultParam( XclExpFuncData& rFuncData )
case ocExternal:
AppendAddInFuncToken( rFuncData.GetExtFuncData(), EXC_TOKCLASS_REF );
break;
+ case ocEuroConvert:
+ AppendEuroToolFuncToken( rFuncData.GetExtFuncData(), EXC_TOKCLASS_REF );
+ break;
case ocMacro:
AppendMacroCallToken( rFuncData.GetExtFuncData(), EXC_TOKCLASS_REF );
break;
@@ -1784,6 +1788,26 @@ void XclExpFmlaCompImpl::AppendTrailingParam( XclExpFuncData& rFuncData )
AppendDefaultParam( rFuncData );
break;
+ case ocGammaDist:
+ if( nParamCount == 3 )
+ {
+ // GAMMADIST function needs 4 parameters in Excel
+ PrepareParam( rFuncData );
+ AppendIntToken( 1 );
+ FinishParam( rFuncData );
+ }
+ break;
+
+ case ocPoissonDist:
+ if( nParamCount == 2 )
+ {
+ // POISSON function needs 3 parameters in Excel
+ PrepareParam( rFuncData );
+ AppendIntToken( 1 );
+ FinishParam( rFuncData );
+ }
+ break;
+
default:;
}
}
@@ -2323,6 +2347,15 @@ void XclExpFmlaCompImpl::AppendAddInFuncToken( const XclExpExtFuncData& rExtFunc
AppendMacroCallToken( rExtFuncData, nExpClass, nSpaces );
}
+void XclExpFmlaCompImpl::AppendEuroToolFuncToken( const XclExpExtFuncData& rExtFuncData, sal_uInt8 nExpClass, sal_uInt8 nSpaces )
+{
+ sal_uInt16 nExtSheet, nExtName;
+ if( mpLinkMgr && mpLinkMgr->InsertEuroTool( nExtSheet, nExtName, rExtFuncData.maFuncName ) )
+ AppendNameXToken( nExtSheet, nExtName, nExpClass, nSpaces );
+ else
+ AppendMacroCallToken( rExtFuncData, nExpClass, nSpaces );
+}
+
void XclExpFmlaCompImpl::AppendParenToken( sal_uInt8 nOpenSpaces, sal_uInt8 nCloseSpaces )
{
AppendSpaceToken( EXC_TOK_ATTR_SPACE_SP_OPEN, nOpenSpaces );
diff --git a/sc/source/filter/excel/xehelper.cxx b/sc/source/filter/excel/xehelper.cxx
index 771c659cbed6..45a44b2c88d1 100644
--- a/sc/source/filter/excel/xehelper.cxx
+++ b/sc/source/filter/excel/xehelper.cxx
@@ -7,7 +7,7 @@
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: xehelper.cxx,v $
- * $Revision: 1.31.32.2 $
+ * $Revision: 1.31.148.1 $
*
* This file is part of OpenOffice.org.
*
@@ -1114,7 +1114,7 @@ void XclExpCachedMatrix::Save( XclExpStream& rStrm ) const
rStrm << EXC_CACHEDVAL_EMPTY;
rStrm.WriteZeroBytes( 8 );
}
- else if( ScMatrix::IsStringType( nMatValType ) )
+ else if( ScMatrix::IsNonValueType( nMatValType ) )
{
XclExpString aStr( pMatVal->GetString(), EXC_STR_DEFAULT );
rStrm.SetSliceSize( 6 );
diff --git a/sc/source/filter/excel/xelink.cxx b/sc/source/filter/excel/xelink.cxx
index f6520d1af861..9d1b7df3e741 100644
--- a/sc/source/filter/excel/xelink.cxx
+++ b/sc/source/filter/excel/xelink.cxx
@@ -140,6 +140,8 @@ public:
/** Inserts an add-in function name
@return The 1-based (Excel-like) list index of the name. */
sal_uInt16 InsertAddIn( const String& rName );
+ /** InsertEuroTool */
+ sal_uInt16 InsertEuroTool( const String& rName );
/** Inserts a DDE link.
@return The 1-based (Excel-like) list index of the DDE link. */
sal_uInt16 InsertDde( const String& rApplic, const String& rTopic, const String& rItem );
@@ -335,6 +337,8 @@ public:
explicit XclExpSupbook( const XclExpRoot& rRoot, sal_uInt16 nXclTabCount );
/** Creates a SUPBOOK record for add-in functions. */
explicit XclExpSupbook( const XclExpRoot& rRoot );
+ /** EUROTOOL SUPBOOK */
+ explicit XclExpSupbook( const XclExpRoot& rRoot, const String& rUrl, XclSupbookType );
/** Creates a SUPBOOK record for an external document. */
explicit XclExpSupbook( const XclExpRoot& rRoot, const String& rUrl );
/** Creates a SUPBOOK record for a DDE link. */
@@ -362,6 +366,8 @@ public:
/** Finds or inserts an EXTERNNAME record for add-ins.
@return The 1-based EXTERNNAME record index; or 0, if the record list is full. */
sal_uInt16 InsertAddIn( const String& rName );
+ /** InsertEuroTool */
+ sal_uInt16 InsertEuroTool( const String& rName );
/** Finds or inserts an EXTERNNAME record for DDE links.
@return The 1-based EXTERNNAME record index; or 0, if the record list is full. */
sal_uInt16 InsertDde( const String& rItem );
@@ -443,6 +449,10 @@ public:
bool InsertAddIn(
sal_uInt16& rnSupbook, sal_uInt16& rnExtName,
const String& rName );
+ /** InsertEuroTool */
+ bool InsertEuroTool(
+ sal_uInt16& rnSupbook, sal_uInt16& rnExtName,
+ const String& rName );
/** Finds or inserts an EXTERNNAME record for DDE links.
@param rnSupbook Returns the index of the SUPBOOK record which contains the DDE link.
@param rnExtName Returns the 1-based EXTERNNAME record index. */
@@ -526,6 +536,11 @@ public:
virtual bool InsertAddIn(
sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
const String& rName ) = 0;
+ /** InsertEuroTool */
+ virtual bool InsertEuroTool(
+ sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
+ const String& rName ) = 0;
+
/** Derived classes find or insert an EXTERNNAME record for DDE links. */
virtual bool InsertDde(
sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
@@ -569,6 +584,11 @@ public:
sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
const String& rName );
+ /** InsertEuroTool */
+ virtual bool InsertEuroTool(
+ sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
+ const String& rName );
+
virtual bool InsertDde(
sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
const String& rApplic, const String& rTopic, const String& rItem );
@@ -633,6 +653,10 @@ public:
virtual bool InsertAddIn(
sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
const String& rName );
+ /** InsertEuroTool */
+ virtual bool InsertEuroTool(
+ sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
+ const String& rName );
virtual bool InsertDde(
sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
@@ -1078,6 +1102,12 @@ sal_uInt16 XclExpExtNameBuffer::InsertAddIn( const String& rName )
return nIndex ? nIndex : AppendNew( new XclExpExtNameAddIn( GetRoot(), rName ) );
}
+sal_uInt16 XclExpExtNameBuffer::InsertEuroTool( const String& rName )
+{
+ sal_uInt16 nIndex = GetIndex( rName );
+ return nIndex ? nIndex : AppendNew( new XclExpExtNameBase( GetRoot(), rName ) );
+}
+
sal_uInt16 XclExpExtNameBuffer::InsertDde(
const String& rApplic, const String& rTopic, const String& rItem )
{
@@ -1421,6 +1451,17 @@ XclExpSupbook::XclExpSupbook( const XclExpRoot& rRoot ) :
{
}
+XclExpSupbook::XclExpSupbook( const XclExpRoot& rRoot, const String& rUrl, XclSupbookType ) :
+ XclExpExternSheetBase( rRoot, EXC_ID_SUPBOOK ),
+ maUrl( rUrl ),
+ maUrlEncoded( rUrl ),
+ meType( EXC_SBTYPE_EUROTOOL ),
+ mnXclTabCount( 0 )
+{
+ SetRecSize( 2 + maUrlEncoded.GetSize() );
+}
+
+
XclExpSupbook::XclExpSupbook( const XclExpRoot& rRoot, const String& rUrl ) :
XclExpExternSheetBase( rRoot, EXC_ID_SUPBOOK ),
maUrl( rUrl ),
@@ -1456,7 +1497,7 @@ XclExpSupbook::XclExpSupbook( const XclExpRoot& rRoot, const String& rApplic, co
bool XclExpSupbook::IsUrlLink( const String& rUrl ) const
{
- return (meType == EXC_SBTYPE_EXTERN) && (maUrl == rUrl);
+ return (meType == EXC_SBTYPE_EXTERN || meType == EXC_SBTYPE_EUROTOOL) && (maUrl == rUrl);
}
bool XclExpSupbook::IsDdeLink( const String& rApplic, const String& rTopic ) const
@@ -1534,6 +1575,11 @@ sal_uInt16 XclExpSupbook::InsertAddIn( const String& rName )
return GetExtNameBuffer().InsertAddIn( rName );
}
+sal_uInt16 XclExpSupbook::InsertEuroTool( const String& rName )
+{
+ return GetExtNameBuffer().InsertEuroTool( rName );
+}
+
sal_uInt16 XclExpSupbook::InsertDde( const String& rItem )
{
return GetExtNameBuffer().InsertDde( maUrl, maDdeTopic, rItem );
@@ -1569,6 +1615,7 @@ void XclExpSupbook::WriteBody( XclExpStream& rStrm )
break;
case EXC_SBTYPE_EXTERN:
case EXC_SBTYPE_SPECIAL:
+ case EXC_SBTYPE_EUROTOOL:
{
sal_uInt16 nCount = ulimit_cast< sal_uInt16 >( maXctList.GetSize() );
rStrm << nCount << maUrlEncoded;
@@ -1806,6 +1853,20 @@ bool XclExpSupbookBuffer::InsertAddIn(
return rnExtName > 0;
}
+bool XclExpSupbookBuffer::InsertEuroTool(
+ sal_uInt16& rnSupbook, sal_uInt16& rnExtName, const String& rName )
+{
+ XclExpSupbookRef xSupbook;
+ String aUrl( RTL_CONSTASCII_USTRINGPARAM("\001\010EUROTOOL.XLA"));
+ if( !GetSupbookUrl( xSupbook, rnSupbook, aUrl ) )
+ {
+ xSupbook.reset( new XclExpSupbook( GetRoot(), aUrl, EXC_SBTYPE_EUROTOOL ) );
+ rnSupbook = Append( xSupbook );
+ }
+ rnExtName = xSupbook->InsertEuroTool( rName );
+ return rnExtName > 0;
+}
+
bool XclExpSupbookBuffer::InsertDde(
sal_uInt16& rnSupbook, sal_uInt16& rnExtName,
const String& rApplic, const String& rTopic, const String& rItem )
@@ -2008,6 +2069,13 @@ bool XclExpLinkManagerImpl5::InsertAddIn(
return false;
}
+bool XclExpLinkManagerImpl5::InsertEuroTool(
+ sal_uInt16& /*rnExtSheet*/, sal_uInt16& /*rnExtName*/, const String& /*rName*/ )
+{
+ return false;
+}
+
+
bool XclExpLinkManagerImpl5::InsertDde(
sal_uInt16& /*rnExtSheet*/, sal_uInt16& /*rnExtName*/,
const String& /*rApplic*/, const String& /*rTopic*/, const String& /*rItem*/ )
@@ -2202,6 +2270,19 @@ bool XclExpLinkManagerImpl8::InsertAddIn(
return false;
}
+bool XclExpLinkManagerImpl8::InsertEuroTool(
+ sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, const String& rName )
+{
+ sal_uInt16 nSupbook;
+ if( maSBBuffer.InsertEuroTool( nSupbook, rnExtName, rName ) )
+ {
+ rnExtSheet = InsertXti( XclExpXti( nSupbook, EXC_TAB_EXTERNAL, EXC_TAB_EXTERNAL ) );
+ return true;
+ }
+ return false;
+}
+
+
bool XclExpLinkManagerImpl8::InsertDde(
sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
const String& rApplic, const String& rTopic, const String& rItem )
@@ -2328,6 +2409,12 @@ bool XclExpLinkManager::InsertAddIn(
return mxImpl->InsertAddIn( rnExtSheet, rnExtName, rName );
}
+bool XclExpLinkManager::InsertEuroTool(
+ sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, const String& rName )
+{
+ return mxImpl->InsertEuroTool( rnExtSheet, rnExtName, rName );
+}
+
bool XclExpLinkManager::InsertDde(
sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
const String& rApplic, const String& rTopic, const String& rItem )
diff --git a/sc/source/filter/excel/xilink.cxx b/sc/source/filter/excel/xilink.cxx
index 5373be4ae726..07b4c8fa4ace 100644
--- a/sc/source/filter/excel/xilink.cxx
+++ b/sc/source/filter/excel/xilink.cxx
@@ -289,7 +289,7 @@ sal_uInt16 XclImpTabInfo::GetCurrentIndex( sal_uInt16 nCreatedId, sal_uInt16 nMa
// External names =============================================================
-XclImpExtName::XclImpExtName( const XclImpSupbook& rSupbook, XclImpStream& rStrm, bool bAddIn, ExcelToSc* pFormulaConv )
+XclImpExtName::XclImpExtName( const XclImpSupbook& rSupbook, XclImpStream& rStrm, XclSupbookType eSubType, ExcelToSc* pFormulaConv )
{
sal_uInt16 nFlags;
sal_uInt8 nLen;
@@ -298,11 +298,14 @@ XclImpExtName::XclImpExtName( const XclImpSupbook& rSupbook, XclImpStream& rStrm
maName = rStrm.ReadUniString( nLen );
if( ::get_flag( nFlags, EXC_EXTN_BUILTIN ) || !::get_flag( nFlags, EXC_EXTN_OLE_OR_DDE ) )
{
- if( bAddIn )
+ if( eSubType == EXC_SBTYPE_ADDIN )
{
meType = xlExtAddIn;
maName = rStrm.GetRoot().GetScAddInName( maName );
}
+ else if ( (eSubType == EXC_SBTYPE_EUROTOOL) &&
+ maName.EqualsIgnoreCaseAscii( "EUROCONVERT" ) )
+ meType = xlExtEuroConvert;
else
{
meType = xlExtName;
@@ -459,7 +462,12 @@ XclImpSupbook::XclImpSupbook( XclImpStream& rStrm ) :
bool bSelf = false;
XclImpUrlHelper::DecodeUrl( maXclUrl, bSelf, GetRoot(), aEncUrl );
- if( nSBTabCnt )
+ if( maXclUrl.EqualsIgnoreCaseAscii( "\010EUROTOOL.XLA" ) )
+ {
+ meType = EXC_SBTYPE_EUROTOOL;
+ maSupbTabList.Append( new XclImpSupbookTab( maXclUrl ) );
+ }
+ else if( nSBTabCnt )
{
meType = EXC_SBTYPE_EXTERN;
for( sal_uInt16 nSBTab = 0; nSBTab < nSBTabCnt; ++nSBTab )
@@ -497,7 +505,7 @@ void XclImpSupbook::ReadCrn( XclImpStream& rStrm )
void XclImpSupbook::ReadExternname( XclImpStream& rStrm, ExcelToSc* pFormulaConv )
{
- maExtNameList.Append( new XclImpExtName( *this, rStrm, meType == EXC_SBTYPE_ADDIN, pFormulaConv ) );
+ maExtNameList.Append( new XclImpExtName( *this, rStrm, meType, pFormulaConv ) );
}
const XclImpExtName* XclImpSupbook::GetExternName( sal_uInt16 nXclIndex ) const
diff --git a/sc/source/filter/excel/xlformula.cxx b/sc/source/filter/excel/xlformula.cxx
index 8b09f7284716..85286469ba62 100644
--- a/sc/source/filter/excel/xlformula.cxx
+++ b/sc/source/filter/excel/xlformula.cxx
@@ -338,7 +338,8 @@ static const XclFunctionInfo saFuncTable_8[] =
{ ocStDevA, 366, 1, 30, V, { R }, 0, 0 },
{ ocVarA, 367, 1, 30, V, { R }, 0, 0 },
{ ocBahtText, 368, 1, 1, V, { V }, EXC_FUNCFLAG_IMPORTONLY, EXC_FUNCNAME_BAHTTEXT },
- { ocBahtText, 255, 2, 2, V, { E, V }, EXC_FUNCFLAG_EXPORTONLY, EXC_FUNCNAME_BAHTTEXT }
+ { ocBahtText, 255, 2, 2, V, { E, V }, EXC_FUNCFLAG_EXPORTONLY, EXC_FUNCNAME_BAHTTEXT },
+ { ocEuroConvert, 255, 4, 6, V, { E, V }, EXC_FUNCFLAG_EXPORTONLY, "EUROCONVERT" }
};
// ----------------------------------------------------------------------------
diff --git a/sc/source/filter/inc/xelink.hxx b/sc/source/filter/inc/xelink.hxx
index dca9df2409f7..b478ad150877 100644
--- a/sc/source/filter/inc/xelink.hxx
+++ b/sc/source/filter/inc/xelink.hxx
@@ -194,6 +194,10 @@ public:
bool InsertAddIn(
sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
const String& rName );
+ /** InsertEuroTool */
+ bool InsertEuroTool(
+ sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
+ const String& rName );
/** Finds or inserts an EXTERNNAME record for DDE links.
@param rnExtSheet (out-param) Returns the index of the EXTSHEET structure for the DDE link.
@param rnExtName (out-param) Returns the 1-based EXTERNNAME record index.
diff --git a/sc/source/filter/inc/xilink.hxx b/sc/source/filter/inc/xilink.hxx
index c4f64700070f..bb64a84a900e 100644
--- a/sc/source/filter/inc/xilink.hxx
+++ b/sc/source/filter/inc/xilink.hxx
@@ -101,7 +101,8 @@ enum XclImpExtNameType
xlExtName, /// An external defined name.
xlExtAddIn, /// An add-in function name.
xlExtDDE, /// A DDE link range.
- xlExtOLE /// An OLE object link.
+ xlExtOLE, /// An OLE object link.
+ xlExtEuroConvert /// An external in Excel, but internal in OO function name.
};
// ----------------------------------------------------------------------------
@@ -116,8 +117,8 @@ class XclImpExtName
{
public:
/** Reads the external name from the stream. */
- explicit XclImpExtName( const XclImpSupbook& rSupbook, XclImpStream& rStrm, bool bAddIn = false,
- ExcelToSc* pFormulaConv = NULL );
+ explicit XclImpExtName( const XclImpSupbook& rSupbook, XclImpStream& rStrm,
+ XclSupbookType eSubType, ExcelToSc* pFormulaConv );
~XclImpExtName();
/** Create and apply the cached list of this DDE Link to the document. */
diff --git a/sc/source/filter/inc/xllink.hxx b/sc/source/filter/inc/xllink.hxx
index 423e364b6941..a291abb52d78 100644
--- a/sc/source/filter/inc/xllink.hxx
+++ b/sc/source/filter/inc/xllink.hxx
@@ -86,7 +86,8 @@ enum XclSupbookType
EXC_SBTYPE_SELF, /// SUPBOOK is used for internal references.
EXC_SBTYPE_EXTERN, /// SUPBOOK is used for external references.
EXC_SBTYPE_ADDIN, /// SUPBOOK contains add-in functions.
- EXC_SBTYPE_SPECIAL /// SUPBOOK is used for DDE or OLE links.
+ EXC_SBTYPE_SPECIAL, /// SUPBOOK is used for DDE or OLE links.
+ EXC_SBTYPE_EUROTOOL /// SUPBOOK is uesd for EUROCONVERT.
};
// ============================================================================
diff --git a/sc/source/filter/xml/XMLExportDDELinks.cxx b/sc/source/filter/xml/XMLExportDDELinks.cxx
index 7a719319efb4..ceb2391c0f94 100644
--- a/sc/source/filter/xml/XMLExportDDELinks.cxx
+++ b/sc/source/filter/xml/XMLExportDDELinks.cxx
@@ -7,7 +7,7 @@
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: XMLExportDDELinks.cxx,v $
- * $Revision: 1.18 $
+ * $Revision: 1.18.148.1 $
*
* This file is part of OpenOffice.org.
*
@@ -135,7 +135,7 @@ void ScXMLExportDDELinks::WriteTable(const sal_Int32 nPos)
{
ScMatValType nType = SC_MATVAL_VALUE;
const ScMatrixValue* pMatVal = pMatrix->Get( static_cast<SCSIZE>(nColumn), static_cast<SCSIZE>(nRow), nType );
- BOOL bIsString = ScMatrix::IsStringType( nType);
+ BOOL bIsString = ScMatrix::IsNonValueType( nType);
if (nColumn == 0)
{
diff --git a/sc/source/ui/src/scfuncs.src b/sc/source/ui/src/scfuncs.src
index 66eb90984f17..bb73e6fd52d8 100644
--- a/sc/source/ui/src/scfuncs.src
+++ b/sc/source/ui/src/scfuncs.src
@@ -3554,7 +3554,7 @@ Resource RID_SC_FUNCTION_DESCRIPTIONS1
0;
ID_FUNCTION_GRP_MATH;
U2S( HID_FUNC_LOG );
- 2; 0; 0;
+ 2; 0; 1;
0;
};
String 2 // Name of Parameter 1
@@ -3571,7 +3571,7 @@ Resource RID_SC_FUNCTION_DESCRIPTIONS1
};
String 5 // Description of Parameter 2
{
- Text [ en-US ] = "The base of the logarithm." ;
+ Text [ en-US ] = "The base of the logarithm. If omitted, the base is regarded as 10." ;
};
};
// -=*# Resource for function LN #*=-
@@ -5678,7 +5678,7 @@ Resource RID_SC_FUNCTION_DESCRIPTIONS2
0;
ID_FUNCTION_GRP_STATISTIC;
U2S( HID_FUNC_POISSON );
- 3; 0; 0; 0;
+ 3; 0; 0; 1;
0;
};
String 2 // Name of Parameter 1
@@ -5699,11 +5699,11 @@ Resource RID_SC_FUNCTION_DESCRIPTIONS2
};
String 6 // Name of Parameter 3
{
- Text [ en-US ] = "C" ;
+ Text [ en-US ] = "Cumulative" ;
};
String 7 // Description of Parameter 3
{
- Text [ en-US ] = "Cumulated. C=0 calculates the density function, C=1 the distribution." ;
+ Text [ en-US ] = "0 or FALSE calculates the probability density function. Any other value or TRUE or omitted calculates the cumulative distribution function." ;
};
};
// -=*# Resource for function NORMVERT #*=-
@@ -5967,14 +5967,14 @@ Resource RID_SC_FUNCTION_DESCRIPTIONS2
{
String 1 // Description
{
- Text [ en-US ] = "Values of the gamma distribution." ;
+ Text [ en-US ] = "Returns the value of the probability density function or the cumulative distribution function for the Gamma distribution." ;
};
ExtraData =
{
0;
ID_FUNCTION_GRP_STATISTIC;
U2S( HID_FUNC_GAMMAVERT );
- 4; 0; 0; 0; 0;
+ 4; 0; 0; 0; 1;
0;
};
String 2 // Name of Parameter 1
@@ -6003,11 +6003,11 @@ Resource RID_SC_FUNCTION_DESCRIPTIONS2
};
String 8 // Name of Parameter 4
{
- Text [ en-US ] = "C" ;
+ Text [ en-US ] = "Cumulative" ;
};
String 9 // Description of Parameter 4
{
- Text [ en-US ] = "Cumulated. C=0 calculates the density function, C=1 the distribution." ;
+ Text [ en-US ] = "0 or FALSE calculates the probability density function. Any other value or TRUE or omitted calculates the cumulative distribution function." ;
};
};
// -=*# Resource for function GAMMAINV #*=-
@@ -6027,7 +6027,7 @@ Resource RID_SC_FUNCTION_DESCRIPTIONS2
};
String 2 // Name of Parameter 1
{
- Text [ en-US ] = "number" ;
+ Text [ en-US ] = "Number" ;
};
String 3 // Description of Parameter 1
{
@@ -6039,7 +6039,7 @@ Resource RID_SC_FUNCTION_DESCRIPTIONS2
};
String 5 // Description of Parameter 2
{
- Text [ en-US ] = "The Alpha parameter of the Gamma distribution." ;
+ Text [ en-US ] = "The Alpha (shape) parameter of the Gamma distribution." ;
};
String 6 // Name of Parameter 3
{
@@ -6047,7 +6047,7 @@ Resource RID_SC_FUNCTION_DESCRIPTIONS2
};
String 7 // Description of Parameter 3
{
- Text [ en-US ] = "The Beta parameter of the Gamma distribution." ;
+ Text [ en-US ] = "The Beta (scale) parameter of the Gamma distribution." ;
};
};
// -=*# Resource for function GAMMALN #*=-
@@ -6074,6 +6074,32 @@ Resource RID_SC_FUNCTION_DESCRIPTIONS2
Text [ en-US ] = "The value for which the natural logarithm of the gamma function is to be calculated." ;
};
};
+
+ // -=*# Resource for function GAMMA #*=-
+ Resource SC_OPCODE_GAMMA
+ {
+ String 1 // Description
+ {
+ Text [ en-US ] = "Returns the value of the Gamma function." ;
+ };
+ ExtraData =
+ {
+ 0;
+ ID_FUNCTION_GRP_STATISTIC;
+ U2S( HID_FUNC_GAMMA );
+ 1; 0;
+ 0;
+ };
+ String 2 // Name of Parameter 1
+ {
+ Text [ en-US ] = "Number" ;
+ };
+ String 3 // Description of Parameter 1
+ {
+ Text [ en-US ] = "The value for which the Gamma function is to be calculated." ;
+ };
+ };
+
// -=*# Resource for function BETAVERT #*=-
Resource SC_OPCODE_BETA_DIST
{
@@ -6086,7 +6112,7 @@ Resource RID_SC_FUNCTION_DESCRIPTIONS2
0;
ID_FUNCTION_GRP_STATISTIC;
U2S( HID_FUNC_BETAVERT );
- 5; 0; 0; 0; 1; 1;
+ 6; 0; 0; 0; 1; 1; 1;
0;
};
String 2 // Name of Parameter 1
@@ -6129,6 +6155,14 @@ Resource RID_SC_FUNCTION_DESCRIPTIONS2
{
Text [ en-US ] = "The final value for the value interval of the distribution." ;
};
+ String 12 // Name of Parameter 6
+ {
+ Text [en-US ] = "Cumulative" ;
+ };
+ String 13 // Description of Parameter 6
+ {
+ Text [ en-US ] = "0 or FALSE for probability density function, any other value or TRUE or omitted for cumulative distribution function.";
+ };
};
// -=*# Resource for function BETAINV #*=-
Resource SC_OPCODE_BETA_INV
@@ -6439,7 +6473,7 @@ Resource RID_SC_FUNCTION_DESCRIPTIONS2
{
String 1 // Description
{
- Text [ en-US ] = "Values of the chi square distribution." ;
+ Text [ en-US ] = "Returns the right-tail probability of the chi-square distribution." ;
};
ExtraData =
{
@@ -6466,12 +6500,55 @@ Resource RID_SC_FUNCTION_DESCRIPTIONS2
Text [ en-US ] = "The degrees of freedom of the chi square distribution." ;
};
};
+
+ // -=*# Resource for function CHISQDIST #*=-
+ Resource SC_OPCODE_CHISQ_DIST
+ {
+ String 1 // Description
+ {
+ Text [ en-US ] = "Returns left-tail probability of the cumulative distribution function or values of the probability density function of the chi-square distribution." ;
+ };
+ ExtraData =
+ {
+ 0;
+ ID_FUNCTION_GRP_STATISTIC;
+ U2S( HID_FUNC_CHISQDIST );
+ 3; 0; 0; 1;
+ 0;
+ };
+ String 2 // Name of Parameter 1
+ {
+ Text [ en-US ] = "Number" ;
+ };
+ String 3 // Description of Parameter 1
+ {
+ Text [ en-US ] = "The value for which the probability density function or cumulative distribution function is to be calculated." ;
+ };
+ String 4 // Name of Parameter 2
+ {
+ Text [ en-US ] = "Degrees of Freedom" ;
+ };
+ String 5 // Description of Parameter 2
+ {
+ Text [ en-US ] = "The degrees of freedom of the chi-square distribution." ;
+ };
+ String 6 // Name of Parameter 3
+ {
+ Text [ en-US ] = "Cumulative" ;
+ };
+ String 7 // Description of Parameter 3
+ {
+ Text [ en-US ] = "0 or FALSE calculates the probability density function. Any other value or TRUE or omitted calculates the cumulative distribution function." ;
+ };
+ };
+
+
// -=*# Resource for function CHIINV #*=-
Resource SC_OPCODE_CHI_INV
{
String 1 // Description
{
- Text [ en-US ] = "Values of the inverse chi-squared distribution." ;
+ Text [ en-US ] = "Values of the inverse of CHIDIST(x; DegreesOfFreedom)." ;
};
ExtraData =
{
@@ -6498,6 +6575,40 @@ Resource RID_SC_FUNCTION_DESCRIPTIONS2
Text [ en-US ] = "The degrees of freedom of the chi square distribution." ;
};
};
+
+ // -=*# Resource for function CHISQINV #*=-
+ Resource SC_OPCODE_CHISQ_INV
+ {
+ String 1 // Description
+ {
+ Text [ en-US ] = "Values of the inverse of CHISQDIST(x;DegreesOfFreedom;TRUE())." ;
+ };
+ ExtraData =
+ {
+ 0;
+ ID_FUNCTION_GRP_STATISTIC;
+ U2S( HID_FUNC_CHISQINV );
+ 2; 0; 0;
+ 0;
+ };
+ String 2 // Name of Parameter 1
+ {
+ Text [ en-US ] = "Probability" ;
+ };
+ String 3 // Description of Parameter 1
+ {
+ Text [ en-US ] = "The probability value for which the inverse of the chi square distribution is to be calculated." ;
+ };
+ String 4 // Name of Parameter 2
+ {
+ Text [ en-US ] = "Degrees of Freedom" ;
+ };
+ String 5 // Description of Parameter 2
+ {
+ Text [ en-US ] = "The degrees of freedom of the chi square distribution." ;
+ };
+ };
+
// -=*# Resource for function STANDARDISIERUNG #*=-
Resource SC_OPCODE_STANDARD
{
@@ -8841,7 +8952,7 @@ Resource RID_SC_FUNCTION_DESCRIPTIONS2
};
ExtraData =
{
- 1; // TODO: implementation and unsuppress
+ 0; // DOING
ID_FUNCTION_GRP_MATH;
U2S( HID_FUNC_EUROCONVERT );
5; 0; 0; 0; 1; 1;