[Libreoffice-commits] core.git: sc/qa sc/source
Libreoffice Gerrit user
logerrit at kemper.freedesktop.org
Fri Nov 30 21:14:46 UTC 2018
sc/qa/unit/data/functions/statistical/fods/large.fods | 16 ++-
sc/qa/unit/data/functions/statistical/fods/small.fods | 17 ++-
sc/source/core/inc/interpre.hxx | 5
sc/source/core/tool/interpr3.cxx | 93 +++++++++++++++++-
sc/source/core/tool/interpr5.cxx | 33 ++++--
5 files changed, 141 insertions(+), 23 deletions(-)
New commits:
commit e4c2d0bb57ab8ea8f5c400d103d01376b8140f22
Author: Takeshi Abe <tabe at fixedpoint.jp>
AuthorDate: Tue Nov 27 11:28:18 2018 +0900
Commit: Eike Rathke <erack at redhat.com>
CommitDate: Fri Nov 30 22:14:17 2018 +0100
i#32345 Support a matrix of rank argument for LARGE()/SMALL()
This is a followup of e22ab5e6f6b0ea49231ca454a567133996306116.
Change-Id: I7052e113173204f7cfcd40622f52c5d4e14b3aa9
Reviewed-on: https://gerrit.libreoffice.org/64139
Tested-by: Jenkins
Reviewed-by: Eike Rathke <erack at redhat.com>
diff --git a/sc/qa/unit/data/functions/statistical/fods/large.fods b/sc/qa/unit/data/functions/statistical/fods/large.fods
index 6e701e71671f..d72e3bde9a20 100644
--- a/sc/qa/unit/data/functions/statistical/fods/large.fods
+++ b/sc/qa/unit/data/functions/statistical/fods/large.fods
@@ -4794,10 +4794,18 @@
<table:table-cell table:number-columns-repeated="2"/>
</table:table-row>
<table:table-row table:style-name="ro8">
- <table:table-cell table:style-name="ce10"/>
- <table:table-cell/>
- <table:table-cell table:style-name="ce17"/>
- <table:table-cell table:style-name="ce22"/>
+ <table:table-cell table:style-name="ce11" table:formula="of:=MDETERM(LARGE([.I30:.I39];{1;2|3;4}))" office:value-type="float" office:value="-2" calcext:value-type="float">
+ <text:p>-2</text:p>
+ </table:table-cell>
+ <table:table-cell office:value-type="float" office:value="-2" calcext:value-type="float">
+ <text:p>-2</text:p>
+ </table:table-cell>
+ <table:table-cell table:style-name="ce16" table:formula="of:=ROUND([.A30];12)=ROUND([.B30];12)" office:value-type="boolean" office:boolean-value="true" calcext:value-type="boolean">
+ <text:p>TRUE</text:p>
+ </table:table-cell>
+ <table:table-cell table:style-name="ce22" table:formula="of:=FORMULA([.A30])" office:value-type="string" office:string-value="=MDETERM(LARGE(I30:I39,{1,2;3,4}))" calcext:value-type="string">
+ <text:p>=MDETERM(LARGE(I30:I39,{1,2;3,4}))</text:p>
+ </table:table-cell>
<table:table-cell table:number-columns-repeated="4"/>
<table:table-cell table:style-name="ce11" office:value-type="float" office:value="2" calcext:value-type="float">
<text:p>2</text:p>
diff --git a/sc/qa/unit/data/functions/statistical/fods/small.fods b/sc/qa/unit/data/functions/statistical/fods/small.fods
index 94a6ae6344ef..549be5c7e187 100644
--- a/sc/qa/unit/data/functions/statistical/fods/small.fods
+++ b/sc/qa/unit/data/functions/statistical/fods/small.fods
@@ -4186,10 +4186,19 @@
<table:table-cell table:style-name="ce27" table:number-columns-repeated="4"/>
<table:table-cell table:number-columns-repeated="2"/>
</table:table-row>
- <table:table-row table:style-name="ro6">
- <table:table-cell table:number-columns-repeated="2"/>
- <table:table-cell table:style-name="ce28"/>
- <table:table-cell table:style-name="ce32"/>
+ <table:table-row table:style-name="ro2">
+ <table:table-cell table:style-name="ce19" table:formula="of:=MDETERM(SMALL([.F1:.F11];{1;2|3;4}))" office:value-type="float" office:value="-13" calcext:value-type="float">
+ <text:p>-13</text:p>
+ </table:table-cell>
+ <table:table-cell office:value-type="float" office:value="-13" calcext:value-type="float">
+ <text:p>-13</text:p>
+ </table:table-cell>
+ <table:table-cell table:style-name="ce25" table:formula="of:=ROUND([.A13];12)=ROUND([.B13];12)" office:value-type="boolean" office:boolean-value="true" calcext:value-type="boolean">
+ <text:p>TRUE</text:p>
+ </table:table-cell>
+ <table:table-cell table:style-name="ce32" table:formula="of:=FORMULA([.A13])" office:value-type="string" office:string-value="=MDETERM(SMALL(F1:F11,{1,2;3,4}))" calcext:value-type="string">
+ <text:p>=MDETERM(SMALL(F1:F11,{1,2;3,4}))</text:p>
+ </table:table-cell>
<table:table-cell table:number-columns-repeated="4"/>
<table:table-cell office:value-type="float" office:value="900000012" calcext:value-type="float">
<text:p>900000012</text:p>
diff --git a/sc/source/core/inc/interpre.hxx b/sc/source/core/inc/interpre.hxx
index 7608098d53bb..b6c68dcdb264 100644
--- a/sc/source/core/inc/interpre.hxx
+++ b/sc/source/core/inc/interpre.hxx
@@ -175,6 +175,8 @@ public:
ScMatrixRef GetNewMat(SCSIZE nC, SCSIZE nR, bool bEmpty = false);
+ ScMatrixRef GetNewMat(SCSIZE nC, SCSIZE nR, const std::vector<double>& rValues);
+
enum VolatileType {
VOLATILE,
VOLATILE_MACRO,
@@ -225,6 +227,8 @@ private:
VolatileType meVolatileType;
+ void MakeMatNew(ScMatrixRef& rMat, SCSIZE nC, SCSIZE nR);
+
/// Merge global and document specific settings.
void MergeCalcConfig();
@@ -934,6 +938,7 @@ private:
void ScMedian();
double GetMedian( ::std::vector<double> & rArray );
double GetPercentileExclusive( ::std::vector<double> & rArray, double fPercentile );
+ std::vector<double> GetTopNumberArray( SCSIZE& rCol, SCSIZE& rRow );
void GetNumberSequenceArray( sal_uInt8 nParamCount, ::std::vector<double>& rArray, bool bConvertTextInArray );
void GetSortArray( sal_uInt8 nParamCount, ::std::vector<double>& rSortArray, ::std::vector<long>* pIndexOrder, bool bConvertTextInArray, bool bAllowEmptyArray );
static void QuickSort(::std::vector<double>& rSortArray, ::std::vector<long>* pIndexOrder);
diff --git a/sc/source/core/tool/interpr3.cxx b/sc/source/core/tool/interpr3.cxx
index ac980b7257da..f91d0037ddb5 100644
--- a/sc/source/core/tool/interpr3.cxx
+++ b/sc/source/core/tool/interpr3.cxx
@@ -3639,14 +3639,15 @@ void ScInterpreter::CalculateSmallLarge(bool bSmall)
if ( !MustHaveParamCount( GetByte(), 2 ) )
return;
- std::vector<double> aArray;
- GetNumberSequenceArray(1, aArray, false);
+ SCSIZE nCol = 0, nRow = 0;
+ auto aArray = GetTopNumberArray(nCol, nRow);
auto aArraySize = aArray.size();
if (aArraySize == 0 || nGlobalError != FormulaError::NONE)
{
PushNoValue();
return;
}
+ assert(aArraySize == nCol * nRow);
for (double fArg : aArray)
{
double f = ::rtl::math::approxFloor(fArg);
@@ -3701,8 +3702,7 @@ void ScInterpreter::CalculateSmallLarge(bool bSmall)
aArray.clear();
for (SCSIZE n : aRankArray)
aArray.push_back(aSortArray[bSmall ? n-1 : nSize-n]);
- ScMatrixRef pResult = GetNewMat(1, aArraySize, true);
- pResult->PutDoubleVector(aArray, 0, 0);
+ ScMatrixRef pResult = GetNewMat(nCol, nRow, aArray);
PushMatrix(pResult);
}
}
@@ -3841,6 +3841,91 @@ void ScInterpreter::ScTrimMean()
}
}
+std::vector<double> ScInterpreter::GetTopNumberArray( SCSIZE& rCol, SCSIZE& rRow )
+{
+ std::vector<double> aArray;
+ switch (GetStackType())
+ {
+ case svDouble:
+ aArray.push_back(PopDouble());
+ rCol = rRow = 1;
+ break;
+ case svSingleRef:
+ {
+ ScAddress aAdr;
+ PopSingleRef(aAdr);
+ ScRefCellValue aCell(*pDok, aAdr);
+ if (aCell.hasNumeric())
+ {
+ aArray.push_back(GetCellValue(aAdr, aCell));
+ rCol = rRow = 1;
+ }
+ }
+ break;
+ case svDoubleRef:
+ {
+ ScRange aRange;
+ PopDoubleRef(aRange, true);
+ if (nGlobalError != FormulaError::NONE)
+ break;
+
+ // give up unless the start and end are in the same sheet
+ if (aRange.aStart.Tab() != aRange.aEnd.Tab())
+ {
+ SetError(FormulaError::IllegalParameter);
+ break;
+ }
+
+ // the range already is in order
+ assert(aRange.aStart.Col() <= aRange.aEnd.Col());
+ assert(aRange.aStart.Row() <= aRange.aEnd.Row());
+ rCol = aRange.aEnd.Col() - aRange.aStart.Col() + 1;
+ rRow = aRange.aEnd.Row() - aRange.aStart.Row() + 1;
+ aArray.reserve(rCol * rRow);
+
+ FormulaError nErr = FormulaError::NONE;
+ double fCellVal;
+ ScValueIterator aValIter(pDok, aRange, mnSubTotalFlags);
+ if (aValIter.GetFirst(fCellVal, nErr))
+ {
+ do
+ aArray.push_back(fCellVal);
+ while (aValIter.GetNext(fCellVal, nErr) && nErr == FormulaError::NONE);
+ }
+ if (aArray.size() != rCol * rRow)
+ {
+ aArray.clear();
+ SetError(nErr);
+ }
+ }
+ break;
+ case svMatrix:
+ case svExternalSingleRef:
+ case svExternalDoubleRef:
+ {
+ ScMatrixRef pMat = GetMatrix();
+ if (!pMat)
+ break;
+
+ if (pMat->IsNumeric())
+ {
+ SCSIZE nCount = pMat->GetElementCount();
+ aArray.reserve(nCount);
+ for (SCSIZE i = 0; i < nCount; ++i)
+ aArray.push_back(pMat->GetDouble(i));
+ pMat->GetDimensions(rCol, rRow);
+ }
+ else
+ SetError(FormulaError::IllegalParameter);
+ }
+ break;
+ default:
+ SetError(FormulaError::IllegalParameter);
+ break;
+ }
+ return aArray;
+}
+
void ScInterpreter::GetNumberSequenceArray( sal_uInt8 nParamCount, vector<double>& rArray, bool bConvertTextInArray )
{
ScAddress aAdr;
diff --git a/sc/source/core/tool/interpr5.cxx b/sc/source/core/tool/interpr5.cxx
index c898d7a95057..db6500b067f1 100644
--- a/sc/source/core/tool/interpr5.cxx
+++ b/sc/source/core/tool/interpr5.cxx
@@ -281,25 +281,36 @@ void ScInterpreter:: ScLCM()
}
}
-ScMatrixRef ScInterpreter::GetNewMat(SCSIZE nC, SCSIZE nR, bool bEmpty)
+void ScInterpreter::MakeMatNew(ScMatrixRef& rMat, SCSIZE nC, SCSIZE nR)
{
- ScMatrixRef pMat;
- if (bEmpty)
- pMat = new ScMatrix(nC, nR);
- else
- pMat = new ScMatrix(nC, nR, 0.0);
-
- pMat->SetErrorInterpreter( this);
+ rMat->SetErrorInterpreter( this);
// A temporary matrix is mutable and ScMatrix::CloneIfConst() returns the
// very matrix.
- pMat->SetMutable();
+ rMat->SetMutable();
SCSIZE nCols, nRows;
- pMat->GetDimensions( nCols, nRows);
+ rMat->GetDimensions( nCols, nRows);
if ( nCols != nC || nRows != nR )
{ // arbitrary limit of elements exceeded
SetError( FormulaError::MatrixSize);
- pMat.reset();
+ rMat.reset();
}
+}
+
+ScMatrixRef ScInterpreter::GetNewMat(SCSIZE nC, SCSIZE nR, bool bEmpty)
+{
+ ScMatrixRef pMat;
+ if (bEmpty)
+ pMat = new ScMatrix(nC, nR);
+ else
+ pMat = new ScMatrix(nC, nR, 0.0);
+ MakeMatNew(pMat, nC, nR);
+ return pMat;
+}
+
+ScMatrixRef ScInterpreter::GetNewMat(SCSIZE nC, SCSIZE nR, const std::vector<double>& rValues)
+{
+ ScMatrixRef pMat(new ScMatrix(nC, nR, rValues));
+ MakeMatNew(pMat, nC, nR);
return pMat;
}
More information about the Libreoffice-commits
mailing list