1b3f79822SAndrew Rist /**************************************************************
2cdf0e10cSrcweir *
3b3f79822SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one
4b3f79822SAndrew Rist * or more contributor license agreements. See the NOTICE file
5b3f79822SAndrew Rist * distributed with this work for additional information
6b3f79822SAndrew Rist * regarding copyright ownership. The ASF licenses this file
7b3f79822SAndrew Rist * to you under the Apache License, Version 2.0 (the
8b3f79822SAndrew Rist * "License"); you may not use this file except in compliance
9b3f79822SAndrew Rist * with the License. You may obtain a copy of the License at
10cdf0e10cSrcweir *
11b3f79822SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir *
13b3f79822SAndrew Rist * Unless required by applicable law or agreed to in writing,
14b3f79822SAndrew Rist * software distributed under the License is distributed on an
15b3f79822SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16b3f79822SAndrew Rist * KIND, either express or implied. See the License for the
17b3f79822SAndrew Rist * specific language governing permissions and limitations
18b3f79822SAndrew Rist * under the License.
19cdf0e10cSrcweir *
20b3f79822SAndrew Rist *************************************************************/
21b3f79822SAndrew Rist
22b3f79822SAndrew Rist
23cdf0e10cSrcweir
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_sc.hxx"
26cdf0e10cSrcweir
27cdf0e10cSrcweir // INCLUDE ---------------------------------------------------------------
28cdf0e10cSrcweir
29cdf0e10cSrcweir #ifndef INCLUDED_RTL_MATH_HXX
30cdf0e10cSrcweir #include <rtl/math.hxx>
31cdf0e10cSrcweir #endif
32cdf0e10cSrcweir #include <rtl/logfile.hxx>
33cdf0e10cSrcweir #include <string.h>
34cdf0e10cSrcweir #include <math.h>
35cdf0e10cSrcweir #include <stdio.h>
36cdf0e10cSrcweir
37cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
38cdf0e10cSrcweir #include <stdio.h>
39cdf0e10cSrcweir #endif
40cdf0e10cSrcweir #include <unotools/bootstrap.hxx>
41cdf0e10cSrcweir #include <svl/zforlist.hxx>
42cdf0e10cSrcweir
43cdf0e10cSrcweir #include "interpre.hxx"
44cdf0e10cSrcweir #include "global.hxx"
45cdf0e10cSrcweir #include "compiler.hxx"
46cdf0e10cSrcweir #include "cell.hxx"
47cdf0e10cSrcweir #include "document.hxx"
48cdf0e10cSrcweir #include "dociter.hxx"
49cdf0e10cSrcweir #include "scmatrix.hxx"
50cdf0e10cSrcweir #include "globstr.hrc"
51cdf0e10cSrcweir #include "cellkeytranslator.hxx"
52cdf0e10cSrcweir #include "osversiondef.hxx"
53cdf0e10cSrcweir
54cdf0e10cSrcweir #include <string.h>
55cdf0e10cSrcweir #include <math.h>
56cdf0e10cSrcweir #include <vector>
57cdf0e10cSrcweir
58cdf0e10cSrcweir using ::std::vector;
59cdf0e10cSrcweir using namespace formula;
60cdf0e10cSrcweir
61cdf0e10cSrcweir const double fInvEpsilon = 1.0E-7;
62cdf0e10cSrcweir
63cdf0e10cSrcweir // -----------------------------------------------------------------------
64cdf0e10cSrcweir struct MatrixAdd : public ::std::binary_function<double,double,double>
65cdf0e10cSrcweir {
operator ()MatrixAdd66cdf0e10cSrcweir inline double operator() (const double& lhs, const double& rhs) const
67cdf0e10cSrcweir {
68cdf0e10cSrcweir return ::rtl::math::approxAdd( lhs,rhs);
69cdf0e10cSrcweir }
70cdf0e10cSrcweir };
71cdf0e10cSrcweir struct MatrixSub : public ::std::binary_function<double,double,double>
72cdf0e10cSrcweir {
operator ()MatrixSub73cdf0e10cSrcweir inline double operator() (const double& lhs, const double& rhs) const
74cdf0e10cSrcweir {
75cdf0e10cSrcweir return ::rtl::math::approxSub( lhs,rhs);
76cdf0e10cSrcweir }
77cdf0e10cSrcweir };
78cdf0e10cSrcweir struct MatrixMul : public ::std::binary_function<double,double,double>
79cdf0e10cSrcweir {
operator ()MatrixMul80cdf0e10cSrcweir inline double operator() (const double& lhs, const double& rhs) const
81cdf0e10cSrcweir {
82cdf0e10cSrcweir return lhs * rhs;
83cdf0e10cSrcweir }
84cdf0e10cSrcweir };
85cdf0e10cSrcweir struct MatrixDiv : public ::std::binary_function<double,double,double>
86cdf0e10cSrcweir {
operator ()MatrixDiv87cdf0e10cSrcweir inline double operator() (const double& lhs, const double& rhs) const
88cdf0e10cSrcweir {
89cdf0e10cSrcweir return ScInterpreter::div( lhs,rhs);
90cdf0e10cSrcweir }
91cdf0e10cSrcweir };
92cdf0e10cSrcweir struct MatrixPow : public ::std::binary_function<double,double,double>
93cdf0e10cSrcweir {
operator ()MatrixPow94cdf0e10cSrcweir inline double operator() (const double& lhs, const double& rhs) const
95cdf0e10cSrcweir {
96cdf0e10cSrcweir return ::pow( lhs,rhs);
97cdf0e10cSrcweir }
98cdf0e10cSrcweir };
99cdf0e10cSrcweir
ScGetGCD(double fx,double fy)100cdf0e10cSrcweir double ScInterpreter::ScGetGCD(double fx, double fy)
101cdf0e10cSrcweir {
102cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::div" );
103cdf0e10cSrcweir // By ODFF definition GCD(0,a) => a. This is also vital for the code in
104cdf0e10cSrcweir // ScGCD() to work correctly with a preset fy=0.0
105cdf0e10cSrcweir if (fy == 0.0)
106cdf0e10cSrcweir return fx;
107cdf0e10cSrcweir else if (fx == 0.0)
108cdf0e10cSrcweir return fy;
109cdf0e10cSrcweir else
110cdf0e10cSrcweir {
111cdf0e10cSrcweir double fz = fmod(fx, fy);
112cdf0e10cSrcweir while (fz > 0.0)
113cdf0e10cSrcweir {
114cdf0e10cSrcweir fx = fy;
115cdf0e10cSrcweir fy = fz;
116cdf0e10cSrcweir fz = fmod(fx, fy);
117cdf0e10cSrcweir }
118cdf0e10cSrcweir return fy;
119cdf0e10cSrcweir }
120cdf0e10cSrcweir }
121cdf0e10cSrcweir
ScGCD()122cdf0e10cSrcweir void ScInterpreter::ScGCD()
123cdf0e10cSrcweir {
124cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScGCD" );
125cdf0e10cSrcweir short nParamCount = GetByte();
126cdf0e10cSrcweir if ( MustHaveParamCountMin( nParamCount, 1 ) )
127cdf0e10cSrcweir {
128cdf0e10cSrcweir double fx, fy = 0.0;
129cdf0e10cSrcweir ScRange aRange;
130cdf0e10cSrcweir size_t nRefInList = 0;
131cdf0e10cSrcweir while (!nGlobalError && nParamCount-- > 0)
132cdf0e10cSrcweir {
133cdf0e10cSrcweir switch (GetStackType())
134cdf0e10cSrcweir {
135cdf0e10cSrcweir case svDouble :
136cdf0e10cSrcweir case svString:
137cdf0e10cSrcweir case svSingleRef:
138cdf0e10cSrcweir {
139cdf0e10cSrcweir fx = ::rtl::math::approxFloor( GetDouble());
140cdf0e10cSrcweir if (fx < 0.0)
141cdf0e10cSrcweir {
142cdf0e10cSrcweir PushIllegalArgument();
143cdf0e10cSrcweir return;
144cdf0e10cSrcweir }
145cdf0e10cSrcweir fy = ScGetGCD(fx, fy);
146cdf0e10cSrcweir }
147cdf0e10cSrcweir break;
148cdf0e10cSrcweir case svDoubleRef :
149cdf0e10cSrcweir case svRefList :
150cdf0e10cSrcweir {
151cdf0e10cSrcweir sal_uInt16 nErr = 0;
152cdf0e10cSrcweir PopDoubleRef( aRange, nParamCount, nRefInList);
153cdf0e10cSrcweir double nCellVal;
154cdf0e10cSrcweir ScValueIterator aValIter(pDok, aRange, glSubTotal);
155cdf0e10cSrcweir if (aValIter.GetFirst(nCellVal, nErr))
156cdf0e10cSrcweir {
157cdf0e10cSrcweir do
158cdf0e10cSrcweir {
159cdf0e10cSrcweir fx = ::rtl::math::approxFloor( nCellVal);
160cdf0e10cSrcweir if (fx < 0.0)
161cdf0e10cSrcweir {
162cdf0e10cSrcweir PushIllegalArgument();
163cdf0e10cSrcweir return;
164cdf0e10cSrcweir }
165cdf0e10cSrcweir fy = ScGetGCD(fx, fy);
166cdf0e10cSrcweir } while (nErr == 0 && aValIter.GetNext(nCellVal, nErr));
167cdf0e10cSrcweir }
168cdf0e10cSrcweir SetError(nErr);
169cdf0e10cSrcweir }
170cdf0e10cSrcweir break;
171cdf0e10cSrcweir case svMatrix :
172cdf0e10cSrcweir {
173cdf0e10cSrcweir ScMatrixRef pMat = PopMatrix();
174cdf0e10cSrcweir if (pMat)
175cdf0e10cSrcweir {
176cdf0e10cSrcweir SCSIZE nC, nR;
177cdf0e10cSrcweir pMat->GetDimensions(nC, nR);
178cdf0e10cSrcweir if (nC == 0 || nR == 0)
179cdf0e10cSrcweir SetError(errIllegalArgument);
180cdf0e10cSrcweir else
181cdf0e10cSrcweir {
182cdf0e10cSrcweir SCSIZE nCount = nC * nR;
183cdf0e10cSrcweir for ( SCSIZE j = 0; j < nCount; j++ )
184cdf0e10cSrcweir {
185cdf0e10cSrcweir if (!pMat->IsValue(j))
186cdf0e10cSrcweir {
187cdf0e10cSrcweir PushIllegalArgument();
188cdf0e10cSrcweir return;
189cdf0e10cSrcweir }
190cdf0e10cSrcweir fx = ::rtl::math::approxFloor( pMat->GetDouble(j));
191cdf0e10cSrcweir if (fx < 0.0)
192cdf0e10cSrcweir {
193cdf0e10cSrcweir PushIllegalArgument();
194cdf0e10cSrcweir return;
195cdf0e10cSrcweir }
196cdf0e10cSrcweir fy = ScGetGCD(fx, fy);
197cdf0e10cSrcweir }
198cdf0e10cSrcweir }
199cdf0e10cSrcweir }
200cdf0e10cSrcweir }
201cdf0e10cSrcweir break;
202cdf0e10cSrcweir default : SetError(errIllegalParameter); break;
203cdf0e10cSrcweir }
204cdf0e10cSrcweir }
205cdf0e10cSrcweir PushDouble(fy);
206cdf0e10cSrcweir }
207cdf0e10cSrcweir }
208cdf0e10cSrcweir
ScLCM()209cdf0e10cSrcweir void ScInterpreter:: ScLCM()
210cdf0e10cSrcweir {
211cdf0e10cSrcweir short nParamCount = GetByte();
212cdf0e10cSrcweir if ( MustHaveParamCountMin( nParamCount, 1 ) )
213cdf0e10cSrcweir {
214cdf0e10cSrcweir double fx, fy = 1.0;
215cdf0e10cSrcweir ScRange aRange;
216cdf0e10cSrcweir size_t nRefInList = 0;
217cdf0e10cSrcweir while (!nGlobalError && nParamCount-- > 0)
218cdf0e10cSrcweir {
219cdf0e10cSrcweir switch (GetStackType())
220cdf0e10cSrcweir {
221cdf0e10cSrcweir case svDouble :
222cdf0e10cSrcweir case svString:
223cdf0e10cSrcweir case svSingleRef:
224cdf0e10cSrcweir {
225cdf0e10cSrcweir fx = ::rtl::math::approxFloor( GetDouble());
226cdf0e10cSrcweir if (fx < 0.0)
227cdf0e10cSrcweir {
228cdf0e10cSrcweir PushIllegalArgument();
229cdf0e10cSrcweir return;
230cdf0e10cSrcweir }
231cdf0e10cSrcweir if (fx == 0.0 || fy == 0.0)
232cdf0e10cSrcweir fy = 0.0;
233cdf0e10cSrcweir else
234cdf0e10cSrcweir fy = fx * fy / ScGetGCD(fx, fy);
235cdf0e10cSrcweir }
236cdf0e10cSrcweir break;
237cdf0e10cSrcweir case svDoubleRef :
238cdf0e10cSrcweir case svRefList :
239cdf0e10cSrcweir {
240cdf0e10cSrcweir sal_uInt16 nErr = 0;
241cdf0e10cSrcweir PopDoubleRef( aRange, nParamCount, nRefInList);
242cdf0e10cSrcweir double nCellVal;
243cdf0e10cSrcweir ScValueIterator aValIter(pDok, aRange, glSubTotal);
244cdf0e10cSrcweir if (aValIter.GetFirst(nCellVal, nErr))
245cdf0e10cSrcweir {
246cdf0e10cSrcweir do
247cdf0e10cSrcweir {
248cdf0e10cSrcweir fx = ::rtl::math::approxFloor( nCellVal);
249cdf0e10cSrcweir if (fx < 0.0)
250cdf0e10cSrcweir {
251cdf0e10cSrcweir PushIllegalArgument();
252cdf0e10cSrcweir return;
253cdf0e10cSrcweir }
254cdf0e10cSrcweir if (fx == 0.0 || fy == 0.0)
255cdf0e10cSrcweir fy = 0.0;
256cdf0e10cSrcweir else
257cdf0e10cSrcweir fy = fx * fy / ScGetGCD(fx, fy);
258cdf0e10cSrcweir } while (nErr == 0 && aValIter.GetNext(nCellVal, nErr));
259cdf0e10cSrcweir }
260cdf0e10cSrcweir SetError(nErr);
261cdf0e10cSrcweir }
262cdf0e10cSrcweir break;
263cdf0e10cSrcweir case svMatrix :
264cdf0e10cSrcweir {
265cdf0e10cSrcweir ScMatrixRef pMat = PopMatrix();
266cdf0e10cSrcweir if (pMat)
267cdf0e10cSrcweir {
268cdf0e10cSrcweir SCSIZE nC, nR;
269cdf0e10cSrcweir pMat->GetDimensions(nC, nR);
270cdf0e10cSrcweir if (nC == 0 || nR == 0)
271cdf0e10cSrcweir SetError(errIllegalArgument);
272cdf0e10cSrcweir else
273cdf0e10cSrcweir {
274cdf0e10cSrcweir SCSIZE nCount = nC * nR;
275cdf0e10cSrcweir for ( SCSIZE j = 0; j < nCount; j++ )
276cdf0e10cSrcweir {
277cdf0e10cSrcweir if (!pMat->IsValue(j))
278cdf0e10cSrcweir {
279cdf0e10cSrcweir PushIllegalArgument();
280cdf0e10cSrcweir return;
281cdf0e10cSrcweir }
282cdf0e10cSrcweir fx = ::rtl::math::approxFloor( pMat->GetDouble(j));
283cdf0e10cSrcweir if (fx < 0.0)
284cdf0e10cSrcweir {
285cdf0e10cSrcweir PushIllegalArgument();
286cdf0e10cSrcweir return;
287cdf0e10cSrcweir }
288cdf0e10cSrcweir if (fx == 0.0 || fy == 0.0)
289cdf0e10cSrcweir fy = 0.0;
290cdf0e10cSrcweir else
291cdf0e10cSrcweir fy = fx * fy / ScGetGCD(fx, fy);
292cdf0e10cSrcweir }
293cdf0e10cSrcweir }
294cdf0e10cSrcweir }
295cdf0e10cSrcweir }
296cdf0e10cSrcweir break;
297cdf0e10cSrcweir default : SetError(errIllegalParameter); break;
298cdf0e10cSrcweir }
299cdf0e10cSrcweir }
300cdf0e10cSrcweir PushDouble(fy);
301cdf0e10cSrcweir }
302cdf0e10cSrcweir }
303cdf0e10cSrcweir
GetNewMat(SCSIZE nC,SCSIZE nR)304cdf0e10cSrcweir ScMatrixRef ScInterpreter::GetNewMat(SCSIZE nC, SCSIZE nR)
305cdf0e10cSrcweir {
306cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::GetNewMat" );
307cdf0e10cSrcweir ScMatrix* pMat = new ScMatrix( nC, nR);
308cdf0e10cSrcweir pMat->SetErrorInterpreter( this);
309cdf0e10cSrcweir // A temporary matrix is mutable and ScMatrix::CloneIfConst() returns the
310cdf0e10cSrcweir // very matrix.
311cdf0e10cSrcweir pMat->SetImmutable( false);
312cdf0e10cSrcweir SCSIZE nCols, nRows;
313cdf0e10cSrcweir pMat->GetDimensions( nCols, nRows);
314cdf0e10cSrcweir if ( nCols != nC || nRows != nR )
315cdf0e10cSrcweir { // arbitray limit of elements exceeded
316cdf0e10cSrcweir SetError( errStackOverflow);
317cdf0e10cSrcweir pMat->Delete();
318cdf0e10cSrcweir pMat = NULL;
319cdf0e10cSrcweir }
320cdf0e10cSrcweir return pMat;
321cdf0e10cSrcweir }
322cdf0e10cSrcweir
CreateMatrixFromDoubleRef(const FormulaToken * pToken,SCCOL nCol1,SCROW nRow1,SCTAB nTab1,SCCOL nCol2,SCROW nRow2,SCTAB nTab2)323cdf0e10cSrcweir ScMatrixRef ScInterpreter::CreateMatrixFromDoubleRef( const FormulaToken* pToken,
324cdf0e10cSrcweir SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
325cdf0e10cSrcweir SCCOL nCol2, SCROW nRow2, SCTAB nTab2 )
326cdf0e10cSrcweir {
327cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::CreateMatrixFromDoubleRef" );
328cdf0e10cSrcweir ScMatrixRef pMat = NULL;
329cdf0e10cSrcweir if (nTab1 == nTab2 && !nGlobalError)
330cdf0e10cSrcweir {
331cdf0e10cSrcweir ScTokenMatrixMap::const_iterator aIter;
332cdf0e10cSrcweir if ( static_cast<SCSIZE>(nRow2 - nRow1 + 1) *
333cdf0e10cSrcweir static_cast<SCSIZE>(nCol2 - nCol1 + 1) >
334cdf0e10cSrcweir ScMatrix::GetElementsMax() )
335cdf0e10cSrcweir SetError(errStackOverflow);
336cdf0e10cSrcweir else if (pTokenMatrixMap && ((aIter = pTokenMatrixMap->find( pToken))
337cdf0e10cSrcweir != pTokenMatrixMap->end()))
338cdf0e10cSrcweir pMat = static_cast<ScToken*>((*aIter).second.get())->GetMatrix();
339cdf0e10cSrcweir else
340cdf0e10cSrcweir {
341cdf0e10cSrcweir SCSIZE nMatCols = static_cast<SCSIZE>(nCol2 - nCol1 + 1);
342cdf0e10cSrcweir SCSIZE nMatRows = static_cast<SCSIZE>(nRow2 - nRow1 + 1);
343cdf0e10cSrcweir pMat = GetNewMat( nMatCols, nMatRows);
344cdf0e10cSrcweir if (pMat && !nGlobalError)
345cdf0e10cSrcweir {
346cdf0e10cSrcweir // Set position where the next entry is expected.
347cdf0e10cSrcweir SCROW nNextRow = nRow1;
348cdf0e10cSrcweir SCCOL nNextCol = nCol1;
349cdf0e10cSrcweir // Set last position as if there was a previous entry.
350cdf0e10cSrcweir SCROW nThisRow = nRow2;
351cdf0e10cSrcweir SCCOL nThisCol = nCol1 - 1;
352cdf0e10cSrcweir ScCellIterator aCellIter( pDok, nCol1, nRow1, nTab1, nCol2,
353cdf0e10cSrcweir nRow2, nTab2);
354cdf0e10cSrcweir for (ScBaseCell* pCell = aCellIter.GetFirst(); pCell; pCell =
355cdf0e10cSrcweir aCellIter.GetNext())
356cdf0e10cSrcweir {
357cdf0e10cSrcweir nThisCol = aCellIter.GetCol();
358cdf0e10cSrcweir nThisRow = aCellIter.GetRow();
359cdf0e10cSrcweir if (nThisCol != nNextCol || nThisRow != nNextRow)
360cdf0e10cSrcweir {
361cdf0e10cSrcweir // Fill empty between iterator's positions.
362cdf0e10cSrcweir for ( ; nNextCol <= nThisCol; ++nNextCol)
363cdf0e10cSrcweir {
364cdf0e10cSrcweir SCSIZE nC = nNextCol - nCol1;
365cdf0e10cSrcweir SCSIZE nMatStopRow = ((nNextCol < nThisCol) ?
366cdf0e10cSrcweir nMatRows : nThisRow - nRow1);
367cdf0e10cSrcweir for (SCSIZE nR = nNextRow - nRow1; nR <
368cdf0e10cSrcweir nMatStopRow; ++nR)
369cdf0e10cSrcweir {
370cdf0e10cSrcweir pMat->PutEmpty( nC, nR);
371cdf0e10cSrcweir }
372cdf0e10cSrcweir nNextRow = nRow1;
373cdf0e10cSrcweir }
374cdf0e10cSrcweir }
375cdf0e10cSrcweir if (nThisRow == nRow2)
376cdf0e10cSrcweir {
377cdf0e10cSrcweir nNextCol = nThisCol + 1;
378cdf0e10cSrcweir nNextRow = nRow1;
379cdf0e10cSrcweir }
380cdf0e10cSrcweir else
381cdf0e10cSrcweir {
382cdf0e10cSrcweir nNextCol = nThisCol;
383cdf0e10cSrcweir nNextRow = nThisRow + 1;
384cdf0e10cSrcweir }
385cdf0e10cSrcweir if (HasCellEmptyData(pCell))
386cdf0e10cSrcweir {
387cdf0e10cSrcweir pMat->PutEmpty( static_cast<SCSIZE>(nThisCol-nCol1),
388cdf0e10cSrcweir static_cast<SCSIZE>(nThisRow-nRow1));
389cdf0e10cSrcweir }
390cdf0e10cSrcweir else if (HasCellValueData(pCell))
391cdf0e10cSrcweir {
392cdf0e10cSrcweir ScAddress aAdr( nThisCol, nThisRow, nTab1);
393cdf0e10cSrcweir double fVal = GetCellValue( aAdr, pCell);
394cdf0e10cSrcweir if ( nGlobalError )
395cdf0e10cSrcweir {
396cdf0e10cSrcweir fVal = CreateDoubleError( nGlobalError);
397cdf0e10cSrcweir nGlobalError = 0;
398cdf0e10cSrcweir }
399cdf0e10cSrcweir pMat->PutDouble( fVal,
400cdf0e10cSrcweir static_cast<SCSIZE>(nThisCol-nCol1),
401cdf0e10cSrcweir static_cast<SCSIZE>(nThisRow-nRow1));
402cdf0e10cSrcweir }
403cdf0e10cSrcweir else
404cdf0e10cSrcweir {
405cdf0e10cSrcweir String aStr;
406cdf0e10cSrcweir GetCellString( aStr, pCell);
407cdf0e10cSrcweir if ( nGlobalError )
408cdf0e10cSrcweir {
409cdf0e10cSrcweir double fVal = CreateDoubleError( nGlobalError);
410cdf0e10cSrcweir nGlobalError = 0;
411cdf0e10cSrcweir pMat->PutDouble( fVal,
412cdf0e10cSrcweir static_cast<SCSIZE>(nThisCol-nCol1),
413cdf0e10cSrcweir static_cast<SCSIZE>(nThisRow-nRow1));
414cdf0e10cSrcweir }
415cdf0e10cSrcweir else
416cdf0e10cSrcweir pMat->PutString( aStr,
417cdf0e10cSrcweir static_cast<SCSIZE>(nThisCol-nCol1),
418cdf0e10cSrcweir static_cast<SCSIZE>(nThisRow-nRow1));
419cdf0e10cSrcweir }
420cdf0e10cSrcweir }
421cdf0e10cSrcweir // Fill empty if iterator's last position wasn't the end.
422cdf0e10cSrcweir if (nThisCol != nCol2 || nThisRow != nRow2)
423cdf0e10cSrcweir {
424cdf0e10cSrcweir for ( ; nNextCol <= nCol2; ++nNextCol)
425cdf0e10cSrcweir {
426cdf0e10cSrcweir SCSIZE nC = nNextCol - nCol1;
427cdf0e10cSrcweir for (SCSIZE nR = nNextRow - nRow1; nR < nMatRows; ++nR)
428cdf0e10cSrcweir {
429cdf0e10cSrcweir pMat->PutEmpty( nC, nR);
430cdf0e10cSrcweir }
431cdf0e10cSrcweir nNextRow = nRow1;
432cdf0e10cSrcweir }
433cdf0e10cSrcweir }
434cdf0e10cSrcweir if (pTokenMatrixMap)
435cdf0e10cSrcweir pTokenMatrixMap->insert( ScTokenMatrixMap::value_type(
436cdf0e10cSrcweir pToken, new ScMatrixToken( pMat)));
437cdf0e10cSrcweir }
438cdf0e10cSrcweir }
439cdf0e10cSrcweir }
440cdf0e10cSrcweir else // not a 2D matrix
441cdf0e10cSrcweir SetError(errIllegalParameter);
442cdf0e10cSrcweir return pMat;
443cdf0e10cSrcweir }
444cdf0e10cSrcweir
445cdf0e10cSrcweir
GetMatrix()446cdf0e10cSrcweir ScMatrixRef ScInterpreter::GetMatrix()
447cdf0e10cSrcweir {
448cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::GetMatrix" );
449cdf0e10cSrcweir ScMatrixRef pMat = NULL;
450cdf0e10cSrcweir switch (GetRawStackType())
451cdf0e10cSrcweir {
452cdf0e10cSrcweir case svSingleRef :
453cdf0e10cSrcweir {
454cdf0e10cSrcweir ScAddress aAdr;
455cdf0e10cSrcweir PopSingleRef( aAdr );
456cdf0e10cSrcweir pMat = GetNewMat(1, 1);
457cdf0e10cSrcweir if (pMat)
458cdf0e10cSrcweir {
459cdf0e10cSrcweir ScBaseCell* pCell = GetCell( aAdr );
460cdf0e10cSrcweir if (HasCellEmptyData(pCell))
461cdf0e10cSrcweir pMat->PutEmpty( 0 );
462cdf0e10cSrcweir else if (HasCellValueData(pCell))
463cdf0e10cSrcweir pMat->PutDouble(GetCellValue(aAdr, pCell), 0);
464cdf0e10cSrcweir else
465cdf0e10cSrcweir {
466cdf0e10cSrcweir String aStr;
467cdf0e10cSrcweir GetCellString(aStr, pCell);
468cdf0e10cSrcweir pMat->PutString(aStr, 0);
469cdf0e10cSrcweir }
470cdf0e10cSrcweir }
471cdf0e10cSrcweir }
472cdf0e10cSrcweir break;
473cdf0e10cSrcweir case svDoubleRef:
474cdf0e10cSrcweir {
475cdf0e10cSrcweir SCCOL nCol1, nCol2;
476cdf0e10cSrcweir SCROW nRow1, nRow2;
477cdf0e10cSrcweir SCTAB nTab1, nTab2;
478cdf0e10cSrcweir const ScToken* p = sp ? static_cast<const ScToken*>(pStack[sp-1]) : NULL;
479cdf0e10cSrcweir PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
480cdf0e10cSrcweir pMat = CreateMatrixFromDoubleRef( p, nCol1, nRow1, nTab1,
481cdf0e10cSrcweir nCol2, nRow2, nTab2);
482cdf0e10cSrcweir }
483cdf0e10cSrcweir break;
484cdf0e10cSrcweir case svMatrix:
485cdf0e10cSrcweir pMat = PopMatrix();
486cdf0e10cSrcweir break;
487cdf0e10cSrcweir case svError :
488cdf0e10cSrcweir case svMissing :
489cdf0e10cSrcweir case svDouble :
490cdf0e10cSrcweir {
491cdf0e10cSrcweir double fVal = GetDouble();
492cdf0e10cSrcweir pMat = GetNewMat( 1, 1);
493cdf0e10cSrcweir if ( pMat )
494cdf0e10cSrcweir {
495cdf0e10cSrcweir if ( nGlobalError )
496cdf0e10cSrcweir {
497cdf0e10cSrcweir fVal = CreateDoubleError( nGlobalError);
498cdf0e10cSrcweir nGlobalError = 0;
499cdf0e10cSrcweir }
500cdf0e10cSrcweir pMat->PutDouble( fVal, 0);
501cdf0e10cSrcweir }
502cdf0e10cSrcweir }
503cdf0e10cSrcweir break;
504cdf0e10cSrcweir case svString :
505cdf0e10cSrcweir {
506cdf0e10cSrcweir String aStr = GetString();
507cdf0e10cSrcweir pMat = GetNewMat( 1, 1);
508cdf0e10cSrcweir if ( pMat )
509cdf0e10cSrcweir {
510cdf0e10cSrcweir if ( nGlobalError )
511cdf0e10cSrcweir {
512cdf0e10cSrcweir double fVal = CreateDoubleError( nGlobalError);
513cdf0e10cSrcweir pMat->PutDouble( fVal, 0);
514cdf0e10cSrcweir nGlobalError = 0;
515cdf0e10cSrcweir }
516cdf0e10cSrcweir else
517cdf0e10cSrcweir pMat->PutString( aStr, 0);
518cdf0e10cSrcweir }
519cdf0e10cSrcweir }
520cdf0e10cSrcweir break;
521cdf0e10cSrcweir default:
522cdf0e10cSrcweir PopError();
523cdf0e10cSrcweir SetError( errIllegalArgument);
524cdf0e10cSrcweir break;
525cdf0e10cSrcweir }
526cdf0e10cSrcweir return pMat;
527cdf0e10cSrcweir }
528cdf0e10cSrcweir
ScMatValue()529cdf0e10cSrcweir void ScInterpreter::ScMatValue()
530cdf0e10cSrcweir {
531cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScMatValue" );
532cdf0e10cSrcweir if ( MustHaveParamCount( GetByte(), 3 ) )
533cdf0e10cSrcweir {
534cdf0e10cSrcweir // 0 to count-1
535cdf0e10cSrcweir SCSIZE nR = static_cast<SCSIZE>(::rtl::math::approxFloor(GetDouble()));
536cdf0e10cSrcweir SCSIZE nC = static_cast<SCSIZE>(::rtl::math::approxFloor(GetDouble()));
537cdf0e10cSrcweir switch (GetStackType())
538cdf0e10cSrcweir {
539cdf0e10cSrcweir case svSingleRef :
540cdf0e10cSrcweir {
541cdf0e10cSrcweir ScAddress aAdr;
542cdf0e10cSrcweir PopSingleRef( aAdr );
543cdf0e10cSrcweir ScBaseCell* pCell = GetCell( aAdr );
544cdf0e10cSrcweir if (pCell && pCell->GetCellType() == CELLTYPE_FORMULA)
545cdf0e10cSrcweir {
546cdf0e10cSrcweir sal_uInt16 nErrCode = ((ScFormulaCell*)pCell)->GetErrCode();
547cdf0e10cSrcweir if (nErrCode != 0)
548cdf0e10cSrcweir PushError( nErrCode);
549cdf0e10cSrcweir else
550cdf0e10cSrcweir {
551cdf0e10cSrcweir const ScMatrix* pMat = ((ScFormulaCell*)pCell)->GetMatrix();
552cdf0e10cSrcweir CalculateMatrixValue(pMat,nC,nR);
553cdf0e10cSrcweir }
554cdf0e10cSrcweir }
555cdf0e10cSrcweir else
556cdf0e10cSrcweir PushIllegalParameter();
557cdf0e10cSrcweir }
558cdf0e10cSrcweir break;
559cdf0e10cSrcweir case svDoubleRef :
560cdf0e10cSrcweir {
561cdf0e10cSrcweir SCCOL nCol1;
562cdf0e10cSrcweir SCROW nRow1;
563cdf0e10cSrcweir SCTAB nTab1;
564cdf0e10cSrcweir SCCOL nCol2;
565cdf0e10cSrcweir SCROW nRow2;
566cdf0e10cSrcweir SCTAB nTab2;
567cdf0e10cSrcweir PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
568cdf0e10cSrcweir if (nCol2 - nCol1 >= static_cast<SCCOL>(nR) &&
569cdf0e10cSrcweir nRow2 - nRow1 >= static_cast<SCROW>(nC) &&
570cdf0e10cSrcweir nTab1 == nTab2)
571cdf0e10cSrcweir {
572cdf0e10cSrcweir ScAddress aAdr( sal::static_int_cast<SCCOL>( nCol1 + nR ),
573cdf0e10cSrcweir sal::static_int_cast<SCROW>( nRow1 + nC ), nTab1 );
574cdf0e10cSrcweir ScBaseCell* pCell = GetCell( aAdr );
575cdf0e10cSrcweir if (HasCellValueData(pCell))
576cdf0e10cSrcweir PushDouble(GetCellValue( aAdr, pCell ));
577cdf0e10cSrcweir else
578cdf0e10cSrcweir {
579cdf0e10cSrcweir String aStr;
580cdf0e10cSrcweir GetCellString(aStr, pCell);
581cdf0e10cSrcweir PushString(aStr);
582cdf0e10cSrcweir }
583cdf0e10cSrcweir }
584cdf0e10cSrcweir else
585cdf0e10cSrcweir PushNoValue();
586cdf0e10cSrcweir }
587cdf0e10cSrcweir break;
588cdf0e10cSrcweir case svMatrix:
589cdf0e10cSrcweir {
590cdf0e10cSrcweir ScMatrixRef pMat = PopMatrix();
591cdf0e10cSrcweir CalculateMatrixValue(pMat,nC,nR);
592cdf0e10cSrcweir }
593cdf0e10cSrcweir break;
594cdf0e10cSrcweir default:
595cdf0e10cSrcweir PopError();
596cdf0e10cSrcweir PushIllegalParameter();
597cdf0e10cSrcweir break;
598cdf0e10cSrcweir }
599cdf0e10cSrcweir }
600cdf0e10cSrcweir }
CalculateMatrixValue(const ScMatrix * pMat,SCSIZE nC,SCSIZE nR)601cdf0e10cSrcweir void ScInterpreter::CalculateMatrixValue(const ScMatrix* pMat,SCSIZE nC,SCSIZE nR)
602cdf0e10cSrcweir {
603cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::CalculateMatrixValue" );
604cdf0e10cSrcweir if (pMat)
605cdf0e10cSrcweir {
606cdf0e10cSrcweir SCSIZE nCl, nRw;
607cdf0e10cSrcweir pMat->GetDimensions(nCl, nRw);
608cdf0e10cSrcweir if (nC < nCl && nR < nRw)
609cdf0e10cSrcweir {
610cdf0e10cSrcweir ScMatValType nMatValType;
611cdf0e10cSrcweir const ScMatrixValue* pMatVal = pMat->Get( nC, nR,nMatValType);
612cdf0e10cSrcweir if (ScMatrix::IsNonValueType( nMatValType))
613cdf0e10cSrcweir PushString( pMatVal->GetString() );
614cdf0e10cSrcweir else
615cdf0e10cSrcweir PushDouble(pMatVal->fVal);
616cdf0e10cSrcweir // also handles DoubleError
617cdf0e10cSrcweir }
618cdf0e10cSrcweir else
619cdf0e10cSrcweir PushNoValue();
620cdf0e10cSrcweir }
621cdf0e10cSrcweir else
622cdf0e10cSrcweir PushNoValue();
623cdf0e10cSrcweir }
624cdf0e10cSrcweir
ScEMat()625cdf0e10cSrcweir void ScInterpreter::ScEMat()
626cdf0e10cSrcweir {
627cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScEMat" );
628cdf0e10cSrcweir if ( MustHaveParamCount( GetByte(), 1 ) )
629cdf0e10cSrcweir {
630cdf0e10cSrcweir SCSIZE nDim = static_cast<SCSIZE>(::rtl::math::approxFloor(GetDouble()));
631cdf0e10cSrcweir if ( nDim * nDim > ScMatrix::GetElementsMax() || nDim == 0)
632cdf0e10cSrcweir PushIllegalArgument();
633cdf0e10cSrcweir else
634cdf0e10cSrcweir {
635cdf0e10cSrcweir ScMatrixRef pRMat = GetNewMat(nDim, nDim);
636cdf0e10cSrcweir if (pRMat)
637cdf0e10cSrcweir {
638cdf0e10cSrcweir MEMat(pRMat, nDim);
639cdf0e10cSrcweir PushMatrix(pRMat);
640cdf0e10cSrcweir }
641cdf0e10cSrcweir else
642cdf0e10cSrcweir PushIllegalArgument();
643cdf0e10cSrcweir }
644cdf0e10cSrcweir }
645cdf0e10cSrcweir }
646cdf0e10cSrcweir
MEMat(ScMatrix * mM,SCSIZE n)647cdf0e10cSrcweir void ScInterpreter::MEMat(ScMatrix* mM, SCSIZE n)
648cdf0e10cSrcweir {
649cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::MEMat" );
650cdf0e10cSrcweir mM->FillDouble(0.0, 0, 0, n-1, n-1);
651cdf0e10cSrcweir for (SCSIZE i = 0; i < n; i++)
652cdf0e10cSrcweir mM->PutDouble(1.0, i, i);
653cdf0e10cSrcweir }
654cdf0e10cSrcweir
655cdf0e10cSrcweir /* Matrix LUP decomposition according to the pseudocode of "Introduction to
656cdf0e10cSrcweir * Algorithms" by Cormen, Leiserson, Rivest, Stein.
657cdf0e10cSrcweir *
658cdf0e10cSrcweir * Added scaling for numeric stability.
659cdf0e10cSrcweir *
660cdf0e10cSrcweir * Given an n x n nonsingular matrix A, find a permutation matrix P, a unit
661cdf0e10cSrcweir * lower-triangular matrix L, and an upper-triangular matrix U such that PA=LU.
662cdf0e10cSrcweir * Compute L and U "in place" in the matrix A, the original content is
663cdf0e10cSrcweir * destroyed. Note that the diagonal elements of the U triangular matrix
664cdf0e10cSrcweir * replace the diagonal elements of the L-unit matrix (that are each ==1). The
665cdf0e10cSrcweir * permutation matrix P is an array, where P[i]=j means that the i-th row of P
666cdf0e10cSrcweir * contains a 1 in column j. Additionally keep track of the number of
667cdf0e10cSrcweir * permutations (row exchanges).
668cdf0e10cSrcweir *
669cdf0e10cSrcweir * Returns 0 if a singular matrix is encountered, else +1 if an even number of
670cdf0e10cSrcweir * permutations occured, or -1 if odd, which is the sign of the determinant.
671cdf0e10cSrcweir * This may be used to calculate the determinant by multiplying the sign with
672cdf0e10cSrcweir * the product of the diagonal elements of the LU matrix.
673cdf0e10cSrcweir */
lcl_LUP_decompose(ScMatrix * mA,const SCSIZE n,::std::vector<SCSIZE> & P)674cdf0e10cSrcweir static int lcl_LUP_decompose( ScMatrix* mA, const SCSIZE n,
675cdf0e10cSrcweir ::std::vector< SCSIZE> & P )
676cdf0e10cSrcweir {
677cdf0e10cSrcweir int nSign = 1;
678cdf0e10cSrcweir // Find scale of each row.
679cdf0e10cSrcweir ::std::vector< double> aScale(n);
680cdf0e10cSrcweir for (SCSIZE i=0; i < n; ++i)
681cdf0e10cSrcweir {
682cdf0e10cSrcweir double fMax = 0.0;
683cdf0e10cSrcweir for (SCSIZE j=0; j < n; ++j)
684cdf0e10cSrcweir {
685cdf0e10cSrcweir double fTmp = fabs( mA->GetDouble( j, i));
686cdf0e10cSrcweir if (fMax < fTmp)
687cdf0e10cSrcweir fMax = fTmp;
688cdf0e10cSrcweir }
689cdf0e10cSrcweir if (fMax == 0.0)
690cdf0e10cSrcweir return 0; // singular matrix
691cdf0e10cSrcweir aScale[i] = 1.0 / fMax;
692cdf0e10cSrcweir }
693cdf0e10cSrcweir // Represent identity permutation, P[i]=i
694cdf0e10cSrcweir for (SCSIZE i=0; i < n; ++i)
695cdf0e10cSrcweir P[i] = i;
696cdf0e10cSrcweir // "Recursion" on the diagonale.
697cdf0e10cSrcweir SCSIZE l = n - 1;
698cdf0e10cSrcweir for (SCSIZE k=0; k < l; ++k)
699cdf0e10cSrcweir {
700cdf0e10cSrcweir // Implicit pivoting. With the scale found for a row, compare values of
701cdf0e10cSrcweir // a column and pick largest.
702cdf0e10cSrcweir double fMax = 0.0;
703cdf0e10cSrcweir double fScale = aScale[k];
704cdf0e10cSrcweir SCSIZE kp = k;
705cdf0e10cSrcweir for (SCSIZE i = k; i < n; ++i)
706cdf0e10cSrcweir {
707cdf0e10cSrcweir double fTmp = fScale * fabs( mA->GetDouble( k, i));
708cdf0e10cSrcweir if (fMax < fTmp)
709cdf0e10cSrcweir {
710cdf0e10cSrcweir fMax = fTmp;
711cdf0e10cSrcweir kp = i;
712cdf0e10cSrcweir }
713cdf0e10cSrcweir }
714cdf0e10cSrcweir if (fMax == 0.0)
715cdf0e10cSrcweir return 0; // singular matrix
716cdf0e10cSrcweir // Swap rows. The pivot element will be at mA[k,kp] (row,col notation)
717cdf0e10cSrcweir if (k != kp)
718cdf0e10cSrcweir {
719cdf0e10cSrcweir // permutations
720cdf0e10cSrcweir SCSIZE nTmp = P[k];
721cdf0e10cSrcweir P[k] = P[kp];
722cdf0e10cSrcweir P[kp] = nTmp;
723cdf0e10cSrcweir nSign = -nSign;
724cdf0e10cSrcweir // scales
725cdf0e10cSrcweir double fTmp = aScale[k];
726cdf0e10cSrcweir aScale[k] = aScale[kp];
727cdf0e10cSrcweir aScale[kp] = fTmp;
728cdf0e10cSrcweir // elements
729cdf0e10cSrcweir for (SCSIZE i=0; i < n; ++i)
730cdf0e10cSrcweir {
731cdf0e10cSrcweir double fMatTmp = mA->GetDouble( i, k);
732cdf0e10cSrcweir mA->PutDouble( mA->GetDouble( i, kp), i, k);
733cdf0e10cSrcweir mA->PutDouble( fMatTmp, i, kp);
734cdf0e10cSrcweir }
735cdf0e10cSrcweir }
736cdf0e10cSrcweir // Compute Schur complement.
737cdf0e10cSrcweir for (SCSIZE i = k+1; i < n; ++i)
738cdf0e10cSrcweir {
739cdf0e10cSrcweir double fTmp = mA->GetDouble( k, i) / mA->GetDouble( k, k);
740cdf0e10cSrcweir mA->PutDouble( fTmp, k, i);
741cdf0e10cSrcweir for (SCSIZE j = k+1; j < n; ++j)
742cdf0e10cSrcweir mA->PutDouble( mA->GetDouble( j, i) - fTmp * mA->GetDouble( j,
743cdf0e10cSrcweir k), j, i);
744cdf0e10cSrcweir }
745cdf0e10cSrcweir }
746cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
747cdf0e10cSrcweir fprintf( stderr, "\n%s\n", "lcl_LUP_decompose(): LU");
748cdf0e10cSrcweir for (SCSIZE i=0; i < n; ++i)
749cdf0e10cSrcweir {
750cdf0e10cSrcweir for (SCSIZE j=0; j < n; ++j)
751cdf0e10cSrcweir fprintf( stderr, "%8.2g ", mA->GetDouble( j, i));
752cdf0e10cSrcweir fprintf( stderr, "\n%s\n", "");
753cdf0e10cSrcweir }
754cdf0e10cSrcweir fprintf( stderr, "\n%s\n", "lcl_LUP_decompose(): P");
755cdf0e10cSrcweir for (SCSIZE j=0; j < n; ++j)
756cdf0e10cSrcweir fprintf( stderr, "%5u ", (unsigned)P[j]);
757cdf0e10cSrcweir fprintf( stderr, "\n%s\n", "");
758cdf0e10cSrcweir #endif
759cdf0e10cSrcweir
760cdf0e10cSrcweir bool bSingular=false;
761cdf0e10cSrcweir for (SCSIZE i=0; i < n && !bSingular; i++)
762cdf0e10cSrcweir bSingular = (mA->GetDouble(i,i) == 0.0);
763cdf0e10cSrcweir if (bSingular)
764cdf0e10cSrcweir nSign = 0;
765cdf0e10cSrcweir
766cdf0e10cSrcweir return nSign;
767cdf0e10cSrcweir }
768cdf0e10cSrcweir
769cdf0e10cSrcweir
770cdf0e10cSrcweir /* Solve a LUP decomposed equation Ax=b. LU is a combined matrix of L and U
771cdf0e10cSrcweir * triangulars and P the permutation vector as obtained from
772cdf0e10cSrcweir * lcl_LUP_decompose(). B is the right-hand side input vector, X is used to
773cdf0e10cSrcweir * return the solution vector.
774cdf0e10cSrcweir */
lcl_LUP_solve(const ScMatrix * mLU,const SCSIZE n,const::std::vector<SCSIZE> & P,const::std::vector<double> & B,::std::vector<double> & X)775cdf0e10cSrcweir static void lcl_LUP_solve( const ScMatrix* mLU, const SCSIZE n,
776cdf0e10cSrcweir const ::std::vector< SCSIZE> & P, const ::std::vector< double> & B,
777cdf0e10cSrcweir ::std::vector< double> & X )
778cdf0e10cSrcweir {
779cdf0e10cSrcweir SCSIZE nFirst = SCSIZE_MAX;
780cdf0e10cSrcweir // Ax=b => PAx=Pb, with decomposition LUx=Pb.
781cdf0e10cSrcweir // Define y=Ux and solve for y in Ly=Pb using forward substitution.
782cdf0e10cSrcweir for (SCSIZE i=0; i < n; ++i)
783cdf0e10cSrcweir {
784cdf0e10cSrcweir double fSum = B[P[i]];
785cdf0e10cSrcweir // Matrix inversion comes with a lot of zeros in the B vectors, we
786cdf0e10cSrcweir // don't have to do all the computing with results multiplied by zero.
787cdf0e10cSrcweir // Until then, simply lookout for the position of the first nonzero
788cdf0e10cSrcweir // value.
789cdf0e10cSrcweir if (nFirst != SCSIZE_MAX)
790cdf0e10cSrcweir {
791cdf0e10cSrcweir for (SCSIZE j = nFirst; j < i; ++j)
792cdf0e10cSrcweir fSum -= mLU->GetDouble( j, i) * X[j]; // X[j] === y[j]
793cdf0e10cSrcweir }
794cdf0e10cSrcweir else if (fSum)
795cdf0e10cSrcweir nFirst = i;
796cdf0e10cSrcweir X[i] = fSum; // X[i] === y[i]
797cdf0e10cSrcweir }
798cdf0e10cSrcweir // Solve for x in Ux=y using back substitution.
799cdf0e10cSrcweir for (SCSIZE i = n; i--; )
800cdf0e10cSrcweir {
801cdf0e10cSrcweir double fSum = X[i]; // X[i] === y[i]
802cdf0e10cSrcweir for (SCSIZE j = i+1; j < n; ++j)
803cdf0e10cSrcweir fSum -= mLU->GetDouble( j, i) * X[j]; // X[j] === x[j]
804cdf0e10cSrcweir X[i] = fSum / mLU->GetDouble( i, i); // X[i] === x[i]
805cdf0e10cSrcweir }
806cdf0e10cSrcweir #if OSL_DEBUG_LEVEL >1
807cdf0e10cSrcweir fprintf( stderr, "\n%s\n", "lcl_LUP_solve():");
808cdf0e10cSrcweir for (SCSIZE i=0; i < n; ++i)
809cdf0e10cSrcweir fprintf( stderr, "%8.2g ", X[i]);
810cdf0e10cSrcweir fprintf( stderr, "%s\n", "");
811cdf0e10cSrcweir #endif
812cdf0e10cSrcweir }
813cdf0e10cSrcweir
814cdf0e10cSrcweir
ScMatDet()815cdf0e10cSrcweir void ScInterpreter::ScMatDet()
816cdf0e10cSrcweir {
817cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScMatDet" );
818cdf0e10cSrcweir if ( MustHaveParamCount( GetByte(), 1 ) )
819cdf0e10cSrcweir {
820cdf0e10cSrcweir ScMatrixRef pMat = GetMatrix();
821cdf0e10cSrcweir if (!pMat)
822cdf0e10cSrcweir {
823cdf0e10cSrcweir PushIllegalParameter();
824cdf0e10cSrcweir return;
825cdf0e10cSrcweir }
826cdf0e10cSrcweir if ( !pMat->IsNumeric() )
827cdf0e10cSrcweir {
828cdf0e10cSrcweir PushNoValue();
829cdf0e10cSrcweir return;
830cdf0e10cSrcweir }
831cdf0e10cSrcweir SCSIZE nC, nR;
832cdf0e10cSrcweir pMat->GetDimensions(nC, nR);
833cdf0e10cSrcweir if ( nC != nR || nC == 0 || (sal_uLong) nC * nC > ScMatrix::GetElementsMax() )
834cdf0e10cSrcweir PushIllegalArgument();
835cdf0e10cSrcweir else
836cdf0e10cSrcweir {
837cdf0e10cSrcweir // LUP decomposition is done inplace, use copy.
838cdf0e10cSrcweir ScMatrixRef xLU = pMat->Clone();
839cdf0e10cSrcweir if (!xLU)
840cdf0e10cSrcweir PushError( errCodeOverflow);
841cdf0e10cSrcweir else
842cdf0e10cSrcweir {
843cdf0e10cSrcweir ::std::vector< SCSIZE> P(nR);
844cdf0e10cSrcweir int nDetSign = lcl_LUP_decompose( xLU, nR, P);
845cdf0e10cSrcweir if (!nDetSign)
846cdf0e10cSrcweir PushInt(0); // singular matrix
847cdf0e10cSrcweir else
848cdf0e10cSrcweir {
849cdf0e10cSrcweir // In an LU matrix the determinant is simply the product of
850cdf0e10cSrcweir // all diagonal elements.
851cdf0e10cSrcweir double fDet = nDetSign;
852cdf0e10cSrcweir ScMatrix* pLU = xLU;
853cdf0e10cSrcweir for (SCSIZE i=0; i < nR; ++i)
854cdf0e10cSrcweir fDet *= pLU->GetDouble( i, i);
855cdf0e10cSrcweir PushDouble( fDet);
856cdf0e10cSrcweir }
857cdf0e10cSrcweir }
858cdf0e10cSrcweir }
859cdf0e10cSrcweir }
860cdf0e10cSrcweir }
861cdf0e10cSrcweir
ScMatInv()862cdf0e10cSrcweir void ScInterpreter::ScMatInv()
863cdf0e10cSrcweir {
864cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScMatInv" );
865cdf0e10cSrcweir if ( MustHaveParamCount( GetByte(), 1 ) )
866cdf0e10cSrcweir {
867cdf0e10cSrcweir ScMatrixRef pMat = GetMatrix();
868cdf0e10cSrcweir if (!pMat)
869cdf0e10cSrcweir {
870cdf0e10cSrcweir PushIllegalParameter();
871cdf0e10cSrcweir return;
872cdf0e10cSrcweir }
873cdf0e10cSrcweir if ( !pMat->IsNumeric() )
874cdf0e10cSrcweir {
875cdf0e10cSrcweir PushNoValue();
876cdf0e10cSrcweir return;
877cdf0e10cSrcweir }
878cdf0e10cSrcweir SCSIZE nC, nR;
879cdf0e10cSrcweir pMat->GetDimensions(nC, nR);
880cdf0e10cSrcweir if ( nC != nR || nC == 0 || (sal_uLong) nC * nC > ScMatrix::GetElementsMax() )
881cdf0e10cSrcweir PushIllegalArgument();
882cdf0e10cSrcweir else
883cdf0e10cSrcweir {
884cdf0e10cSrcweir // LUP decomposition is done inplace, use copy.
885cdf0e10cSrcweir ScMatrixRef xLU = pMat->Clone();
886cdf0e10cSrcweir // The result matrix.
887cdf0e10cSrcweir ScMatrixRef xY = GetNewMat( nR, nR);
888cdf0e10cSrcweir if (!xLU || !xY)
889cdf0e10cSrcweir PushError( errCodeOverflow);
890cdf0e10cSrcweir else
891cdf0e10cSrcweir {
892cdf0e10cSrcweir ::std::vector< SCSIZE> P(nR);
893cdf0e10cSrcweir int nDetSign = lcl_LUP_decompose( xLU, nR, P);
894cdf0e10cSrcweir if (!nDetSign)
895cdf0e10cSrcweir PushIllegalArgument();
896cdf0e10cSrcweir else
897cdf0e10cSrcweir {
898cdf0e10cSrcweir // Solve equation for each column.
899cdf0e10cSrcweir ScMatrix* pY = xY;
900cdf0e10cSrcweir ::std::vector< double> B(nR);
901cdf0e10cSrcweir ::std::vector< double> X(nR);
902cdf0e10cSrcweir for (SCSIZE j=0; j < nR; ++j)
903cdf0e10cSrcweir {
904cdf0e10cSrcweir for (SCSIZE i=0; i < nR; ++i)
905cdf0e10cSrcweir B[i] = 0.0;
906cdf0e10cSrcweir B[j] = 1.0;
907cdf0e10cSrcweir lcl_LUP_solve( xLU, nR, P, B, X);
908cdf0e10cSrcweir for (SCSIZE i=0; i < nR; ++i)
909cdf0e10cSrcweir pY->PutDouble( X[i], j, i);
910cdf0e10cSrcweir }
911cdf0e10cSrcweir #if 0
912cdf0e10cSrcweir /* Possible checks for ill-condition:
913cdf0e10cSrcweir * 1. Scale matrix, invert scaled matrix. If there are
914cdf0e10cSrcweir * elements of the inverted matrix that are several
915cdf0e10cSrcweir * orders of magnitude greater than 1 =>
916cdf0e10cSrcweir * ill-conditioned.
917cdf0e10cSrcweir * Just how much is "several orders"?
918cdf0e10cSrcweir * 2. Invert the inverted matrix and assess whether the
919cdf0e10cSrcweir * result is sufficiently close to the original matrix.
920cdf0e10cSrcweir * If not => ill-conditioned.
921cdf0e10cSrcweir * Just what is sufficient?
922cdf0e10cSrcweir * 3. Multiplying the inverse by the original matrix should
923cdf0e10cSrcweir * produce a result sufficiently close to the identity
924cdf0e10cSrcweir * matrix.
925cdf0e10cSrcweir * Just what is sufficient?
926cdf0e10cSrcweir *
927cdf0e10cSrcweir * The following is #3.
928cdf0e10cSrcweir */
929cdf0e10cSrcweir ScMatrixRef xR = GetNewMat( nR, nR);
930cdf0e10cSrcweir if (xR)
931cdf0e10cSrcweir {
932cdf0e10cSrcweir ScMatrix* pR = xR;
933cdf0e10cSrcweir lcl_MFastMult( pMat, pY, pR, nR, nR, nR);
934cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
935cdf0e10cSrcweir fprintf( stderr, "\n%s\n", "ScMatInv(): mult-identity");
936cdf0e10cSrcweir #endif
937cdf0e10cSrcweir for (SCSIZE i=0; i < nR; ++i)
938cdf0e10cSrcweir {
939cdf0e10cSrcweir for (SCSIZE j=0; j < nR; ++j)
940cdf0e10cSrcweir {
941cdf0e10cSrcweir double fTmp = pR->GetDouble( j, i);
942cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
943cdf0e10cSrcweir fprintf( stderr, "%8.2g ", fTmp);
944cdf0e10cSrcweir #endif
945cdf0e10cSrcweir if (fabs( fTmp - (i == j)) > fInvEpsilon)
946cdf0e10cSrcweir SetError( errIllegalArgument);
947cdf0e10cSrcweir }
948cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
949cdf0e10cSrcweir fprintf( stderr, "\n%s\n", "");
950cdf0e10cSrcweir #endif
951cdf0e10cSrcweir }
952cdf0e10cSrcweir }
953cdf0e10cSrcweir #endif
954cdf0e10cSrcweir if (nGlobalError)
955cdf0e10cSrcweir PushError( nGlobalError);
956cdf0e10cSrcweir else
957cdf0e10cSrcweir PushMatrix( pY);
958cdf0e10cSrcweir }
959cdf0e10cSrcweir }
960cdf0e10cSrcweir }
961cdf0e10cSrcweir }
962cdf0e10cSrcweir }
963cdf0e10cSrcweir
ScMatMult()964cdf0e10cSrcweir void ScInterpreter::ScMatMult()
965cdf0e10cSrcweir {
966cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScMatMult" );
967cdf0e10cSrcweir if ( MustHaveParamCount( GetByte(), 2 ) )
968cdf0e10cSrcweir {
969cdf0e10cSrcweir ScMatrixRef pMat2 = GetMatrix();
970cdf0e10cSrcweir ScMatrixRef pMat1 = GetMatrix();
971cdf0e10cSrcweir ScMatrixRef pRMat;
972cdf0e10cSrcweir if (pMat1 && pMat2)
973cdf0e10cSrcweir {
974cdf0e10cSrcweir if ( pMat1->IsNumeric() && pMat2->IsNumeric() )
975cdf0e10cSrcweir {
976cdf0e10cSrcweir SCSIZE nC1, nC2;
977cdf0e10cSrcweir SCSIZE nR1, nR2;
978cdf0e10cSrcweir pMat1->GetDimensions(nC1, nR1);
979cdf0e10cSrcweir pMat2->GetDimensions(nC2, nR2);
980cdf0e10cSrcweir if (nC1 != nR2)
981cdf0e10cSrcweir PushIllegalArgument();
982cdf0e10cSrcweir else
983cdf0e10cSrcweir {
984cdf0e10cSrcweir pRMat = GetNewMat(nC2, nR1);
985cdf0e10cSrcweir if (pRMat)
986cdf0e10cSrcweir {
987cdf0e10cSrcweir double sum;
988cdf0e10cSrcweir for (SCSIZE i = 0; i < nR1; i++)
989cdf0e10cSrcweir {
990cdf0e10cSrcweir for (SCSIZE j = 0; j < nC2; j++)
991cdf0e10cSrcweir {
992cdf0e10cSrcweir sum = 0.0;
993cdf0e10cSrcweir for (SCSIZE k = 0; k < nC1; k++)
994cdf0e10cSrcweir {
995cdf0e10cSrcweir sum += pMat1->GetDouble(k,i)*pMat2->GetDouble(j,k);
996cdf0e10cSrcweir }
997cdf0e10cSrcweir pRMat->PutDouble(sum, j, i);
998cdf0e10cSrcweir }
999cdf0e10cSrcweir }
1000cdf0e10cSrcweir PushMatrix(pRMat);
1001cdf0e10cSrcweir }
1002cdf0e10cSrcweir else
1003cdf0e10cSrcweir PushIllegalArgument();
1004cdf0e10cSrcweir }
1005cdf0e10cSrcweir }
1006cdf0e10cSrcweir else
1007cdf0e10cSrcweir PushNoValue();
1008cdf0e10cSrcweir }
1009cdf0e10cSrcweir else
1010cdf0e10cSrcweir PushIllegalParameter();
1011cdf0e10cSrcweir }
1012cdf0e10cSrcweir }
1013cdf0e10cSrcweir
ScMatTrans()1014cdf0e10cSrcweir void ScInterpreter::ScMatTrans()
1015cdf0e10cSrcweir {
1016cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScMatTrans" );
1017cdf0e10cSrcweir if ( MustHaveParamCount( GetByte(), 1 ) )
1018cdf0e10cSrcweir {
1019cdf0e10cSrcweir ScMatrixRef pMat = GetMatrix();
1020cdf0e10cSrcweir ScMatrixRef pRMat;
1021cdf0e10cSrcweir if (pMat)
1022cdf0e10cSrcweir {
1023cdf0e10cSrcweir SCSIZE nC, nR;
1024cdf0e10cSrcweir pMat->GetDimensions(nC, nR);
1025cdf0e10cSrcweir pRMat = GetNewMat(nR, nC);
1026cdf0e10cSrcweir if ( pRMat )
1027cdf0e10cSrcweir {
1028cdf0e10cSrcweir pMat->MatTrans(*pRMat);
1029cdf0e10cSrcweir PushMatrix(pRMat);
1030cdf0e10cSrcweir }
1031cdf0e10cSrcweir else
1032cdf0e10cSrcweir PushIllegalArgument();
1033cdf0e10cSrcweir }
1034cdf0e10cSrcweir else
1035cdf0e10cSrcweir PushIllegalParameter();
1036cdf0e10cSrcweir }
1037cdf0e10cSrcweir }
1038cdf0e10cSrcweir
1039cdf0e10cSrcweir
1040cdf0e10cSrcweir /** Minimum extent of one result matrix dimension.
1041cdf0e10cSrcweir For a row or column vector to be replicated the larger matrix dimension is
1042cdf0e10cSrcweir returned, else the smaller dimension.
1043cdf0e10cSrcweir */
lcl_GetMinExtent(SCSIZE n1,SCSIZE n2)1044cdf0e10cSrcweir inline SCSIZE lcl_GetMinExtent( SCSIZE n1, SCSIZE n2 )
1045cdf0e10cSrcweir {
1046cdf0e10cSrcweir if (n1 == 1)
1047cdf0e10cSrcweir return n2;
1048cdf0e10cSrcweir else if (n2 == 1)
1049cdf0e10cSrcweir return n1;
1050cdf0e10cSrcweir else if (n1 < n2)
1051cdf0e10cSrcweir return n1;
1052cdf0e10cSrcweir else
1053cdf0e10cSrcweir return n2;
1054cdf0e10cSrcweir }
1055cdf0e10cSrcweir
1056cdf0e10cSrcweir template<class _Function>
lcl_MatrixCalculation(const _Function & _pOperation,ScMatrix * pMat1,ScMatrix * pMat2,ScInterpreter * _pIterpreter)1057cdf0e10cSrcweir ScMatrixRef lcl_MatrixCalculation(const _Function& _pOperation,ScMatrix* pMat1, ScMatrix* pMat2,ScInterpreter* _pIterpreter)
1058cdf0e10cSrcweir {
1059cdf0e10cSrcweir SCSIZE nC1, nC2, nMinC;
1060cdf0e10cSrcweir SCSIZE nR1, nR2, nMinR;
1061cdf0e10cSrcweir SCSIZE i, j;
1062cdf0e10cSrcweir pMat1->GetDimensions(nC1, nR1);
1063cdf0e10cSrcweir pMat2->GetDimensions(nC2, nR2);
1064cdf0e10cSrcweir nMinC = lcl_GetMinExtent( nC1, nC2);
1065cdf0e10cSrcweir nMinR = lcl_GetMinExtent( nR1, nR2);
1066cdf0e10cSrcweir ScMatrixRef xResMat = _pIterpreter->GetNewMat(nMinC, nMinR);
1067cdf0e10cSrcweir if (xResMat)
1068cdf0e10cSrcweir {
1069cdf0e10cSrcweir ScMatrix* pResMat = xResMat;
1070cdf0e10cSrcweir for (i = 0; i < nMinC; i++)
1071cdf0e10cSrcweir {
1072cdf0e10cSrcweir for (j = 0; j < nMinR; j++)
1073cdf0e10cSrcweir {
1074cdf0e10cSrcweir if (pMat1->IsValueOrEmpty(i,j) && pMat2->IsValueOrEmpty(i,j))
1075cdf0e10cSrcweir {
1076cdf0e10cSrcweir double d = _pOperation(pMat1->GetDouble(i,j),pMat2->GetDouble(i,j));
1077cdf0e10cSrcweir pResMat->PutDouble( d, i, j);
1078cdf0e10cSrcweir }
1079cdf0e10cSrcweir else
1080cdf0e10cSrcweir pResMat->PutString(ScGlobal::GetRscString(STR_NO_VALUE), i, j);
1081cdf0e10cSrcweir }
1082cdf0e10cSrcweir }
1083cdf0e10cSrcweir }
1084cdf0e10cSrcweir return xResMat;
1085cdf0e10cSrcweir }
1086cdf0e10cSrcweir
MatConcat(ScMatrix * pMat1,ScMatrix * pMat2)1087cdf0e10cSrcweir ScMatrixRef ScInterpreter::MatConcat(ScMatrix* pMat1, ScMatrix* pMat2)
1088cdf0e10cSrcweir {
1089cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::MatConcat" );
1090cdf0e10cSrcweir SCSIZE nC1, nC2, nMinC;
1091cdf0e10cSrcweir SCSIZE nR1, nR2, nMinR;
1092cdf0e10cSrcweir SCSIZE i, j;
1093cdf0e10cSrcweir pMat1->GetDimensions(nC1, nR1);
1094cdf0e10cSrcweir pMat2->GetDimensions(nC2, nR2);
1095cdf0e10cSrcweir nMinC = lcl_GetMinExtent( nC1, nC2);
1096cdf0e10cSrcweir nMinR = lcl_GetMinExtent( nR1, nR2);
1097cdf0e10cSrcweir ScMatrixRef xResMat = GetNewMat(nMinC, nMinR);
1098cdf0e10cSrcweir if (xResMat)
1099cdf0e10cSrcweir {
1100cdf0e10cSrcweir ScMatrix* pResMat = xResMat;
1101cdf0e10cSrcweir for (i = 0; i < nMinC; i++)
1102cdf0e10cSrcweir {
1103cdf0e10cSrcweir for (j = 0; j < nMinR; j++)
1104cdf0e10cSrcweir {
1105cdf0e10cSrcweir sal_uInt16 nErr = pMat1->GetErrorIfNotString( i, j);
1106cdf0e10cSrcweir if (!nErr)
1107cdf0e10cSrcweir nErr = pMat2->GetErrorIfNotString( i, j);
1108cdf0e10cSrcweir if (nErr)
1109cdf0e10cSrcweir pResMat->PutError( nErr, i, j);
1110cdf0e10cSrcweir else
1111cdf0e10cSrcweir {
1112cdf0e10cSrcweir String aTmp( pMat1->GetString( *pFormatter, i, j));
1113cdf0e10cSrcweir aTmp += pMat2->GetString( *pFormatter, i, j);
1114cdf0e10cSrcweir pResMat->PutString( aTmp, i, j);
1115cdf0e10cSrcweir }
1116cdf0e10cSrcweir }
1117cdf0e10cSrcweir }
1118cdf0e10cSrcweir }
1119cdf0e10cSrcweir return xResMat;
1120cdf0e10cSrcweir }
1121cdf0e10cSrcweir
1122cdf0e10cSrcweir
1123cdf0e10cSrcweir // fuer DATE, TIME, DATETIME
lcl_GetDiffDateTimeFmtType(short & nFuncFmt,short nFmt1,short nFmt2)1124cdf0e10cSrcweir void lcl_GetDiffDateTimeFmtType( short& nFuncFmt, short nFmt1, short nFmt2 )
1125cdf0e10cSrcweir {
1126cdf0e10cSrcweir if ( nFmt1 != NUMBERFORMAT_UNDEFINED || nFmt2 != NUMBERFORMAT_UNDEFINED )
1127cdf0e10cSrcweir {
1128cdf0e10cSrcweir if ( nFmt1 == nFmt2 )
1129cdf0e10cSrcweir {
1130cdf0e10cSrcweir if ( nFmt1 == NUMBERFORMAT_TIME || nFmt1 == NUMBERFORMAT_DATETIME )
1131cdf0e10cSrcweir nFuncFmt = NUMBERFORMAT_TIME; // Zeiten ergeben Zeit
1132cdf0e10cSrcweir // else: nichts besonderes, Zahl (Datum - Datum := Tage)
1133cdf0e10cSrcweir }
1134cdf0e10cSrcweir else if ( nFmt1 == NUMBERFORMAT_UNDEFINED )
1135cdf0e10cSrcweir nFuncFmt = nFmt2; // z.B. Datum + Tage := Datum
1136cdf0e10cSrcweir else if ( nFmt2 == NUMBERFORMAT_UNDEFINED )
1137cdf0e10cSrcweir nFuncFmt = nFmt1;
1138cdf0e10cSrcweir else
1139cdf0e10cSrcweir {
1140cdf0e10cSrcweir if ( nFmt1 == NUMBERFORMAT_DATE || nFmt2 == NUMBERFORMAT_DATE ||
1141cdf0e10cSrcweir nFmt1 == NUMBERFORMAT_DATETIME || nFmt2 == NUMBERFORMAT_DATETIME )
1142cdf0e10cSrcweir {
1143cdf0e10cSrcweir if ( nFmt1 == NUMBERFORMAT_TIME || nFmt2 == NUMBERFORMAT_TIME )
1144cdf0e10cSrcweir nFuncFmt = NUMBERFORMAT_DATETIME; // Datum + Zeit
1145cdf0e10cSrcweir }
1146cdf0e10cSrcweir }
1147cdf0e10cSrcweir }
1148cdf0e10cSrcweir }
1149cdf0e10cSrcweir
1150cdf0e10cSrcweir
ScAdd()1151cdf0e10cSrcweir void ScInterpreter::ScAdd()
1152cdf0e10cSrcweir {
1153cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScAdd" );
1154cdf0e10cSrcweir CalculateAddSub(sal_False);
1155cdf0e10cSrcweir }
CalculateAddSub(sal_Bool _bSub)1156cdf0e10cSrcweir void ScInterpreter::CalculateAddSub(sal_Bool _bSub)
1157cdf0e10cSrcweir {
1158cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::CalculateAddSub" );
1159cdf0e10cSrcweir ScMatrixRef pMat1 = NULL;
1160cdf0e10cSrcweir ScMatrixRef pMat2 = NULL;
1161cdf0e10cSrcweir double fVal1 = 0.0, fVal2 = 0.0;
1162cdf0e10cSrcweir short nFmt1, nFmt2;
1163cdf0e10cSrcweir nFmt1 = nFmt2 = NUMBERFORMAT_UNDEFINED;
1164cdf0e10cSrcweir short nFmtCurrencyType = nCurFmtType;
1165cdf0e10cSrcweir sal_uLong nFmtCurrencyIndex = nCurFmtIndex;
1166cdf0e10cSrcweir short nFmtPercentType = nCurFmtType;
1167cdf0e10cSrcweir if ( GetStackType() == svMatrix )
1168cdf0e10cSrcweir pMat2 = GetMatrix();
1169cdf0e10cSrcweir else
1170cdf0e10cSrcweir {
1171cdf0e10cSrcweir fVal2 = GetDouble();
1172cdf0e10cSrcweir switch ( nCurFmtType )
1173cdf0e10cSrcweir {
1174cdf0e10cSrcweir case NUMBERFORMAT_DATE :
1175cdf0e10cSrcweir case NUMBERFORMAT_TIME :
1176cdf0e10cSrcweir case NUMBERFORMAT_DATETIME :
1177cdf0e10cSrcweir nFmt2 = nCurFmtType;
1178cdf0e10cSrcweir break;
1179cdf0e10cSrcweir case NUMBERFORMAT_CURRENCY :
1180cdf0e10cSrcweir nFmtCurrencyType = nCurFmtType;
1181cdf0e10cSrcweir nFmtCurrencyIndex = nCurFmtIndex;
1182cdf0e10cSrcweir break;
1183cdf0e10cSrcweir case NUMBERFORMAT_PERCENT :
1184cdf0e10cSrcweir nFmtPercentType = NUMBERFORMAT_PERCENT;
1185cdf0e10cSrcweir break;
1186cdf0e10cSrcweir }
1187cdf0e10cSrcweir }
1188cdf0e10cSrcweir if ( GetStackType() == svMatrix )
1189cdf0e10cSrcweir pMat1 = GetMatrix();
1190cdf0e10cSrcweir else
1191cdf0e10cSrcweir {
1192cdf0e10cSrcweir fVal1 = GetDouble();
1193cdf0e10cSrcweir switch ( nCurFmtType )
1194cdf0e10cSrcweir {
1195cdf0e10cSrcweir case NUMBERFORMAT_DATE :
1196cdf0e10cSrcweir case NUMBERFORMAT_TIME :
1197cdf0e10cSrcweir case NUMBERFORMAT_DATETIME :
1198cdf0e10cSrcweir nFmt1 = nCurFmtType;
1199cdf0e10cSrcweir break;
1200cdf0e10cSrcweir case NUMBERFORMAT_CURRENCY :
1201cdf0e10cSrcweir nFmtCurrencyType = nCurFmtType;
1202cdf0e10cSrcweir nFmtCurrencyIndex = nCurFmtIndex;
1203cdf0e10cSrcweir break;
1204cdf0e10cSrcweir case NUMBERFORMAT_PERCENT :
1205cdf0e10cSrcweir nFmtPercentType = NUMBERFORMAT_PERCENT;
1206cdf0e10cSrcweir break;
1207cdf0e10cSrcweir }
1208cdf0e10cSrcweir }
1209cdf0e10cSrcweir if (pMat1 && pMat2)
1210cdf0e10cSrcweir {
1211cdf0e10cSrcweir ScMatrixRef pResMat;
1212cdf0e10cSrcweir if ( _bSub )
1213cdf0e10cSrcweir {
1214cdf0e10cSrcweir MatrixSub aSub;
1215cdf0e10cSrcweir pResMat = lcl_MatrixCalculation(aSub ,pMat1, pMat2,this);
1216cdf0e10cSrcweir }
1217cdf0e10cSrcweir else
1218cdf0e10cSrcweir {
1219cdf0e10cSrcweir MatrixAdd aAdd;
1220cdf0e10cSrcweir pResMat = lcl_MatrixCalculation(aAdd ,pMat1, pMat2,this);
1221cdf0e10cSrcweir }
1222cdf0e10cSrcweir
1223cdf0e10cSrcweir if (!pResMat)
1224cdf0e10cSrcweir PushNoValue();
1225cdf0e10cSrcweir else
1226cdf0e10cSrcweir PushMatrix(pResMat);
1227cdf0e10cSrcweir }
1228cdf0e10cSrcweir else if (pMat1 || pMat2)
1229cdf0e10cSrcweir {
1230cdf0e10cSrcweir double fVal;
1231cdf0e10cSrcweir sal_Bool bFlag;
1232cdf0e10cSrcweir ScMatrixRef pMat = pMat1;
1233cdf0e10cSrcweir if (!pMat)
1234cdf0e10cSrcweir {
1235cdf0e10cSrcweir fVal = fVal1;
1236cdf0e10cSrcweir pMat = pMat2;
1237cdf0e10cSrcweir bFlag = sal_True; // double - Matrix
1238cdf0e10cSrcweir }
1239cdf0e10cSrcweir else
1240cdf0e10cSrcweir {
1241cdf0e10cSrcweir fVal = fVal2;
1242cdf0e10cSrcweir bFlag = sal_False; // Matrix - double
1243cdf0e10cSrcweir }
1244cdf0e10cSrcweir SCSIZE nC, nR;
1245cdf0e10cSrcweir pMat->GetDimensions(nC, nR);
1246cdf0e10cSrcweir ScMatrixRef pResMat = GetNewMat(nC, nR);
1247cdf0e10cSrcweir if (pResMat)
1248cdf0e10cSrcweir {
1249cdf0e10cSrcweir SCSIZE nCount = nC * nR;
1250cdf0e10cSrcweir if (bFlag || !_bSub )
1251cdf0e10cSrcweir {
1252cdf0e10cSrcweir for ( SCSIZE i = 0; i < nCount; i++ )
1253cdf0e10cSrcweir {
1254cdf0e10cSrcweir if (pMat->IsValue(i))
1255cdf0e10cSrcweir pResMat->PutDouble( _bSub ? ::rtl::math::approxSub( fVal, pMat->GetDouble(i)) : ::rtl::math::approxAdd( pMat->GetDouble(i), fVal), i);
1256cdf0e10cSrcweir else
1257cdf0e10cSrcweir pResMat->PutString(ScGlobal::GetRscString(STR_NO_VALUE), i);
1258cdf0e10cSrcweir } // for ( SCSIZE i = 0; i < nCount; i++ )
1259cdf0e10cSrcweir } // if (bFlag || !_bSub )
1260cdf0e10cSrcweir else
1261cdf0e10cSrcweir {
1262cdf0e10cSrcweir for ( SCSIZE i = 0; i < nCount; i++ )
1263cdf0e10cSrcweir { if (pMat->IsValue(i))
1264cdf0e10cSrcweir pResMat->PutDouble( ::rtl::math::approxSub( pMat->GetDouble(i), fVal), i);
1265cdf0e10cSrcweir else
1266cdf0e10cSrcweir pResMat->PutString(ScGlobal::GetRscString(STR_NO_VALUE), i);
1267cdf0e10cSrcweir } // for ( SCSIZE i = 0; i < nCount; i++ )
1268cdf0e10cSrcweir }
1269cdf0e10cSrcweir PushMatrix(pResMat);
1270cdf0e10cSrcweir }
1271cdf0e10cSrcweir else
1272cdf0e10cSrcweir PushIllegalArgument();
1273cdf0e10cSrcweir }
1274cdf0e10cSrcweir else if ( _bSub )
1275cdf0e10cSrcweir PushDouble( ::rtl::math::approxSub( fVal1, fVal2 ) );
1276cdf0e10cSrcweir else
1277cdf0e10cSrcweir PushDouble( ::rtl::math::approxAdd( fVal1, fVal2 ) );
1278cdf0e10cSrcweir if ( nFmtCurrencyType == NUMBERFORMAT_CURRENCY )
1279cdf0e10cSrcweir {
1280cdf0e10cSrcweir nFuncFmtType = nFmtCurrencyType;
1281cdf0e10cSrcweir nFuncFmtIndex = nFmtCurrencyIndex;
1282cdf0e10cSrcweir }
1283cdf0e10cSrcweir else
1284cdf0e10cSrcweir {
1285cdf0e10cSrcweir lcl_GetDiffDateTimeFmtType( nFuncFmtType, nFmt1, nFmt2 );
1286cdf0e10cSrcweir if ( nFmtPercentType == NUMBERFORMAT_PERCENT && nFuncFmtType == NUMBERFORMAT_NUMBER )
1287cdf0e10cSrcweir nFuncFmtType = NUMBERFORMAT_PERCENT;
1288cdf0e10cSrcweir }
1289cdf0e10cSrcweir }
1290cdf0e10cSrcweir
ScAmpersand()1291cdf0e10cSrcweir void ScInterpreter::ScAmpersand()
1292cdf0e10cSrcweir {
1293cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScAmpersand" );
1294cdf0e10cSrcweir ScMatrixRef pMat1 = NULL;
1295cdf0e10cSrcweir ScMatrixRef pMat2 = NULL;
1296cdf0e10cSrcweir String sStr1, sStr2;
1297cdf0e10cSrcweir if ( GetStackType() == svMatrix )
1298cdf0e10cSrcweir pMat2 = GetMatrix();
1299cdf0e10cSrcweir else
1300cdf0e10cSrcweir sStr2 = GetString();
1301cdf0e10cSrcweir if ( GetStackType() == svMatrix )
1302cdf0e10cSrcweir pMat1 = GetMatrix();
1303cdf0e10cSrcweir else
1304cdf0e10cSrcweir sStr1 = GetString();
1305cdf0e10cSrcweir if (pMat1 && pMat2)
1306cdf0e10cSrcweir {
1307cdf0e10cSrcweir ScMatrixRef pResMat = MatConcat(pMat1, pMat2);
1308cdf0e10cSrcweir if (!pResMat)
1309cdf0e10cSrcweir PushNoValue();
1310cdf0e10cSrcweir else
1311cdf0e10cSrcweir PushMatrix(pResMat);
1312cdf0e10cSrcweir }
1313cdf0e10cSrcweir else if (pMat1 || pMat2)
1314cdf0e10cSrcweir {
1315cdf0e10cSrcweir String sStr;
1316cdf0e10cSrcweir sal_Bool bFlag;
1317cdf0e10cSrcweir ScMatrixRef pMat = pMat1;
1318cdf0e10cSrcweir if (!pMat)
1319cdf0e10cSrcweir {
1320cdf0e10cSrcweir sStr = sStr1;
1321cdf0e10cSrcweir pMat = pMat2;
1322cdf0e10cSrcweir bFlag = sal_True; // double - Matrix
1323cdf0e10cSrcweir }
1324cdf0e10cSrcweir else
1325cdf0e10cSrcweir {
1326cdf0e10cSrcweir sStr = sStr2;
1327cdf0e10cSrcweir bFlag = sal_False; // Matrix - double
1328cdf0e10cSrcweir }
1329cdf0e10cSrcweir SCSIZE nC, nR;
1330cdf0e10cSrcweir pMat->GetDimensions(nC, nR);
1331cdf0e10cSrcweir ScMatrixRef pResMat = GetNewMat(nC, nR);
1332cdf0e10cSrcweir if (pResMat)
1333cdf0e10cSrcweir {
1334cdf0e10cSrcweir SCSIZE nCount = nC * nR;
1335cdf0e10cSrcweir if (nGlobalError)
1336cdf0e10cSrcweir {
1337cdf0e10cSrcweir for ( SCSIZE i = 0; i < nCount; i++ )
1338cdf0e10cSrcweir pResMat->PutError( nGlobalError, i);
1339cdf0e10cSrcweir }
1340cdf0e10cSrcweir else if (bFlag)
1341cdf0e10cSrcweir {
1342cdf0e10cSrcweir for ( SCSIZE i = 0; i < nCount; i++ )
1343cdf0e10cSrcweir {
1344cdf0e10cSrcweir sal_uInt16 nErr = pMat->GetErrorIfNotString( i);
1345cdf0e10cSrcweir if (nErr)
1346cdf0e10cSrcweir pResMat->PutError( nErr, i);
1347cdf0e10cSrcweir else
1348cdf0e10cSrcweir {
1349cdf0e10cSrcweir String aTmp( sStr);
1350cdf0e10cSrcweir aTmp += pMat->GetString( *pFormatter, i);
1351cdf0e10cSrcweir pResMat->PutString( aTmp, i);
1352cdf0e10cSrcweir }
1353cdf0e10cSrcweir }
1354cdf0e10cSrcweir }
1355cdf0e10cSrcweir else
1356cdf0e10cSrcweir {
1357cdf0e10cSrcweir for ( SCSIZE i = 0; i < nCount; i++ )
1358cdf0e10cSrcweir {
1359cdf0e10cSrcweir sal_uInt16 nErr = pMat->GetErrorIfNotString( i);
1360cdf0e10cSrcweir if (nErr)
1361cdf0e10cSrcweir pResMat->PutError( nErr, i);
1362cdf0e10cSrcweir else
1363cdf0e10cSrcweir {
1364cdf0e10cSrcweir String aTmp( pMat->GetString( *pFormatter, i));
1365cdf0e10cSrcweir aTmp += sStr;
1366cdf0e10cSrcweir pResMat->PutString( aTmp, i);
1367cdf0e10cSrcweir }
1368cdf0e10cSrcweir }
1369cdf0e10cSrcweir }
1370cdf0e10cSrcweir PushMatrix(pResMat);
1371cdf0e10cSrcweir }
1372cdf0e10cSrcweir else
1373cdf0e10cSrcweir PushIllegalArgument();
1374cdf0e10cSrcweir }
1375cdf0e10cSrcweir else
1376cdf0e10cSrcweir {
1377cdf0e10cSrcweir if ( CheckStringResultLen( sStr1, sStr2 ) )
1378cdf0e10cSrcweir sStr1 += sStr2;
1379cdf0e10cSrcweir PushString(sStr1);
1380cdf0e10cSrcweir }
1381cdf0e10cSrcweir }
1382cdf0e10cSrcweir
ScSub()1383cdf0e10cSrcweir void ScInterpreter::ScSub()
1384cdf0e10cSrcweir {
1385cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScSub" );
1386cdf0e10cSrcweir CalculateAddSub(sal_True);
1387cdf0e10cSrcweir }
1388cdf0e10cSrcweir
ScMul()1389cdf0e10cSrcweir void ScInterpreter::ScMul()
1390cdf0e10cSrcweir {
1391cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScMul" );
1392cdf0e10cSrcweir ScMatrixRef pMat1 = NULL;
1393cdf0e10cSrcweir ScMatrixRef pMat2 = NULL;
1394cdf0e10cSrcweir double fVal1 = 0.0, fVal2 = 0.0;
1395cdf0e10cSrcweir short nFmtCurrencyType = nCurFmtType;
1396cdf0e10cSrcweir sal_uLong nFmtCurrencyIndex = nCurFmtIndex;
1397cdf0e10cSrcweir if ( GetStackType() == svMatrix )
1398cdf0e10cSrcweir pMat2 = GetMatrix();
1399cdf0e10cSrcweir else
1400cdf0e10cSrcweir {
1401cdf0e10cSrcweir fVal2 = GetDouble();
1402cdf0e10cSrcweir switch ( nCurFmtType )
1403cdf0e10cSrcweir {
1404cdf0e10cSrcweir case NUMBERFORMAT_CURRENCY :
1405cdf0e10cSrcweir nFmtCurrencyType = nCurFmtType;
1406cdf0e10cSrcweir nFmtCurrencyIndex = nCurFmtIndex;
1407cdf0e10cSrcweir break;
1408cdf0e10cSrcweir }
1409cdf0e10cSrcweir }
1410cdf0e10cSrcweir if ( GetStackType() == svMatrix )
1411cdf0e10cSrcweir pMat1 = GetMatrix();
1412cdf0e10cSrcweir else
1413cdf0e10cSrcweir {
1414cdf0e10cSrcweir fVal1 = GetDouble();
1415cdf0e10cSrcweir switch ( nCurFmtType )
1416cdf0e10cSrcweir {
1417cdf0e10cSrcweir case NUMBERFORMAT_CURRENCY :
1418cdf0e10cSrcweir nFmtCurrencyType = nCurFmtType;
1419cdf0e10cSrcweir nFmtCurrencyIndex = nCurFmtIndex;
1420cdf0e10cSrcweir break;
1421cdf0e10cSrcweir }
1422cdf0e10cSrcweir }
1423cdf0e10cSrcweir if (pMat1 && pMat2)
1424cdf0e10cSrcweir {
1425cdf0e10cSrcweir MatrixMul aMul;
1426cdf0e10cSrcweir ScMatrixRef pResMat = lcl_MatrixCalculation(aMul,pMat1, pMat2,this);
1427cdf0e10cSrcweir if (!pResMat)
1428cdf0e10cSrcweir PushNoValue();
1429cdf0e10cSrcweir else
1430cdf0e10cSrcweir PushMatrix(pResMat);
1431cdf0e10cSrcweir }
1432cdf0e10cSrcweir else if (pMat1 || pMat2)
1433cdf0e10cSrcweir {
1434cdf0e10cSrcweir double fVal;
1435cdf0e10cSrcweir ScMatrixRef pMat = pMat1;
1436cdf0e10cSrcweir if (!pMat)
1437cdf0e10cSrcweir {
1438cdf0e10cSrcweir fVal = fVal1;
1439cdf0e10cSrcweir pMat = pMat2;
1440cdf0e10cSrcweir }
1441cdf0e10cSrcweir else
1442cdf0e10cSrcweir fVal = fVal2;
1443cdf0e10cSrcweir SCSIZE nC, nR;
1444cdf0e10cSrcweir pMat->GetDimensions(nC, nR);
1445cdf0e10cSrcweir ScMatrixRef pResMat = GetNewMat(nC, nR);
1446cdf0e10cSrcweir if (pResMat)
1447cdf0e10cSrcweir {
1448cdf0e10cSrcweir SCSIZE nCount = nC * nR;
1449cdf0e10cSrcweir for ( SCSIZE i = 0; i < nCount; i++ )
1450cdf0e10cSrcweir if (pMat->IsValue(i))
1451cdf0e10cSrcweir pResMat->PutDouble(pMat->GetDouble(i)*fVal, i);
1452cdf0e10cSrcweir else
1453cdf0e10cSrcweir pResMat->PutString(ScGlobal::GetRscString(STR_NO_VALUE), i);
1454cdf0e10cSrcweir PushMatrix(pResMat);
1455cdf0e10cSrcweir }
1456cdf0e10cSrcweir else
1457cdf0e10cSrcweir PushIllegalArgument();
1458cdf0e10cSrcweir }
1459cdf0e10cSrcweir else
1460cdf0e10cSrcweir PushDouble(fVal1 * fVal2);
1461cdf0e10cSrcweir if ( nFmtCurrencyType == NUMBERFORMAT_CURRENCY )
1462cdf0e10cSrcweir {
1463cdf0e10cSrcweir nFuncFmtType = nFmtCurrencyType;
1464cdf0e10cSrcweir nFuncFmtIndex = nFmtCurrencyIndex;
1465cdf0e10cSrcweir }
1466cdf0e10cSrcweir }
1467cdf0e10cSrcweir
ScDiv()1468cdf0e10cSrcweir void ScInterpreter::ScDiv()
1469cdf0e10cSrcweir {
1470cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScDiv" );
1471cdf0e10cSrcweir ScMatrixRef pMat1 = NULL;
1472cdf0e10cSrcweir ScMatrixRef pMat2 = NULL;
1473cdf0e10cSrcweir double fVal1 = 0.0, fVal2 = 0.0;
1474cdf0e10cSrcweir short nFmtCurrencyType = nCurFmtType;
1475cdf0e10cSrcweir sal_uLong nFmtCurrencyIndex = nCurFmtIndex;
1476cdf0e10cSrcweir short nFmtCurrencyType2 = NUMBERFORMAT_UNDEFINED;
1477cdf0e10cSrcweir if ( GetStackType() == svMatrix )
1478cdf0e10cSrcweir pMat2 = GetMatrix();
1479cdf0e10cSrcweir else
1480cdf0e10cSrcweir {
1481cdf0e10cSrcweir fVal2 = GetDouble();
1482cdf0e10cSrcweir // hier kein Currency uebernehmen, 123kg/456DM sind nicht DM
1483cdf0e10cSrcweir nFmtCurrencyType2 = nCurFmtType;
1484cdf0e10cSrcweir }
1485cdf0e10cSrcweir if ( GetStackType() == svMatrix )
1486cdf0e10cSrcweir pMat1 = GetMatrix();
1487cdf0e10cSrcweir else
1488cdf0e10cSrcweir {
1489cdf0e10cSrcweir fVal1 = GetDouble();
1490cdf0e10cSrcweir switch ( nCurFmtType )
1491cdf0e10cSrcweir {
1492cdf0e10cSrcweir case NUMBERFORMAT_CURRENCY :
1493cdf0e10cSrcweir nFmtCurrencyType = nCurFmtType;
1494cdf0e10cSrcweir nFmtCurrencyIndex = nCurFmtIndex;
1495cdf0e10cSrcweir break;
1496cdf0e10cSrcweir }
1497cdf0e10cSrcweir }
1498cdf0e10cSrcweir if (pMat1 && pMat2)
1499cdf0e10cSrcweir {
1500cdf0e10cSrcweir MatrixDiv aDiv;
1501cdf0e10cSrcweir ScMatrixRef pResMat = lcl_MatrixCalculation(aDiv,pMat1, pMat2,this);
1502cdf0e10cSrcweir if (!pResMat)
1503cdf0e10cSrcweir PushNoValue();
1504cdf0e10cSrcweir else
1505cdf0e10cSrcweir PushMatrix(pResMat);
1506cdf0e10cSrcweir }
1507cdf0e10cSrcweir else if (pMat1 || pMat2)
1508cdf0e10cSrcweir {
1509cdf0e10cSrcweir double fVal;
1510cdf0e10cSrcweir sal_Bool bFlag;
1511cdf0e10cSrcweir ScMatrixRef pMat = pMat1;
1512cdf0e10cSrcweir if (!pMat)
1513cdf0e10cSrcweir {
1514cdf0e10cSrcweir fVal = fVal1;
1515cdf0e10cSrcweir pMat = pMat2;
1516cdf0e10cSrcweir bFlag = sal_True; // double - Matrix
1517cdf0e10cSrcweir }
1518cdf0e10cSrcweir else
1519cdf0e10cSrcweir {
1520cdf0e10cSrcweir fVal = fVal2;
1521cdf0e10cSrcweir bFlag = sal_False; // Matrix - double
1522cdf0e10cSrcweir }
1523cdf0e10cSrcweir SCSIZE nC, nR;
1524cdf0e10cSrcweir pMat->GetDimensions(nC, nR);
1525cdf0e10cSrcweir ScMatrixRef pResMat = GetNewMat(nC, nR);
1526cdf0e10cSrcweir if (pResMat)
1527cdf0e10cSrcweir {
1528cdf0e10cSrcweir SCSIZE nCount = nC * nR;
1529cdf0e10cSrcweir if (bFlag)
1530cdf0e10cSrcweir { for ( SCSIZE i = 0; i < nCount; i++ )
1531cdf0e10cSrcweir if (pMat->IsValue(i))
1532cdf0e10cSrcweir pResMat->PutDouble( div( fVal, pMat->GetDouble(i)), i);
1533cdf0e10cSrcweir else
1534cdf0e10cSrcweir pResMat->PutString(ScGlobal::GetRscString(STR_NO_VALUE), i);
1535cdf0e10cSrcweir }
1536cdf0e10cSrcweir else
1537cdf0e10cSrcweir { for ( SCSIZE i = 0; i < nCount; i++ )
1538cdf0e10cSrcweir if (pMat->IsValue(i))
1539cdf0e10cSrcweir pResMat->PutDouble( div( pMat->GetDouble(i), fVal), i);
1540cdf0e10cSrcweir else
1541cdf0e10cSrcweir pResMat->PutString(ScGlobal::GetRscString(STR_NO_VALUE), i);
1542cdf0e10cSrcweir }
1543cdf0e10cSrcweir PushMatrix(pResMat);
1544cdf0e10cSrcweir }
1545cdf0e10cSrcweir else
1546cdf0e10cSrcweir PushIllegalArgument();
1547cdf0e10cSrcweir }
1548cdf0e10cSrcweir else
1549cdf0e10cSrcweir {
1550cdf0e10cSrcweir PushDouble( div( fVal1, fVal2) );
1551cdf0e10cSrcweir }
1552cdf0e10cSrcweir if ( nFmtCurrencyType == NUMBERFORMAT_CURRENCY && nFmtCurrencyType2 != NUMBERFORMAT_CURRENCY )
1553cdf0e10cSrcweir { // auch DM/DM ist nicht DM bzw. DEM/EUR nicht DEM
1554cdf0e10cSrcweir nFuncFmtType = nFmtCurrencyType;
1555cdf0e10cSrcweir nFuncFmtIndex = nFmtCurrencyIndex;
1556cdf0e10cSrcweir }
1557cdf0e10cSrcweir }
1558cdf0e10cSrcweir
ScPower()1559cdf0e10cSrcweir void ScInterpreter::ScPower()
1560cdf0e10cSrcweir {
1561cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScPower" );
1562cdf0e10cSrcweir if ( MustHaveParamCount( GetByte(), 2 ) )
1563cdf0e10cSrcweir ScPow();
1564cdf0e10cSrcweir }
1565cdf0e10cSrcweir
ScPow()1566cdf0e10cSrcweir void ScInterpreter::ScPow()
1567cdf0e10cSrcweir {
1568cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScPow" );
1569cdf0e10cSrcweir ScMatrixRef pMat1 = NULL;
1570cdf0e10cSrcweir ScMatrixRef pMat2 = NULL;
1571cdf0e10cSrcweir double fVal1 = 0.0, fVal2 = 0.0;
1572cdf0e10cSrcweir if ( GetStackType() == svMatrix )
1573cdf0e10cSrcweir pMat2 = GetMatrix();
1574cdf0e10cSrcweir else
1575cdf0e10cSrcweir fVal2 = GetDouble();
1576cdf0e10cSrcweir if ( GetStackType() == svMatrix )
1577cdf0e10cSrcweir pMat1 = GetMatrix();
1578cdf0e10cSrcweir else
1579cdf0e10cSrcweir fVal1 = GetDouble();
1580cdf0e10cSrcweir if (pMat1 && pMat2)
1581cdf0e10cSrcweir {
1582cdf0e10cSrcweir MatrixPow aPow;
1583cdf0e10cSrcweir ScMatrixRef pResMat = lcl_MatrixCalculation(aPow,pMat1, pMat2,this);
1584cdf0e10cSrcweir if (!pResMat)
1585cdf0e10cSrcweir PushNoValue();
1586cdf0e10cSrcweir else
1587cdf0e10cSrcweir PushMatrix(pResMat);
1588cdf0e10cSrcweir }
1589cdf0e10cSrcweir else if (pMat1 || pMat2)
1590cdf0e10cSrcweir {
1591cdf0e10cSrcweir double fVal;
1592cdf0e10cSrcweir sal_Bool bFlag;
1593cdf0e10cSrcweir ScMatrixRef pMat = pMat1;
1594cdf0e10cSrcweir if (!pMat)
1595cdf0e10cSrcweir {
1596cdf0e10cSrcweir fVal = fVal1;
1597cdf0e10cSrcweir pMat = pMat2;
1598cdf0e10cSrcweir bFlag = sal_True; // double - Matrix
1599cdf0e10cSrcweir }
1600cdf0e10cSrcweir else
1601cdf0e10cSrcweir {
1602cdf0e10cSrcweir fVal = fVal2;
1603cdf0e10cSrcweir bFlag = sal_False; // Matrix - double
1604cdf0e10cSrcweir }
1605cdf0e10cSrcweir SCSIZE nC, nR;
1606cdf0e10cSrcweir pMat->GetDimensions(nC, nR);
1607cdf0e10cSrcweir ScMatrixRef pResMat = GetNewMat(nC, nR);
1608cdf0e10cSrcweir if (pResMat)
1609cdf0e10cSrcweir {
1610cdf0e10cSrcweir SCSIZE nCount = nC * nR;
1611cdf0e10cSrcweir if (bFlag)
1612cdf0e10cSrcweir { for ( SCSIZE i = 0; i < nCount; i++ )
1613cdf0e10cSrcweir if (pMat->IsValue(i))
1614*a067bd65SRob Weir pResMat->PutDouble(pow(fVal,pMat->GetDouble(i)), i);
1615cdf0e10cSrcweir else
1616cdf0e10cSrcweir pResMat->PutString(ScGlobal::GetRscString(STR_NO_VALUE), i);
1617cdf0e10cSrcweir }
1618cdf0e10cSrcweir else
1619cdf0e10cSrcweir { for ( SCSIZE i = 0; i < nCount; i++ )
1620cdf0e10cSrcweir if (pMat->IsValue(i))
1621*a067bd65SRob Weir pResMat->PutDouble(pow(pMat->GetDouble(i),fVal), i);
1622cdf0e10cSrcweir else
1623cdf0e10cSrcweir pResMat->PutString(ScGlobal::GetRscString(STR_NO_VALUE), i);
1624cdf0e10cSrcweir }
1625cdf0e10cSrcweir PushMatrix(pResMat);
1626cdf0e10cSrcweir }
1627cdf0e10cSrcweir else
1628cdf0e10cSrcweir PushIllegalArgument();
1629cdf0e10cSrcweir }
1630cdf0e10cSrcweir else
1631*a067bd65SRob Weir PushDouble(pow(fVal1,fVal2));
1632cdf0e10cSrcweir }
1633cdf0e10cSrcweir
ScSumProduct()1634cdf0e10cSrcweir void ScInterpreter::ScSumProduct()
1635cdf0e10cSrcweir {
1636cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScSumProduct" );
1637cdf0e10cSrcweir sal_uInt8 nParamCount = GetByte();
1638cdf0e10cSrcweir if ( !MustHaveParamCount( nParamCount, 1, 30 ) )
1639cdf0e10cSrcweir return;
1640cdf0e10cSrcweir
1641cdf0e10cSrcweir ScMatrixRef pMat1 = NULL;
1642cdf0e10cSrcweir ScMatrixRef pMat2 = NULL;
1643cdf0e10cSrcweir ScMatrixRef pMat = NULL;
1644cdf0e10cSrcweir pMat2 = GetMatrix();
1645cdf0e10cSrcweir if (!pMat2)
1646cdf0e10cSrcweir {
1647cdf0e10cSrcweir PushIllegalParameter();
1648cdf0e10cSrcweir return;
1649cdf0e10cSrcweir }
1650cdf0e10cSrcweir SCSIZE nC, nC1;
1651cdf0e10cSrcweir SCSIZE nR, nR1;
1652cdf0e10cSrcweir pMat2->GetDimensions(nC, nR);
1653cdf0e10cSrcweir pMat = pMat2;
1654cdf0e10cSrcweir MatrixMul aMul;
1655cdf0e10cSrcweir for (sal_uInt16 i = 1; i < nParamCount; i++)
1656cdf0e10cSrcweir {
1657cdf0e10cSrcweir pMat1 = GetMatrix();
1658cdf0e10cSrcweir if (!pMat1)
1659cdf0e10cSrcweir {
1660cdf0e10cSrcweir PushIllegalParameter();
1661cdf0e10cSrcweir return;
1662cdf0e10cSrcweir }
1663cdf0e10cSrcweir pMat1->GetDimensions(nC1, nR1);
1664cdf0e10cSrcweir if (nC1 != nC || nR1 != nR)
1665cdf0e10cSrcweir {
1666cdf0e10cSrcweir PushNoValue();
1667cdf0e10cSrcweir return;
1668cdf0e10cSrcweir }
1669cdf0e10cSrcweir ScMatrixRef pResMat = lcl_MatrixCalculation(aMul,pMat1, pMat,this);
1670cdf0e10cSrcweir if (!pResMat)
1671cdf0e10cSrcweir {
1672cdf0e10cSrcweir PushNoValue();
1673cdf0e10cSrcweir return;
1674cdf0e10cSrcweir }
1675cdf0e10cSrcweir else
1676cdf0e10cSrcweir pMat = pResMat;
1677cdf0e10cSrcweir }
1678cdf0e10cSrcweir double fSum = 0.0;
1679cdf0e10cSrcweir SCSIZE nCount = pMat->GetElementCount();
1680cdf0e10cSrcweir for (SCSIZE j = 0; j < nCount; j++)
1681cdf0e10cSrcweir {
1682cdf0e10cSrcweir if (!pMat->IsString(j))
1683cdf0e10cSrcweir fSum += pMat->GetDouble(j);
1684cdf0e10cSrcweir }
1685cdf0e10cSrcweir PushDouble(fSum);
1686cdf0e10cSrcweir }
1687cdf0e10cSrcweir
ScSumX2MY2()1688cdf0e10cSrcweir void ScInterpreter::ScSumX2MY2()
1689cdf0e10cSrcweir {
1690cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScSumX2MY2" );
1691cdf0e10cSrcweir CalculateSumX2MY2SumX2DY2(sal_False);
1692cdf0e10cSrcweir }
CalculateSumX2MY2SumX2DY2(sal_Bool _bSumX2DY2)1693cdf0e10cSrcweir void ScInterpreter::CalculateSumX2MY2SumX2DY2(sal_Bool _bSumX2DY2)
1694cdf0e10cSrcweir {
1695cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::CalculateSumX2MY2SumX2DY2" );
1696cdf0e10cSrcweir if ( !MustHaveParamCount( GetByte(), 2 ) )
1697cdf0e10cSrcweir return;
1698cdf0e10cSrcweir
1699cdf0e10cSrcweir ScMatrixRef pMat1 = NULL;
1700cdf0e10cSrcweir ScMatrixRef pMat2 = NULL;
1701cdf0e10cSrcweir SCSIZE i, j;
1702cdf0e10cSrcweir pMat2 = GetMatrix();
1703cdf0e10cSrcweir pMat1 = GetMatrix();
1704cdf0e10cSrcweir if (!pMat2 || !pMat1)
1705cdf0e10cSrcweir {
1706cdf0e10cSrcweir PushIllegalParameter();
1707cdf0e10cSrcweir return;
1708cdf0e10cSrcweir }
1709cdf0e10cSrcweir SCSIZE nC1, nC2;
1710cdf0e10cSrcweir SCSIZE nR1, nR2;
1711cdf0e10cSrcweir pMat2->GetDimensions(nC2, nR2);
1712cdf0e10cSrcweir pMat1->GetDimensions(nC1, nR1);
1713cdf0e10cSrcweir if (nC1 != nC2 || nR1 != nR2)
1714cdf0e10cSrcweir {
1715cdf0e10cSrcweir PushNoValue();
1716cdf0e10cSrcweir return;
1717cdf0e10cSrcweir }
1718cdf0e10cSrcweir double fVal, fSum = 0.0;
1719cdf0e10cSrcweir for (i = 0; i < nC1; i++)
1720cdf0e10cSrcweir for (j = 0; j < nR1; j++)
1721cdf0e10cSrcweir if (!pMat1->IsString(i,j) && !pMat2->IsString(i,j))
1722cdf0e10cSrcweir {
1723cdf0e10cSrcweir fVal = pMat1->GetDouble(i,j);
1724cdf0e10cSrcweir fSum += fVal * fVal;
1725cdf0e10cSrcweir fVal = pMat2->GetDouble(i,j);
1726cdf0e10cSrcweir if ( _bSumX2DY2 )
1727cdf0e10cSrcweir fSum += fVal * fVal;
1728cdf0e10cSrcweir else
1729cdf0e10cSrcweir fSum -= fVal * fVal;
1730cdf0e10cSrcweir }
1731cdf0e10cSrcweir PushDouble(fSum);
1732cdf0e10cSrcweir }
1733cdf0e10cSrcweir
ScSumX2DY2()1734cdf0e10cSrcweir void ScInterpreter::ScSumX2DY2()
1735cdf0e10cSrcweir {
1736cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScSumX2DY2" );
1737cdf0e10cSrcweir CalculateSumX2MY2SumX2DY2(sal_True);
1738cdf0e10cSrcweir }
1739cdf0e10cSrcweir
ScSumXMY2()1740cdf0e10cSrcweir void ScInterpreter::ScSumXMY2()
1741cdf0e10cSrcweir {
1742cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScSumXMY2" );
1743cdf0e10cSrcweir if ( !MustHaveParamCount( GetByte(), 2 ) )
1744cdf0e10cSrcweir return;
1745cdf0e10cSrcweir
1746cdf0e10cSrcweir ScMatrixRef pMat1 = NULL;
1747cdf0e10cSrcweir ScMatrixRef pMat2 = NULL;
1748cdf0e10cSrcweir pMat2 = GetMatrix();
1749cdf0e10cSrcweir pMat1 = GetMatrix();
1750cdf0e10cSrcweir if (!pMat2 || !pMat1)
1751cdf0e10cSrcweir {
1752cdf0e10cSrcweir PushIllegalParameter();
1753cdf0e10cSrcweir return;
1754cdf0e10cSrcweir }
1755cdf0e10cSrcweir SCSIZE nC1, nC2;
1756cdf0e10cSrcweir SCSIZE nR1, nR2;
1757cdf0e10cSrcweir pMat2->GetDimensions(nC2, nR2);
1758cdf0e10cSrcweir pMat1->GetDimensions(nC1, nR1);
1759cdf0e10cSrcweir if (nC1 != nC2 || nR1 != nR2)
1760cdf0e10cSrcweir {
1761cdf0e10cSrcweir PushNoValue();
1762cdf0e10cSrcweir return;
1763cdf0e10cSrcweir } // if (nC1 != nC2 || nR1 != nR2)
1764cdf0e10cSrcweir MatrixSub aSub;
1765cdf0e10cSrcweir ScMatrixRef pResMat = lcl_MatrixCalculation(aSub,pMat1, pMat2,this);
1766cdf0e10cSrcweir if (!pResMat)
1767cdf0e10cSrcweir {
1768cdf0e10cSrcweir PushNoValue();
1769cdf0e10cSrcweir }
1770cdf0e10cSrcweir else
1771cdf0e10cSrcweir {
1772cdf0e10cSrcweir double fVal, fSum = 0.0;
1773cdf0e10cSrcweir SCSIZE nCount = pResMat->GetElementCount();
1774cdf0e10cSrcweir for (SCSIZE i = 0; i < nCount; i++)
1775cdf0e10cSrcweir if (!pResMat->IsString(i))
1776cdf0e10cSrcweir {
1777cdf0e10cSrcweir fVal = pResMat->GetDouble(i);
1778cdf0e10cSrcweir fSum += fVal * fVal;
1779cdf0e10cSrcweir }
1780cdf0e10cSrcweir PushDouble(fSum);
1781cdf0e10cSrcweir }
1782cdf0e10cSrcweir }
1783cdf0e10cSrcweir
ScFrequency()1784cdf0e10cSrcweir void ScInterpreter::ScFrequency()
1785cdf0e10cSrcweir {
1786cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScFrequency" );
1787cdf0e10cSrcweir if ( !MustHaveParamCount( GetByte(), 2 ) )
1788cdf0e10cSrcweir return;
1789cdf0e10cSrcweir
1790cdf0e10cSrcweir vector<double> aBinArray;
1791cdf0e10cSrcweir vector<long> aBinIndexOrder;
1792cdf0e10cSrcweir
1793cdf0e10cSrcweir GetSortArray(1, aBinArray, &aBinIndexOrder);
1794cdf0e10cSrcweir SCSIZE nBinSize = aBinArray.size();
1795cdf0e10cSrcweir if (nGlobalError)
1796cdf0e10cSrcweir {
1797cdf0e10cSrcweir PushNoValue();
1798cdf0e10cSrcweir return;
1799cdf0e10cSrcweir }
1800cdf0e10cSrcweir
1801cdf0e10cSrcweir vector<double> aDataArray;
1802cdf0e10cSrcweir GetSortArray(1, aDataArray);
1803cdf0e10cSrcweir SCSIZE nDataSize = aDataArray.size();
1804cdf0e10cSrcweir
1805cdf0e10cSrcweir if (aDataArray.empty() || nGlobalError)
1806cdf0e10cSrcweir {
1807cdf0e10cSrcweir PushNoValue();
1808cdf0e10cSrcweir return;
1809cdf0e10cSrcweir }
1810cdf0e10cSrcweir ScMatrixRef pResMat = GetNewMat(1, nBinSize+1);
1811cdf0e10cSrcweir if (!pResMat)
1812cdf0e10cSrcweir {
1813cdf0e10cSrcweir PushIllegalArgument();
1814cdf0e10cSrcweir return;
1815cdf0e10cSrcweir }
1816cdf0e10cSrcweir
1817cdf0e10cSrcweir if (nBinSize != aBinIndexOrder.size())
1818cdf0e10cSrcweir {
1819cdf0e10cSrcweir PushIllegalArgument();
1820cdf0e10cSrcweir return;
1821cdf0e10cSrcweir }
1822cdf0e10cSrcweir
1823cdf0e10cSrcweir SCSIZE j;
1824cdf0e10cSrcweir SCSIZE i = 0;
1825cdf0e10cSrcweir for (j = 0; j < nBinSize; ++j)
1826cdf0e10cSrcweir {
1827cdf0e10cSrcweir SCSIZE nCount = 0;
1828cdf0e10cSrcweir while (i < nDataSize && aDataArray[i] <= aBinArray[j])
1829cdf0e10cSrcweir {
1830cdf0e10cSrcweir ++nCount;
1831cdf0e10cSrcweir ++i;
1832cdf0e10cSrcweir }
1833cdf0e10cSrcweir pResMat->PutDouble(static_cast<double>(nCount), aBinIndexOrder[j]);
1834cdf0e10cSrcweir }
1835cdf0e10cSrcweir pResMat->PutDouble(static_cast<double>(nDataSize-i), j);
1836cdf0e10cSrcweir PushMatrix(pResMat);
1837cdf0e10cSrcweir }
1838cdf0e10cSrcweir
1839cdf0e10cSrcweir // -----------------------------------------------------------------------------
1840cdf0e10cSrcweir // Helper methods for LINEST/LOGEST and TREND/GROWTH
1841cdf0e10cSrcweir // All matrices must already exist and have the needed size, no control tests
1842cdf0e10cSrcweir // done. Those methodes, which names start with lcl_T, are adapted to case 3,
1843cdf0e10cSrcweir // where Y (=observed values) is given as row.
1844cdf0e10cSrcweir // Remember, ScMatrix matrices are zero based, index access (column,row).
1845cdf0e10cSrcweir // -----------------------------------------------------------------------------
1846cdf0e10cSrcweir
1847cdf0e10cSrcweir // Multiply n x m Mat A with m x l Mat B to n x l Mat R
lcl_MFastMult(ScMatrixRef pA,ScMatrixRef pB,ScMatrixRef pR,SCSIZE n,SCSIZE m,SCSIZE l)1848cdf0e10cSrcweir void lcl_MFastMult( ScMatrixRef pA, ScMatrixRef pB, ScMatrixRef pR, SCSIZE n, SCSIZE m, SCSIZE l )
1849cdf0e10cSrcweir {
1850cdf0e10cSrcweir double sum;
1851cdf0e10cSrcweir for (SCSIZE row = 0; row < n; row++)
1852cdf0e10cSrcweir {
1853cdf0e10cSrcweir for (SCSIZE col = 0; col < l; col++)
1854cdf0e10cSrcweir { // result element(col, row) =sum[ (row of A) * (column of B)]
1855cdf0e10cSrcweir sum = 0.0;
1856cdf0e10cSrcweir for (SCSIZE k = 0; k < m; k++)
1857cdf0e10cSrcweir sum += pA->GetDouble(k,row) * pB->GetDouble(col,k);
1858cdf0e10cSrcweir pR->PutDouble(sum, col, row);
1859cdf0e10cSrcweir }
1860cdf0e10cSrcweir }
1861cdf0e10cSrcweir }
1862cdf0e10cSrcweir
1863cdf0e10cSrcweir // <A;B> over all elements; uses the matrices as vectors of length M
lcl_GetSumProduct(ScMatrixRef pMatA,ScMatrixRef pMatB,SCSIZE nM)1864cdf0e10cSrcweir double lcl_GetSumProduct( ScMatrixRef pMatA, ScMatrixRef pMatB, SCSIZE nM )
1865cdf0e10cSrcweir {
1866cdf0e10cSrcweir double fSum = 0.0;
1867cdf0e10cSrcweir for (SCSIZE i=0; i<nM; i++)
1868cdf0e10cSrcweir fSum += pMatA->GetDouble(i) * pMatB->GetDouble(i);
1869cdf0e10cSrcweir return fSum;
1870cdf0e10cSrcweir }
1871cdf0e10cSrcweir
1872cdf0e10cSrcweir // Special version for use within QR decomposition.
1873cdf0e10cSrcweir // Euclidean norm of column index C starting in row index R;
1874cdf0e10cSrcweir // matrix A has count N rows.
lcl_GetColumnEuclideanNorm(ScMatrixRef pMatA,SCSIZE nC,SCSIZE nR,SCSIZE nN)1875cdf0e10cSrcweir double lcl_GetColumnEuclideanNorm( ScMatrixRef pMatA, SCSIZE nC, SCSIZE nR, SCSIZE nN )
1876cdf0e10cSrcweir {
1877cdf0e10cSrcweir double fNorm = 0.0;
1878cdf0e10cSrcweir for (SCSIZE row=nR; row<nN; row++)
1879cdf0e10cSrcweir fNorm += (pMatA->GetDouble(nC,row)) * (pMatA->GetDouble(nC,row));
1880cdf0e10cSrcweir return sqrt(fNorm);
1881cdf0e10cSrcweir }
1882cdf0e10cSrcweir
1883cdf0e10cSrcweir // Euclidean norm of row index R starting in column index C;
1884cdf0e10cSrcweir // matrix A has count N columns.
lcl_TGetColumnEuclideanNorm(ScMatrixRef pMatA,SCSIZE nR,SCSIZE nC,SCSIZE nN)1885cdf0e10cSrcweir double lcl_TGetColumnEuclideanNorm( ScMatrixRef pMatA, SCSIZE nR, SCSIZE nC, SCSIZE nN )
1886cdf0e10cSrcweir {
1887cdf0e10cSrcweir double fNorm = 0.0;
1888cdf0e10cSrcweir for (SCSIZE col=nC; col<nN; col++)
1889cdf0e10cSrcweir fNorm += (pMatA->GetDouble(col,nR)) * (pMatA->GetDouble(col,nR));
1890cdf0e10cSrcweir return sqrt(fNorm);
1891cdf0e10cSrcweir }
1892cdf0e10cSrcweir
1893cdf0e10cSrcweir // Special version for use within QR decomposition.
1894cdf0e10cSrcweir // Maximum norm of column index C starting in row index R;
1895cdf0e10cSrcweir // matrix A has count N rows.
lcl_GetColumnMaximumNorm(ScMatrixRef pMatA,SCSIZE nC,SCSIZE nR,SCSIZE nN)1896cdf0e10cSrcweir double lcl_GetColumnMaximumNorm( ScMatrixRef pMatA, SCSIZE nC, SCSIZE nR, SCSIZE nN )
1897cdf0e10cSrcweir {
1898cdf0e10cSrcweir double fNorm = 0.0;
1899cdf0e10cSrcweir for (SCSIZE row=nR; row<nN; row++)
1900cdf0e10cSrcweir if (fNorm < fabs(pMatA->GetDouble(nC,row)))
1901cdf0e10cSrcweir fNorm = fabs(pMatA->GetDouble(nC,row));
1902cdf0e10cSrcweir return fNorm;
1903cdf0e10cSrcweir }
1904cdf0e10cSrcweir
1905cdf0e10cSrcweir // Maximum norm of row index R starting in col index C;
1906cdf0e10cSrcweir // matrix A has count N columns.
lcl_TGetColumnMaximumNorm(ScMatrixRef pMatA,SCSIZE nR,SCSIZE nC,SCSIZE nN)1907cdf0e10cSrcweir double lcl_TGetColumnMaximumNorm( ScMatrixRef pMatA, SCSIZE nR, SCSIZE nC, SCSIZE nN )
1908cdf0e10cSrcweir {
1909cdf0e10cSrcweir double fNorm = 0.0;
1910cdf0e10cSrcweir for (SCSIZE col=nC; col<nN; col++)
1911cdf0e10cSrcweir if (fNorm < fabs(pMatA->GetDouble(col,nR)))
1912cdf0e10cSrcweir fNorm = fabs(pMatA->GetDouble(col,nR));
1913cdf0e10cSrcweir return fNorm;
1914cdf0e10cSrcweir }
1915cdf0e10cSrcweir
1916cdf0e10cSrcweir // Special version for use within QR decomposition.
1917cdf0e10cSrcweir // <A(Ca);B(Cb)> starting in row index R;
1918cdf0e10cSrcweir // Ca and Cb are indices of columns, matrices A and B have count N rows.
lcl_GetColumnSumProduct(ScMatrixRef pMatA,SCSIZE nCa,ScMatrixRef pMatB,SCSIZE nCb,SCSIZE nR,SCSIZE nN)1919cdf0e10cSrcweir double lcl_GetColumnSumProduct( ScMatrixRef pMatA, SCSIZE nCa, ScMatrixRef pMatB,
1920cdf0e10cSrcweir SCSIZE nCb, SCSIZE nR, SCSIZE nN )
1921cdf0e10cSrcweir {
1922cdf0e10cSrcweir double fResult = 0.0;
1923cdf0e10cSrcweir for (SCSIZE row=nR; row<nN; row++)
1924cdf0e10cSrcweir fResult += pMatA->GetDouble(nCa,row) * pMatB->GetDouble(nCb,row);
1925cdf0e10cSrcweir return fResult;
1926cdf0e10cSrcweir }
1927cdf0e10cSrcweir
1928cdf0e10cSrcweir // <A(Ra);B(Rb)> starting in column index C;
1929cdf0e10cSrcweir // Ra and Rb are indices of rows, matrices A and B have count N columns.
lcl_TGetColumnSumProduct(ScMatrixRef pMatA,SCSIZE nRa,ScMatrixRef pMatB,SCSIZE nRb,SCSIZE nC,SCSIZE nN)1930cdf0e10cSrcweir double lcl_TGetColumnSumProduct( ScMatrixRef pMatA, SCSIZE nRa,
1931cdf0e10cSrcweir ScMatrixRef pMatB, SCSIZE nRb, SCSIZE nC, SCSIZE nN )
1932cdf0e10cSrcweir {
1933cdf0e10cSrcweir double fResult = 0.0;
1934cdf0e10cSrcweir for (SCSIZE col=nC; col<nN; col++)
1935cdf0e10cSrcweir fResult += pMatA->GetDouble(col,nRa) * pMatB->GetDouble(col,nRb);
1936cdf0e10cSrcweir return fResult;
1937cdf0e10cSrcweir }
1938cdf0e10cSrcweir
1939320f78b8SArmin Le Grand // #118029# no mathematical signum, but used to switch between adding and subtracting
lcl_GetSign(double fValue)1940cdf0e10cSrcweir double lcl_GetSign(double fValue)
1941cdf0e10cSrcweir {
1942320f78b8SArmin Le Grand return (fValue >= 0.0 ? 1.0 : -1.0 );
1943cdf0e10cSrcweir }
1944cdf0e10cSrcweir
1945cdf0e10cSrcweir /* Calculates a QR decomposition with Householder reflection.
1946cdf0e10cSrcweir * For each NxK matrix A exists a decomposition A=Q*R with an orthogonal
1947cdf0e10cSrcweir * NxN matrix Q and a NxK matrix R.
1948cdf0e10cSrcweir * Q=H1*H2*...*Hk with Householder matrices H. Such a householder matrix can
1949cdf0e10cSrcweir * be build from a vector u by H=I-(2/u'u)*(u u'). This vectors u are returned
1950cdf0e10cSrcweir * in the columns of matrix A, overwriting the old content.
1951cdf0e10cSrcweir * The matrix R has a quadric upper part KxK with values in the upper right
1952cdf0e10cSrcweir * triangle and zeros in all other elements. Here the diagonal elements of R
1953cdf0e10cSrcweir * are stored in the vector R and the other upper right elements in the upper
1954cdf0e10cSrcweir * right of the matrix A.
1955cdf0e10cSrcweir * The function returns false, if calculation breaks. But because of round-off
1956cdf0e10cSrcweir * errors singularity is often not detected.
1957cdf0e10cSrcweir */
lcl_CalculateQRdecomposition(ScMatrixRef pMatA,::std::vector<double> & pVecR,SCSIZE nK,SCSIZE nN)1958cdf0e10cSrcweir bool lcl_CalculateQRdecomposition(ScMatrixRef pMatA,
1959cdf0e10cSrcweir ::std::vector< double>& pVecR, SCSIZE nK, SCSIZE nN)
1960cdf0e10cSrcweir {
1961cdf0e10cSrcweir double fScale ;
1962cdf0e10cSrcweir double fEuclid ;
1963cdf0e10cSrcweir double fFactor ;
1964cdf0e10cSrcweir double fSignum ;
1965cdf0e10cSrcweir double fSum ;
1966cdf0e10cSrcweir // ScMatrix matrices are zero based, index access (column,row)
1967cdf0e10cSrcweir for (SCSIZE col = 0; col <nK; col++)
1968cdf0e10cSrcweir {
1969cdf0e10cSrcweir // calculate vector u of the householder transformation
1970cdf0e10cSrcweir fScale = lcl_GetColumnMaximumNorm(pMatA, col, col, nN);
1971cdf0e10cSrcweir if (fScale == 0.0)
1972cdf0e10cSrcweir // A is singular
1973cdf0e10cSrcweir return false;
1974cdf0e10cSrcweir
1975cdf0e10cSrcweir for (SCSIZE row = col; row <nN; row++)
1976cdf0e10cSrcweir pMatA->PutDouble( pMatA->GetDouble(col,row)/fScale, col, row);
1977cdf0e10cSrcweir
1978cdf0e10cSrcweir fEuclid = lcl_GetColumnEuclideanNorm(pMatA, col, col, nN);
1979cdf0e10cSrcweir fFactor = 1.0/fEuclid/(fEuclid + fabs(pMatA->GetDouble(col,col)));
1980cdf0e10cSrcweir fSignum = lcl_GetSign(pMatA->GetDouble(col,col));
1981cdf0e10cSrcweir pMatA->PutDouble( pMatA->GetDouble(col,col) + fSignum*fEuclid, col,col);
1982cdf0e10cSrcweir pVecR[col] = -fSignum * fScale * fEuclid;
1983cdf0e10cSrcweir
1984cdf0e10cSrcweir // apply Householder transformation to A
1985cdf0e10cSrcweir for (SCSIZE c=col+1; c<nK; c++)
1986cdf0e10cSrcweir {
1987cdf0e10cSrcweir fSum =lcl_GetColumnSumProduct(pMatA, col, pMatA, c, col, nN);
1988cdf0e10cSrcweir for (SCSIZE row = col; row <nN; row++)
1989cdf0e10cSrcweir pMatA->PutDouble( pMatA->GetDouble(c,row)
1990cdf0e10cSrcweir - fSum * fFactor * pMatA->GetDouble(col,row), c, row);
1991cdf0e10cSrcweir }
1992cdf0e10cSrcweir }
1993cdf0e10cSrcweir return true;
1994cdf0e10cSrcweir }
1995cdf0e10cSrcweir
1996cdf0e10cSrcweir // same with transposed matrix A, N is count of columns, K count of rows
lcl_TCalculateQRdecomposition(ScMatrixRef pMatA,::std::vector<double> & pVecR,SCSIZE nK,SCSIZE nN)1997cdf0e10cSrcweir bool lcl_TCalculateQRdecomposition(ScMatrixRef pMatA,
1998cdf0e10cSrcweir ::std::vector< double>& pVecR, SCSIZE nK, SCSIZE nN)
1999cdf0e10cSrcweir {
2000cdf0e10cSrcweir double fScale ;
2001cdf0e10cSrcweir double fEuclid ;
2002cdf0e10cSrcweir double fFactor ;
2003cdf0e10cSrcweir double fSignum ;
2004cdf0e10cSrcweir double fSum ;
2005cdf0e10cSrcweir // ScMatrix matrices are zero based, index access (column,row)
2006cdf0e10cSrcweir for (SCSIZE row = 0; row <nK; row++)
2007cdf0e10cSrcweir {
2008cdf0e10cSrcweir // calculate vector u of the householder transformation
2009cdf0e10cSrcweir fScale = lcl_TGetColumnMaximumNorm(pMatA, row, row, nN);
2010cdf0e10cSrcweir if (fScale == 0.0)
2011cdf0e10cSrcweir // A is singular
2012cdf0e10cSrcweir return false;
2013cdf0e10cSrcweir
2014cdf0e10cSrcweir for (SCSIZE col = row; col <nN; col++)
2015cdf0e10cSrcweir pMatA->PutDouble( pMatA->GetDouble(col,row)/fScale, col, row);
2016cdf0e10cSrcweir
2017cdf0e10cSrcweir fEuclid = lcl_TGetColumnEuclideanNorm(pMatA, row, row, nN);
2018cdf0e10cSrcweir fFactor = 1.0/fEuclid/(fEuclid + fabs(pMatA->GetDouble(row,row)));
2019cdf0e10cSrcweir fSignum = lcl_GetSign(pMatA->GetDouble(row,row));
2020cdf0e10cSrcweir pMatA->PutDouble( pMatA->GetDouble(row,row) + fSignum*fEuclid, row,row);
2021cdf0e10cSrcweir pVecR[row] = -fSignum * fScale * fEuclid;
2022cdf0e10cSrcweir
2023cdf0e10cSrcweir // apply Householder transformation to A
2024cdf0e10cSrcweir for (SCSIZE r=row+1; r<nK; r++)
2025cdf0e10cSrcweir {
2026cdf0e10cSrcweir fSum =lcl_TGetColumnSumProduct(pMatA, row, pMatA, r, row, nN);
2027cdf0e10cSrcweir for (SCSIZE col = row; col <nN; col++)
2028cdf0e10cSrcweir pMatA->PutDouble( pMatA->GetDouble(col,r)
2029cdf0e10cSrcweir - fSum * fFactor * pMatA->GetDouble(col,row), col, r);
2030cdf0e10cSrcweir }
2031cdf0e10cSrcweir }
2032cdf0e10cSrcweir return true;
2033cdf0e10cSrcweir }
2034cdf0e10cSrcweir
2035cdf0e10cSrcweir
2036cdf0e10cSrcweir /* Applies a Householder transformation to a column vector Y with is given as
2037cdf0e10cSrcweir * Nx1 Matrix. The Vektor u, from which the Householder transformation is build,
2038cdf0e10cSrcweir * is the column part in matrix A, with column index C, starting with row
2039cdf0e10cSrcweir * index C. A is the result of the QR decomposition as obtained from
2040cdf0e10cSrcweir * lcl_CaluclateQRdecomposition.
2041cdf0e10cSrcweir */
lcl_ApplyHouseholderTransformation(ScMatrixRef pMatA,SCSIZE nC,ScMatrixRef pMatY,SCSIZE nN)2042cdf0e10cSrcweir void lcl_ApplyHouseholderTransformation(ScMatrixRef pMatA, SCSIZE nC,
2043cdf0e10cSrcweir ScMatrixRef pMatY, SCSIZE nN)
2044cdf0e10cSrcweir {
2045cdf0e10cSrcweir // ScMatrix matrices are zero based, index access (column,row)
2046cdf0e10cSrcweir double fDenominator = lcl_GetColumnSumProduct(pMatA, nC, pMatA, nC, nC, nN);
2047cdf0e10cSrcweir double fNumerator = lcl_GetColumnSumProduct(pMatA, nC, pMatY, 0, nC, nN);
2048cdf0e10cSrcweir double fFactor = 2.0 * (fNumerator/fDenominator);
2049cdf0e10cSrcweir for (SCSIZE row = nC; row < nN; row++)
2050cdf0e10cSrcweir pMatY->PutDouble(
2051cdf0e10cSrcweir pMatY->GetDouble(row) - fFactor * pMatA->GetDouble(nC,row), row);
2052cdf0e10cSrcweir }
2053cdf0e10cSrcweir
2054cdf0e10cSrcweir // Same with transposed matrices A and Y.
lcl_TApplyHouseholderTransformation(ScMatrixRef pMatA,SCSIZE nR,ScMatrixRef pMatY,SCSIZE nN)2055cdf0e10cSrcweir void lcl_TApplyHouseholderTransformation(ScMatrixRef pMatA, SCSIZE nR,
2056cdf0e10cSrcweir ScMatrixRef pMatY, SCSIZE nN)
2057cdf0e10cSrcweir {
2058cdf0e10cSrcweir // ScMatrix matrices are zero based, index access (column,row)
2059cdf0e10cSrcweir double fDenominator = lcl_TGetColumnSumProduct(pMatA, nR, pMatA, nR, nR, nN);
2060cdf0e10cSrcweir double fNumerator = lcl_TGetColumnSumProduct(pMatA, nR, pMatY, 0, nR, nN);
2061cdf0e10cSrcweir double fFactor = 2.0 * (fNumerator/fDenominator);
2062cdf0e10cSrcweir for (SCSIZE col = nR; col < nN; col++)
2063cdf0e10cSrcweir pMatY->PutDouble(
2064cdf0e10cSrcweir pMatY->GetDouble(col) - fFactor * pMatA->GetDouble(col,nR), col);
2065cdf0e10cSrcweir }
2066cdf0e10cSrcweir
2067cdf0e10cSrcweir /* Solve for X in R*X=S using back substitution. The solution X overwrites S.
2068cdf0e10cSrcweir * Uses R from the result of the QR decomposition of a NxK matrix A.
2069cdf0e10cSrcweir * S is a column vector given as matrix, with at least elements on index
2070cdf0e10cSrcweir * 0 to K-1; elements on index>=K are ignored. Vector R must not have zero
2071cdf0e10cSrcweir * elements, no check is done.
2072cdf0e10cSrcweir */
lcl_SolveWithUpperRightTriangle(ScMatrixRef pMatA,::std::vector<double> & pVecR,ScMatrixRef pMatS,SCSIZE nK,bool bIsTransposed)2073cdf0e10cSrcweir void lcl_SolveWithUpperRightTriangle(ScMatrixRef pMatA,
2074cdf0e10cSrcweir ::std::vector< double>& pVecR, ScMatrixRef pMatS,
2075cdf0e10cSrcweir SCSIZE nK, bool bIsTransposed)
2076cdf0e10cSrcweir {
2077cdf0e10cSrcweir // ScMatrix matrices are zero based, index access (column,row)
2078cdf0e10cSrcweir double fSum;
2079cdf0e10cSrcweir SCSIZE row;
2080cdf0e10cSrcweir // SCSIZE is never negative, therefore test with rowp1=row+1
2081cdf0e10cSrcweir for (SCSIZE rowp1 = nK; rowp1>0; rowp1--)
2082cdf0e10cSrcweir {
2083cdf0e10cSrcweir row = rowp1-1;
2084cdf0e10cSrcweir fSum = pMatS->GetDouble(row);
2085cdf0e10cSrcweir for (SCSIZE col = rowp1; col<nK ; col++)
2086cdf0e10cSrcweir if (bIsTransposed)
2087cdf0e10cSrcweir fSum -= pMatA->GetDouble(row,col) * pMatS->GetDouble(col);
2088cdf0e10cSrcweir else
2089cdf0e10cSrcweir fSum -= pMatA->GetDouble(col,row) * pMatS->GetDouble(col);
2090cdf0e10cSrcweir pMatS->PutDouble( fSum / pVecR[row] , row);
2091cdf0e10cSrcweir }
2092cdf0e10cSrcweir }
2093cdf0e10cSrcweir
2094cdf0e10cSrcweir /* Solve for X in R' * X= T using forward substitution. The solution X
2095cdf0e10cSrcweir * overwrites T. Uses R from the result of the QR decomposition of a NxK
2096cdf0e10cSrcweir * matrix A. T is a column vectors given as matrix, with at least elements on
2097cdf0e10cSrcweir * index 0 to K-1; elements on index>=K are ignored. Vector R must not have
2098cdf0e10cSrcweir * zero elements, no check is done.
2099cdf0e10cSrcweir */
lcl_SolveWithLowerLeftTriangle(ScMatrixRef pMatA,::std::vector<double> & pVecR,ScMatrixRef pMatT,SCSIZE nK,bool bIsTransposed)2100cdf0e10cSrcweir void lcl_SolveWithLowerLeftTriangle(ScMatrixRef pMatA,
2101cdf0e10cSrcweir ::std::vector< double>& pVecR, ScMatrixRef pMatT,
2102cdf0e10cSrcweir SCSIZE nK, bool bIsTransposed)
2103cdf0e10cSrcweir {
2104cdf0e10cSrcweir // ScMatrix matrices are zero based, index access (column,row)
2105cdf0e10cSrcweir double fSum;
2106cdf0e10cSrcweir for (SCSIZE row = 0; row < nK; row++)
2107cdf0e10cSrcweir {
2108cdf0e10cSrcweir fSum = pMatT -> GetDouble(row);
2109cdf0e10cSrcweir for (SCSIZE col=0; col < row; col++)
2110cdf0e10cSrcweir {
2111cdf0e10cSrcweir if (bIsTransposed)
2112cdf0e10cSrcweir fSum -= pMatA->GetDouble(col,row) * pMatT->GetDouble(col);
2113cdf0e10cSrcweir else
2114cdf0e10cSrcweir fSum -= pMatA->GetDouble(row,col) * pMatT->GetDouble(col);
2115cdf0e10cSrcweir }
2116cdf0e10cSrcweir pMatT->PutDouble( fSum / pVecR[row] , row);
2117cdf0e10cSrcweir }
2118cdf0e10cSrcweir }
2119cdf0e10cSrcweir
2120cdf0e10cSrcweir /* Calculates Z = R * B
2121cdf0e10cSrcweir * R is given in matrix A and vector VecR as obtained from the QR
2122cdf0e10cSrcweir * decompostion in lcl_CalculateQRdecomposition. B and Z are column vectors
2123cdf0e10cSrcweir * given as matrix with at least index 0 to K-1; elements on index>=K are
2124cdf0e10cSrcweir * not used.
2125cdf0e10cSrcweir */
lcl_ApplyUpperRightTriangle(ScMatrixRef pMatA,::std::vector<double> & pVecR,ScMatrixRef pMatB,ScMatrixRef pMatZ,SCSIZE nK,bool bIsTransposed)2126cdf0e10cSrcweir void lcl_ApplyUpperRightTriangle(ScMatrixRef pMatA,
2127cdf0e10cSrcweir ::std::vector< double>& pVecR, ScMatrixRef pMatB,
2128cdf0e10cSrcweir ScMatrixRef pMatZ, SCSIZE nK, bool bIsTransposed)
2129cdf0e10cSrcweir {
2130cdf0e10cSrcweir // ScMatrix matrices are zero based, index access (column,row)
2131cdf0e10cSrcweir double fSum;
2132cdf0e10cSrcweir for (SCSIZE row = 0; row < nK; row++)
2133cdf0e10cSrcweir {
2134cdf0e10cSrcweir fSum = pVecR[row] * pMatB->GetDouble(row);
2135cdf0e10cSrcweir for (SCSIZE col = row+1; col < nK; col++)
2136cdf0e10cSrcweir if (bIsTransposed)
2137cdf0e10cSrcweir fSum += pMatA->GetDouble(row,col) * pMatB->GetDouble(col);
2138cdf0e10cSrcweir else
2139cdf0e10cSrcweir fSum += pMatA->GetDouble(col,row) * pMatB->GetDouble(col);
2140cdf0e10cSrcweir pMatZ->PutDouble( fSum, row);
2141cdf0e10cSrcweir }
2142cdf0e10cSrcweir }
2143cdf0e10cSrcweir
2144cdf0e10cSrcweir
2145cdf0e10cSrcweir
lcl_GetMeanOverAll(ScMatrixRef pMat,SCSIZE nN)2146cdf0e10cSrcweir double lcl_GetMeanOverAll(ScMatrixRef pMat, SCSIZE nN)
2147cdf0e10cSrcweir {
2148cdf0e10cSrcweir double fSum = 0.0;
2149cdf0e10cSrcweir for (SCSIZE i=0 ; i<nN; i++)
2150cdf0e10cSrcweir fSum += pMat->GetDouble(i);
2151cdf0e10cSrcweir return fSum/static_cast<double>(nN);
2152cdf0e10cSrcweir }
2153cdf0e10cSrcweir
2154cdf0e10cSrcweir // Calculates means of the columns of matrix X. X is a RxC matrix;
2155cdf0e10cSrcweir // ResMat is a 1xC matrix (=row).
lcl_CalculateColumnMeans(ScMatrixRef pX,ScMatrixRef pResMat,SCSIZE nC,SCSIZE nR)2156cdf0e10cSrcweir void lcl_CalculateColumnMeans(ScMatrixRef pX, ScMatrixRef pResMat,
2157cdf0e10cSrcweir SCSIZE nC, SCSIZE nR)
2158cdf0e10cSrcweir {
2159cdf0e10cSrcweir double fSum = 0.0;
2160cdf0e10cSrcweir for (SCSIZE i=0; i < nC; i++)
2161cdf0e10cSrcweir {
2162cdf0e10cSrcweir fSum =0.0;
2163cdf0e10cSrcweir for (SCSIZE k=0; k < nR; k++)
2164cdf0e10cSrcweir fSum += pX->GetDouble(i,k); // GetDouble(Column,Row)
2165cdf0e10cSrcweir pResMat ->PutDouble( fSum/static_cast<double>(nR),i);
2166cdf0e10cSrcweir }
2167cdf0e10cSrcweir }
2168cdf0e10cSrcweir
2169cdf0e10cSrcweir // Calculates means of the rows of matrix X. X is a RxC matrix;
2170cdf0e10cSrcweir // ResMat is a Rx1 matrix (=column).
lcl_CalculateRowMeans(ScMatrixRef pX,ScMatrixRef pResMat,SCSIZE nC,SCSIZE nR)2171cdf0e10cSrcweir void lcl_CalculateRowMeans(ScMatrixRef pX, ScMatrixRef pResMat,
2172cdf0e10cSrcweir SCSIZE nC, SCSIZE nR)
2173cdf0e10cSrcweir {
2174cdf0e10cSrcweir double fSum = 0.0;
2175cdf0e10cSrcweir for (SCSIZE k=0; k < nR; k++)
2176cdf0e10cSrcweir {
2177cdf0e10cSrcweir fSum =0.0;
2178cdf0e10cSrcweir for (SCSIZE i=0; i < nC; i++)
2179cdf0e10cSrcweir fSum += pX->GetDouble(i,k); // GetDouble(Column,Row)
2180cdf0e10cSrcweir pResMat ->PutDouble( fSum/static_cast<double>(nC),k);
2181cdf0e10cSrcweir }
2182cdf0e10cSrcweir }
2183cdf0e10cSrcweir
lcl_CalculateColumnsDelta(ScMatrixRef pMat,ScMatrixRef pColumnMeans,SCSIZE nC,SCSIZE nR)2184cdf0e10cSrcweir void lcl_CalculateColumnsDelta(ScMatrixRef pMat, ScMatrixRef pColumnMeans,
2185cdf0e10cSrcweir SCSIZE nC, SCSIZE nR)
2186cdf0e10cSrcweir {
2187cdf0e10cSrcweir for (SCSIZE i = 0; i < nC; i++)
2188cdf0e10cSrcweir for (SCSIZE k = 0; k < nR; k++)
2189cdf0e10cSrcweir pMat->PutDouble( ::rtl::math::approxSub
2190cdf0e10cSrcweir (pMat->GetDouble(i,k) , pColumnMeans->GetDouble(i) ) , i, k);
2191cdf0e10cSrcweir }
2192cdf0e10cSrcweir
lcl_CalculateRowsDelta(ScMatrixRef pMat,ScMatrixRef pRowMeans,SCSIZE nC,SCSIZE nR)2193cdf0e10cSrcweir void lcl_CalculateRowsDelta(ScMatrixRef pMat, ScMatrixRef pRowMeans,
2194cdf0e10cSrcweir SCSIZE nC, SCSIZE nR)
2195cdf0e10cSrcweir {
2196cdf0e10cSrcweir for (SCSIZE k = 0; k < nR; k++)
2197cdf0e10cSrcweir for (SCSIZE i = 0; i < nC; i++)
2198cdf0e10cSrcweir pMat->PutDouble( ::rtl::math::approxSub
2199cdf0e10cSrcweir ( pMat->GetDouble(i,k) , pRowMeans->GetDouble(k) ) , i, k);
2200cdf0e10cSrcweir }
2201cdf0e10cSrcweir
2202cdf0e10cSrcweir // Case1 = simple regression
2203cdf0e10cSrcweir // MatX = X - MeanX, MatY = Y - MeanY, y - haty = (y - MeanY) - (haty - MeanY)
2204cdf0e10cSrcweir // = (y-MeanY)-((slope*x+a)-(slope*MeanX+a)) = (y-MeanY)-slope*(x-MeanX)
lcl_GetSSresid(ScMatrixRef pMatX,ScMatrixRef pMatY,double fSlope,SCSIZE nN)2205cdf0e10cSrcweir double lcl_GetSSresid(ScMatrixRef pMatX, ScMatrixRef pMatY, double fSlope,
2206cdf0e10cSrcweir SCSIZE nN)
2207cdf0e10cSrcweir {
2208cdf0e10cSrcweir double fSum = 0.0;
2209cdf0e10cSrcweir double fTemp = 0.0;
2210cdf0e10cSrcweir for (SCSIZE i=0; i<nN; i++)
2211cdf0e10cSrcweir {
2212cdf0e10cSrcweir fTemp = pMatY->GetDouble(i) - fSlope * pMatX->GetDouble(i);
2213cdf0e10cSrcweir fSum += fTemp * fTemp;
2214cdf0e10cSrcweir }
2215cdf0e10cSrcweir return fSum;
2216cdf0e10cSrcweir }
2217cdf0e10cSrcweir
2218cdf0e10cSrcweir // Fill default values in matrix X, transform Y to log(Y) in case LOGEST|GROWTH,
2219cdf0e10cSrcweir // determine sizes of matrices X and Y, determine kind of regression, clone
2220cdf0e10cSrcweir // Y in case LOGEST|GROWTH, if constant.
CheckMatrix(bool _bLOG,sal_uInt8 & nCase,SCSIZE & nCX,SCSIZE & nCY,SCSIZE & nRX,SCSIZE & nRY,SCSIZE & M,SCSIZE & N,ScMatrixRef & pMatX,ScMatrixRef & pMatY)2221cdf0e10cSrcweir bool ScInterpreter::CheckMatrix(bool _bLOG, sal_uInt8& nCase, SCSIZE& nCX,
2222cdf0e10cSrcweir SCSIZE& nCY, SCSIZE& nRX, SCSIZE& nRY, SCSIZE& M,
2223cdf0e10cSrcweir SCSIZE& N, ScMatrixRef& pMatX, ScMatrixRef& pMatY)
2224cdf0e10cSrcweir {
2225cdf0e10cSrcweir
2226cdf0e10cSrcweir nCX = 0;
2227cdf0e10cSrcweir nCY = 0;
2228cdf0e10cSrcweir nRX = 0;
2229cdf0e10cSrcweir nRY = 0;
2230cdf0e10cSrcweir M = 0;
2231cdf0e10cSrcweir N = 0;
2232cdf0e10cSrcweir pMatY->GetDimensions(nCY, nRY);
2233cdf0e10cSrcweir const SCSIZE nCountY = nCY * nRY;
2234cdf0e10cSrcweir for ( SCSIZE i = 0; i < nCountY; i++ )
2235cdf0e10cSrcweir {
2236cdf0e10cSrcweir if (!pMatY->IsValue(i))
2237cdf0e10cSrcweir {
2238cdf0e10cSrcweir PushIllegalArgument();
2239cdf0e10cSrcweir return false;
2240cdf0e10cSrcweir }
2241cdf0e10cSrcweir }
2242cdf0e10cSrcweir
2243cdf0e10cSrcweir if ( _bLOG )
2244cdf0e10cSrcweir {
2245cdf0e10cSrcweir ScMatrixRef pNewY = pMatY->CloneIfConst();
2246cdf0e10cSrcweir for (SCSIZE nElem = 0; nElem < nCountY; nElem++)
2247cdf0e10cSrcweir {
2248cdf0e10cSrcweir const double fVal = pNewY->GetDouble(nElem);
2249cdf0e10cSrcweir if (fVal <= 0.0)
2250cdf0e10cSrcweir {
2251cdf0e10cSrcweir PushIllegalArgument();
2252cdf0e10cSrcweir return false;
2253cdf0e10cSrcweir }
2254cdf0e10cSrcweir else
2255cdf0e10cSrcweir pNewY->PutDouble(log(fVal), nElem);
2256cdf0e10cSrcweir }
2257cdf0e10cSrcweir pMatY = pNewY;
2258cdf0e10cSrcweir }
2259cdf0e10cSrcweir
2260cdf0e10cSrcweir if (pMatX)
2261cdf0e10cSrcweir {
2262cdf0e10cSrcweir pMatX->GetDimensions(nCX, nRX);
2263cdf0e10cSrcweir const SCSIZE nCountX = nCX * nRX;
2264cdf0e10cSrcweir for ( SCSIZE i = 0; i < nCountX; i++ )
2265cdf0e10cSrcweir if (!pMatX->IsValue(i))
2266cdf0e10cSrcweir {
2267cdf0e10cSrcweir PushIllegalArgument();
2268cdf0e10cSrcweir return false;
2269cdf0e10cSrcweir }
2270cdf0e10cSrcweir if (nCX == nCY && nRX == nRY)
2271cdf0e10cSrcweir {
2272cdf0e10cSrcweir nCase = 1; // simple regression
2273cdf0e10cSrcweir M = 1;
2274cdf0e10cSrcweir N = nCountY;
2275cdf0e10cSrcweir }
2276cdf0e10cSrcweir else if (nCY != 1 && nRY != 1)
2277cdf0e10cSrcweir {
2278cdf0e10cSrcweir PushIllegalArgument();
2279cdf0e10cSrcweir return false;
2280cdf0e10cSrcweir }
2281cdf0e10cSrcweir else if (nCY == 1)
2282cdf0e10cSrcweir {
2283cdf0e10cSrcweir if (nRX != nRY)
2284cdf0e10cSrcweir {
2285cdf0e10cSrcweir PushIllegalArgument();
2286cdf0e10cSrcweir return false;
2287cdf0e10cSrcweir }
2288cdf0e10cSrcweir else
2289cdf0e10cSrcweir {
2290cdf0e10cSrcweir nCase = 2; // Y is column
2291cdf0e10cSrcweir N = nRY;
2292cdf0e10cSrcweir M = nCX;
2293cdf0e10cSrcweir }
2294cdf0e10cSrcweir }
2295cdf0e10cSrcweir else if (nCX != nCY)
2296cdf0e10cSrcweir {
2297cdf0e10cSrcweir PushIllegalArgument();
2298cdf0e10cSrcweir return false;
2299cdf0e10cSrcweir }
2300cdf0e10cSrcweir else
2301cdf0e10cSrcweir {
2302cdf0e10cSrcweir nCase = 3; // Y is row
2303cdf0e10cSrcweir N = nCY;
2304cdf0e10cSrcweir M = nRX;
2305cdf0e10cSrcweir }
2306cdf0e10cSrcweir }
2307cdf0e10cSrcweir else
2308cdf0e10cSrcweir {
2309cdf0e10cSrcweir pMatX = GetNewMat(nCY, nRY);
2310cdf0e10cSrcweir nCX = nCY;
2311cdf0e10cSrcweir nRX = nRY;
2312cdf0e10cSrcweir if (!pMatX)
2313cdf0e10cSrcweir {
2314cdf0e10cSrcweir PushIllegalArgument();
2315cdf0e10cSrcweir return false;
2316cdf0e10cSrcweir }
2317cdf0e10cSrcweir for ( SCSIZE i = 1; i <= nCountY; i++ )
2318cdf0e10cSrcweir pMatX->PutDouble(static_cast<double>(i), i-1);
2319cdf0e10cSrcweir nCase = 1;
2320cdf0e10cSrcweir N = nCountY;
2321cdf0e10cSrcweir M = 1;
2322cdf0e10cSrcweir }
2323cdf0e10cSrcweir return true;
2324cdf0e10cSrcweir }
2325cdf0e10cSrcweir // -----------------------------------------------------------------------------
2326cdf0e10cSrcweir
2327cdf0e10cSrcweir // LINEST
ScRGP()2328cdf0e10cSrcweir void ScInterpreter::ScRGP()
2329cdf0e10cSrcweir {
2330cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScRGP" );
2331cdf0e10cSrcweir CalulateRGPRKP(false);
2332cdf0e10cSrcweir }
2333cdf0e10cSrcweir
2334cdf0e10cSrcweir // LOGEST
ScRKP()2335cdf0e10cSrcweir void ScInterpreter::ScRKP()
2336cdf0e10cSrcweir {
2337cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScRKP" );
2338cdf0e10cSrcweir CalulateRGPRKP(true);
2339cdf0e10cSrcweir }
2340cdf0e10cSrcweir
CalulateRGPRKP(bool _bRKP)2341cdf0e10cSrcweir void ScInterpreter::CalulateRGPRKP(bool _bRKP)
2342cdf0e10cSrcweir {
2343cdf0e10cSrcweir sal_uInt8 nParamCount = GetByte();
2344cdf0e10cSrcweir if ( !MustHaveParamCount( nParamCount, 1, 4 ) )
2345cdf0e10cSrcweir return;
2346cdf0e10cSrcweir bool bConstant, bStats;
2347cdf0e10cSrcweir
2348cdf0e10cSrcweir // optional forth parameter
2349cdf0e10cSrcweir if (nParamCount == 4)
2350cdf0e10cSrcweir bStats = GetBool();
2351cdf0e10cSrcweir else
2352cdf0e10cSrcweir bStats = false;
2353cdf0e10cSrcweir
2354cdf0e10cSrcweir // The third parameter may not be missing in ODF, if the forth parameter
2355cdf0e10cSrcweir // is present. But Excel allows it with default true, we too.
2356cdf0e10cSrcweir if (nParamCount >= 3)
2357cdf0e10cSrcweir {
2358cdf0e10cSrcweir if (IsMissing())
2359cdf0e10cSrcweir {
2360cdf0e10cSrcweir Pop();
2361cdf0e10cSrcweir bConstant = true;
2362cdf0e10cSrcweir // PushIllegalParameter(); if ODF behavior is desired
2363cdf0e10cSrcweir // return;
2364cdf0e10cSrcweir }
2365cdf0e10cSrcweir else
2366cdf0e10cSrcweir bConstant = GetBool();
2367cdf0e10cSrcweir }
2368cdf0e10cSrcweir else
2369cdf0e10cSrcweir bConstant = true;
2370cdf0e10cSrcweir
2371cdf0e10cSrcweir ScMatrixRef pMatX;
2372cdf0e10cSrcweir if (nParamCount >= 2)
2373cdf0e10cSrcweir {
2374cdf0e10cSrcweir if (IsMissing())
2375cdf0e10cSrcweir {
2376cdf0e10cSrcweir // In ODF1.2 empty second parameter (which is two ;; ) is allowed
2377cdf0e10cSrcweir Pop();
2378cdf0e10cSrcweir pMatX = NULL;
2379cdf0e10cSrcweir }
2380cdf0e10cSrcweir else
2381cdf0e10cSrcweir {
2382cdf0e10cSrcweir pMatX = GetMatrix();
2383cdf0e10cSrcweir }
2384cdf0e10cSrcweir }
2385cdf0e10cSrcweir else
2386cdf0e10cSrcweir pMatX = NULL;
2387cdf0e10cSrcweir
2388cdf0e10cSrcweir ScMatrixRef pMatY;
2389cdf0e10cSrcweir pMatY = GetMatrix();
2390cdf0e10cSrcweir if (!pMatY)
2391cdf0e10cSrcweir {
2392cdf0e10cSrcweir PushIllegalParameter();
2393cdf0e10cSrcweir return;
2394cdf0e10cSrcweir }
2395cdf0e10cSrcweir
2396cdf0e10cSrcweir // 1 = simple; 2 = multiple with Y as column; 3 = multiple with Y as row
2397cdf0e10cSrcweir sal_uInt8 nCase;
2398cdf0e10cSrcweir
2399cdf0e10cSrcweir SCSIZE nCX, nCY; // number of columns
2400cdf0e10cSrcweir SCSIZE nRX, nRY; // number of rows
2401cdf0e10cSrcweir SCSIZE K = 0, N = 0; // K=number of variables X, N=number of data samples
2402cdf0e10cSrcweir if ( !CheckMatrix(_bRKP,nCase,nCX,nCY,nRX,nRY,K,N,pMatX,pMatY) )
2403cdf0e10cSrcweir {
2404cdf0e10cSrcweir PushIllegalParameter();
2405cdf0e10cSrcweir return;
2406cdf0e10cSrcweir }
2407cdf0e10cSrcweir
2408cdf0e10cSrcweir // Enough data samples?
2409cdf0e10cSrcweir if ( (bConstant && (N<K+1)) || (!bConstant && (N<K)) || (N<1) || (K<1) )
2410cdf0e10cSrcweir {
2411cdf0e10cSrcweir PushIllegalParameter();
2412cdf0e10cSrcweir return;
2413cdf0e10cSrcweir }
2414cdf0e10cSrcweir
2415cdf0e10cSrcweir ScMatrixRef pResMat;
2416cdf0e10cSrcweir if (bStats)
2417cdf0e10cSrcweir pResMat = GetNewMat(K+1,5);
2418cdf0e10cSrcweir else
2419cdf0e10cSrcweir pResMat = GetNewMat(K+1,1);
2420cdf0e10cSrcweir if (!pResMat)
2421cdf0e10cSrcweir {
2422cdf0e10cSrcweir PushError(errCodeOverflow);
2423cdf0e10cSrcweir return;
2424cdf0e10cSrcweir }
2425cdf0e10cSrcweir // Fill unused cells in pResMat; order (column,row)
2426cdf0e10cSrcweir if (bStats)
2427cdf0e10cSrcweir {
2428cdf0e10cSrcweir for (SCSIZE i=2; i<K+1; i++)
2429cdf0e10cSrcweir {
2430cdf0e10cSrcweir pResMat->PutString(ScGlobal::GetRscString(STR_NV_STR), i, 2 );
2431cdf0e10cSrcweir pResMat->PutString(ScGlobal::GetRscString(STR_NV_STR), i, 3 );
2432cdf0e10cSrcweir pResMat->PutString(ScGlobal::GetRscString(STR_NV_STR), i, 4 );
2433cdf0e10cSrcweir }
2434cdf0e10cSrcweir }
2435cdf0e10cSrcweir
2436cdf0e10cSrcweir // Uses sum(x-MeanX)^2 and not [sum x^2]-N * MeanX^2 in case bConstant.
2437cdf0e10cSrcweir // Clone constant matrices, so that Mat = Mat - Mean is possible.
2438cdf0e10cSrcweir double fMeanY = 0.0;
2439cdf0e10cSrcweir if (bConstant)
2440cdf0e10cSrcweir {
2441cdf0e10cSrcweir ScMatrixRef pNewX = pMatX->CloneIfConst();
2442cdf0e10cSrcweir ScMatrixRef pNewY = pMatY->CloneIfConst();
2443cdf0e10cSrcweir if (!pNewX || !pNewY)
2444cdf0e10cSrcweir {
2445cdf0e10cSrcweir PushError(errCodeOverflow);
2446cdf0e10cSrcweir return;
2447cdf0e10cSrcweir }
2448cdf0e10cSrcweir pMatX = pNewX;
2449cdf0e10cSrcweir pMatY = pNewY;
2450cdf0e10cSrcweir // DeltaY is possible here; DeltaX depends on nCase, so later
2451cdf0e10cSrcweir fMeanY = lcl_GetMeanOverAll(pMatY, N);
2452cdf0e10cSrcweir for (SCSIZE i=0; i<N; i++)
2453cdf0e10cSrcweir {
2454cdf0e10cSrcweir pMatY->PutDouble( ::rtl::math::approxSub(pMatY->GetDouble(i),fMeanY), i );
2455cdf0e10cSrcweir }
2456cdf0e10cSrcweir }
2457cdf0e10cSrcweir
2458cdf0e10cSrcweir if (nCase==1)
2459cdf0e10cSrcweir {
2460cdf0e10cSrcweir // calculate simple regression
2461cdf0e10cSrcweir double fMeanX = 0.0;
2462cdf0e10cSrcweir if (bConstant)
2463cdf0e10cSrcweir { // Mat = Mat - Mean
2464cdf0e10cSrcweir fMeanX = lcl_GetMeanOverAll(pMatX, N);
2465cdf0e10cSrcweir for (SCSIZE i=0; i<N; i++)
2466cdf0e10cSrcweir {
2467cdf0e10cSrcweir pMatX->PutDouble( ::rtl::math::approxSub(pMatX->GetDouble(i),fMeanX), i );
2468cdf0e10cSrcweir }
2469cdf0e10cSrcweir }
2470cdf0e10cSrcweir double fSumXY = lcl_GetSumProduct(pMatX,pMatY,N);
2471cdf0e10cSrcweir double fSumX2 = lcl_GetSumProduct(pMatX,pMatX,N);
2472cdf0e10cSrcweir if (fSumX2==0.0)
2473cdf0e10cSrcweir {
2474cdf0e10cSrcweir PushNoValue(); // all x-values are identical
2475cdf0e10cSrcweir return;
2476cdf0e10cSrcweir }
2477cdf0e10cSrcweir double fSlope = fSumXY / fSumX2;
2478cdf0e10cSrcweir double fIntercept = 0.0;
2479cdf0e10cSrcweir if (bConstant)
2480cdf0e10cSrcweir fIntercept = fMeanY - fSlope * fMeanX;
2481cdf0e10cSrcweir pResMat->PutDouble(_bRKP ? exp(fIntercept) : fIntercept, 1, 0); //order (column,row)
2482cdf0e10cSrcweir pResMat->PutDouble(_bRKP ? exp(fSlope) : fSlope, 0, 0);
2483cdf0e10cSrcweir
2484cdf0e10cSrcweir if (bStats)
2485cdf0e10cSrcweir {
2486cdf0e10cSrcweir double fSSreg = fSlope * fSlope * fSumX2;
2487cdf0e10cSrcweir pResMat->PutDouble(fSSreg, 0, 4);
2488cdf0e10cSrcweir
2489cdf0e10cSrcweir double fDegreesFreedom =static_cast<double>( (bConstant) ? N-2 : N-1 );
2490cdf0e10cSrcweir pResMat->PutDouble(fDegreesFreedom, 1, 3);
2491cdf0e10cSrcweir
2492cdf0e10cSrcweir double fSSresid = lcl_GetSSresid(pMatX,pMatY,fSlope,N);
2493cdf0e10cSrcweir pResMat->PutDouble(fSSresid, 1, 4);
2494cdf0e10cSrcweir
2495cdf0e10cSrcweir if (fDegreesFreedom == 0.0 || fSSresid == 0.0 || fSSreg == 0.0)
2496cdf0e10cSrcweir { // exact fit; test SSreg too, because SSresid might be
2497cdf0e10cSrcweir // unequal zero due to round of errors
2498cdf0e10cSrcweir pResMat->PutDouble(0.0, 1, 4); // SSresid
2499cdf0e10cSrcweir pResMat->PutString(ScGlobal::GetRscString(STR_NV_STR), 0, 3); // F
2500cdf0e10cSrcweir pResMat->PutDouble(0.0, 1, 2); // RMSE
2501cdf0e10cSrcweir pResMat->PutDouble(0.0, 0, 1); // SigmaSlope
2502cdf0e10cSrcweir if (bConstant)
2503cdf0e10cSrcweir pResMat->PutDouble(0.0, 1, 1); //SigmaIntercept
2504cdf0e10cSrcweir else
2505cdf0e10cSrcweir pResMat->PutString(ScGlobal::GetRscString(STR_NV_STR), 1, 1);
2506cdf0e10cSrcweir pResMat->PutDouble(1.0, 0, 2); // R^2
2507cdf0e10cSrcweir }
2508cdf0e10cSrcweir else
2509cdf0e10cSrcweir {
2510cdf0e10cSrcweir double fFstatistic = (fSSreg / static_cast<double>(K))
2511cdf0e10cSrcweir / (fSSresid / fDegreesFreedom);
2512cdf0e10cSrcweir pResMat->PutDouble(fFstatistic, 0, 3);
2513cdf0e10cSrcweir
2514cdf0e10cSrcweir // standard error of estimate
2515cdf0e10cSrcweir double fRMSE = sqrt(fSSresid / fDegreesFreedom);
2516cdf0e10cSrcweir pResMat->PutDouble(fRMSE, 1, 2);
2517cdf0e10cSrcweir
2518cdf0e10cSrcweir double fSigmaSlope = fRMSE / sqrt(fSumX2);
2519cdf0e10cSrcweir pResMat->PutDouble(fSigmaSlope, 0, 1);
2520cdf0e10cSrcweir
2521cdf0e10cSrcweir if (bConstant)
2522cdf0e10cSrcweir {
2523cdf0e10cSrcweir double fSigmaIntercept = fRMSE
2524cdf0e10cSrcweir * sqrt(fMeanX*fMeanX/fSumX2 + 1.0/static_cast<double>(N));
2525cdf0e10cSrcweir pResMat->PutDouble(fSigmaIntercept, 1, 1);
2526cdf0e10cSrcweir }
2527cdf0e10cSrcweir else
2528cdf0e10cSrcweir {
2529cdf0e10cSrcweir pResMat->PutString(ScGlobal::GetRscString(STR_NV_STR), 1, 1);
2530cdf0e10cSrcweir }
2531cdf0e10cSrcweir
2532cdf0e10cSrcweir double fR2 = fSSreg / (fSSreg + fSSresid);
2533cdf0e10cSrcweir pResMat->PutDouble(fR2, 0, 2);
2534cdf0e10cSrcweir }
2535cdf0e10cSrcweir }
2536cdf0e10cSrcweir PushMatrix(pResMat);
2537cdf0e10cSrcweir }
2538cdf0e10cSrcweir else // calculate multiple regression;
2539cdf0e10cSrcweir {
2540cdf0e10cSrcweir // Uses a QR decomposition X = QR. The solution B = (X'X)^(-1) * X' * Y
2541cdf0e10cSrcweir // becomes B = R^(-1) * Q' * Y
2542cdf0e10cSrcweir if (nCase ==2) // Y is column
2543cdf0e10cSrcweir {
2544cdf0e10cSrcweir ::std::vector< double> aVecR(N); // for QR decomposition
2545cdf0e10cSrcweir // Enough memory for needed matrices?
2546cdf0e10cSrcweir ScMatrixRef pMeans = GetNewMat(K, 1); // mean of each column
2547cdf0e10cSrcweir ScMatrixRef pMatZ; // for Q' * Y , inter alia
2548cdf0e10cSrcweir if (bStats)
2549cdf0e10cSrcweir pMatZ = pMatY->Clone(); // Y is used in statistic, keep it
2550cdf0e10cSrcweir else
2551cdf0e10cSrcweir pMatZ = pMatY; // Y can be overwritten
2552cdf0e10cSrcweir ScMatrixRef pSlopes = GetNewMat(1,K); // from b1 to bK
2553cdf0e10cSrcweir if (!pMeans || !pMatZ || !pSlopes)
2554cdf0e10cSrcweir {
2555cdf0e10cSrcweir PushError(errCodeOverflow);
2556cdf0e10cSrcweir return;
2557cdf0e10cSrcweir }
2558cdf0e10cSrcweir if (bConstant)
2559cdf0e10cSrcweir {
2560cdf0e10cSrcweir lcl_CalculateColumnMeans(pMatX, pMeans, K, N);
2561cdf0e10cSrcweir lcl_CalculateColumnsDelta(pMatX, pMeans, K, N);
2562cdf0e10cSrcweir }
2563cdf0e10cSrcweir if (!lcl_CalculateQRdecomposition(pMatX, aVecR, K, N))
2564cdf0e10cSrcweir {
2565cdf0e10cSrcweir PushNoValue();
2566cdf0e10cSrcweir return;
2567cdf0e10cSrcweir }
2568cdf0e10cSrcweir // Later on we will divide by elements of aVecR, so make sure
2569cdf0e10cSrcweir // that they aren't zero.
2570cdf0e10cSrcweir bool bIsSingular=false;
2571cdf0e10cSrcweir for (SCSIZE row=0; row < K && !bIsSingular; row++)
2572cdf0e10cSrcweir bIsSingular = bIsSingular || aVecR[row]==0.0;
2573cdf0e10cSrcweir if (bIsSingular)
2574cdf0e10cSrcweir {
2575cdf0e10cSrcweir PushNoValue();
2576cdf0e10cSrcweir return;
2577cdf0e10cSrcweir }
2578cdf0e10cSrcweir // Z = Q' Y;
2579cdf0e10cSrcweir for (SCSIZE col = 0; col < K; col++)
2580cdf0e10cSrcweir {
2581cdf0e10cSrcweir lcl_ApplyHouseholderTransformation(pMatX, col, pMatZ, N);
2582cdf0e10cSrcweir }
2583cdf0e10cSrcweir // B = R^(-1) * Q' * Y <=> B = R^(-1) * Z <=> R * B = Z
2584cdf0e10cSrcweir // result Z should have zeros for index>=K; if not, ignore values
2585cdf0e10cSrcweir for (SCSIZE col = 0; col < K ; col++)
2586cdf0e10cSrcweir {
2587cdf0e10cSrcweir pSlopes->PutDouble( pMatZ->GetDouble(col), col);
2588cdf0e10cSrcweir }
2589cdf0e10cSrcweir lcl_SolveWithUpperRightTriangle(pMatX, aVecR, pSlopes, K, false);
2590cdf0e10cSrcweir double fIntercept = 0.0;
2591cdf0e10cSrcweir if (bConstant)
2592cdf0e10cSrcweir fIntercept = fMeanY - lcl_GetSumProduct(pMeans,pSlopes,K);
2593cdf0e10cSrcweir // Fill first line in result matrix
2594cdf0e10cSrcweir pResMat->PutDouble(_bRKP ? exp(fIntercept) : fIntercept, K, 0 );
2595cdf0e10cSrcweir for (SCSIZE i = 0; i < K; i++)
2596cdf0e10cSrcweir pResMat->PutDouble(_bRKP ? exp(pSlopes->GetDouble(i))
2597cdf0e10cSrcweir : pSlopes->GetDouble(i) , K-1-i, 0);
2598cdf0e10cSrcweir
2599cdf0e10cSrcweir
2600cdf0e10cSrcweir if (bStats)
2601cdf0e10cSrcweir {
2602cdf0e10cSrcweir double fSSreg = 0.0;
2603cdf0e10cSrcweir double fSSresid = 0.0;
2604cdf0e10cSrcweir // re-use memory of Z;
2605cdf0e10cSrcweir pMatZ->FillDouble(0.0, 0, 0, 0, N-1);
2606cdf0e10cSrcweir // Z = R * Slopes
2607cdf0e10cSrcweir lcl_ApplyUpperRightTriangle(pMatX, aVecR, pSlopes, pMatZ, K, false);
2608cdf0e10cSrcweir // Z = Q * Z, that is Q * R * Slopes = X * Slopes
2609cdf0e10cSrcweir for (SCSIZE colp1 = K; colp1 > 0; colp1--)
2610cdf0e10cSrcweir {
2611cdf0e10cSrcweir lcl_ApplyHouseholderTransformation(pMatX, colp1-1, pMatZ,N);
2612cdf0e10cSrcweir }
2613cdf0e10cSrcweir fSSreg =lcl_GetSumProduct(pMatZ, pMatZ, N);
2614cdf0e10cSrcweir // re-use Y for residuals, Y = Y-Z
2615cdf0e10cSrcweir for (SCSIZE row = 0; row < N; row++)
2616cdf0e10cSrcweir pMatY->PutDouble(pMatY->GetDouble(row) - pMatZ->GetDouble(row), row);
2617cdf0e10cSrcweir fSSresid = lcl_GetSumProduct(pMatY, pMatY, N);
2618cdf0e10cSrcweir pResMat->PutDouble(fSSreg, 0, 4);
2619cdf0e10cSrcweir pResMat->PutDouble(fSSresid, 1, 4);
2620cdf0e10cSrcweir
2621cdf0e10cSrcweir double fDegreesFreedom =static_cast<double>( (bConstant) ? N-K-1 : N-K );
2622cdf0e10cSrcweir pResMat->PutDouble(fDegreesFreedom, 1, 3);
2623cdf0e10cSrcweir
2624cdf0e10cSrcweir if (fDegreesFreedom == 0.0 || fSSresid == 0.0 || fSSreg == 0.0)
2625cdf0e10cSrcweir { // exact fit; incl. observed values Y are identical
2626cdf0e10cSrcweir pResMat->PutDouble(0.0, 1, 4); // SSresid
2627cdf0e10cSrcweir // F = (SSreg/K) / (SSresid/df) = #DIV/0!
2628cdf0e10cSrcweir pResMat->PutString(ScGlobal::GetRscString(STR_NV_STR), 0, 3); // F
2629cdf0e10cSrcweir // RMSE = sqrt(SSresid / df) = sqrt(0 / df) = 0
2630cdf0e10cSrcweir pResMat->PutDouble(0.0, 1, 2); // RMSE
2631cdf0e10cSrcweir // SigmaSlope[i] = RMSE * sqrt(matrix[i,i]) = 0 * sqrt(...) = 0
2632cdf0e10cSrcweir for (SCSIZE i=0; i<K; i++)
2633cdf0e10cSrcweir pResMat->PutDouble(0.0, K-1-i, 1);
2634cdf0e10cSrcweir
2635cdf0e10cSrcweir // SigmaIntercept = RMSE * sqrt(...) = 0
2636cdf0e10cSrcweir if (bConstant)
2637cdf0e10cSrcweir pResMat->PutDouble(0.0, K, 1); //SigmaIntercept
2638cdf0e10cSrcweir else
2639cdf0e10cSrcweir pResMat->PutString(ScGlobal::GetRscString(STR_NV_STR), K, 1);
2640cdf0e10cSrcweir
2641cdf0e10cSrcweir // R^2 = SSreg / (SSreg + SSresid) = 1.0
2642cdf0e10cSrcweir pResMat->PutDouble(1.0, 0, 2); // R^2
2643cdf0e10cSrcweir }
2644cdf0e10cSrcweir else
2645cdf0e10cSrcweir {
2646cdf0e10cSrcweir double fFstatistic = (fSSreg / static_cast<double>(K))
2647cdf0e10cSrcweir / (fSSresid / fDegreesFreedom);
2648cdf0e10cSrcweir pResMat->PutDouble(fFstatistic, 0, 3);
2649cdf0e10cSrcweir
2650cdf0e10cSrcweir // standard error of estimate = root mean SSE
2651cdf0e10cSrcweir double fRMSE = sqrt(fSSresid / fDegreesFreedom);
2652cdf0e10cSrcweir pResMat->PutDouble(fRMSE, 1, 2);
2653cdf0e10cSrcweir
2654cdf0e10cSrcweir // standard error of slopes
2655cdf0e10cSrcweir // = RMSE * sqrt(diagonal element of (R' R)^(-1) )
2656cdf0e10cSrcweir // standard error of intercept
2657cdf0e10cSrcweir // = RMSE * sqrt( Xmean * (R' R)^(-1) * Xmean' + 1/N)
2658cdf0e10cSrcweir // (R' R)^(-1) = R^(-1) * (R')^(-1). Do not calculate it as
2659cdf0e10cSrcweir // a whole matrix, but iterate over unit vectors.
2660cdf0e10cSrcweir double fSigmaSlope = 0.0;
2661cdf0e10cSrcweir double fSigmaIntercept = 0.0;
2662cdf0e10cSrcweir double fPart; // for Xmean * single column of (R' R)^(-1)
2663cdf0e10cSrcweir for (SCSIZE col = 0; col < K; col++)
2664cdf0e10cSrcweir {
2665cdf0e10cSrcweir //re-use memory of MatZ
2666cdf0e10cSrcweir pMatZ->FillDouble(0.0,0,0,0,K-1); // Z = unit vector e
2667cdf0e10cSrcweir pMatZ->PutDouble(1.0, col);
2668cdf0e10cSrcweir //Solve R' * Z = e
2669cdf0e10cSrcweir lcl_SolveWithLowerLeftTriangle(pMatX, aVecR, pMatZ, K, false);
2670cdf0e10cSrcweir // Solve R * Znew = Zold
2671cdf0e10cSrcweir lcl_SolveWithUpperRightTriangle(pMatX, aVecR, pMatZ, K, false);
2672cdf0e10cSrcweir // now Z is column col in (R' R)^(-1)
2673cdf0e10cSrcweir fSigmaSlope = fRMSE * sqrt(pMatZ->GetDouble(col));
2674cdf0e10cSrcweir pResMat->PutDouble(fSigmaSlope, K-1-col, 1);
2675cdf0e10cSrcweir // (R' R) ^(-1) is symmetric
2676cdf0e10cSrcweir if (bConstant)
2677cdf0e10cSrcweir {
2678cdf0e10cSrcweir fPart = lcl_GetSumProduct(pMeans, pMatZ, K);
2679cdf0e10cSrcweir fSigmaIntercept += fPart * pMeans->GetDouble(col);
2680cdf0e10cSrcweir }
2681cdf0e10cSrcweir }
2682cdf0e10cSrcweir if (bConstant)
2683cdf0e10cSrcweir {
2684cdf0e10cSrcweir fSigmaIntercept = fRMSE
2685cdf0e10cSrcweir * sqrt(fSigmaIntercept + 1.0 / static_cast<double>(N));
2686cdf0e10cSrcweir pResMat->PutDouble(fSigmaIntercept, K, 1);
2687cdf0e10cSrcweir }
2688cdf0e10cSrcweir else
2689cdf0e10cSrcweir {
2690cdf0e10cSrcweir pResMat->PutString(ScGlobal::GetRscString(STR_NV_STR), K, 1);
2691cdf0e10cSrcweir }
2692cdf0e10cSrcweir
2693cdf0e10cSrcweir double fR2 = fSSreg / (fSSreg + fSSresid);
2694cdf0e10cSrcweir pResMat->PutDouble(fR2, 0, 2);
2695cdf0e10cSrcweir }
2696cdf0e10cSrcweir }
2697cdf0e10cSrcweir PushMatrix(pResMat);
2698cdf0e10cSrcweir }
2699cdf0e10cSrcweir else // nCase == 3, Y is row, all matrices are transposed
2700cdf0e10cSrcweir {
2701cdf0e10cSrcweir ::std::vector< double> aVecR(N); // for QR decomposition
2702cdf0e10cSrcweir // Enough memory for needed matrices?
2703cdf0e10cSrcweir ScMatrixRef pMeans = GetNewMat(1, K); // mean of each row
2704cdf0e10cSrcweir ScMatrixRef pMatZ; // for Q' * Y , inter alia
2705cdf0e10cSrcweir if (bStats)
2706cdf0e10cSrcweir pMatZ = pMatY->Clone(); // Y is used in statistic, keep it
2707cdf0e10cSrcweir else
2708cdf0e10cSrcweir pMatZ = pMatY; // Y can be overwritten
2709cdf0e10cSrcweir ScMatrixRef pSlopes = GetNewMat(K,1); // from b1 to bK
2710cdf0e10cSrcweir if (!pMeans || !pMatZ || !pSlopes)
2711cdf0e10cSrcweir {
2712cdf0e10cSrcweir PushError(errCodeOverflow);
2713cdf0e10cSrcweir return;
2714cdf0e10cSrcweir }
2715cdf0e10cSrcweir if (bConstant)
2716cdf0e10cSrcweir {
2717cdf0e10cSrcweir lcl_CalculateRowMeans(pMatX, pMeans, N, K);
2718cdf0e10cSrcweir lcl_CalculateRowsDelta(pMatX, pMeans, N, K);
2719cdf0e10cSrcweir }
2720cdf0e10cSrcweir
2721cdf0e10cSrcweir if (!lcl_TCalculateQRdecomposition(pMatX, aVecR, K, N))
2722cdf0e10cSrcweir {
2723cdf0e10cSrcweir PushNoValue();
2724cdf0e10cSrcweir return;
2725cdf0e10cSrcweir }
2726cdf0e10cSrcweir
2727cdf0e10cSrcweir // Later on we will divide by elements of aVecR, so make sure
2728cdf0e10cSrcweir // that they aren't zero.
2729cdf0e10cSrcweir bool bIsSingular=false;
2730cdf0e10cSrcweir for (SCSIZE row=0; row < K && !bIsSingular; row++)
2731cdf0e10cSrcweir bIsSingular = bIsSingular || aVecR[row]==0.0;
2732cdf0e10cSrcweir if (bIsSingular)
2733cdf0e10cSrcweir {
2734cdf0e10cSrcweir PushNoValue();
2735cdf0e10cSrcweir return;
2736cdf0e10cSrcweir }
2737cdf0e10cSrcweir // Z = Q' Y
2738cdf0e10cSrcweir for (SCSIZE row = 0; row < K; row++)
2739cdf0e10cSrcweir {
2740cdf0e10cSrcweir lcl_TApplyHouseholderTransformation(pMatX, row, pMatZ, N);
2741cdf0e10cSrcweir }
2742cdf0e10cSrcweir // B = R^(-1) * Q' * Y <=> B = R^(-1) * Z <=> R * B = Z
2743cdf0e10cSrcweir // result Z should have zeros for index>=K; if not, ignore values
2744cdf0e10cSrcweir for (SCSIZE col = 0; col < K ; col++)
2745cdf0e10cSrcweir {
2746cdf0e10cSrcweir pSlopes->PutDouble( pMatZ->GetDouble(col), col);
2747cdf0e10cSrcweir }
2748cdf0e10cSrcweir lcl_SolveWithUpperRightTriangle(pMatX, aVecR, pSlopes, K, true);
2749cdf0e10cSrcweir double fIntercept = 0.0;
2750cdf0e10cSrcweir if (bConstant)
2751cdf0e10cSrcweir fIntercept = fMeanY - lcl_GetSumProduct(pMeans,pSlopes,K);
2752cdf0e10cSrcweir // Fill first line in result matrix
2753cdf0e10cSrcweir pResMat->PutDouble(_bRKP ? exp(fIntercept) : fIntercept, K, 0 );
2754cdf0e10cSrcweir for (SCSIZE i = 0; i < K; i++)
2755cdf0e10cSrcweir pResMat->PutDouble(_bRKP ? exp(pSlopes->GetDouble(i))
2756cdf0e10cSrcweir : pSlopes->GetDouble(i) , K-1-i, 0);
2757cdf0e10cSrcweir
2758cdf0e10cSrcweir
2759cdf0e10cSrcweir if (bStats)
2760cdf0e10cSrcweir {
2761cdf0e10cSrcweir double fSSreg = 0.0;
2762cdf0e10cSrcweir double fSSresid = 0.0;
2763cdf0e10cSrcweir // re-use memory of Z;
2764cdf0e10cSrcweir pMatZ->FillDouble(0.0, 0, 0, N-1, 0);
2765cdf0e10cSrcweir // Z = R * Slopes
2766cdf0e10cSrcweir lcl_ApplyUpperRightTriangle(pMatX, aVecR, pSlopes, pMatZ, K, true);
2767cdf0e10cSrcweir // Z = Q * Z, that is Q * R * Slopes = X * Slopes
2768cdf0e10cSrcweir for (SCSIZE rowp1 = K; rowp1 > 0; rowp1--)
2769cdf0e10cSrcweir {
2770cdf0e10cSrcweir lcl_TApplyHouseholderTransformation(pMatX, rowp1-1, pMatZ,N);
2771cdf0e10cSrcweir }
2772cdf0e10cSrcweir fSSreg =lcl_GetSumProduct(pMatZ, pMatZ, N);
2773cdf0e10cSrcweir // re-use Y for residuals, Y = Y-Z
2774cdf0e10cSrcweir for (SCSIZE col = 0; col < N; col++)
2775cdf0e10cSrcweir pMatY->PutDouble(pMatY->GetDouble(col) - pMatZ->GetDouble(col), col);
2776cdf0e10cSrcweir fSSresid = lcl_GetSumProduct(pMatY, pMatY, N);
2777cdf0e10cSrcweir pResMat->PutDouble(fSSreg, 0, 4);
2778cdf0e10cSrcweir pResMat->PutDouble(fSSresid, 1, 4);
2779cdf0e10cSrcweir
2780cdf0e10cSrcweir double fDegreesFreedom =static_cast<double>( (bConstant) ? N-K-1 : N-K );
2781cdf0e10cSrcweir pResMat->PutDouble(fDegreesFreedom, 1, 3);
2782cdf0e10cSrcweir
2783cdf0e10cSrcweir if (fDegreesFreedom == 0.0 || fSSresid == 0.0 || fSSreg == 0.0)
2784cdf0e10cSrcweir { // exact fit; incl. case observed values Y are identical
2785cdf0e10cSrcweir pResMat->PutDouble(0.0, 1, 4); // SSresid
2786cdf0e10cSrcweir // F = (SSreg/K) / (SSresid/df) = #DIV/0!
2787cdf0e10cSrcweir pResMat->PutString(ScGlobal::GetRscString(STR_NV_STR), 0, 3); // F
2788cdf0e10cSrcweir // RMSE = sqrt(SSresid / df) = sqrt(0 / df) = 0
2789cdf0e10cSrcweir pResMat->PutDouble(0.0, 1, 2); // RMSE
2790cdf0e10cSrcweir // SigmaSlope[i] = RMSE * sqrt(matrix[i,i]) = 0 * sqrt(...) = 0
2791cdf0e10cSrcweir for (SCSIZE i=0; i<K; i++)
2792cdf0e10cSrcweir pResMat->PutDouble(0.0, K-1-i, 1);
2793cdf0e10cSrcweir
2794cdf0e10cSrcweir // SigmaIntercept = RMSE * sqrt(...) = 0
2795cdf0e10cSrcweir if (bConstant)
2796cdf0e10cSrcweir pResMat->PutDouble(0.0, K, 1); //SigmaIntercept
2797cdf0e10cSrcweir else
2798cdf0e10cSrcweir pResMat->PutString(ScGlobal::GetRscString(STR_NV_STR), K, 1);
2799cdf0e10cSrcweir
2800cdf0e10cSrcweir // R^2 = SSreg / (SSreg + SSresid) = 1.0
2801cdf0e10cSrcweir pResMat->PutDouble(1.0, 0, 2); // R^2
2802cdf0e10cSrcweir }
2803cdf0e10cSrcweir else
2804cdf0e10cSrcweir {
2805cdf0e10cSrcweir double fFstatistic = (fSSreg / static_cast<double>(K))
2806cdf0e10cSrcweir / (fSSresid / fDegreesFreedom);
2807cdf0e10cSrcweir pResMat->PutDouble(fFstatistic, 0, 3);
2808cdf0e10cSrcweir
2809cdf0e10cSrcweir // standard error of estimate = root mean SSE
2810cdf0e10cSrcweir double fRMSE = sqrt(fSSresid / fDegreesFreedom);
2811cdf0e10cSrcweir pResMat->PutDouble(fRMSE, 1, 2);
2812cdf0e10cSrcweir
2813cdf0e10cSrcweir // standard error of slopes
2814cdf0e10cSrcweir // = RMSE * sqrt(diagonal element of (R' R)^(-1) )
2815cdf0e10cSrcweir // standard error of intercept
2816cdf0e10cSrcweir // = RMSE * sqrt( Xmean * (R' R)^(-1) * Xmean' + 1/N)
2817cdf0e10cSrcweir // (R' R)^(-1) = R^(-1) * (R')^(-1). Do not calculate it as
2818cdf0e10cSrcweir // a whole matrix, but iterate over unit vectors.
2819cdf0e10cSrcweir // (R' R) ^(-1) is symmetric
2820cdf0e10cSrcweir double fSigmaSlope = 0.0;
2821cdf0e10cSrcweir double fSigmaIntercept = 0.0;
2822cdf0e10cSrcweir double fPart; // for Xmean * single col of (R' R)^(-1)
2823cdf0e10cSrcweir for (SCSIZE row = 0; row < K; row++)
2824cdf0e10cSrcweir {
2825cdf0e10cSrcweir //re-use memory of MatZ
2826cdf0e10cSrcweir pMatZ->FillDouble(0.0,0,0,K-1,0); // Z = unit vector e
2827cdf0e10cSrcweir pMatZ->PutDouble(1.0, row);
2828cdf0e10cSrcweir //Solve R' * Z = e
2829cdf0e10cSrcweir lcl_SolveWithLowerLeftTriangle(pMatX, aVecR, pMatZ, K, true);
2830cdf0e10cSrcweir // Solve R * Znew = Zold
2831cdf0e10cSrcweir lcl_SolveWithUpperRightTriangle(pMatX, aVecR, pMatZ, K, true);
2832cdf0e10cSrcweir // now Z is column col in (R' R)^(-1)
2833cdf0e10cSrcweir fSigmaSlope = fRMSE * sqrt(pMatZ->GetDouble(row));
2834cdf0e10cSrcweir pResMat->PutDouble(fSigmaSlope, K-1-row, 1);
2835cdf0e10cSrcweir if (bConstant)
2836cdf0e10cSrcweir {
2837cdf0e10cSrcweir fPart = lcl_GetSumProduct(pMeans, pMatZ, K);
2838cdf0e10cSrcweir fSigmaIntercept += fPart * pMeans->GetDouble(row);
2839cdf0e10cSrcweir }
2840cdf0e10cSrcweir }
2841cdf0e10cSrcweir if (bConstant)
2842cdf0e10cSrcweir {
2843cdf0e10cSrcweir fSigmaIntercept = fRMSE
2844cdf0e10cSrcweir * sqrt(fSigmaIntercept + 1.0 / static_cast<double>(N));
2845cdf0e10cSrcweir pResMat->PutDouble(fSigmaIntercept, K, 1);
2846cdf0e10cSrcweir }
2847cdf0e10cSrcweir else
2848cdf0e10cSrcweir {
2849cdf0e10cSrcweir pResMat->PutString(ScGlobal::GetRscString(STR_NV_STR), K, 1);
2850cdf0e10cSrcweir }
2851cdf0e10cSrcweir
2852cdf0e10cSrcweir double fR2 = fSSreg / (fSSreg + fSSresid);
2853cdf0e10cSrcweir pResMat->PutDouble(fR2, 0, 2);
2854cdf0e10cSrcweir }
2855cdf0e10cSrcweir }
2856cdf0e10cSrcweir PushMatrix(pResMat);
2857cdf0e10cSrcweir }
2858cdf0e10cSrcweir }
2859cdf0e10cSrcweir return;
2860cdf0e10cSrcweir }
2861cdf0e10cSrcweir
ScTrend()2862cdf0e10cSrcweir void ScInterpreter::ScTrend()
2863cdf0e10cSrcweir {
2864cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScTrend" );
2865cdf0e10cSrcweir CalculateTrendGrowth(false);
2866cdf0e10cSrcweir }
2867cdf0e10cSrcweir
ScGrowth()2868cdf0e10cSrcweir void ScInterpreter::ScGrowth()
2869cdf0e10cSrcweir {
2870cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScGrowth" );
2871cdf0e10cSrcweir CalculateTrendGrowth(true);
2872cdf0e10cSrcweir }
2873cdf0e10cSrcweir
CalculateTrendGrowth(bool _bGrowth)2874cdf0e10cSrcweir void ScInterpreter::CalculateTrendGrowth(bool _bGrowth)
2875cdf0e10cSrcweir {
2876cdf0e10cSrcweir sal_uInt8 nParamCount = GetByte();
2877cdf0e10cSrcweir if ( !MustHaveParamCount( nParamCount, 1, 4 ) )
2878cdf0e10cSrcweir return;
2879cdf0e10cSrcweir
2880cdf0e10cSrcweir // optional fourth parameter
2881cdf0e10cSrcweir bool bConstant;
2882cdf0e10cSrcweir if (nParamCount == 4)
2883cdf0e10cSrcweir bConstant = GetBool();
2884cdf0e10cSrcweir else
2885cdf0e10cSrcweir bConstant = true;
2886cdf0e10cSrcweir
2887cdf0e10cSrcweir // The third parameter may be missing in ODF, although the fourth parameter
2888cdf0e10cSrcweir // is present. Default values depend on data not yet read.
2889cdf0e10cSrcweir ScMatrixRef pMatNewX;
2890cdf0e10cSrcweir if (nParamCount >= 3)
2891cdf0e10cSrcweir {
2892cdf0e10cSrcweir if (IsMissing())
2893cdf0e10cSrcweir {
2894cdf0e10cSrcweir Pop();
2895cdf0e10cSrcweir pMatNewX = NULL;
2896cdf0e10cSrcweir }
2897cdf0e10cSrcweir else
2898cdf0e10cSrcweir pMatNewX = GetMatrix();
2899cdf0e10cSrcweir }
2900cdf0e10cSrcweir else
2901cdf0e10cSrcweir pMatNewX = NULL;
2902cdf0e10cSrcweir
2903cdf0e10cSrcweir // In ODF1.2 empty second parameter (which is two ;; ) is allowed.
2904cdf0e10cSrcweir // Defaults will be set in CheckMatrix.
2905cdf0e10cSrcweir ScMatrixRef pMatX;
2906cdf0e10cSrcweir if (nParamCount >= 2)
2907cdf0e10cSrcweir {
2908cdf0e10cSrcweir if (IsMissing())
2909cdf0e10cSrcweir {
2910cdf0e10cSrcweir Pop();
2911cdf0e10cSrcweir pMatX = NULL;
2912cdf0e10cSrcweir }
2913cdf0e10cSrcweir else
2914cdf0e10cSrcweir {
2915cdf0e10cSrcweir pMatX = GetMatrix();
2916cdf0e10cSrcweir }
2917cdf0e10cSrcweir }
2918cdf0e10cSrcweir else
2919cdf0e10cSrcweir pMatX = NULL;
2920cdf0e10cSrcweir
2921cdf0e10cSrcweir ScMatrixRef pMatY;
2922cdf0e10cSrcweir pMatY = GetMatrix();
2923cdf0e10cSrcweir if (!pMatY)
2924cdf0e10cSrcweir {
2925cdf0e10cSrcweir PushIllegalParameter();
2926cdf0e10cSrcweir return;
2927cdf0e10cSrcweir }
2928cdf0e10cSrcweir
2929cdf0e10cSrcweir // 1 = simple; 2 = multiple with Y as column; 3 = multiple with Y as row
2930cdf0e10cSrcweir sal_uInt8 nCase;
2931cdf0e10cSrcweir
2932cdf0e10cSrcweir SCSIZE nCX, nCY; // number of columns
2933cdf0e10cSrcweir SCSIZE nRX, nRY; // number of rows
2934cdf0e10cSrcweir SCSIZE K = 0, N = 0; // K=number of variables X, N=number of data samples
2935cdf0e10cSrcweir if ( !CheckMatrix(_bGrowth,nCase,nCX,nCY,nRX,nRY,K,N,pMatX,pMatY) )
2936cdf0e10cSrcweir {
2937cdf0e10cSrcweir PushIllegalParameter();
2938cdf0e10cSrcweir return;
2939cdf0e10cSrcweir }
2940cdf0e10cSrcweir
2941cdf0e10cSrcweir // Enough data samples?
2942cdf0e10cSrcweir if ( (bConstant && (N<K+1)) || (!bConstant && (N<K)) || (N<1) || (K<1) )
2943cdf0e10cSrcweir {
2944cdf0e10cSrcweir PushIllegalParameter();
2945cdf0e10cSrcweir return;
2946cdf0e10cSrcweir }
2947cdf0e10cSrcweir
2948cdf0e10cSrcweir // Set default pMatNewX if necessary
2949cdf0e10cSrcweir SCSIZE nCXN, nRXN;
2950cdf0e10cSrcweir SCSIZE nCountXN;
2951cdf0e10cSrcweir if (!pMatNewX)
2952cdf0e10cSrcweir {
2953cdf0e10cSrcweir nCXN = nCX;
2954cdf0e10cSrcweir nRXN = nRX;
2955cdf0e10cSrcweir nCountXN = nCXN * nRXN;
2956cdf0e10cSrcweir pMatNewX = pMatX->Clone(); // pMatX will be changed to X-meanX
2957cdf0e10cSrcweir }
2958cdf0e10cSrcweir else
2959cdf0e10cSrcweir {
2960cdf0e10cSrcweir pMatNewX->GetDimensions(nCXN, nRXN);
2961cdf0e10cSrcweir if ((nCase == 2 && K != nCXN) || (nCase == 3 && K != nRXN))
2962cdf0e10cSrcweir {
2963cdf0e10cSrcweir PushIllegalArgument();
2964cdf0e10cSrcweir return;
2965cdf0e10cSrcweir }
2966cdf0e10cSrcweir nCountXN = nCXN * nRXN;
2967cdf0e10cSrcweir for ( SCSIZE i = 0; i < nCountXN; i++ )
2968cdf0e10cSrcweir if (!pMatNewX->IsValue(i))
2969cdf0e10cSrcweir {
2970cdf0e10cSrcweir PushIllegalArgument();
2971cdf0e10cSrcweir return;
2972cdf0e10cSrcweir }
2973cdf0e10cSrcweir }
2974cdf0e10cSrcweir ScMatrixRef pResMat; // size depends on nCase
2975cdf0e10cSrcweir if (nCase == 1)
2976cdf0e10cSrcweir pResMat = GetNewMat(nCXN,nRXN);
2977cdf0e10cSrcweir else
2978cdf0e10cSrcweir {
2979cdf0e10cSrcweir if (nCase==2)
2980cdf0e10cSrcweir pResMat = GetNewMat(1,nRXN);
2981cdf0e10cSrcweir else
2982cdf0e10cSrcweir pResMat = GetNewMat(nCXN,1);
2983cdf0e10cSrcweir }
2984cdf0e10cSrcweir if (!pResMat)
2985cdf0e10cSrcweir {
2986cdf0e10cSrcweir PushError(errCodeOverflow);
2987cdf0e10cSrcweir return;
2988cdf0e10cSrcweir }
2989cdf0e10cSrcweir // Uses sum(x-MeanX)^2 and not [sum x^2]-N * MeanX^2 in case bConstant.
2990cdf0e10cSrcweir // Clone constant matrices, so that Mat = Mat - Mean is possible.
2991cdf0e10cSrcweir double fMeanY = 0.0;
2992cdf0e10cSrcweir if (bConstant)
2993cdf0e10cSrcweir {
2994cdf0e10cSrcweir ScMatrixRef pCopyX = pMatX->CloneIfConst();
2995cdf0e10cSrcweir ScMatrixRef pCopyY = pMatY->CloneIfConst();
2996cdf0e10cSrcweir if (!pCopyX || !pCopyY)
2997cdf0e10cSrcweir {
2998cdf0e10cSrcweir PushError(errStackOverflow);
2999cdf0e10cSrcweir return;
3000cdf0e10cSrcweir }
3001cdf0e10cSrcweir pMatX = pCopyX;
3002cdf0e10cSrcweir pMatY = pCopyY;
3003cdf0e10cSrcweir // DeltaY is possible here; DeltaX depends on nCase, so later
3004cdf0e10cSrcweir fMeanY = lcl_GetMeanOverAll(pMatY, N);
3005cdf0e10cSrcweir for (SCSIZE i=0; i<N; i++)
3006cdf0e10cSrcweir {
3007cdf0e10cSrcweir pMatY->PutDouble( ::rtl::math::approxSub(pMatY->GetDouble(i),fMeanY), i );
3008cdf0e10cSrcweir }
3009cdf0e10cSrcweir }
3010cdf0e10cSrcweir
3011cdf0e10cSrcweir if (nCase==1)
3012cdf0e10cSrcweir {
3013cdf0e10cSrcweir // calculate simple regression
3014cdf0e10cSrcweir double fMeanX = 0.0;
3015cdf0e10cSrcweir if (bConstant)
3016cdf0e10cSrcweir { // Mat = Mat - Mean
3017cdf0e10cSrcweir fMeanX = lcl_GetMeanOverAll(pMatX, N);
3018cdf0e10cSrcweir for (SCSIZE i=0; i<N; i++)
3019cdf0e10cSrcweir {
3020cdf0e10cSrcweir pMatX->PutDouble( ::rtl::math::approxSub(pMatX->GetDouble(i),fMeanX), i );
3021cdf0e10cSrcweir }
3022cdf0e10cSrcweir }
3023cdf0e10cSrcweir double fSumXY = lcl_GetSumProduct(pMatX,pMatY,N);
3024cdf0e10cSrcweir double fSumX2 = lcl_GetSumProduct(pMatX,pMatX,N);
3025cdf0e10cSrcweir if (fSumX2==0.0)
3026cdf0e10cSrcweir {
3027cdf0e10cSrcweir PushNoValue(); // all x-values are identical
3028cdf0e10cSrcweir return;
3029cdf0e10cSrcweir }
3030cdf0e10cSrcweir double fSlope = fSumXY / fSumX2;
3031cdf0e10cSrcweir double fIntercept = 0.0;
3032cdf0e10cSrcweir double fHelp;
3033cdf0e10cSrcweir if (bConstant)
3034cdf0e10cSrcweir {
3035cdf0e10cSrcweir fIntercept = fMeanY - fSlope * fMeanX;
3036cdf0e10cSrcweir for (SCSIZE i = 0; i < nCountXN; i++)
3037cdf0e10cSrcweir {
3038cdf0e10cSrcweir fHelp = pMatNewX->GetDouble(i)*fSlope + fIntercept;
3039cdf0e10cSrcweir pResMat->PutDouble(_bGrowth ? exp(fHelp) : fHelp, i);
3040cdf0e10cSrcweir }
3041cdf0e10cSrcweir }
3042cdf0e10cSrcweir else
3043cdf0e10cSrcweir {
3044cdf0e10cSrcweir for (SCSIZE i = 0; i < nCountXN; i++)
3045cdf0e10cSrcweir {
3046cdf0e10cSrcweir fHelp = pMatNewX->GetDouble(i)*fSlope;
3047cdf0e10cSrcweir pResMat->PutDouble(_bGrowth ? exp(fHelp) : fHelp, i);
3048cdf0e10cSrcweir }
3049cdf0e10cSrcweir }
3050cdf0e10cSrcweir }
3051cdf0e10cSrcweir else // calculate multiple regression;
3052cdf0e10cSrcweir {
3053cdf0e10cSrcweir if (nCase ==2) // Y is column
3054cdf0e10cSrcweir {
3055cdf0e10cSrcweir ::std::vector< double> aVecR(N); // for QR decomposition
3056cdf0e10cSrcweir // Enough memory for needed matrices?
3057cdf0e10cSrcweir ScMatrixRef pMeans = GetNewMat(K, 1); // mean of each column
3058cdf0e10cSrcweir ScMatrixRef pSlopes = GetNewMat(1,K); // from b1 to bK
3059cdf0e10cSrcweir if (!pMeans || !pSlopes)
3060cdf0e10cSrcweir {
3061cdf0e10cSrcweir PushError(errCodeOverflow);
3062cdf0e10cSrcweir return;
3063cdf0e10cSrcweir }
3064cdf0e10cSrcweir if (bConstant)
3065cdf0e10cSrcweir {
3066cdf0e10cSrcweir lcl_CalculateColumnMeans(pMatX, pMeans, K, N);
3067cdf0e10cSrcweir lcl_CalculateColumnsDelta(pMatX, pMeans, K, N);
3068cdf0e10cSrcweir }
3069cdf0e10cSrcweir if (!lcl_CalculateQRdecomposition(pMatX, aVecR, K, N))
3070cdf0e10cSrcweir {
3071cdf0e10cSrcweir PushNoValue();
3072cdf0e10cSrcweir return;
3073cdf0e10cSrcweir }
3074cdf0e10cSrcweir // Later on we will divide by elements of aVecR, so make sure
3075cdf0e10cSrcweir // that they aren't zero.
3076cdf0e10cSrcweir bool bIsSingular=false;
3077cdf0e10cSrcweir for (SCSIZE row=0; row < K && !bIsSingular; row++)
3078cdf0e10cSrcweir bIsSingular = bIsSingular || aVecR[row]==0.0;
3079cdf0e10cSrcweir if (bIsSingular)
3080cdf0e10cSrcweir {
3081cdf0e10cSrcweir PushNoValue();
3082cdf0e10cSrcweir return;
3083cdf0e10cSrcweir }
3084cdf0e10cSrcweir // Z := Q' Y; Y is overwritten with result Z
3085cdf0e10cSrcweir for (SCSIZE col = 0; col < K; col++)
3086cdf0e10cSrcweir {
3087cdf0e10cSrcweir lcl_ApplyHouseholderTransformation(pMatX, col, pMatY, N);
3088cdf0e10cSrcweir }
3089cdf0e10cSrcweir // B = R^(-1) * Q' * Y <=> B = R^(-1) * Z <=> R * B = Z
3090cdf0e10cSrcweir // result Z should have zeros for index>=K; if not, ignore values
3091cdf0e10cSrcweir for (SCSIZE col = 0; col < K ; col++)
3092cdf0e10cSrcweir {
3093cdf0e10cSrcweir pSlopes->PutDouble( pMatY->GetDouble(col), col);
3094cdf0e10cSrcweir }
3095cdf0e10cSrcweir lcl_SolveWithUpperRightTriangle(pMatX, aVecR, pSlopes, K, false);
3096cdf0e10cSrcweir
3097cdf0e10cSrcweir // Fill result matrix
3098cdf0e10cSrcweir lcl_MFastMult(pMatNewX,pSlopes,pResMat,nRXN,K,1);
3099cdf0e10cSrcweir if (bConstant)
3100cdf0e10cSrcweir {
3101cdf0e10cSrcweir double fIntercept = fMeanY - lcl_GetSumProduct(pMeans,pSlopes,K);
3102cdf0e10cSrcweir for (SCSIZE row = 0; row < nRXN; row++)
3103cdf0e10cSrcweir pResMat->PutDouble(pResMat->GetDouble(row)+fIntercept, row);
3104cdf0e10cSrcweir }
3105cdf0e10cSrcweir if (_bGrowth)
3106cdf0e10cSrcweir {
3107cdf0e10cSrcweir for (SCSIZE i = 0; i < nRXN; i++)
3108cdf0e10cSrcweir pResMat->PutDouble(exp(pResMat->GetDouble(i)), i);
3109cdf0e10cSrcweir }
3110cdf0e10cSrcweir }
3111cdf0e10cSrcweir else
3112cdf0e10cSrcweir { // nCase == 3, Y is row, all matrices are transposed
3113cdf0e10cSrcweir
3114cdf0e10cSrcweir ::std::vector< double> aVecR(N); // for QR decomposition
3115cdf0e10cSrcweir // Enough memory for needed matrices?
3116cdf0e10cSrcweir ScMatrixRef pMeans = GetNewMat(1, K); // mean of each row
3117cdf0e10cSrcweir ScMatrixRef pSlopes = GetNewMat(K,1); // row from b1 to bK
3118cdf0e10cSrcweir if (!pMeans || !pSlopes)
3119cdf0e10cSrcweir {
3120cdf0e10cSrcweir PushError(errCodeOverflow);
3121cdf0e10cSrcweir return;
3122cdf0e10cSrcweir }
3123cdf0e10cSrcweir if (bConstant)
3124cdf0e10cSrcweir {
3125cdf0e10cSrcweir lcl_CalculateRowMeans(pMatX, pMeans, N, K);
3126cdf0e10cSrcweir lcl_CalculateRowsDelta(pMatX, pMeans, N, K);
3127cdf0e10cSrcweir }
3128cdf0e10cSrcweir if (!lcl_TCalculateQRdecomposition(pMatX, aVecR, K, N))
3129cdf0e10cSrcweir {
3130cdf0e10cSrcweir PushNoValue();
3131cdf0e10cSrcweir return;
3132cdf0e10cSrcweir }
3133cdf0e10cSrcweir // Later on we will divide by elements of aVecR, so make sure
3134cdf0e10cSrcweir // that they aren't zero.
3135cdf0e10cSrcweir bool bIsSingular=false;
3136cdf0e10cSrcweir for (SCSIZE row=0; row < K && !bIsSingular; row++)
3137cdf0e10cSrcweir bIsSingular = bIsSingular || aVecR[row]==0.0;
3138cdf0e10cSrcweir if (bIsSingular)
3139cdf0e10cSrcweir {
3140cdf0e10cSrcweir PushNoValue();
3141cdf0e10cSrcweir return;
3142cdf0e10cSrcweir }
3143cdf0e10cSrcweir // Z := Q' Y; Y is overwritten with result Z
3144cdf0e10cSrcweir for (SCSIZE row = 0; row < K; row++)
3145cdf0e10cSrcweir {
3146cdf0e10cSrcweir lcl_TApplyHouseholderTransformation(pMatX, row, pMatY, N);
3147cdf0e10cSrcweir }
3148cdf0e10cSrcweir // B = R^(-1) * Q' * Y <=> B = R^(-1) * Z <=> R * B = Z
3149cdf0e10cSrcweir // result Z should have zeros for index>=K; if not, ignore values
3150cdf0e10cSrcweir for (SCSIZE col = 0; col < K ; col++)
3151cdf0e10cSrcweir {
3152cdf0e10cSrcweir pSlopes->PutDouble( pMatY->GetDouble(col), col);
3153cdf0e10cSrcweir }
3154cdf0e10cSrcweir lcl_SolveWithUpperRightTriangle(pMatX, aVecR, pSlopes, K, true);
3155cdf0e10cSrcweir
3156cdf0e10cSrcweir // Fill result matrix
3157cdf0e10cSrcweir lcl_MFastMult(pSlopes,pMatNewX,pResMat,1,K,nCXN);
3158cdf0e10cSrcweir if (bConstant)
3159cdf0e10cSrcweir {
3160cdf0e10cSrcweir double fIntercept = fMeanY - lcl_GetSumProduct(pMeans,pSlopes,K);
3161cdf0e10cSrcweir for (SCSIZE col = 0; col < nCXN; col++)
3162cdf0e10cSrcweir pResMat->PutDouble(pResMat->GetDouble(col)+fIntercept, col);
3163cdf0e10cSrcweir }
3164cdf0e10cSrcweir if (_bGrowth)
3165cdf0e10cSrcweir {
3166cdf0e10cSrcweir for (SCSIZE i = 0; i < nCXN; i++)
3167cdf0e10cSrcweir pResMat->PutDouble(exp(pResMat->GetDouble(i)), i);
3168cdf0e10cSrcweir }
3169cdf0e10cSrcweir }
3170cdf0e10cSrcweir }
3171cdf0e10cSrcweir PushMatrix(pResMat);
3172cdf0e10cSrcweir return;
3173cdf0e10cSrcweir }
3174cdf0e10cSrcweir
ScMatRef()3175cdf0e10cSrcweir void ScInterpreter::ScMatRef()
3176cdf0e10cSrcweir {
3177cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScMatRef" );
3178cdf0e10cSrcweir // Falls Deltarefs drin sind...
3179cdf0e10cSrcweir Push( (FormulaToken&)*pCur );
3180cdf0e10cSrcweir ScAddress aAdr;
3181cdf0e10cSrcweir PopSingleRef( aAdr );
3182cdf0e10cSrcweir ScFormulaCell* pCell = (ScFormulaCell*) GetCell( aAdr );
3183cdf0e10cSrcweir if( pCell && pCell->GetCellType() == CELLTYPE_FORMULA )
3184cdf0e10cSrcweir {
3185cdf0e10cSrcweir const ScMatrix* pMat = pCell->GetMatrix();
3186cdf0e10cSrcweir if( pMat )
3187cdf0e10cSrcweir {
3188cdf0e10cSrcweir SCSIZE nCols, nRows;
3189cdf0e10cSrcweir pMat->GetDimensions( nCols, nRows );
3190cdf0e10cSrcweir SCSIZE nC = static_cast<SCSIZE>(aPos.Col() - aAdr.Col());
3191cdf0e10cSrcweir SCSIZE nR = static_cast<SCSIZE>(aPos.Row() - aAdr.Row());
3192cdf0e10cSrcweir if ((nCols <= nC && nCols != 1) || (nRows <= nR && nRows != 1))
3193cdf0e10cSrcweir PushNA();
3194cdf0e10cSrcweir else
3195cdf0e10cSrcweir {
3196cdf0e10cSrcweir ScMatValType nMatValType;
3197cdf0e10cSrcweir const ScMatrixValue* pMatVal = pMat->Get( nC, nR, nMatValType);
3198cdf0e10cSrcweir if (ScMatrix::IsNonValueType( nMatValType))
3199cdf0e10cSrcweir {
3200cdf0e10cSrcweir if (ScMatrix::IsEmptyPathType( nMatValType))
3201cdf0e10cSrcweir { // result of empty sal_False jump path
3202cdf0e10cSrcweir nFuncFmtType = NUMBERFORMAT_LOGICAL;
3203cdf0e10cSrcweir PushInt(0);
3204cdf0e10cSrcweir }
3205cdf0e10cSrcweir else if (ScMatrix::IsEmptyType( nMatValType))
3206cdf0e10cSrcweir {
3207cdf0e10cSrcweir // Not inherited (really?) and display as empty string, not 0.
3208cdf0e10cSrcweir PushTempToken( new ScEmptyCellToken( false, true));
3209cdf0e10cSrcweir }
3210cdf0e10cSrcweir else
3211cdf0e10cSrcweir PushString( pMatVal->GetString() );
3212cdf0e10cSrcweir }
3213cdf0e10cSrcweir else
3214cdf0e10cSrcweir {
3215cdf0e10cSrcweir PushDouble(pMatVal->fVal); // handles DoubleError
3216cdf0e10cSrcweir pDok->GetNumberFormatInfo( nCurFmtType, nCurFmtIndex, aAdr, pCell );
3217cdf0e10cSrcweir nFuncFmtType = nCurFmtType;
3218cdf0e10cSrcweir nFuncFmtIndex = nCurFmtIndex;
3219cdf0e10cSrcweir }
3220cdf0e10cSrcweir }
3221cdf0e10cSrcweir }
3222cdf0e10cSrcweir else
3223cdf0e10cSrcweir {
3224cdf0e10cSrcweir // If not a result matrix, obtain the cell value.
3225cdf0e10cSrcweir sal_uInt16 nErr = pCell->GetErrCode();
3226cdf0e10cSrcweir if (nErr)
3227cdf0e10cSrcweir PushError( nErr );
3228cdf0e10cSrcweir else if( pCell->IsValue() )
3229cdf0e10cSrcweir PushDouble( pCell->GetValue() );
3230cdf0e10cSrcweir else
3231cdf0e10cSrcweir {
3232cdf0e10cSrcweir String aVal;
3233cdf0e10cSrcweir pCell->GetString( aVal );
3234cdf0e10cSrcweir PushString( aVal );
3235cdf0e10cSrcweir }
3236cdf0e10cSrcweir pDok->GetNumberFormatInfo( nCurFmtType, nCurFmtIndex, aAdr, pCell );
3237cdf0e10cSrcweir nFuncFmtType = nCurFmtType;
3238cdf0e10cSrcweir nFuncFmtIndex = nCurFmtIndex;
3239cdf0e10cSrcweir }
3240cdf0e10cSrcweir }
3241cdf0e10cSrcweir else
3242cdf0e10cSrcweir PushError( errNoRef );
3243cdf0e10cSrcweir }
3244cdf0e10cSrcweir
ScInfo()3245cdf0e10cSrcweir void ScInterpreter::ScInfo()
3246cdf0e10cSrcweir {
3247cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScInfo" );
3248cdf0e10cSrcweir if( MustHaveParamCount( GetByte(), 1 ) )
3249cdf0e10cSrcweir {
3250cdf0e10cSrcweir String aStr = GetString();
3251cdf0e10cSrcweir ScCellKeywordTranslator::transKeyword(aStr, ScGlobal::GetLocale(), ocInfo);
3252cdf0e10cSrcweir if( aStr.EqualsAscii( "SYSTEM" ) )
3253cdf0e10cSrcweir PushString( String( RTL_CONSTASCII_USTRINGPARAM( SC_INFO_OSVERSION ) ) );
3254cdf0e10cSrcweir else if( aStr.EqualsAscii( "OSVERSION" ) )
3255cdf0e10cSrcweir PushString( String( RTL_CONSTASCII_USTRINGPARAM( "Windows (32-bit) NT 5.01" ) ) );
3256cdf0e10cSrcweir else if( aStr.EqualsAscii( "RELEASE" ) )
3257cdf0e10cSrcweir PushString( ::utl::Bootstrap::getBuildIdData( ::rtl::OUString() ) );
3258cdf0e10cSrcweir else if( aStr.EqualsAscii( "NUMFILE" ) )
3259cdf0e10cSrcweir PushDouble( 1 );
3260cdf0e10cSrcweir else if( aStr.EqualsAscii( "RECALC" ) )
3261cdf0e10cSrcweir PushString( ScGlobal::GetRscString( pDok->GetAutoCalc() ? STR_RECALC_AUTO : STR_RECALC_MANUAL ) );
3262cdf0e10cSrcweir else
3263cdf0e10cSrcweir PushIllegalArgument();
3264cdf0e10cSrcweir }
3265cdf0e10cSrcweir }
3266