1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: interpr5.cxx,v $
10 * $Revision: 1.33.36.3 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sc.hxx"
34 // INCLUDE ---------------------------------------------------------------
36 #ifndef INCLUDED_RTL_MATH_HXX
37 #include <rtl/math.hxx>
39 #include <rtl/logfile.hxx>
44 #if OSL_DEBUG_LEVEL > 1
47 #include <unotools/bootstrap.hxx>
48 #include <svtools/zforlist.hxx>
50 #include "interpre.hxx"
52 #include "compiler.hxx"
54 #include "document.hxx"
55 #include "dociter.hxx"
56 #include "scmatrix.hxx"
57 #include "globstr.hrc"
58 #include "cellkeytranslator.hxx"
59 #include "osversiondef.hxx"
66 using namespace formula
;
68 const double fInvEpsilon
= 1.0E-7;
70 // -----------------------------------------------------------------------
71 struct MatrixAdd
: public ::std::binary_function
<double,double,double>
73 inline double operator() (const double& lhs
, const double& rhs
) const
75 return ::rtl::math::approxAdd( lhs
,rhs
);
78 struct MatrixSub
: public ::std::binary_function
<double,double,double>
80 inline double operator() (const double& lhs
, const double& rhs
) const
82 return ::rtl::math::approxSub( lhs
,rhs
);
85 struct MatrixMul
: public ::std::binary_function
<double,double,double>
87 inline double operator() (const double& lhs
, const double& rhs
) const
92 struct MatrixDiv
: public ::std::binary_function
<double,double,double>
94 inline double operator() (const double& lhs
, const double& rhs
) const
96 return ScInterpreter::div( lhs
,rhs
);
99 struct MatrixPow
: public ::std::binary_function
<double,double,double>
101 inline double operator() (const double& lhs
, const double& rhs
) const
103 return ::pow( lhs
,rhs
);
107 double ScInterpreter::ScGetGCD(double fx
, double fy
)
109 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "sc", "er", "ScInterpreter::div" );
110 // By ODFF definition GCD(0,a) => a. This is also vital for the code in
111 // ScGCD() to work correctly with a preset fy=0.0
118 double fz
= fmod(fx
, fy
);
129 void ScInterpreter::ScGCD()
131 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "sc", "er", "ScInterpreter::ScGCD" );
132 short nParamCount
= GetByte();
133 if ( MustHaveParamCountMin( nParamCount
, 1 ) )
137 size_t nRefInList
= 0;
138 while (!nGlobalError
&& nParamCount
-- > 0)
140 switch (GetStackType())
146 fx
= ::rtl::math::approxFloor( GetDouble());
149 PushIllegalArgument();
152 fy
= ScGetGCD(fx
, fy
);
159 PopDoubleRef( aRange
, nParamCount
, nRefInList
);
161 ScValueIterator
aValIter(pDok
, aRange
, glSubTotal
);
162 if (aValIter
.GetFirst(nCellVal
, nErr
))
166 fx
= ::rtl::math::approxFloor( nCellVal
);
169 PushIllegalArgument();
172 fy
= ScGetGCD(fx
, fy
);
173 } while (nErr
== 0 && aValIter
.GetNext(nCellVal
, nErr
));
180 ScMatrixRef pMat
= PopMatrix();
184 pMat
->GetDimensions(nC
, nR
);
185 if (nC
== 0 || nR
== 0)
186 SetError(errIllegalArgument
);
189 SCSIZE nCount
= nC
* nR
;
190 for ( SCSIZE j
= 0; j
< nCount
; j
++ )
192 if (!pMat
->IsValue(j
))
194 PushIllegalArgument();
197 fx
= ::rtl::math::approxFloor( pMat
->GetDouble(j
));
200 PushIllegalArgument();
203 fy
= ScGetGCD(fx
, fy
);
209 default : SetError(errIllegalParameter
); break;
216 void ScInterpreter:: ScLCM()
218 short nParamCount
= GetByte();
219 if ( MustHaveParamCountMin( nParamCount
, 1 ) )
223 size_t nRefInList
= 0;
224 while (!nGlobalError
&& nParamCount
-- > 0)
226 switch (GetStackType())
232 fx
= ::rtl::math::approxFloor( GetDouble());
235 PushIllegalArgument();
238 if (fx
== 0.0 || fy
== 0.0)
241 fy
= fx
* fy
/ ScGetGCD(fx
, fy
);
248 PopDoubleRef( aRange
, nParamCount
, nRefInList
);
250 ScValueIterator
aValIter(pDok
, aRange
, glSubTotal
);
251 if (aValIter
.GetFirst(nCellVal
, nErr
))
255 fx
= ::rtl::math::approxFloor( nCellVal
);
258 PushIllegalArgument();
261 if (fx
== 0.0 || fy
== 0.0)
264 fy
= fx
* fy
/ ScGetGCD(fx
, fy
);
265 } while (nErr
== 0 && aValIter
.GetNext(nCellVal
, nErr
));
272 ScMatrixRef pMat
= PopMatrix();
276 pMat
->GetDimensions(nC
, nR
);
277 if (nC
== 0 || nR
== 0)
278 SetError(errIllegalArgument
);
281 SCSIZE nCount
= nC
* nR
;
282 for ( SCSIZE j
= 0; j
< nCount
; j
++ )
284 if (!pMat
->IsValue(j
))
286 PushIllegalArgument();
289 fx
= ::rtl::math::approxFloor( pMat
->GetDouble(j
));
292 PushIllegalArgument();
295 if (fx
== 0.0 || fy
== 0.0)
298 fy
= fx
* fy
/ ScGetGCD(fx
, fy
);
304 default : SetError(errIllegalParameter
); break;
311 ScMatrixRef
ScInterpreter::GetNewMat(SCSIZE nC
, SCSIZE nR
)
313 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "sc", "er", "ScInterpreter::GetNewMat" );
314 ScMatrix
* pMat
= new ScMatrix( nC
, nR
);
315 pMat
->SetErrorInterpreter( this);
317 pMat
->GetDimensions( nCols
, nRows
);
318 if ( nCols
!= nC
|| nRows
!= nR
)
319 { // arbitray limit of elements exceeded
320 SetError( errStackOverflow
);
327 ScInterpreter::VolatileType
ScInterpreter::GetVolatileType() const
329 return meVolaileType
;
332 ScMatrixRef
ScInterpreter::CreateMatrixFromDoubleRef( const FormulaToken
* pToken
,
333 SCCOL nCol1
, SCROW nRow1
, SCTAB nTab1
,
334 SCCOL nCol2
, SCROW nRow2
, SCTAB nTab2
)
336 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "sc", "er", "ScInterpreter::CreateMatrixFromDoubleRef" );
337 ScMatrixRef pMat
= NULL
;
338 if (nTab1
== nTab2
&& !nGlobalError
)
340 ScTokenMatrixMap::const_iterator aIter
;
341 if ( static_cast<SCSIZE
>(nRow2
- nRow1
+ 1) *
342 static_cast<SCSIZE
>(nCol2
- nCol1
+ 1) >
343 ScMatrix::GetElementsMax() )
344 SetError(errStackOverflow
);
345 else if (pTokenMatrixMap
&& ((aIter
= pTokenMatrixMap
->find( pToken
))
346 != pTokenMatrixMap
->end()))
347 pMat
= static_cast<ScToken
*>((*aIter
).second
.get())->GetMatrix();
350 SCSIZE nMatCols
= static_cast<SCSIZE
>(nCol2
- nCol1
+ 1);
351 SCSIZE nMatRows
= static_cast<SCSIZE
>(nRow2
- nRow1
+ 1);
352 pMat
= GetNewMat( nMatCols
, nMatRows
);
353 if (pMat
&& !nGlobalError
)
355 // Set position where the next entry is expected.
356 SCROW nNextRow
= nRow1
;
357 SCCOL nNextCol
= nCol1
;
358 // Set last position as if there was a previous entry.
359 SCROW nThisRow
= nRow2
;
360 SCCOL nThisCol
= nCol1
- 1;
361 ScCellIterator
aCellIter( pDok
, nCol1
, nRow1
, nTab1
, nCol2
,
363 for (ScBaseCell
* pCell
= aCellIter
.GetFirst(); pCell
; pCell
=
366 nThisCol
= aCellIter
.GetCol();
367 nThisRow
= aCellIter
.GetRow();
368 if (nThisCol
!= nNextCol
|| nThisRow
!= nNextRow
)
370 // Fill empty between iterator's positions.
371 for ( ; nNextCol
<= nThisCol
; ++nNextCol
)
373 SCSIZE nC
= nNextCol
- nCol1
;
374 SCSIZE nMatStopRow
= ((nNextCol
< nThisCol
) ?
375 nMatRows
: nThisRow
- nRow1
);
376 for (SCSIZE nR
= nNextRow
- nRow1
; nR
<
379 pMat
->PutEmpty( nC
, nR
);
384 if (nThisRow
== nRow2
)
386 nNextCol
= nThisCol
+ 1;
392 nNextRow
= nThisRow
+ 1;
394 if (HasCellEmptyData(pCell
))
396 pMat
->PutEmpty( static_cast<SCSIZE
>(nThisCol
-nCol1
),
397 static_cast<SCSIZE
>(nThisRow
-nRow1
));
399 else if (HasCellValueData(pCell
))
401 ScAddress
aAdr( nThisCol
, nThisRow
, nTab1
);
402 double fVal
= GetCellValue( aAdr
, pCell
);
405 fVal
= CreateDoubleError( nGlobalError
);
408 pMat
->PutDouble( fVal
,
409 static_cast<SCSIZE
>(nThisCol
-nCol1
),
410 static_cast<SCSIZE
>(nThisRow
-nRow1
));
415 GetCellString( aStr
, pCell
);
418 double fVal
= CreateDoubleError( nGlobalError
);
420 pMat
->PutDouble( fVal
,
421 static_cast<SCSIZE
>(nThisCol
-nCol1
),
422 static_cast<SCSIZE
>(nThisRow
-nRow1
));
425 pMat
->PutString( aStr
,
426 static_cast<SCSIZE
>(nThisCol
-nCol1
),
427 static_cast<SCSIZE
>(nThisRow
-nRow1
));
430 // Fill empty if iterator's last position wasn't the end.
431 if (nThisCol
!= nCol2
|| nThisRow
!= nRow2
)
433 for ( ; nNextCol
<= nCol2
; ++nNextCol
)
435 SCSIZE nC
= nNextCol
- nCol1
;
436 for (SCSIZE nR
= nNextRow
- nRow1
; nR
< nMatRows
; ++nR
)
438 pMat
->PutEmpty( nC
, nR
);
444 pTokenMatrixMap
->insert( ScTokenMatrixMap::value_type(
445 pToken
, new ScMatrixToken( pMat
)));
449 else // not a 2D matrix
450 SetError(errIllegalParameter
);
455 ScMatrixRef
ScInterpreter::GetMatrix()
457 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "sc", "er", "ScInterpreter::GetMatrix" );
458 ScMatrixRef pMat
= NULL
;
459 switch (GetRawStackType())
464 PopSingleRef( aAdr
);
465 pMat
= GetNewMat(1, 1);
468 ScBaseCell
* pCell
= GetCell( aAdr
);
469 if (HasCellEmptyData(pCell
))
471 else if (HasCellValueData(pCell
))
472 pMat
->PutDouble(GetCellValue(aAdr
, pCell
), 0);
476 GetCellString(aStr
, pCell
);
477 pMat
->PutString(aStr
, 0);
487 const ScToken
* p
= sp
? static_cast<const ScToken
*>(pStack
[sp
-1]) : NULL
;
488 PopDoubleRef(nCol1
, nRow1
, nTab1
, nCol2
, nRow2
, nTab2
);
489 pMat
= CreateMatrixFromDoubleRef( p
, nCol1
, nRow1
, nTab1
,
490 nCol2
, nRow2
, nTab2
);
500 double fVal
= GetDouble();
501 pMat
= GetNewMat( 1, 1);
506 fVal
= CreateDoubleError( nGlobalError
);
509 pMat
->PutDouble( fVal
, 0);
515 String aStr
= GetString();
516 pMat
= GetNewMat( 1, 1);
521 double fVal
= CreateDoubleError( nGlobalError
);
522 pMat
->PutDouble( fVal
, 0);
526 pMat
->PutString( aStr
, 0);
532 SetError( errIllegalArgument
);
538 void ScInterpreter::ScMatValue()
540 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "sc", "er", "ScInterpreter::ScMatValue" );
541 if ( MustHaveParamCount( GetByte(), 3 ) )
544 SCSIZE nR
= static_cast<SCSIZE
>(::rtl::math::approxFloor(GetDouble()));
545 SCSIZE nC
= static_cast<SCSIZE
>(::rtl::math::approxFloor(GetDouble()));
546 switch (GetStackType())
551 PopSingleRef( aAdr
);
552 ScBaseCell
* pCell
= GetCell( aAdr
);
553 if (pCell
&& pCell
->GetCellType() == CELLTYPE_FORMULA
)
555 USHORT nErrCode
= ((ScFormulaCell
*)pCell
)->GetErrCode();
557 PushError( nErrCode
);
560 const ScMatrix
* pMat
= ((ScFormulaCell
*)pCell
)->GetMatrix();
561 CalculateMatrixValue(pMat
,nC
,nR
);
565 PushIllegalParameter();
576 PopDoubleRef(nCol1
, nRow1
, nTab1
, nCol2
, nRow2
, nTab2
);
577 if (nCol2
- nCol1
>= static_cast<SCCOL
>(nR
) &&
578 nRow2
- nRow1
>= static_cast<SCROW
>(nC
) &&
581 ScAddress
aAdr( sal::static_int_cast
<SCCOL
>( nCol1
+ nR
),
582 sal::static_int_cast
<SCROW
>( nRow1
+ nC
), nTab1
);
583 ScBaseCell
* pCell
= GetCell( aAdr
);
584 if (HasCellValueData(pCell
))
585 PushDouble(GetCellValue( aAdr
, pCell
));
589 GetCellString(aStr
, pCell
);
599 ScMatrixRef pMat
= PopMatrix();
600 CalculateMatrixValue(pMat
,nC
,nR
);
605 PushIllegalParameter();
610 void ScInterpreter::CalculateMatrixValue(const ScMatrix
* pMat
,SCSIZE nC
,SCSIZE nR
)
612 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "sc", "er", "ScInterpreter::CalculateMatrixValue" );
616 pMat
->GetDimensions(nCl
, nRw
);
617 if (nC
< nCl
&& nR
< nRw
)
619 ScMatValType nMatValType
;
620 const ScMatrixValue
* pMatVal
= pMat
->Get( nC
, nR
,nMatValType
);
621 if (ScMatrix::IsNonValueType( nMatValType
))
622 PushString( pMatVal
->GetString() );
624 PushDouble(pMatVal
->fVal
);
625 // also handles DoubleError
634 void ScInterpreter::ScEMat()
636 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "sc", "er", "ScInterpreter::ScEMat" );
637 if ( MustHaveParamCount( GetByte(), 1 ) )
639 SCSIZE nDim
= static_cast<SCSIZE
>(::rtl::math::approxFloor(GetDouble()));
640 if ( nDim
* nDim
> ScMatrix::GetElementsMax() || nDim
== 0)
641 PushIllegalArgument();
644 ScMatrixRef pRMat
= GetNewMat(nDim
, nDim
);
651 PushIllegalArgument();
656 void ScInterpreter::MEMat(ScMatrix
* mM
, SCSIZE n
)
658 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "sc", "er", "ScInterpreter::MEMat" );
659 mM
->FillDouble(0.0, 0, 0, n
-1, n
-1);
660 for (SCSIZE i
= 0; i
< n
; i
++)
661 mM
->PutDouble(1.0, i
, i
);
664 void ScInterpreter::MFastMult(ScMatrix
* pA
, ScMatrix
* pB
, ScMatrix
* pR
,
665 SCSIZE n
, SCSIZE m
, SCSIZE l
)
666 // Multipliziert n x m Mat a mit m x l Mat b nach Mat r
668 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "sc", "er", "ScInterpreter::MFastMult" );
670 for (SCSIZE i
= 0; i
< n
; i
++)
672 for (SCSIZE j
= 0; j
< l
; j
++)
675 for (SCSIZE k
= 0; k
< m
; k
++)
676 sum
+= pA
->GetDouble(i
,k
)*pB
->GetDouble(k
,j
);
677 pR
->PutDouble(sum
, i
, j
);
683 /* Matrix LUP decomposition according to the pseudocode of "Introduction to
684 * Algorithms" by Cormen, Leiserson, Rivest, Stein.
686 * Added scaling for numeric stability.
688 * Given an n x n nonsingular matrix A, find a permutation matrix P, a unit
689 * lower-triangular matrix L, and an upper-triangular matrix U such that PA=LU.
690 * Compute L and U "in place" in the matrix A, the original content is
691 * destroyed. Note that the diagonal elements of the U triangular matrix
692 * replace the diagonal elements of the L-unit matrix (that are each ==1). The
693 * permutation matrix P is an array, where P[i]=j means that the i-th row of P
694 * contains a 1 in column j. Additionally keep track of the number of
695 * permutations (row exchanges).
697 * Returns 0 if a singular matrix is encountered, else +1 if an even number of
698 * permutations occured, or -1 if odd, which is the sign of the determinant.
699 * This may be used to calculate the determinant by multiplying the sign with
700 * the product of the diagonal elements of the LU matrix.
702 static int lcl_LUP_decompose( ScMatrix
* mA
, const SCSIZE n
,
703 ::std::vector
< SCSIZE
> & P
)
706 // Find scale of each row.
707 ::std::vector
< double> aScale(n
);
708 for (SCSIZE i
=0; i
< n
; ++i
)
711 for (SCSIZE j
=0; j
< n
; ++j
)
713 double fTmp
= fabs( mA
->GetDouble( j
, i
));
718 return 0; // singular matrix
719 aScale
[i
] = 1.0 / fMax
;
721 // Represent identity permutation, P[i]=i
722 for (SCSIZE i
=0; i
< n
; ++i
)
724 // "Recursion" on the diagonale.
726 for (SCSIZE k
=0; k
< l
; ++k
)
728 // Implicit pivoting. With the scale found for a row, compare values of
729 // a column and pick largest.
731 double fScale
= aScale
[k
];
733 for (SCSIZE i
= k
; i
< n
; ++i
)
735 double fTmp
= fScale
* fabs( mA
->GetDouble( k
, i
));
743 return 0; // singular matrix
744 // Swap rows. The pivot element will be at mA[k,kp] (row,col notation)
753 double fTmp
= aScale
[k
];
754 aScale
[k
] = aScale
[kp
];
757 for (SCSIZE i
=0; i
< n
; ++i
)
759 double fMatTmp
= mA
->GetDouble( i
, k
);
760 mA
->PutDouble( mA
->GetDouble( i
, kp
), i
, k
);
761 mA
->PutDouble( fMatTmp
, i
, kp
);
764 // Compute Schur complement.
765 for (SCSIZE i
= k
+1; i
< n
; ++i
)
767 double fTmp
= mA
->GetDouble( k
, i
) / mA
->GetDouble( k
, k
);
768 mA
->PutDouble( fTmp
, k
, i
);
769 for (SCSIZE j
= k
+1; j
< n
; ++j
)
770 mA
->PutDouble( mA
->GetDouble( j
, i
) - fTmp
* mA
->GetDouble( j
,
774 #if OSL_DEBUG_LEVEL > 1
775 fprintf( stderr
, "\n%s\n", "lcl_LUP_decompose(): LU");
776 for (SCSIZE i
=0; i
< n
; ++i
)
778 for (SCSIZE j
=0; j
< n
; ++j
)
779 fprintf( stderr
, "%8.2g ", mA
->GetDouble( j
, i
));
780 fprintf( stderr
, "\n%s\n", "");
782 fprintf( stderr
, "\n%s\n", "lcl_LUP_decompose(): P");
783 for (SCSIZE j
=0; j
< n
; ++j
)
784 fprintf( stderr
, "%5u ", (unsigned)P
[j
]);
785 fprintf( stderr
, "\n%s\n", "");
791 /* Solve a LUP decomposed equation Ax=b. LU is a combined matrix of L and U
792 * triangulars and P the permutation vector as obtained from
793 * lcl_LUP_decompose(). B is the right-hand side input vector, X is used to
794 * return the solution vector.
796 static void lcl_LUP_solve( const ScMatrix
* mLU
, const SCSIZE n
,
797 const ::std::vector
< SCSIZE
> & P
, const ::std::vector
< double> & B
,
798 ::std::vector
< double> & X
)
800 SCSIZE nFirst
= SCSIZE_MAX
;
801 // Ax=b => PAx=Pb, with decomposition LUx=Pb.
802 // Define y=Ux and solve for y in Ly=Pb using forward substitution.
803 for (SCSIZE i
=0; i
< n
; ++i
)
805 double fSum
= B
[P
[i
]];
806 // Matrix inversion comes with a lot of zeros in the B vectors, we
807 // don't have to do all the computing with results multiplied by zero.
808 // Until then, simply lookout for the position of the first nonzero
810 if (nFirst
!= SCSIZE_MAX
)
812 for (SCSIZE j
= nFirst
; j
< i
; ++j
)
813 fSum
-= mLU
->GetDouble( j
, i
) * X
[j
]; // X[j] === y[j]
817 X
[i
] = fSum
; // X[i] === y[i]
819 // Solve for x in Ux=y using back substitution.
820 for (SCSIZE i
= n
; i
--; )
822 double fSum
= X
[i
]; // X[i] === y[i]
823 for (SCSIZE j
= i
+1; j
< n
; ++j
)
824 fSum
-= mLU
->GetDouble( j
, i
) * X
[j
]; // X[j] === x[j]
825 X
[i
] = fSum
/ mLU
->GetDouble( i
, i
); // X[i] === x[i]
827 #if OSL_DEBUG_LEVEL >1
828 fprintf( stderr
, "\n%s\n", "lcl_LUP_solve():");
829 for (SCSIZE i
=0; i
< n
; ++i
)
830 fprintf( stderr
, "%8.2g ", X
[i
]);
831 fprintf( stderr
, "%s\n", "");
836 void ScInterpreter::ScMatDet()
838 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "sc", "er", "ScInterpreter::ScMatDet" );
839 if ( MustHaveParamCount( GetByte(), 1 ) )
841 ScMatrixRef pMat
= GetMatrix();
844 PushIllegalParameter();
847 if ( !pMat
->IsNumeric() )
853 pMat
->GetDimensions(nC
, nR
);
854 if ( nC
!= nR
|| nC
== 0 || (ULONG
) nC
* nC
> ScMatrix::GetElementsMax() )
855 PushIllegalArgument();
858 // LUP decomposition is done inplace, use copy.
859 ScMatrixRef xLU
= pMat
->Clone();
861 PushError( errCodeOverflow
);
864 ::std::vector
< SCSIZE
> P(nR
);
865 int nDetSign
= lcl_LUP_decompose( xLU
, nR
, P
);
867 PushInt(0); // singular matrix
870 // In an LU matrix the determinant is simply the product of
871 // all diagonal elements.
872 double fDet
= nDetSign
;
874 for (SCSIZE i
=0; i
< nR
; ++i
)
875 fDet
*= pLU
->GetDouble( i
, i
);
883 void ScInterpreter::ScMatInv()
885 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "sc", "er", "ScInterpreter::ScMatInv" );
886 if ( MustHaveParamCount( GetByte(), 1 ) )
888 ScMatrixRef pMat
= GetMatrix();
891 PushIllegalParameter();
894 if ( !pMat
->IsNumeric() )
900 pMat
->GetDimensions(nC
, nR
);
901 if ( nC
!= nR
|| nC
== 0 || (ULONG
) nC
* nC
> ScMatrix::GetElementsMax() )
902 PushIllegalArgument();
905 // LUP decomposition is done inplace, use copy.
906 ScMatrixRef xLU
= pMat
->Clone();
907 // The result matrix.
908 ScMatrixRef xY
= GetNewMat( nR
, nR
);
910 PushError( errCodeOverflow
);
913 ::std::vector
< SCSIZE
> P(nR
);
914 int nDetSign
= lcl_LUP_decompose( xLU
, nR
, P
);
916 PushIllegalArgument();
919 // Solve equation for each column.
921 ::std::vector
< double> B(nR
);
922 ::std::vector
< double> X(nR
);
923 for (SCSIZE j
=0; j
< nR
; ++j
)
925 for (SCSIZE i
=0; i
< nR
; ++i
)
928 lcl_LUP_solve( xLU
, nR
, P
, B
, X
);
929 for (SCSIZE i
=0; i
< nR
; ++i
)
930 pY
->PutDouble( X
[i
], j
, i
);
933 /* Possible checks for ill-condition:
934 * 1. Scale matrix, invert scaled matrix. If there are
935 * elements of the inverted matrix that are several
936 * orders of magnitude greater than 1 =>
938 * Just how much is "several orders"?
939 * 2. Invert the inverted matrix and assess whether the
940 * result is sufficiently close to the original matrix.
941 * If not => ill-conditioned.
942 * Just what is sufficient?
943 * 3. Multiplying the inverse by the original matrix should
944 * produce a result sufficiently close to the identity
946 * Just what is sufficient?
948 * The following is #3.
950 ScMatrixRef xR
= GetNewMat( nR
, nR
);
954 MFastMult( pMat
, pY
, pR
, nR
, nR
, nR
);
955 #if OSL_DEBUG_LEVEL > 1
956 fprintf( stderr
, "\n%s\n", "ScMatInv(): mult-identity");
958 for (SCSIZE i
=0; i
< nR
; ++i
)
960 for (SCSIZE j
=0; j
< nR
; ++j
)
962 double fTmp
= pR
->GetDouble( j
, i
);
963 #if OSL_DEBUG_LEVEL > 1
964 fprintf( stderr
, "%8.2g ", fTmp
);
966 if (fabs( fTmp
- (i
== j
)) > fInvEpsilon
)
967 SetError( errIllegalArgument
);
969 #if OSL_DEBUG_LEVEL > 1
970 fprintf( stderr
, "\n%s\n", "");
976 PushError( nGlobalError
);
985 void ScInterpreter::ScMatMult()
987 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "sc", "er", "ScInterpreter::ScMatMult" );
988 if ( MustHaveParamCount( GetByte(), 2 ) )
990 ScMatrixRef pMat2
= GetMatrix();
991 ScMatrixRef pMat1
= GetMatrix();
995 if ( pMat1
->IsNumeric() && pMat2
->IsNumeric() )
999 pMat1
->GetDimensions(nC1
, nR1
);
1000 pMat2
->GetDimensions(nC2
, nR2
);
1002 PushIllegalArgument();
1005 pRMat
= GetNewMat(nC2
, nR1
);
1009 for (SCSIZE i
= 0; i
< nR1
; i
++)
1011 for (SCSIZE j
= 0; j
< nC2
; j
++)
1014 for (SCSIZE k
= 0; k
< nC1
; k
++)
1016 sum
+= pMat1
->GetDouble(k
,i
)*pMat2
->GetDouble(j
,k
);
1018 pRMat
->PutDouble(sum
, j
, i
);
1024 PushIllegalArgument();
1031 PushIllegalParameter();
1035 void ScInterpreter::ScMatTrans()
1037 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "sc", "er", "ScInterpreter::ScMatTrans" );
1038 if ( MustHaveParamCount( GetByte(), 1 ) )
1040 ScMatrixRef pMat
= GetMatrix();
1045 pMat
->GetDimensions(nC
, nR
);
1046 pRMat
= GetNewMat(nR
, nC
);
1049 pMat
->MatTrans(*pRMat
);
1053 PushIllegalArgument();
1056 PushIllegalParameter();
1061 /** Minimum extent of one result matrix dimension.
1062 For a row or column vector to be replicated the larger matrix dimension is
1063 returned, else the smaller dimension.
1065 inline SCSIZE
lcl_GetMinExtent( SCSIZE n1
, SCSIZE n2
)
1077 template<class _Function
>
1078 ScMatrixRef
lcl_MatrixCalculation(const _Function
& _pOperation
,ScMatrix
* pMat1
, ScMatrix
* pMat2
,ScInterpreter
* _pIterpreter
)
1080 SCSIZE nC1
, nC2
, nMinC
;
1081 SCSIZE nR1
, nR2
, nMinR
;
1083 pMat1
->GetDimensions(nC1
, nR1
);
1084 pMat2
->GetDimensions(nC2
, nR2
);
1085 nMinC
= lcl_GetMinExtent( nC1
, nC2
);
1086 nMinR
= lcl_GetMinExtent( nR1
, nR2
);
1087 ScMatrixRef xResMat
= _pIterpreter
->GetNewMat(nMinC
, nMinR
);
1090 ScMatrix
* pResMat
= xResMat
;
1091 for (i
= 0; i
< nMinC
; i
++)
1093 for (j
= 0; j
< nMinR
; j
++)
1095 if (pMat1
->IsValueOrEmpty(i
,j
) && pMat2
->IsValueOrEmpty(i
,j
))
1097 double d
= _pOperation(pMat1
->GetDouble(i
,j
),pMat2
->GetDouble(i
,j
));
1098 pResMat
->PutDouble( d
, i
, j
);
1101 pResMat
->PutString(ScGlobal::GetRscString(STR_NO_VALUE
), i
, j
);
1108 ScMatrixRef
ScInterpreter::MatConcat(ScMatrix
* pMat1
, ScMatrix
* pMat2
)
1110 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "sc", "er", "ScInterpreter::MatConcat" );
1111 SCSIZE nC1
, nC2
, nMinC
;
1112 SCSIZE nR1
, nR2
, nMinR
;
1114 pMat1
->GetDimensions(nC1
, nR1
);
1115 pMat2
->GetDimensions(nC2
, nR2
);
1116 nMinC
= lcl_GetMinExtent( nC1
, nC2
);
1117 nMinR
= lcl_GetMinExtent( nR1
, nR2
);
1118 ScMatrixRef xResMat
= GetNewMat(nMinC
, nMinR
);
1121 ScMatrix
* pResMat
= xResMat
;
1122 for (i
= 0; i
< nMinC
; i
++)
1124 for (j
= 0; j
< nMinR
; j
++)
1126 USHORT nErr
= pMat1
->GetErrorIfNotString( i
, j
);
1128 nErr
= pMat2
->GetErrorIfNotString( i
, j
);
1130 pResMat
->PutError( nErr
, i
, j
);
1133 String
aTmp( pMat1
->GetString( *pFormatter
, i
, j
));
1134 aTmp
+= pMat2
->GetString( *pFormatter
, i
, j
);
1135 pResMat
->PutString( aTmp
, i
, j
);
1144 // fuer DATE, TIME, DATETIME
1145 void lcl_GetDiffDateTimeFmtType( short& nFuncFmt
, short nFmt1
, short nFmt2
)
1147 if ( nFmt1
!= NUMBERFORMAT_UNDEFINED
|| nFmt2
!= NUMBERFORMAT_UNDEFINED
)
1149 if ( nFmt1
== nFmt2
)
1151 if ( nFmt1
== NUMBERFORMAT_TIME
|| nFmt1
== NUMBERFORMAT_DATETIME
)
1152 nFuncFmt
= NUMBERFORMAT_TIME
; // Zeiten ergeben Zeit
1153 // else: nichts besonderes, Zahl (Datum - Datum := Tage)
1155 else if ( nFmt1
== NUMBERFORMAT_UNDEFINED
)
1156 nFuncFmt
= nFmt2
; // z.B. Datum + Tage := Datum
1157 else if ( nFmt2
== NUMBERFORMAT_UNDEFINED
)
1161 if ( nFmt1
== NUMBERFORMAT_DATE
|| nFmt2
== NUMBERFORMAT_DATE
||
1162 nFmt1
== NUMBERFORMAT_DATETIME
|| nFmt2
== NUMBERFORMAT_DATETIME
)
1164 if ( nFmt1
== NUMBERFORMAT_TIME
|| nFmt2
== NUMBERFORMAT_TIME
)
1165 nFuncFmt
= NUMBERFORMAT_DATETIME
; // Datum + Zeit
1172 void ScInterpreter::ScAdd()
1174 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "sc", "er", "ScInterpreter::ScAdd" );
1175 CalculateAddSub(FALSE
);
1177 void ScInterpreter::CalculateAddSub(BOOL _bSub
)
1179 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "sc", "er", "ScInterpreter::CalculateAddSub" );
1180 ScMatrixRef pMat1
= NULL
;
1181 ScMatrixRef pMat2
= NULL
;
1182 double fVal1
= 0.0, fVal2
= 0.0;
1184 nFmt1
= nFmt2
= NUMBERFORMAT_UNDEFINED
;
1185 short nFmtCurrencyType
= nCurFmtType
;
1186 ULONG nFmtCurrencyIndex
= nCurFmtIndex
;
1187 short nFmtPercentType
= nCurFmtType
;
1188 if ( GetStackType() == svMatrix
)
1189 pMat2
= GetMatrix();
1192 fVal2
= GetDouble();
1193 switch ( nCurFmtType
)
1195 case NUMBERFORMAT_DATE
:
1196 case NUMBERFORMAT_TIME
:
1197 case NUMBERFORMAT_DATETIME
:
1198 nFmt2
= nCurFmtType
;
1200 case NUMBERFORMAT_CURRENCY
:
1201 nFmtCurrencyType
= nCurFmtType
;
1202 nFmtCurrencyIndex
= nCurFmtIndex
;
1204 case NUMBERFORMAT_PERCENT
:
1205 nFmtPercentType
= NUMBERFORMAT_PERCENT
;
1209 if ( GetStackType() == svMatrix
)
1210 pMat1
= GetMatrix();
1213 fVal1
= GetDouble();
1214 switch ( nCurFmtType
)
1216 case NUMBERFORMAT_DATE
:
1217 case NUMBERFORMAT_TIME
:
1218 case NUMBERFORMAT_DATETIME
:
1219 nFmt1
= nCurFmtType
;
1221 case NUMBERFORMAT_CURRENCY
:
1222 nFmtCurrencyType
= nCurFmtType
;
1223 nFmtCurrencyIndex
= nCurFmtIndex
;
1225 case NUMBERFORMAT_PERCENT
:
1226 nFmtPercentType
= NUMBERFORMAT_PERCENT
;
1232 ScMatrixRef pResMat
;
1236 pResMat
= lcl_MatrixCalculation(aSub
,pMat1
, pMat2
,this);
1241 pResMat
= lcl_MatrixCalculation(aAdd
,pMat1
, pMat2
,this);
1247 PushMatrix(pResMat
);
1249 else if (pMat1
|| pMat2
)
1253 ScMatrixRef pMat
= pMat1
;
1258 bFlag
= TRUE
; // double - Matrix
1263 bFlag
= FALSE
; // Matrix - double
1266 pMat
->GetDimensions(nC
, nR
);
1267 ScMatrixRef pResMat
= GetNewMat(nC
, nR
);
1270 SCSIZE nCount
= nC
* nR
;
1271 if (bFlag
|| !_bSub
)
1273 for ( SCSIZE i
= 0; i
< nCount
; i
++ )
1275 if (pMat
->IsValue(i
))
1276 pResMat
->PutDouble( _bSub
? ::rtl::math::approxSub( fVal
, pMat
->GetDouble(i
)) : ::rtl::math::approxAdd( pMat
->GetDouble(i
), fVal
), i
);
1278 pResMat
->PutString(ScGlobal::GetRscString(STR_NO_VALUE
), i
);
1279 } // for ( SCSIZE i = 0; i < nCount; i++ )
1280 } // if (bFlag || !_bSub )
1283 for ( SCSIZE i
= 0; i
< nCount
; i
++ )
1284 { if (pMat
->IsValue(i
))
1285 pResMat
->PutDouble( ::rtl::math::approxSub( pMat
->GetDouble(i
), fVal
), i
);
1287 pResMat
->PutString(ScGlobal::GetRscString(STR_NO_VALUE
), i
);
1288 } // for ( SCSIZE i = 0; i < nCount; i++ )
1290 PushMatrix(pResMat
);
1293 PushIllegalArgument();
1296 PushDouble( ::rtl::math::approxSub( fVal1
, fVal2
) );
1298 PushDouble( ::rtl::math::approxAdd( fVal1
, fVal2
) );
1299 if ( nFmtCurrencyType
== NUMBERFORMAT_CURRENCY
)
1301 nFuncFmtType
= nFmtCurrencyType
;
1302 nFuncFmtIndex
= nFmtCurrencyIndex
;
1306 lcl_GetDiffDateTimeFmtType( nFuncFmtType
, nFmt1
, nFmt2
);
1307 if ( nFmtPercentType
== NUMBERFORMAT_PERCENT
&& nFuncFmtType
== NUMBERFORMAT_NUMBER
)
1308 nFuncFmtType
= NUMBERFORMAT_PERCENT
;
1312 void ScInterpreter::ScAmpersand()
1314 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "sc", "er", "ScInterpreter::ScAmpersand" );
1315 ScMatrixRef pMat1
= NULL
;
1316 ScMatrixRef pMat2
= NULL
;
1317 String sStr1
, sStr2
;
1318 if ( GetStackType() == svMatrix
)
1319 pMat2
= GetMatrix();
1321 sStr2
= GetString();
1322 if ( GetStackType() == svMatrix
)
1323 pMat1
= GetMatrix();
1325 sStr1
= GetString();
1328 ScMatrixRef pResMat
= MatConcat(pMat1
, pMat2
);
1332 PushMatrix(pResMat
);
1334 else if (pMat1
|| pMat2
)
1338 ScMatrixRef pMat
= pMat1
;
1343 bFlag
= TRUE
; // double - Matrix
1348 bFlag
= FALSE
; // Matrix - double
1351 pMat
->GetDimensions(nC
, nR
);
1352 ScMatrixRef pResMat
= GetNewMat(nC
, nR
);
1355 SCSIZE nCount
= nC
* nR
;
1358 for ( SCSIZE i
= 0; i
< nCount
; i
++ )
1359 pResMat
->PutError( nGlobalError
, i
);
1363 for ( SCSIZE i
= 0; i
< nCount
; i
++ )
1365 USHORT nErr
= pMat
->GetErrorIfNotString( i
);
1367 pResMat
->PutError( nErr
, i
);
1371 aTmp
+= pMat
->GetString( *pFormatter
, i
);
1372 pResMat
->PutString( aTmp
, i
);
1378 for ( SCSIZE i
= 0; i
< nCount
; i
++ )
1380 USHORT nErr
= pMat
->GetErrorIfNotString( i
);
1382 pResMat
->PutError( nErr
, i
);
1385 String
aTmp( pMat
->GetString( *pFormatter
, i
));
1387 pResMat
->PutString( aTmp
, i
);
1391 PushMatrix(pResMat
);
1394 PushIllegalArgument();
1398 if ( CheckStringResultLen( sStr1
, sStr2
) )
1404 void ScInterpreter::ScSub()
1406 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "sc", "er", "ScInterpreter::ScSub" );
1407 CalculateAddSub(TRUE
);
1410 void ScInterpreter::ScMul()
1412 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "sc", "er", "ScInterpreter::ScMul" );
1413 ScMatrixRef pMat1
= NULL
;
1414 ScMatrixRef pMat2
= NULL
;
1415 double fVal1
= 0.0, fVal2
= 0.0;
1416 short nFmtCurrencyType
= nCurFmtType
;
1417 ULONG nFmtCurrencyIndex
= nCurFmtIndex
;
1418 if ( GetStackType() == svMatrix
)
1419 pMat2
= GetMatrix();
1422 fVal2
= GetDouble();
1423 switch ( nCurFmtType
)
1425 case NUMBERFORMAT_CURRENCY
:
1426 nFmtCurrencyType
= nCurFmtType
;
1427 nFmtCurrencyIndex
= nCurFmtIndex
;
1431 if ( GetStackType() == svMatrix
)
1432 pMat1
= GetMatrix();
1435 fVal1
= GetDouble();
1436 switch ( nCurFmtType
)
1438 case NUMBERFORMAT_CURRENCY
:
1439 nFmtCurrencyType
= nCurFmtType
;
1440 nFmtCurrencyIndex
= nCurFmtIndex
;
1447 ScMatrixRef pResMat
= lcl_MatrixCalculation(aMul
,pMat1
, pMat2
,this);
1451 PushMatrix(pResMat
);
1453 else if (pMat1
|| pMat2
)
1456 ScMatrixRef pMat
= pMat1
;
1465 pMat
->GetDimensions(nC
, nR
);
1466 ScMatrixRef pResMat
= GetNewMat(nC
, nR
);
1469 SCSIZE nCount
= nC
* nR
;
1470 for ( SCSIZE i
= 0; i
< nCount
; i
++ )
1471 if (pMat
->IsValue(i
))
1472 pResMat
->PutDouble(pMat
->GetDouble(i
)*fVal
, i
);
1474 pResMat
->PutString(ScGlobal::GetRscString(STR_NO_VALUE
), i
);
1475 PushMatrix(pResMat
);
1478 PushIllegalArgument();
1481 PushDouble(fVal1
* fVal2
);
1482 if ( nFmtCurrencyType
== NUMBERFORMAT_CURRENCY
)
1484 nFuncFmtType
= nFmtCurrencyType
;
1485 nFuncFmtIndex
= nFmtCurrencyIndex
;
1489 void ScInterpreter::ScDiv()
1491 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "sc", "er", "ScInterpreter::ScDiv" );
1492 ScMatrixRef pMat1
= NULL
;
1493 ScMatrixRef pMat2
= NULL
;
1494 double fVal1
= 0.0, fVal2
= 0.0;
1495 short nFmtCurrencyType
= nCurFmtType
;
1496 ULONG nFmtCurrencyIndex
= nCurFmtIndex
;
1497 short nFmtCurrencyType2
= NUMBERFORMAT_UNDEFINED
;
1498 if ( GetStackType() == svMatrix
)
1499 pMat2
= GetMatrix();
1502 fVal2
= GetDouble();
1503 // hier kein Currency uebernehmen, 123kg/456DM sind nicht DM
1504 nFmtCurrencyType2
= nCurFmtType
;
1506 if ( GetStackType() == svMatrix
)
1507 pMat1
= GetMatrix();
1510 fVal1
= GetDouble();
1511 switch ( nCurFmtType
)
1513 case NUMBERFORMAT_CURRENCY
:
1514 nFmtCurrencyType
= nCurFmtType
;
1515 nFmtCurrencyIndex
= nCurFmtIndex
;
1522 ScMatrixRef pResMat
= lcl_MatrixCalculation(aDiv
,pMat1
, pMat2
,this);
1526 PushMatrix(pResMat
);
1528 else if (pMat1
|| pMat2
)
1532 ScMatrixRef pMat
= pMat1
;
1537 bFlag
= TRUE
; // double - Matrix
1542 bFlag
= FALSE
; // Matrix - double
1545 pMat
->GetDimensions(nC
, nR
);
1546 ScMatrixRef pResMat
= GetNewMat(nC
, nR
);
1549 SCSIZE nCount
= nC
* nR
;
1551 { for ( SCSIZE i
= 0; i
< nCount
; i
++ )
1552 if (pMat
->IsValue(i
))
1553 pResMat
->PutDouble( div( fVal
, pMat
->GetDouble(i
)), i
);
1555 pResMat
->PutString(ScGlobal::GetRscString(STR_NO_VALUE
), i
);
1558 { for ( SCSIZE i
= 0; i
< nCount
; i
++ )
1559 if (pMat
->IsValue(i
))
1560 pResMat
->PutDouble( div( pMat
->GetDouble(i
), fVal
), i
);
1562 pResMat
->PutString(ScGlobal::GetRscString(STR_NO_VALUE
), i
);
1564 PushMatrix(pResMat
);
1567 PushIllegalArgument();
1571 PushDouble( div( fVal1
, fVal2
) );
1573 if ( nFmtCurrencyType
== NUMBERFORMAT_CURRENCY
&& nFmtCurrencyType2
!= NUMBERFORMAT_CURRENCY
)
1574 { // auch DM/DM ist nicht DM bzw. DEM/EUR nicht DEM
1575 nFuncFmtType
= nFmtCurrencyType
;
1576 nFuncFmtIndex
= nFmtCurrencyIndex
;
1580 void ScInterpreter::ScPower()
1582 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "sc", "er", "ScInterpreter::ScPower" );
1583 if ( MustHaveParamCount( GetByte(), 2 ) )
1587 void ScInterpreter::ScPow()
1589 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "sc", "er", "ScInterpreter::ScPow" );
1590 ScMatrixRef pMat1
= NULL
;
1591 ScMatrixRef pMat2
= NULL
;
1592 double fVal1
= 0.0, fVal2
= 0.0;
1593 if ( GetStackType() == svMatrix
)
1594 pMat2
= GetMatrix();
1596 fVal2
= GetDouble();
1597 if ( GetStackType() == svMatrix
)
1598 pMat1
= GetMatrix();
1600 fVal1
= GetDouble();
1604 ScMatrixRef pResMat
= lcl_MatrixCalculation(aPow
,pMat1
, pMat2
,this);
1608 PushMatrix(pResMat
);
1610 else if (pMat1
|| pMat2
)
1614 ScMatrixRef pMat
= pMat1
;
1619 bFlag
= TRUE
; // double - Matrix
1624 bFlag
= FALSE
; // Matrix - double
1627 pMat
->GetDimensions(nC
, nR
);
1628 ScMatrixRef pResMat
= GetNewMat(nC
, nR
);
1631 SCSIZE nCount
= nC
* nR
;
1633 { for ( SCSIZE i
= 0; i
< nCount
; i
++ )
1634 if (pMat
->IsValue(i
))
1635 pResMat
->PutDouble(pow(fVal
,pMat
->GetDouble(i
)), i
);
1637 pResMat
->PutString(ScGlobal::GetRscString(STR_NO_VALUE
), i
);
1640 { for ( SCSIZE i
= 0; i
< nCount
; i
++ )
1641 if (pMat
->IsValue(i
))
1642 pResMat
->PutDouble(pow(pMat
->GetDouble(i
),fVal
), i
);
1644 pResMat
->PutString(ScGlobal::GetRscString(STR_NO_VALUE
), i
);
1646 PushMatrix(pResMat
);
1649 PushIllegalArgument();
1652 PushDouble(pow(fVal1
,fVal2
));
1655 void ScInterpreter::ScSumProduct()
1657 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "sc", "er", "ScInterpreter::ScSumProduct" );
1658 BYTE nParamCount
= GetByte();
1659 if ( !MustHaveParamCount( nParamCount
, 1, 30 ) )
1662 ScMatrixRef pMat1
= NULL
;
1663 ScMatrixRef pMat2
= NULL
;
1664 ScMatrixRef pMat
= NULL
;
1665 pMat2
= GetMatrix();
1668 PushIllegalParameter();
1673 pMat2
->GetDimensions(nC
, nR
);
1676 for (USHORT i
= 1; i
< nParamCount
; i
++)
1678 pMat1
= GetMatrix();
1681 PushIllegalParameter();
1684 pMat1
->GetDimensions(nC1
, nR1
);
1685 if (nC1
!= nC
|| nR1
!= nR
)
1690 ScMatrixRef pResMat
= lcl_MatrixCalculation(aMul
,pMat1
, pMat
,this);
1700 SCSIZE nCount
= pMat
->GetElementCount();
1701 for (SCSIZE j
= 0; j
< nCount
; j
++)
1703 if (!pMat
->IsString(j
))
1704 fSum
+= pMat
->GetDouble(j
);
1709 void ScInterpreter::ScSumX2MY2()
1711 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "sc", "er", "ScInterpreter::ScSumX2MY2" );
1712 CalculateSumX2MY2SumX2DY2(FALSE
);
1714 void ScInterpreter::CalculateSumX2MY2SumX2DY2(BOOL _bSumX2DY2
)
1716 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "sc", "er", "ScInterpreter::CalculateSumX2MY2SumX2DY2" );
1717 if ( !MustHaveParamCount( GetByte(), 2 ) )
1720 ScMatrixRef pMat1
= NULL
;
1721 ScMatrixRef pMat2
= NULL
;
1723 pMat2
= GetMatrix();
1724 pMat1
= GetMatrix();
1725 if (!pMat2
|| !pMat1
)
1727 PushIllegalParameter();
1732 pMat2
->GetDimensions(nC2
, nR2
);
1733 pMat1
->GetDimensions(nC1
, nR1
);
1734 if (nC1
!= nC2
|| nR1
!= nR2
)
1739 double fVal
, fSum
= 0.0;
1740 for (i
= 0; i
< nC1
; i
++)
1741 for (j
= 0; j
< nR1
; j
++)
1742 if (!pMat1
->IsString(i
,j
) && !pMat2
->IsString(i
,j
))
1744 fVal
= pMat1
->GetDouble(i
,j
);
1745 fSum
+= fVal
* fVal
;
1746 fVal
= pMat2
->GetDouble(i
,j
);
1748 fSum
+= fVal
* fVal
;
1750 fSum
-= fVal
* fVal
;
1755 void ScInterpreter::ScSumX2DY2()
1757 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "sc", "er", "ScInterpreter::ScSumX2DY2" );
1758 CalculateSumX2MY2SumX2DY2(TRUE
);
1761 void ScInterpreter::ScSumXMY2()
1763 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "sc", "er", "ScInterpreter::ScSumXMY2" );
1764 if ( !MustHaveParamCount( GetByte(), 2 ) )
1767 ScMatrixRef pMat1
= NULL
;
1768 ScMatrixRef pMat2
= NULL
;
1769 pMat2
= GetMatrix();
1770 pMat1
= GetMatrix();
1771 if (!pMat2
|| !pMat1
)
1773 PushIllegalParameter();
1778 pMat2
->GetDimensions(nC2
, nR2
);
1779 pMat1
->GetDimensions(nC1
, nR1
);
1780 if (nC1
!= nC2
|| nR1
!= nR2
)
1784 } // if (nC1 != nC2 || nR1 != nR2)
1786 ScMatrixRef pResMat
= lcl_MatrixCalculation(aSub
,pMat1
, pMat2
,this);
1793 double fVal
, fSum
= 0.0;
1794 SCSIZE nCount
= pResMat
->GetElementCount();
1795 for (SCSIZE i
= 0; i
< nCount
; i
++)
1796 if (!pResMat
->IsString(i
))
1798 fVal
= pResMat
->GetDouble(i
);
1799 fSum
+= fVal
* fVal
;
1805 void ScInterpreter::ScFrequency()
1807 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "sc", "er", "ScInterpreter::ScFrequency" );
1808 if ( !MustHaveParamCount( GetByte(), 2 ) )
1811 vector
<double> aBinArray
;
1812 vector
<long> aBinIndexOrder
;
1814 GetSortArray(1, aBinArray
, &aBinIndexOrder
);
1815 SCSIZE nBinSize
= aBinArray
.size();
1822 vector
<double> aDataArray
;
1823 GetSortArray(1, aDataArray
);
1824 SCSIZE nDataSize
= aDataArray
.size();
1826 if (aDataArray
.empty() || nGlobalError
)
1831 ScMatrixRef pResMat
= GetNewMat(1, nBinSize
+1);
1834 PushIllegalArgument();
1838 if (nBinSize
!= aBinIndexOrder
.size())
1840 PushIllegalArgument();
1846 for (j
= 0; j
< nBinSize
; ++j
)
1849 while (i
< nDataSize
&& aDataArray
[i
] <= aBinArray
[j
])
1854 pResMat
->PutDouble(static_cast<double>(nCount
), aBinIndexOrder
[j
]);
1856 pResMat
->PutDouble(static_cast<double>(nDataSize
-i
), j
);
1857 PushMatrix(pResMat
);
1860 BOOL
ScInterpreter::RGetVariances( ScMatrix
* pV
, ScMatrix
* pX
,
1861 SCSIZE nC
, SCSIZE nR
, BOOL bSwapColRow
, BOOL bZeroConstant
)
1862 { // multiple Regression: Varianzen der Koeffizienten
1863 // bSwapColRow==TRUE : Koeffizienten in Zeilen statt Spalten angeordnet
1866 ScMatrixRef pC
= GetNewMat(nC
, nC
);
1869 // X transformiert mit X multipziert, X'X Matrix
1870 if ( !bZeroConstant
)
1871 { // in der X-Designmatrix existiert ein gedachtes X0j==1
1874 for ( i
=0; i
<nC
; i
++ )
1876 for ( j
=0; j
<nC
; j
++ )
1879 for ( k
=0; k
<nR
; k
++ )
1881 sum
+= (j
==0 ? 1 : pX
->GetDouble(k
,j
-1))
1882 * (i
==0 ? 1 : pX
->GetDouble(k
,i
-1));
1884 pC
->PutDouble(sum
, i
, j
);
1890 for ( i
=0; i
<nC
; i
++ )
1892 for ( j
=0; j
<nC
; j
++ )
1895 for ( k
=0; k
<nR
; k
++ )
1897 sum
+= (j
==0 ? 1 : pX
->GetDouble(j
-1,k
))
1898 * (i
==0 ? 1 : pX
->GetDouble(i
-1,k
));
1900 pC
->PutDouble(sum
, i
, j
);
1909 for ( i
=0; i
<nC
; i
++ )
1911 for ( j
=0; j
<nC
; j
++ )
1914 for ( k
=0; k
<nR
; k
++ )
1916 sum
+= pX
->GetDouble(k
,j
) * pX
->GetDouble(k
,i
);
1918 pC
->PutDouble(sum
, i
, j
);
1924 for ( i
=0; i
<nC
; i
++ )
1926 for ( j
=0; j
<nC
; j
++ )
1929 for ( k
=0; k
<nR
; k
++ )
1931 sum
+= pX
->GetDouble(j
,k
) * pX
->GetDouble(i
,k
);
1933 pC
->PutDouble(sum
, i
, j
);
1940 USHORT nErr
= nGlobalError
;
1948 nGlobalError
= nErr
;
1953 // #i61216# ScMatInv no longer modifies the original matrix, so just calling Pop() doesn't work
1957 // Varianzen auf der Diagonalen, andere sind Kovarianzen
1958 for (i
= 0; i
< nC
; i
++)
1959 pV
->PutDouble(pC
->GetDouble(i
, i
), i
);
1964 // -----------------------------------------------------------------------------
1965 void ScInterpreter::Calculate(ScMatrixRef
& pResMat
,ScMatrixRef
& pE
,ScMatrixRef
& pQ
,ScMatrixRef
& pV
,ScMatrixRef
& pMatX
,BOOL bConstant
,SCSIZE N
,SCSIZE M
,BYTE nCase
)
1967 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "sc", "er", "ScInterpreter::RGetVariances" );
1968 // pE[0] := Sigma i=1...n (Yi)
1969 // pE[k] := Sigma i=1...n (Xki*Yi)
1970 // pE[M+1] := Sigma i=1...n (Yi**2)
1973 double fSQR
, fSQT
, fSQE
;
1974 fSQT
= pE
->GetDouble(M
+1)
1975 - pE
->GetDouble(0) * pE
->GetDouble(0) / (double)N
;
1976 fSQR
= pE
->GetDouble(M
+1);
1978 for (i
= 0; i
< M
+1; i
++)
1979 fSQR
-= pQ
->GetDouble(i
, M
+1) * pE
->GetDouble(i
);
1981 // r2 (Bestimmtheitsmass, 0...1)
1983 pResMat
->PutString(ScGlobal::GetRscString(STR_NO_VALUE
), 0, 2);
1985 pResMat
->PutDouble (fSQE
/fSQT
, 0, 2);
1986 // ssReg (Regressions-Quadratsumme)
1987 pResMat
->PutDouble(fSQE
, 0, 4);
1988 // ssResid (Residual-Quadratsumme, Summe der Abweichungsquadrate)
1989 pResMat
->PutDouble(fSQR
, 1, 4);
1990 for (i
= 2; i
< 5; i
++)
1991 for (j
= 2; j
< M
+1; j
++)
1992 pResMat
->PutString(ScGlobal::GetRscString(STR_NV_STR
), j
, i
);
1997 pResMat
->PutString(ScGlobal::GetRscString(STR_NO_VALUE
), 1, 2);
1998 for (i
= 0; i
< M
+1; i
++)
1999 pResMat
->PutString(ScGlobal::GetRscString(STR_NO_VALUE
), i
, 1);
2003 double fSE2
= fSQR
/(N
-M
-1);
2004 // sey (Standardfehler des Schaetzwertes y)
2005 pResMat
->PutDouble(sqrt(fSE2
), 1, 2);
2006 // sen...se1 (Standardfehler der Koeffizienten mn...m1)
2007 // seb (Standardfehler der Konstanten b)
2008 if ( RGetVariances( pV
, pMatX
, M
+1, N
, nCase
!= 2, FALSE
) )
2010 for (i
= 0; i
< M
+1; i
++)
2011 pResMat
->PutDouble( sqrt(fSE2
* pV
->GetDouble(i
)), M
-i
, 1 );
2015 for (i
= 0; i
< M
+1; i
++)
2016 pResMat
->PutString(ScGlobal::GetRscString(STR_NV_STR
), i
, 1);
2021 pResMat
->PutString(ScGlobal::GetRscString(STR_NO_VALUE
), 0, 3);
2023 pResMat
->PutDouble(((double)(N
-M
-1))*fSQE
/fSQR
/((double)M
),0, 3);
2024 // df (Freiheitsgrad)
2025 pResMat
->PutDouble(((double)(N
-M
-1)), 1, 3);
2031 pResMat
->PutString(ScGlobal::GetRscString(STR_NO_VALUE
), 1, 2);
2032 for (i
= 0; i
< M
+1; i
++)
2033 pResMat
->PutString(ScGlobal::GetRscString(STR_NO_VALUE
), i
, 1);
2037 double fSE2
= fSQR
/(N
-M
);
2038 pResMat
->PutDouble(sqrt(fSE2
), 1, 2);
2039 if ( RGetVariances( pV
, pMatX
, M
, N
, nCase
!= 2, TRUE
) )
2041 for (i
= 0; i
< M
; i
++)
2042 pResMat
->PutDouble( sqrt(fSE2
* pV
->GetDouble(i
)), M
-i
-1, 1 );
2043 pResMat
->PutString(ScGlobal::GetRscString(STR_NV_STR
), M
, 1);
2047 for (i
= 0; i
< M
+1; i
++)
2048 pResMat
->PutString(ScGlobal::GetRscString(STR_NV_STR
), i
, 1);
2052 pResMat
->PutString(ScGlobal::GetRscString(STR_NO_VALUE
), 0, 3);
2054 pResMat
->PutDouble(((double)(N
-M
))*fSQE
/fSQR
/((double)M
),0, 3);
2055 pResMat
->PutDouble(((double)(N
-M
)), 1, 3);
2059 void ScInterpreter::ScRGP()
2061 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "sc", "er", "ScInterpreter::ScRGP" );
2062 CalulateRGPRKP(FALSE
);
2064 bool ScInterpreter::CheckMatrix(BOOL _bLOG
,BOOL _bTrendGrowth
,BYTE
& nCase
,SCSIZE
& nCX
,SCSIZE
& nCY
,SCSIZE
& nRX
,SCSIZE
& nRY
,SCSIZE
& M
,SCSIZE
& N
,ScMatrixRef
& pMatX
,ScMatrixRef
& pMatY
)
2072 pMatY
->GetDimensions(nCY
, nRY
);
2073 const SCSIZE nCountY
= nCY
* nRY
;
2074 for ( SCSIZE i
= 0; i
< nCountY
; i
++ )
2076 if (!pMatY
->IsValue(i
))
2078 PushIllegalArgument();
2080 } // if (!pMatY->IsValue(i))
2081 } // for ( SCSIZE i = 0; i < nCountY; i++ )
2084 for (SCSIZE nElem
= 0; nElem
< nCountY
; nElem
++)
2086 const double fVal
= pMatY
->GetDouble(nElem
);
2089 PushIllegalArgument();
2093 pMatY
->PutDouble(log(fVal
), nElem
);
2094 } // for (nElem = 0; nElem < nCountY; nElem++)
2100 pMatX
->GetDimensions(nCX
, nRX
);
2101 const SCSIZE nCountX
= nCX
* nRX
;
2102 for ( SCSIZE i
= 0; i
< nCountX
; i
++ )
2103 if (!pMatX
->IsValue(i
))
2105 PushIllegalArgument();
2108 if (nCX
== nCY
&& nRX
== nRY
)
2109 nCase
= 1; // einfache Regression
2110 else if (nCY
!= 1 && nRY
!= 1)
2112 PushIllegalArgument();
2119 PushIllegalArgument();
2124 nCase
= 2; // zeilenweise
2129 else if (nCX
!= nCY
)
2131 PushIllegalArgument();
2136 nCase
= 3; // spaltenweise
2143 pMatX
= GetNewMat(nCY
, nRY
);
2144 if ( _bTrendGrowth
)
2151 PushIllegalArgument();
2154 for ( SCSIZE i
= 1; i
<= nCountY
; i
++ )
2155 pMatX
->PutDouble((double)i
, i
-1);
2160 void ScInterpreter::CalulateRGPRKP(BOOL _bRKP
)
2162 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "sc", "er", "ScInterpreter::CheckMatrix" );
2163 BYTE nParamCount
= GetByte();
2164 if ( !MustHaveParamCount( nParamCount
, 1, 4 ) )
2166 BOOL bConstant
, bStats
;
2167 if (nParamCount
== 4)
2171 if (nParamCount
>= 3)
2172 bConstant
= GetBool();
2177 if (nParamCount
>= 2)
2178 pMatX
= GetMatrix();
2181 pMatY
= GetMatrix();
2184 PushIllegalParameter();
2187 BYTE nCase
; // 1 = normal, 2,3 = mehrfach
2190 SCSIZE M
= 0, N
= 0;
2191 if ( !CheckMatrix(_bRKP
,FALSE
,nCase
,nCX
,nCY
,nRX
,nRY
,M
,N
,pMatX
,pMatY
) )
2194 ScMatrixRef pResMat
;
2198 pResMat
= GetNewMat(2,1);
2200 pResMat
= GetNewMat(2,5);
2203 PushIllegalArgument();
2206 double fCount
= 0.0;
2208 double fSumSqrX
= 0.0;
2210 double fSumSqrY
= 0.0;
2211 double fSumXY
= 0.0;
2212 double fValX
, fValY
;
2213 for (SCSIZE i
= 0; i
< nCY
; i
++)
2214 for (SCSIZE j
= 0; j
< nRY
; j
++)
2216 fValX
= pMatX
->GetDouble(i
,j
);
2217 fValY
= pMatY
->GetDouble(i
,j
);
2219 fSumSqrX
+= fValX
* fValX
;
2221 fSumSqrY
+= fValY
* fValY
;
2222 fSumXY
+= fValX
*fValY
;
2229 double f1
= fCount
*fSumXY
-fSumX
*fSumY
;
2230 double fX
= fCount
*fSumSqrX
-fSumX
*fSumX
;
2234 b
= fSumY
/fCount
- f1
/fX
*fSumX
/fCount
;
2240 m
= fSumXY
/fSumSqrX
;
2242 pResMat
->PutDouble(_bRKP
? exp(m
) : m
, 0, 0);
2243 pResMat
->PutDouble(_bRKP
? exp(b
) : b
, 1, 0);
2246 double fY
= fCount
*fSumSqrY
-fSumY
*fSumY
;
2247 double fSyx
= fSumSqrY
-b
*fSumY
-m
*fSumXY
;
2248 double fR2
= f1
*f1
/(fX
*fY
);
2249 pResMat
->PutDouble (fR2
, 0, 2);
2252 pResMat
->PutString(ScGlobal::GetRscString(STR_NO_VALUE
), 0, 1 );
2253 pResMat
->PutString(ScGlobal::GetRscString(STR_NO_VALUE
), 1, 1 );
2254 pResMat
->PutString(ScGlobal::GetRscString(STR_NO_VALUE
), 1, 2 );
2255 pResMat
->PutString(ScGlobal::GetRscString(STR_NO_VALUE
), 0, 3 );
2259 pResMat
->PutDouble(sqrt(fSyx
*fCount
/(fX
*(fCount
-2.0))), 0, 1);
2260 pResMat
->PutDouble(sqrt(fSyx
*fSumSqrX
/fX
/(fCount
-2.0)), 1, 1);
2262 sqrt((fCount
*fSumSqrY
- fSumY
*fSumY
- f1
*f1
/fX
)/
2263 (fCount
*(fCount
-2.0))), 1, 2);
2265 pResMat
->PutString(ScGlobal::GetRscString(STR_NO_VALUE
), 0, 3 );
2267 pResMat
->PutDouble(fR2
*(fCount
-2.0)/(1.0-fR2
), 0, 3);
2269 pResMat
->PutDouble(((double)(nCY
*nRY
))-2.0, 1, 3);
2270 pResMat
->PutDouble(fY
/fCount
-fSyx
, 0, 4);
2271 pResMat
->PutDouble(fSyx
, 1, 4);
2274 } // if (nCase == 1)
2279 pResMat
= GetNewMat(M
+1,1);
2281 pResMat
= GetNewMat(M
+1,5);
2284 PushIllegalArgument();
2287 ScMatrixRef pQ
= GetNewMat(M
+1, M
+2);
2288 ScMatrixRef pE
= GetNewMat(M
+2, 1);
2289 ScMatrixRef pV
= GetNewMat(M
+1, 1);
2290 pE
->PutDouble(0.0, M
+1);
2291 pQ
->FillDouble(0.0, 0, 0, M
, M
+1);
2294 for (k
= 0; k
< N
; k
++)
2296 double Yk
= pMatY
->GetDouble(k
);
2297 pE
->PutDouble( pE
->GetDouble(M
+1)+Yk
*Yk
, M
+1 );
2298 double sumYk
= pQ
->GetDouble(0, M
+1) + Yk
;
2299 pQ
->PutDouble( sumYk
, 0, M
+1 );
2300 pE
->PutDouble( sumYk
, 0 );
2301 for (i
= 0; i
< M
; i
++)
2303 double Xik
= pMatX
->GetDouble(i
,k
);
2304 double sumXik
= pQ
->GetDouble(0, i
+1) + Xik
;
2305 pQ
->PutDouble( sumXik
, 0, i
+1);
2306 pQ
->PutDouble( sumXik
, i
+1, 0);
2307 double sumXikYk
= pQ
->GetDouble(i
+1, M
+1) + Xik
* Yk
;
2308 pQ
->PutDouble( sumXikYk
, i
+1, M
+1);
2309 pE
->PutDouble( sumXikYk
, i
+1);
2310 for (j
= i
; j
< M
; j
++)
2312 const double fVal
= pMatX
->GetDouble(j
,k
);
2313 double sumXikXjk
= pQ
->GetDouble(j
+1, i
+1) +
2315 pQ
->PutDouble( sumXikXjk
, j
+1, i
+1);
2316 pQ
->PutDouble( sumXikXjk
, i
+1, j
+1);
2323 for (k
= 0; k
< N
; k
++)
2325 double Yk
= pMatY
->GetDouble(k
);
2326 pE
->PutDouble( pE
->GetDouble(M
+1)+Yk
*Yk
, M
+1 );
2327 double sumYk
= pQ
->GetDouble(0, M
+1) + Yk
;
2328 pQ
->PutDouble( sumYk
, 0, M
+1 );
2329 pE
->PutDouble( sumYk
, 0 );
2330 for (i
= 0; i
< M
; i
++)
2332 double Xki
= pMatX
->GetDouble(k
,i
);
2333 double sumXki
= pQ
->GetDouble(0, i
+1) + Xki
;
2334 pQ
->PutDouble( sumXki
, 0, i
+1);
2335 pQ
->PutDouble( sumXki
, i
+1, 0);
2336 double sumXkiYk
= pQ
->GetDouble(i
+1, M
+1) + Xki
* Yk
;
2337 pQ
->PutDouble( sumXkiYk
, i
+1, M
+1);
2338 pE
->PutDouble( sumXkiYk
, i
+1);
2339 for (j
= i
; j
< M
; j
++)
2341 const double fVal
= pMatX
->GetDouble(k
,j
);
2342 double sumXkiXkj
= pQ
->GetDouble(j
+1, i
+1) +
2344 pQ
->PutDouble( sumXkiXkj
, j
+1, i
+1);
2345 pQ
->PutDouble( sumXkiXkj
, i
+1, j
+1);
2350 if ( !Calculate4(_bRKP
,pResMat
,pQ
,bConstant
,N
,M
) )
2354 Calculate(pResMat
,pE
,pQ
,pV
,pMatX
,bConstant
,N
,M
,nCase
);
2356 PushMatrix(pResMat
);
2359 void ScInterpreter::ScRKP()
2361 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "sc", "er", "ScInterpreter::ScRKP" );
2362 CalulateRGPRKP(TRUE
);
2364 // -----------------------------------------------------------------------------
2365 bool ScInterpreter::Calculate4(BOOL _bExp
,ScMatrixRef
& pResMat
,ScMatrixRef
& pQ
,BOOL bConstant
,SCSIZE N
,SCSIZE M
)
2367 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "sc", "er", "ScInterpreter::Calculate4" );
2368 pQ
->PutDouble((double)N
, 0, 0);
2372 for (S
= 0; S
< M
+1; S
++)
2375 while (i
< M
+1 && pQ
->GetDouble(i
, S
) == 0.0)
2383 for (L
= 0; L
< M
+2; L
++)
2385 fVal
= pQ
->GetDouble(S
, L
);
2386 pQ
->PutDouble(pQ
->GetDouble(i
, L
), S
, L
);
2387 pQ
->PutDouble(fVal
, i
, L
);
2389 fVal
= 1.0/pQ
->GetDouble(S
, S
);
2390 for (L
= 0; L
< M
+2; L
++)
2391 pQ
->PutDouble(pQ
->GetDouble(S
, L
)*fVal
, S
, L
);
2392 for (i
= 0; i
< M
+1; i
++)
2396 fVal
= -pQ
->GetDouble(i
, S
);
2397 for (L
= 0; L
< M
+2; L
++)
2399 pQ
->GetDouble(i
,L
)+fVal
*pQ
->GetDouble(S
,L
),i
,L
);
2406 if ( !Calculate3(M
,pQ
) )
2410 for (SCSIZE i
= 0; i
< M
+1; i
++)
2412 const double d
= pQ
->GetDouble(M
-i
,M
+1);
2413 pResMat
->PutDouble(_bExp
? exp(d
) : d
, i
, 0);
2414 } // for (SCSIZE i = 0; i < M+1; i++)
2418 ScMatrixRef
ScInterpreter::Calculate2(const BOOL bConstant
,const SCSIZE M
,const SCSIZE N
,ScMatrixRef
& pMatX
,ScMatrixRef
& pMatY
,BYTE nCase
)
2420 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "sc", "er", "ScInterpreter::Calculate2" );
2422 ScMatrixRef pQ
= GetNewMat(M
+1, M
+2);
2423 ScMatrixRef pE
= GetNewMat(M
+2, 1);
2424 pE
->PutDouble(0.0, M
+1);
2425 pQ
->FillDouble(0.0, 0, 0, M
, M
+1);
2428 for (k
= 0; k
< N
; k
++)
2431 pE
->GetDouble(M
+1)+pMatY
->GetDouble(k
)*pMatY
->GetDouble(k
), M
+1);
2432 pQ
->PutDouble(pQ
->GetDouble(0, M
+1) + pMatY
->GetDouble(k
), 0, M
+1);
2433 pE
->PutDouble(pQ
->GetDouble(0, M
+1), 0);
2434 for (i
= 0; i
< M
; i
++)
2436 pQ
->PutDouble(pQ
->GetDouble(0, i
+1)+pMatX
->GetDouble(i
,k
), 0, i
+1);
2437 pQ
->PutDouble(pQ
->GetDouble(0, i
+1), i
+1, 0);
2438 pQ
->PutDouble(pQ
->GetDouble(i
+1, M
+1) +
2439 pMatX
->GetDouble(i
,k
)*pMatY
->GetDouble(k
), i
+1, M
+1);
2440 pE
->PutDouble(pQ
->GetDouble(i
+1, M
+1), i
+1);
2441 for (j
= i
; j
< M
; j
++)
2443 pQ
->PutDouble(pQ
->GetDouble(j
+1, i
+1) +
2444 pMatX
->GetDouble(i
,k
)*pMatX
->GetDouble(j
,k
), j
+1, i
+1);
2445 pQ
->PutDouble(pQ
->GetDouble(j
+1, i
+1), i
+1, j
+1);
2452 for (k
= 0; k
< N
; k
++)
2455 pE
->GetDouble(M
+1)+pMatY
->GetDouble(k
)*pMatY
->GetDouble(k
), M
+1);
2456 pQ
->PutDouble(pQ
->GetDouble(0, M
+1) + pMatY
->GetDouble(k
), 0, M
+1);
2457 pE
->PutDouble(pQ
->GetDouble(0, M
+1), 0);
2458 for (i
= 0; i
< M
; i
++)
2460 pQ
->PutDouble(pQ
->GetDouble(0, i
+1)+pMatX
->GetDouble(k
,i
), 0, i
+1);
2461 pQ
->PutDouble(pQ
->GetDouble(0, i
+1), i
+1, 0);
2462 pQ
->PutDouble(pQ
->GetDouble(i
+1, M
+1) +
2463 pMatX
->GetDouble(k
,i
)*pMatY
->GetDouble(k
), i
+1, M
+1);
2464 pE
->PutDouble(pQ
->GetDouble(i
+1, M
+1), i
+1);
2465 for (j
= i
; j
< M
; j
++)
2467 pQ
->PutDouble(pQ
->GetDouble(j
+1, i
+1) +
2468 pMatX
->GetDouble(k
, i
)*pMatX
->GetDouble(k
, j
), j
+1, i
+1);
2469 pQ
->PutDouble(pQ
->GetDouble(j
+1, i
+1), i
+1, j
+1);
2474 pQ
->PutDouble((double)N
, 0, 0);
2478 for (S
= 0; S
< M
+1; S
++)
2481 while (i
< M
+1 && pQ
->GetDouble(i
, S
) == 0.0)
2486 return ScMatrixRef();
2489 for (L
= 0; L
< M
+2; L
++)
2491 fVal
= pQ
->GetDouble(S
, L
);
2492 pQ
->PutDouble(pQ
->GetDouble(i
, L
), S
, L
);
2493 pQ
->PutDouble(fVal
, i
, L
);
2495 fVal
= 1.0/pQ
->GetDouble(S
, S
);
2496 for (L
= 0; L
< M
+2; L
++)
2497 pQ
->PutDouble(pQ
->GetDouble(S
, L
)*fVal
, S
, L
);
2498 for (i
= 0; i
< M
+1; i
++)
2502 fVal
= -pQ
->GetDouble(i
, S
);
2503 for (L
= 0; L
< M
+2; L
++)
2505 pQ
->GetDouble(i
,L
)+fVal
*pQ
->GetDouble(S
,L
),i
,L
);
2512 if ( !Calculate3(M
,pQ
) )
2513 return ScMatrixRef();
2517 bool ScInterpreter::Calculate3(const SCSIZE M
,ScMatrixRef
& pQ
)
2519 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "sc", "er", "ScInterpreter::Calculate3" );
2521 for (S
= 1; S
< M
+1; S
++)
2524 while (i
< M
+1 && pQ
->GetDouble(i
, S
) == 0.0)
2529 return ScMatrixRef();
2532 for (L
= 1; L
< M
+2; L
++)
2534 fVal
= pQ
->GetDouble(S
, L
);
2535 pQ
->PutDouble(pQ
->GetDouble(i
, L
), S
, L
);
2536 pQ
->PutDouble(fVal
, i
, L
);
2538 fVal
= 1.0/pQ
->GetDouble(S
, S
);
2539 for (L
= 1; L
< M
+2; L
++)
2540 pQ
->PutDouble(pQ
->GetDouble(S
, L
)*fVal
, S
, L
);
2541 for (i
= 1; i
< M
+1; i
++)
2545 fVal
= -pQ
->GetDouble(i
, S
);
2546 for (L
= 1; L
< M
+2; L
++)
2548 pQ
->GetDouble(i
,L
)+fVal
*pQ
->GetDouble(S
,L
),i
,L
);
2551 pQ
->PutDouble(0.0, 0, M
+1);
2552 } // for (S = 1; S < M+1; S++)
2556 void ScInterpreter::ScTrend()
2558 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "sc", "er", "ScInterpreter::ScTrend" );
2559 CalculateTrendGrowth(FALSE
);
2561 void ScInterpreter::CalculateTrendGrowth(BOOL _bGrowth
)
2563 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "sc", "er", "ScInterpreter::CalculateTrendGrowth" );
2564 BYTE nParamCount
= GetByte();
2565 if ( !MustHaveParamCount( nParamCount
, 1, 4 ) )
2568 if (nParamCount
== 4)
2569 bConstant
= GetBool();
2574 ScMatrixRef pMatNewX
;
2575 if (nParamCount
>= 3)
2576 pMatNewX
= GetMatrix();
2579 if (nParamCount
>= 2)
2580 pMatX
= GetMatrix();
2583 pMatY
= GetMatrix();
2586 PushIllegalParameter();
2590 BYTE nCase
; // 1 = normal, 2,3 = mehrfach
2593 SCSIZE M
= 0, N
= 0;
2594 if ( !CheckMatrix(_bGrowth
,TRUE
,nCase
,nCX
,nCY
,nRX
,nRY
,M
,N
,pMatX
,pMatY
) )
2604 nCountXN
= nCXN
* nRXN
;
2609 pMatNewX
->GetDimensions(nCXN
, nRXN
);
2610 if ((nCase
== 2 && nCX
!= nCXN
) || (nCase
== 3 && nRX
!= nRXN
))
2612 PushIllegalArgument();
2615 nCountXN
= nCXN
* nRXN
;
2616 for ( SCSIZE i
= 0; i
< nCountXN
; i
++ )
2617 if (!pMatNewX
->IsValue(i
))
2619 PushIllegalArgument();
2623 ScMatrixRef pResMat
;
2626 double fCount
= 0.0;
2628 double fSumSqrX
= 0.0;
2630 double fSumSqrY
= 0.0;
2631 double fSumXY
= 0.0;
2632 double fValX
, fValY
;
2634 for (i
= 0; i
< nCY
; i
++)
2635 for (SCSIZE j
= 0; j
< nRY
; j
++)
2637 fValX
= pMatX
->GetDouble(i
,j
);
2638 fValY
= pMatY
->GetDouble(i
,j
);
2640 fSumSqrX
+= fValX
* fValX
;
2642 fSumSqrY
+= fValY
* fValY
;
2643 fSumXY
+= fValX
*fValY
;
2653 double f1
= fCount
*fSumXY
-fSumX
*fSumY
;
2654 double fX
= fCount
*fSumSqrX
-fSumX
*fSumX
;
2658 b
= fSumY
/fCount
- f1
/fX
*fSumX
/fCount
;
2664 m
= fSumXY
/fSumSqrX
;
2666 pResMat
= GetNewMat(nCXN
, nRXN
);
2669 PushIllegalArgument();
2672 for (i
= 0; i
< nCountXN
; i
++)
2674 const double d
= pMatNewX
->GetDouble(i
)*m
+b
;
2675 pResMat
->PutDouble(_bGrowth
? exp(d
) : d
, i
);
2681 ScMatrixRef pQ
= Calculate2(bConstant
,M
,N
,pMatX
,pMatY
,nCase
);
2686 pResMat
= GetNewMat(1, nRXN
);
2689 PushIllegalArgument();
2693 for (SCSIZE i
= 0; i
< nRXN
; i
++)
2695 fVal
= pQ
->GetDouble(0, M
+1);
2696 for (SCSIZE j
= 0; j
< M
; j
++)
2697 fVal
+= pQ
->GetDouble(j
+1, M
+1)*pMatNewX
->GetDouble(j
, i
);
2698 pResMat
->PutDouble(_bGrowth
? exp(fVal
) : fVal
, i
);
2703 pResMat
= GetNewMat(nCXN
, 1);
2706 PushIllegalArgument();
2710 for (SCSIZE i
= 0; i
< nCXN
; i
++)
2712 fVal
= pQ
->GetDouble(0, M
+1);
2713 for (SCSIZE j
= 0; j
< M
; j
++)
2714 fVal
+= pQ
->GetDouble(j
+1, M
+1)*pMatNewX
->GetDouble(i
, j
);
2715 pResMat
->PutDouble(_bGrowth
? exp(fVal
) : fVal
, i
);
2719 PushMatrix(pResMat
);
2722 void ScInterpreter::ScGrowth()
2724 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "sc", "er", "ScInterpreter::ScGrowth" );
2725 CalculateTrendGrowth(TRUE
);
2728 void ScInterpreter::ScMatRef()
2730 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "sc", "er", "ScInterpreter::ScMatRef" );
2731 // Falls Deltarefs drin sind...
2732 Push( (FormulaToken
&)*pCur
);
2734 PopSingleRef( aAdr
);
2735 ScFormulaCell
* pCell
= (ScFormulaCell
*) GetCell( aAdr
);
2736 if( pCell
&& pCell
->GetCellType() == CELLTYPE_FORMULA
)
2738 const ScMatrix
* pMat
= pCell
->GetMatrix();
2741 SCSIZE nCols
, nRows
;
2742 pMat
->GetDimensions( nCols
, nRows
);
2743 SCSIZE nC
= static_cast<SCSIZE
>(aPos
.Col() - aAdr
.Col());
2744 SCSIZE nR
= static_cast<SCSIZE
>(aPos
.Row() - aAdr
.Row());
2745 if ((nCols
<= nC
&& nCols
!= 1) || (nRows
<= nR
&& nRows
!= 1))
2749 ScMatValType nMatValType
;
2750 const ScMatrixValue
* pMatVal
= pMat
->Get( nC
, nR
, nMatValType
);
2751 if (ScMatrix::IsNonValueType( nMatValType
))
2753 if (ScMatrix::IsEmptyPathType( nMatValType
))
2754 { // result of empty FALSE jump path
2755 nFuncFmtType
= NUMBERFORMAT_LOGICAL
;
2758 else if (ScMatrix::IsEmptyType( nMatValType
))
2760 // Not inherited (really?) and display as empty string, not 0.
2761 PushTempToken( new ScEmptyCellToken( false, true));
2764 PushString( pMatVal
->GetString() );
2768 PushDouble(pMatVal
->fVal
); // handles DoubleError
2769 pDok
->GetNumberFormatInfo( nCurFmtType
, nCurFmtIndex
, aAdr
, pCell
);
2770 nFuncFmtType
= nCurFmtType
;
2771 nFuncFmtIndex
= nCurFmtIndex
;
2777 // If not a result matrix, obtain the cell value.
2778 USHORT nErr
= pCell
->GetErrCode();
2781 else if( pCell
->IsValue() )
2782 PushDouble( pCell
->GetValue() );
2786 pCell
->GetString( aVal
);
2789 pDok
->GetNumberFormatInfo( nCurFmtType
, nCurFmtIndex
, aAdr
, pCell
);
2790 nFuncFmtType
= nCurFmtType
;
2791 nFuncFmtIndex
= nCurFmtIndex
;
2795 PushError( errNoRef
);
2798 void ScInterpreter::ScInfo()
2800 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "sc", "er", "ScInterpreter::ScInfo" );
2801 if( MustHaveParamCount( GetByte(), 1 ) )
2803 String aStr
= GetString();
2804 ScCellKeywordTranslator::transKeyword(aStr
, ScGlobal::GetLocale(), ocInfo
);
2805 if( aStr
.EqualsAscii( "SYSTEM" ) )
2806 PushString( String( RTL_CONSTASCII_USTRINGPARAM( SC_INFO_OSVERSION
) ) );
2807 else if( aStr
.EqualsAscii( "OSVERSION" ) )
2808 PushString( String( RTL_CONSTASCII_USTRINGPARAM( "Windows (32-bit) NT 5.01" ) ) );
2809 else if( aStr
.EqualsAscii( "RELEASE" ) )
2810 PushString( ::utl::Bootstrap::getBuildIdData( ::rtl::OUString() ) );
2811 else if( aStr
.EqualsAscii( "NUMFILE" ) )
2813 else if( aStr
.EqualsAscii( "RECALC" ) )
2814 PushString( ScGlobal::GetRscString( pDok
->GetAutoCalc() ? STR_RECALC_AUTO
: STR_RECALC_MANUAL
) );
2816 PushIllegalArgument();