/libreoffice-3.6.0.2/binfilter/bf_sc/source/core/tool/sc_interpr5.cxx
C++ | 4058 lines | 3932 code | 64 blank | 62 comment | 915 complexity | c9a4ec24175cae2fb65466adfd8f45bd MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, LGPL-2.1, AGPL-1.0, BSD-3-Clause-No-Nuclear-License-2014, GPL-3.0, LGPL-3.0
Large files files are truncated, but you can click here to view the full file
- /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
- /*************************************************************************
- *
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * Copyright 2000, 2010 Oracle and/or its affiliates.
- *
- * OpenOffice.org - a multi-platform office productivity suite
- *
- * This file is part of OpenOffice.org.
- *
- * OpenOffice.org is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License version 3
- * only, as published by the Free Software Foundation.
- *
- * OpenOffice.org is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License version 3 for more details
- * (a copy is included in the LICENSE file that accompanied this code).
- *
- * You should have received a copy of the GNU Lesser General Public License
- * version 3 along with OpenOffice.org. If not, see
- * <http://www.openoffice.org/license.html>
- * for a copy of the LGPLv3 License.
- *
- ************************************************************************/
- #ifdef _MSC_VER
- #pragma hdrstop
- #endif
- #include <string.h>
- #include <bf_svtools/zforlist.hxx>
- #include "interpre.hxx"
- #include "dociter.hxx"
- #include "scmatrix.hxx"
- #include "globstr.hrc"
- namespace binfilter {
- // STATIC DATA -----------------------------------------------------------
- #define SCdEpsilon 1.0E-7
- // -----------------------------------------------------------------------
- double ScInterpreter::ScGetGGT(double fx, double fy)
- {
- if (fy == 0.0 || fx == 0.0)
- {
- SetError(errIllegalArgument);
- return 1.0;
- }
- else
- {
- double fz = fmod(fx, fy);
- while (fz > 0.0)
- {
- fx = fy;
- fy = fz;
- fz = fmod(fx, fy);
- }
- return fy;
- }
- }
- void ScInterpreter::ScGGT()
- {
- BYTE nParamCount = GetByte();
- if ( MustHaveParamCountMin( nParamCount, 1 ) )
- {
- double fSign = 1.0;
- double fx, fy = 0.0;
- switch (GetStackType())
- {
- case svDouble :
- case svString:
- case svSingleRef:
- {
- fy = GetDouble();
- if (fy < 0.0)
- {
- fy *= -1.0;
- fSign *= -1.0;
- }
- }
- break;
- case svDoubleRef :
- {
- ScRange aRange;
- USHORT nErr = 0;
- PopDoubleRef( aRange );
- double nCellVal;
- ScValueIterator aValIter(pDok, aRange, glSubTotal);
- if (aValIter.GetFirst(nCellVal, nErr))
- {
- fy = nCellVal;
- if (fy < 0.0)
- {
- fy *= -1.0;
- fSign *= -1.0;
- }
- while (nErr == 0 && aValIter.GetNext(nCellVal, nErr))
- {
- fx = nCellVal;
- if (fx < 0.0)
- {
- fx *= -1.0;
- fSign *= -1.0;
- }
- fy = ScGetGGT(fx, fy);
- }
- SetError(nErr);
- }
- else
- SetError(errIllegalArgument);
- }
- break;
- case svMatrix :
- {
- ScMatrix* pMat = PopMatrix();
- if (pMat)
- {
- USHORT nC, nR;
- pMat->GetDimensions(nC, nR);
- if (nC == 0 || nR == 0)
- SetError(errIllegalArgument);
- else
- {
- if (!pMat->IsValue(0))
- {
- SetIllegalArgument();
- return;
- }
- fy = pMat->GetDouble(0);
- if (fy < 0.0)
- {
- fy *= -1.0;
- fSign *= -1.0;
- }
- ULONG nCount = (ULONG) nC * nR;
- for ( ULONG j = 1; j < nCount; j++ )
- {
- if (!pMat->IsValue(j))
- {
- SetIllegalArgument();
- return;
- }
- fx = pMat->GetDouble(j);
- if (fx < 0.0)
- {
- fx *= -1.0;
- fSign *= -1.0;
- }
- fy = ScGetGGT(fx, fy);
- }
- }
- }
- }
- break;
- default : SetError(errIllegalParameter); break;
- }
- ScRange aRange;
- for (short i = 0; i < (short) nParamCount - 1; i++)
- {
- switch (GetStackType())
- {
- case svDouble :
- case svString:
- case svSingleRef:
- {
- fx = GetDouble();
- if (fx < 0.0)
- {
- fx *= -1.0;
- fSign *= -1.0;
- }
- fy = ScGetGGT(fx, fy);
- }
- break;
- case svDoubleRef :
- {
- USHORT nErr = 0;
- PopDoubleRef( aRange );
- double nCellVal;
- ScValueIterator aValIter(pDok, aRange, glSubTotal);
- if (aValIter.GetFirst(nCellVal, nErr))
- {
- fx = nCellVal;
- if (fx < 0.0)
- {
- fx *= -1.0;
- fSign *= -1.0;
- }
- fy = ScGetGGT(fx, fy);
- while (nErr == 0 && aValIter.GetNext(nCellVal, nErr))
- {
- fx = nCellVal;
- if (fx < 0.0)
- {
- fx *= -1.0;
- fSign *= -1.0;
- }
- fy = ScGetGGT(fx, fy);
- }
- SetError(nErr);
- }
- else
- SetError(errIllegalArgument);
- }
- break;
- case svMatrix :
- {
- ScMatrix* pMat = PopMatrix();
- if (pMat)
- {
- USHORT nC, nR;
- pMat->GetDimensions(nC, nR);
- if (nC == 0 || nR == 0)
- SetError(errIllegalArgument);
- else
- {
- if (!pMat->IsValue(0))
- {
- SetIllegalArgument();
- return;
- }
- fx = pMat->GetDouble(0);
- if (fx < 0.0)
- {
- fx *= -1.0;
- fSign *= -1.0;
- }
- fy = ScGetGGT(fx, fy);
- ULONG nCount = (ULONG) nC * nR;
- for ( ULONG j = 1; j < nCount; j++ )
- {
- if (!pMat->IsValue(j))
- {
- SetIllegalArgument();
- return;
- }
- fx = pMat->GetDouble(j);
- if (fx < 0.0)
- {
- fx *= -1.0;
- fSign *= -1.0;
- }
- fy = ScGetGGT(fx, fy);
- }
- }
- }
- }
- break;
- default : SetError(errIllegalParameter); break;
- }
- }
- if (fSign == -1.0)
- PushDouble(-fy);
- else
- PushDouble(fy);
- }
- }
- void ScInterpreter:: ScKGV()
- {
- BYTE nParamCount = GetByte();
- if ( MustHaveParamCountMin( nParamCount, 1 ) )
- {
- double fSign = 1.0;
- double fx, fy = 0.0;
- switch (GetStackType())
- {
- case svDouble :
- case svString:
- case svSingleRef:
- {
- fy = GetDouble();
- if (fy < 0.0)
- {
- fy *= -1.0;
- fSign *= -1.0;
- }
- }
- break;
- case svDoubleRef :
- {
- ScRange aRange;
- USHORT nErr = 0;
- PopDoubleRef( aRange );
- double nCellVal;
- ScValueIterator aValIter(pDok, aRange, glSubTotal);
- if (aValIter.GetFirst(nCellVal, nErr))
- {
- fy = nCellVal;
- if (fy < 0.0)
- {
- fy *= -1.0;
- fSign *= -1.0;
- }
- while (nErr == 0 && aValIter.GetNext(nCellVal, nErr))
- {
- fx = nCellVal;
- if (fx < 0.0)
- {
- fx *= -1.0;
- fSign *= -1.0;
- }
- fy = fx * fy / ScGetGGT(fx, fy);
- }
- SetError(nErr);
- }
- else
- SetError(errIllegalArgument);
- }
- break;
- case svMatrix :
- {
- ScMatrix* pMat = PopMatrix();
- if (pMat)
- {
- USHORT nC, nR;
- pMat->GetDimensions(nC, nR);
- if (nC == 0 || nR == 0)
- SetError(errIllegalArgument);
- else
- {
- if (!pMat->IsValue(0))
- {
- SetIllegalArgument();
- return;
- }
- fy = pMat->GetDouble(0);
- if (fy < 0.0)
- {
- fy *= -1.0;
- fSign *= -1.0;
- }
- ULONG nCount = (ULONG) nC * nR;
- for ( ULONG j = 1; j < nCount; j++ )
- {
- if (!pMat->IsValue(j))
- {
- SetIllegalArgument();
- return;
- }
- fx = pMat->GetDouble(j);
- if (fx < 0.0)
- {
- fx *= -1.0;
- fSign *= -1.0;
- }
- fy = fx * fy / ScGetGGT(fx, fy);
- }
- }
- }
- }
- break;
- default : SetError(errIllegalParameter); break;
- }
- ScRange aRange;
- for (short i = 0; i < (short) nParamCount - 1; i++)
- {
- switch (GetStackType())
- {
- case svDouble :
- case svString:
- case svSingleRef:
- {
- fx = GetDouble();
- if (fx < 0.0)
- {
- fx *= -1.0;
- fSign *= -1.0;
- }
- fy = fx * fy / ScGetGGT(fx, fy);
- }
- break;
- case svDoubleRef :
- {
- USHORT nErr = 0;
- PopDoubleRef( aRange );
- double nCellVal;
- ScValueIterator aValIter(pDok, aRange, glSubTotal);
- if (aValIter.GetFirst(nCellVal, nErr))
- {
- fx = nCellVal;
- if (fx < 0.0)
- {
- fx *= -1.0;
- fSign *= -1.0;
- }
- fy = fx * fy / ScGetGGT(fx, fy);
- while (nErr == 0 && aValIter.GetNext(nCellVal, nErr))
- {
- fx = nCellVal;
- if (fx < 0.0)
- {
- fx *= -1.0;
- fSign *= -1.0;
- }
- fy = fx * fy / ScGetGGT(fx, fy);
- }
- SetError(nErr);
- }
- else
- SetError(errIllegalArgument);
- }
- break;
- case svMatrix :
- {
- ScMatrix* pMat = PopMatrix();
- if (pMat)
- {
- USHORT nC, nR;
- pMat->GetDimensions(nC, nR);
- if (nC == 0 || nR == 0)
- SetError(errIllegalArgument);
- else
- {
- if (!pMat->IsValue(0))
- {
- SetIllegalArgument();
- return;
- }
- fx = pMat->GetDouble(0);
- if (fx < 0.0)
- {
- fx *= -1.0;
- fSign *= -1.0;
- }
- fy = fx * fy / ScGetGGT(fx, fy);
- ULONG nCount = (ULONG) nC * nR;
- for ( ULONG j = 1; j < nCount; j++ )
- {
- if (!pMat->IsValue(j))
- {
- SetIllegalArgument();
- return;
- }
- fx = pMat->GetDouble(j);
- if (fx < 0.0)
- {
- fx *= -1.0;
- fSign *= -1.0;
- }
- fy = fx * fy / ScGetGGT(fx, fy);
- }
- }
- }
- }
- break;
- default : SetError(errIllegalParameter); break;
- }
- }
- if (fSign == -1.0)
- PushDouble(-fy);
- else
- PushDouble(fy);
- }
- }
- /*N*/ ScMatrix* ScInterpreter::GetNewMat(USHORT nC, USHORT nR, USHORT& nMatInd)
- /*N*/ {
- /*N*/ if (nMatCount == MAX_ANZ_MAT)
- /*N*/ {
- /*N*/ OSL_FAIL("ScInterpreter::GetNewMat: Matrixueberlauf");
- /*N*/ SetError(errCodeOverflow);
- /*N*/ nMatInd = MAX_ANZ_MAT;
- /*N*/ return NULL;
- /*N*/ }
- /*N*/ else
- /*N*/ {
- /*N*/ if (!bMatDel) // beim ersten Mal
- /*N*/ {
- /*N*/ ppTempMatArray = new ScMatrix* [MAX_ANZ_MAT];
- /*N*/ for (USHORT i = 0; i < MAX_ANZ_MAT; i++)
- /*N*/ ppTempMatArray[i] = NULL;
- /*N*/ bMatDel = TRUE;
- /*N*/ }
- /*N*/ ppTempMatArray[nMatCount] = new ScMatrix(nC, nR);
- /*N*/ nMatInd = nMatCount++;
- /*N*/ return ppTempMatArray[nMatInd];
- /*N*/ }
- /*N*/ }
- /*N*/ void ScInterpreter::ResetNewMat(USHORT nIndex)
- /*N*/ {
- /*N*/ if (nIndex < MAX_ANZ_MAT)
- /*N*/ {
- /*N*/ ppTempMatArray[nIndex] = NULL;
- /*N*/ if (nIndex == nMatCount - 1)
- /*N*/ nMatCount--;
- /*N*/ }
- /*N*/ }
- /*N*/ ScMatrix* ScInterpreter::GetMatrix(USHORT& nMatInd)
- /*N*/ {
- /*N*/ ScMatrix* pMat = NULL;
- /*N*/ switch (GetStackType())
- /*N*/ {
- /*?*/ case svSingleRef :
- /*?*/ {
- /*?*/ ScAddress aAdr;
- /*?*/ PopSingleRef( aAdr );
- /*?*/ pMat = GetNewMat(1, 1, nMatInd);
- /*?*/ if (pMat)
- /*?*/ {
- /*?*/ ScBaseCell* pCell = GetCell( aAdr );
- /*?*/ if ( pCell && pCell->GetCellType() != CELLTYPE_NOTE )
- /*?*/ {
- /*?*/ if (HasCellValueData(pCell))
- /*?*/ pMat->PutDouble(GetCellValue(aAdr, pCell), 0);
- /*?*/ else
- /*?*/ {
- /*?*/ String aStr;
- /*?*/ GetCellString(aStr, pCell);
- /*?*/ pMat->PutString(aStr, 0);
- /*?*/ }
- /*?*/ }
- /*?*/ else
- /*?*/ pMat->PutEmpty( 0 );
- /*?*/ }
- /*?*/ else
- /*?*/ SetError(errCodeOverflow);
- /*?*/ }
- /*?*/ break;
- /*N*/ case svDoubleRef:
- /*N*/ {
- /*N*/ USHORT nCol1, nRow1, nTab1, nCol2, nRow2, nTab2;
- /*N*/ PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
- /*N*/ if (nTab1 == nTab2)
- /*N*/ {
- /*N*/ USHORT i, j;
- /*N*/ if ( (ULONG) (nRow2 - nRow1 + 1) * (nCol2 - nCol1 + 1) >
- /*N*/ ScMatrix::GetElementsMax() )
- /*N*/ SetError(errStackOverflow);
- /*N*/ else
- /*N*/ {
- /*N*/ pMat = GetNewMat(nCol2 - nCol1 + 1, nRow2 - nRow1 + 1, nMatInd);
- /*N*/ if (pMat)
- /*N*/ {
- /*N*/ ScAddress aAdr( nCol1, nRow1, nTab1 );
- /*N*/ for (i = nRow1; i <= nRow2; i++)
- /*N*/ {
- /*N*/ aAdr.SetRow( i );
- /*N*/ for (j = nCol1; j <= nCol2; j++)
- /*N*/ {
- /*N*/ aAdr.SetCol( j );
- /*N*/ ScBaseCell* pCell = GetCell( aAdr );
- /*N*/ if ( pCell && pCell->GetCellType() != CELLTYPE_NOTE )
- /*N*/ {
- /*N*/ if (HasCellValueData(pCell))
- /*N*/ pMat->PutDouble(
- /*N*/ GetCellValue( aAdr, pCell ),
- /*N*/ j-nCol1, i-nRow1);
- /*N*/ else
- /*N*/ {
- /*?*/ String aStr;
- /*?*/ GetCellString(aStr, pCell);
- /*?*/ pMat->PutString(aStr, j-nCol1, i-nRow1);
- /*N*/ }
- /*N*/ }
- /*N*/ else
- /*?*/ pMat->PutEmpty( j-nCol1, i-nRow1 );
- /*N*/ }
- /*N*/ }
- /*N*/ }
- /*N*/ else
- /*N*/ SetError(errCodeOverflow);
- /*N*/ }
- /*N*/ }
- /*N*/ else // keine 2D-Matrix
- /*N*/ {
- /*N*/ nMatInd = MAX_ANZ_MAT;
- /*N*/ SetError(errIllegalParameter);
- /*N*/ }
- /*N*/ }
- /*N*/ break;
- /*N*/ case svMatrix:
- /*N*/ pMat = PopMatrix();
- /*N*/ nMatInd = MAX_ANZ_MAT;
- /*N*/ break;
- /*?*/ default:
- /*?*/ Pop();
- /*?*/ nMatInd = MAX_ANZ_MAT;
- /*?*/ SetError(errIllegalParameter);
- /*?*/ break;
- /*N*/ }
- /*N*/ return pMat;
- /*N*/ }
- void ScInterpreter::ScMatValue()
- {
- if ( MustHaveParamCount( GetByte(), 3 ) )
- {
- USHORT nR = (USHORT) ::rtl::math::approxFloor(GetDouble()); // 0 bis nAnz - 1
- USHORT nC = (USHORT) ::rtl::math::approxFloor(GetDouble()); // 0 bis nAnz - 1
- switch (GetStackType())
- {
- case svSingleRef :
- {
- ScAddress aAdr;
- PopSingleRef( aAdr );
- ScBaseCell* pCell = GetCell( aAdr );
- if (pCell && pCell->GetCellType() == CELLTYPE_FORMULA)
- {
- USHORT nErrCode = ((ScFormulaCell*)pCell)->GetErrCode();
- if (nErrCode != 0)
- {
- SetError(nErrCode);
- PushInt(0);
- }
- else
- {
- ScMatrix* pMat;
- ((ScFormulaCell*)pCell)->GetMatrix(&pMat);
- if (pMat)
- {
- USHORT nCl, nRw;
- pMat->GetDimensions(nCl, nRw);
- if (nC < nCl && nR < nRw)
- {
- BOOL bIsString;
- const MatValue* pMatVal = pMat->Get(nC, nR, bIsString);
- if (bIsString)
- PushString( pMatVal->GetString() );
- else
- PushDouble(pMatVal->fVal);
- }
- else
- SetNoValue();
- }
- else
- SetNoValue();
- }
- }
- else
- SetIllegalParameter();
- }
- break;
- case svDoubleRef :
- {
- USHORT nCol1, nRow1, nTab1, nCol2, nRow2, nTab2;
- PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
- if (nCol2 - nCol1 >= nR && nRow2 - nRow1 >= nC && nTab1 == nTab2)
- {
- ScAddress aAdr( nCol1 + nR, nRow1 + nC, nTab1 );
- ScBaseCell* pCell = GetCell( aAdr );
- if (HasCellValueData(pCell))
- PushDouble(GetCellValue( aAdr, pCell ));
- else
- {
- String aStr;
- GetCellString(aStr, pCell);
- PushString(aStr);
- }
- }
- else
- SetNoValue();
- }
- break;
- case svMatrix:
- {
- ScMatrix* pMat = PopMatrix();
- if (pMat)
- {
- USHORT nCl, nRw;
- pMat->GetDimensions(nCl, nRw);
- if (nC < nCl && nR < nRw)
- {
- BOOL bIsString;
- const MatValue* pMatVal = pMat->Get(nC, nR, bIsString);
- if (bIsString)
- PushString( pMatVal->GetString() );
- else
- PushDouble(pMatVal->fVal);
- }
- else
- SetNoValue();
- }
- else
- SetNoValue();
- }
- break;
- default:
- Pop();
- SetIllegalParameter();
- break;
- }
- }
- }
- void ScInterpreter::ScEMat()
- {
- if ( MustHaveParamCount( GetByte(), 1 ) )
- {
- ULONG nDim = (ULONG) ::rtl::math::approxFloor(GetDouble());
- if ( nDim * nDim > ScMatrix::GetElementsMax() || nDim == 0)
- SetIllegalArgument();
- else
- {
- USHORT nMatInd;
- ScMatrix* pRMat = GetNewMat((USHORT)nDim, (USHORT)nDim, nMatInd);
- if (pRMat)
- {
- MEMat(pRMat, (USHORT) nDim);
- nRetMat = nMatInd;
- PushMatrix(pRMat);
- }
- else
- SetError(errStackOverflow);
- }
- }
- }
- void ScInterpreter::MEMat(ScMatrix* mM, USHORT n)
- {
- mM->FillDouble(0.0, 0, 0, n-1, n-1);
- for (USHORT i = 0; i < n; i++)
- mM->PutDouble(1.0, i, i);
- }
- void ScInterpreter::MFastMult(ScMatrix* pA, ScMatrix* pB, ScMatrix* pR,
- USHORT n, USHORT m, USHORT l)
- // Multipliziert n x m Mat a mit m x l Mat b nach Mat r
- {
- double sum;
- for (USHORT i = 0; i < n; i++)
- {
- for (USHORT j = 0; j < l; j++)
- {
- sum = 0.0;
- for (USHORT k = 0; k < m; k++)
- sum += pA->GetDouble(i,k)*pB->GetDouble(k,j);
- pR->PutDouble(sum, i, j);
- }
- }
- }
- void ScInterpreter::MFastSub(ScMatrix* pA, ScMatrix* pB, ScMatrix* pR,
- USHORT n, USHORT m)
- // Subtrahiert n x m Mat a - m x l Mat b nach Mat r
- {
- for (USHORT i = 0; i < n; i++)
- {
- for (USHORT j = 0; j < m; j++)
- pR->PutDouble(pA->GetDouble(i,j) - pB->GetDouble(i,j), i, j);
- }
- }
- void ScInterpreter::MFastTrans(ScMatrix* pA, ScMatrix* pR,
- USHORT n, USHORT m)
- // Transponiert n x m Mat a nach Mat r
- {
- for (USHORT i = 0; i < n; i++)
- for (USHORT j = 0; j < m; j++)
- pR->PutDouble(pA->GetDouble(i, j), j, i);
- }
- BOOL ScInterpreter::MFastBackSubst(ScMatrix* pA, ScMatrix* pR, USHORT n, BOOL bIsUpper)
- // F?hrt R?ckwaertsersetzung der Dreickesmatrix Mat a nach Mat r durch
- // 2 Versionen fuer obere (U) oder untere (L- Unit) Dreiecksmatrizen
- {
- short i, j, k;
- double fSum;
- if (!bIsUpper) // L-Matrix, immer invertierbar
- {
- MEMat(pR, n);
- for (i = 1; i < (short) n; i++)
- {
- for (j = 0; j < i; j++)
- {
- fSum = 0.0;
- for (k = 0; k < i; k++)
- fSum += pA->GetDouble(i,k) * pR->GetDouble(k,j);
- pR->PutDouble(-fSum, i, j);
- }
- }
- }
- else // U-Matrix
- {
- for (i = 0; i < (short) n; i++) // Ist invertierbar?
- if (fabs(pA->GetDouble(i,i)) < SCdEpsilon)
- return FALSE;
- pR->FillDoubleLowerLeft(0.0, n-1); // untere Haelfte
- pR->PutDouble(1.0/pA->GetDouble(n-1, n-1), n-1, n-1); // n-1, n-1
- for (i = (short) n-2; i >= 0; i--)
- {
- for (j = (short) n-1; j > i; j--)
- {
- fSum = 0.0;
- for (k = (short) n-1; k > i; k--)
- fSum += pA->GetDouble(i, k) * pR->GetDouble(k, j);
- pR->PutDouble(-fSum/pA->GetDouble(i, i), i, j);
- }
- fSum = 0.0; // Hauptdiagonale:
- for (k = (short) n-1; k > i; k--)
- fSum += pA->GetDouble(i, k) * pR->GetDouble(k, j);
- pR->PutDouble((1.0-fSum)/pA->GetDouble(i, i), i, i);
- }
- }
- return TRUE;
- }
- BOOL ScInterpreter::ScMatLUP(ScMatrix* mA, USHORT m, USHORT p,
- ScMatrix* mL, ScMatrix* mU, ScMatrix* mP,
- ULONG& rPermutCounter, BOOL& bIsInvertable)
- // Returnwert = False <=> Matrixarray voll
- // BIsInvertable = False: <= mA hat nicht Rang m
- {
- USHORT nMatInd1, nMatInd2, nMatInd3, nMatInd4, nMatInd5;
- USHORT i, j;
- if (m == 1)
- {
- mL->PutDouble(1.0,0,0);
- for (j = 0; j < p; j++)
- if (fabs(mA->GetDouble(0, j)) >= SCdEpsilon)
- break;
- if (j == p)
- {
- bIsInvertable = FALSE;
- return TRUE;
- }
- MEMat(mP, p);
- if (j > 0 && j < p)
- {
- mP->PutDouble(0.0, 0, 0);
- mP->PutDouble(1.0, j, 0);
- mP->PutDouble(0.0, j, j);
- mP->PutDouble(1.0, 0, j);
- rPermutCounter++;
- }
- MFastMult(mA, mP, mU, m, p, p);
- }
- else
- {
- USHORT md2 = m/2;
- ScMatrix* mB = GetNewMat(md2, p, nMatInd1);
- ScMatrix* mC = GetNewMat(md2, p, nMatInd2);
- ScMatrix* mL1 = GetNewMat(md2, md2, nMatInd3);
- ScMatrix* mU1 = GetNewMat(md2, p, nMatInd4);
- ScMatrix* mP1 = GetNewMat(p, p, nMatInd5);
- if (!mB || !mC || !mL1 || !mU1 || !mP1 )
- return FALSE;
- for (i = 0; i < md2; i++)
- {
- for (j = 0; j < p; j++)
- {
- mB->PutDouble(mA->GetDouble(i, j), i, j);
- mC->PutDouble(mA->GetDouble(md2+i,j), i, j);
- }
- }
- if (!ScMatLUP(mB, md2, p, mL1, mU1, mP1, rPermutCounter, bIsInvertable))
- return FALSE;
- if (!bIsInvertable)
- {
- ResetNewMat(nMatInd5);
- ResetNewMat(nMatInd4);
- ResetNewMat(nMatInd3);
- ResetNewMat(nMatInd2);
- ResetNewMat(nMatInd1);
- delete mP1;
- delete mU1;
- delete mL1;
- delete mC;
- delete mB;
- return TRUE;
- }
- USHORT nMatInd6, nMatInd7, nMatInd8, nMatInd9, nMatInd10;
- USHORT nMatInd11, nMatInd12, nMatInd13;
- ScMatrix* mE = GetNewMat(md2, md2, nMatInd6);
- ScMatrix* mF = GetNewMat(md2, md2, nMatInd7);
- ScMatrix* mEInv = GetNewMat(md2, md2, nMatInd8);
- ScMatrix* mG = GetNewMat(md2, p, nMatInd9);
- ScMatrix* mGs = GetNewMat(md2, p - md2, nMatInd10);
- ScMatrix* mU2 = GetNewMat(md2, p - md2, nMatInd11);
- ScMatrix* mP2 = GetNewMat(p - md2, p - md2, nMatInd12);
- if (!mP2 || !mU2 || !mGs|| !mG || !mEInv || !mF || !mE)
- return FALSE;
- MFastTrans(mP1, mP, p, p); // mP = mP1 hoch -1
- ScMatrix* mD = mB; // mB wird nicht mehr gebraucht
- MFastMult(mC, mP, mD, md2, p, p);
- for (i = 0; i < md2; i++)
- {
- for (j = 0; j < md2; j++)
- {
- mE->PutDouble(mU1->GetDouble(i, j), i, j);
- mF->PutDouble(mD->GetDouble(i, j), i, j);
- }
- }
- BOOL bEInvok = MFastBackSubst(mE, mEInv, md2, TRUE); // MeInv = E hoch -1
- if (!bEInvok)
- {
- bIsInvertable = FALSE;
- ResetNewMat(nMatInd12);
- ResetNewMat(nMatInd11);
- ResetNewMat(nMatInd10);
- ResetNewMat(nMatInd9);
- ResetNewMat(nMatInd8);
- ResetNewMat(nMatInd7);
- ResetNewMat(nMatInd6);
- ResetNewMat(nMatInd5);
- ResetNewMat(nMatInd4);
- ResetNewMat(nMatInd3);
- ResetNewMat(nMatInd2);
- ResetNewMat(nMatInd1);
- delete mP2;
- delete mU2;
- delete mGs;
- delete mG;
- delete mEInv;
- delete mF;
- delete mE;
- delete mP1;
- delete mU1;
- delete mL1;
- delete mC;
- delete mB;
- return TRUE;
- }
- ScMatrix* mFEInv = mE; // mE wird nicht mehr gebraucht.
- MFastMult(mF, mEInv, mFEInv, md2, md2, md2);
- ScMatrix* mFEInvU1 = mC; // mC wird nicht mehr gebraucht
- MFastMult(mFEInv, mU1, mFEInvU1, md2, md2, p);
- MFastSub(mD, mFEInvU1, mG, md2, p);
- for (i = 0; i < md2; i++)
- {
- for (j = 0; j < p-md2; j++)
- mGs->PutDouble(mG->GetDouble(i, md2+j), i, j);
- }
- ScMatrix* mL2 = mF; // mF wird nicht mehr gebraucht
- if (!ScMatLUP(mGs, md2, p - md2, mL2, mU2, mP2, rPermutCounter, bIsInvertable))
- return FALSE;
- if (!bIsInvertable)
- {
- ResetNewMat(nMatInd12);
- ResetNewMat(nMatInd11);
- ResetNewMat(nMatInd10);
- ResetNewMat(nMatInd9);
- ResetNewMat(nMatInd8);
- ResetNewMat(nMatInd7);
- ResetNewMat(nMatInd6);
- ResetNewMat(nMatInd5);
- ResetNewMat(nMatInd4);
- ResetNewMat(nMatInd3);
- ResetNewMat(nMatInd2);
- ResetNewMat(nMatInd1);
- delete mP2;
- delete mU2;
- delete mGs;
- delete mG;
- delete mEInv;
- delete mF;
- delete mE;
- delete mP1;
- delete mU1;
- delete mL1;
- delete mC;
- delete mB;
- return TRUE;
- }
- ScMatrix* mP3 = GetNewMat(p, p, nMatInd13);
- if (!mP3)
- return FALSE;
- MEMat(mP3, p);
- for (i = md2; i < p; i++)
- {
- for (j = md2; j < p; j++)
- mP3->PutDouble(mP2->GetDouble(i-md2, j-md2), i, j);
- }
- MFastMult(mP3, mP1, mP, p, p, p); // Ergebnis P !!
- ScMatrix* mP3Inv = mP1; // mP1 wird nicht mehr gebraucht;
- MFastTrans(mP3, mP3Inv, p, p);
- ScMatrix* mH = mD; // mD wird nicht mehr gebraucht
- MFastMult(mU1, mP3Inv, mH, md2, p, p);
- MEMat(mL, m); // Ergebnis L :
- for (i = 0; i < md2; i++)
- {
- for (j = 0; j < i; j++)
- mL->PutDouble(mL1->GetDouble(i, j), i, j);
- }
- for (i = md2; i < m; i++)
- for (j = md2; j < i; j++)
- mL->PutDouble(mL2->GetDouble(i-md2, j-md2), i, j);
- for (i = md2; i < m; i++)
- for (j = 0; j < md2; j++)
- mL->PutDouble(mFEInv->GetDouble(i-md2, j), i, j);
- // Ergebnis U:
- mU->FillDoubleLowerLeft(0.0, m-1);
- for (i = 0; i < md2; i++)
- for (j = i; j < p; j++)
- mU->PutDouble(mH->GetDouble(i, j), i, j);
- for (i = md2; i < m; i++)
- for (j = i; j < p; j++)
- mU->PutDouble(mU2->GetDouble(i - md2, j - md2), i, j);
- ResetNewMat(nMatInd13); // alle wieder freigeben;
- ResetNewMat(nMatInd12);
- ResetNewMat(nMatInd11);
- ResetNewMat(nMatInd10);
- ResetNewMat(nMatInd9);
- ResetNewMat(nMatInd8);
- ResetNewMat(nMatInd7);
- ResetNewMat(nMatInd6);
- ResetNewMat(nMatInd5);
- ResetNewMat(nMatInd4);
- ResetNewMat(nMatInd3);
- ResetNewMat(nMatInd2);
- ResetNewMat(nMatInd1);
- delete mP3;
- delete mP2;
- delete mU2;
- delete mGs;
- delete mG;
- delete mEInv;
- delete mF;
- delete mE;
- delete mP1;
- delete mU1;
- delete mL1;
- delete mC;
- delete mB;
- }
- return TRUE;
- }
- void ScInterpreter::ScMatDet()
- {
- if ( MustHaveParamCount( GetByte(), 1 ) )
- {
- USHORT nMatInd;
- ScMatrix* pMat = GetMatrix(nMatInd);
- if (!pMat)
- {
- SetIllegalParameter();
- return;
- }
- if ( !pMat->IsNumeric() )
- {
- SetNoValue();
- return;
- }
- USHORT nC, nR;
- pMat->GetDimensions(nC, nR);
- if ( nC != nR || nC == 0 || (ULONG) nC * nC > ScMatrix::GetElementsMax() )
- SetIllegalParameter();
- else
- {
- double fVal = log((double)nC) / log(2.0);
- if (fVal - floor(fVal) != 0.0)
- fVal = floor(fVal) + 1.0;
- USHORT nDim = (USHORT) pow(2.0, fVal);
- USHORT nMatInd1, nMatInd2, nMatInd3;
- USHORT nMatInd4 = MAX_ANZ_MAT;
- ScMatrix* pU = GetNewMat(nDim, nDim, nMatInd1);
- ScMatrix* pL = GetNewMat(nDim, nDim, nMatInd2);
- ScMatrix* pP = GetNewMat(nDim, nDim, nMatInd3);
- ScMatrix* pA;
- if (nC == nDim)
- pA = pMat;
- else
- {
- pA = GetNewMat(nDim, nDim, nMatInd4);
- MEMat(pA, nDim);
- for (USHORT i = 0; i < nC; i++)
- for (USHORT j = 0; j < nC; j++)
- {
- pA->PutDouble(pMat->GetDouble(i, j), i, j);
- }
- }
- ULONG nPermutCounter = 0;
- BOOL bIsInvertable = TRUE;
- BOOL bOk = ScMatLUP(pA, nDim, nDim, pL, pU, pP,
- nPermutCounter, bIsInvertable);
- ResetNewMat(nMatInd4);
- ResetNewMat(nMatInd3);
- ResetNewMat(nMatInd2);
- if (nC != nDim)
- delete pA;
- delete pP;
- delete pL;
- if (bOk)
- {
- if (!bIsInvertable)
- PushInt(0);
- else
- {
- double fDet = 1.0;
- for (USHORT i = 0; i < nC; i++)
- fDet *= pU->GetDouble(i, i);
- if (nPermutCounter % 2 != 0)
- fDet *= -1.0;
- PushDouble(fDet);
- }
- }
- else
- {
- SetError(errCodeOverflow);
- PushInt(0);
- }
- ResetNewMat(nMatInd1);
- delete pU;
- }
- }
- }
- void ScInterpreter::ScMatInv()
- {
- if ( MustHaveParamCount( GetByte(), 1 ) )
- {
- USHORT nMatInd;
- ScMatrix* pMat = GetMatrix(nMatInd);
- if (!pMat)
- {
- SetIllegalParameter();
- return;
- }
- if ( !pMat->IsNumeric() )
- {
- SetNoValue();
- return;
- }
- USHORT nC, nR;
- pMat->GetDimensions(nC, nR);
- if ( nC != nR || nC == 0 || (ULONG) nC * nC > ScMatrix::GetElementsMax() )
- SetIllegalParameter();
- else
- {
- double fVal = log((double)nC) / log(2.0);
- if (fVal - floor(fVal) != 0.0)
- fVal = floor(fVal) + 1.0;
- USHORT nDim = (USHORT) pow(2.0, fVal);
- USHORT nMatInd1, nMatInd2, nMatInd3;
- USHORT nMatInd4 = MAX_ANZ_MAT;
- ScMatrix* pU = GetNewMat(nDim, nDim, nMatInd1);
- ScMatrix* pL = GetNewMat(nDim, nDim, nMatInd2);
- ScMatrix* pP = GetNewMat(nDim, nDim, nMatInd3);
- ScMatrix* pA;
- if (nC == nDim)
- pA = pMat;
- else
- {
- pA = GetNewMat(nDim, nDim, nMatInd4);
- MEMat(pA, nDim);
- for (USHORT i = 0; i < nC; i++)
- for (USHORT j = 0; j < nC; j++)
- {
- pA->PutDouble(pMat->GetDouble(i, j), i, j);
- }
- }
- ULONG nPermutCounter = 0;
- BOOL bIsInvertable = TRUE;
- BOOL bOk = ScMatLUP(pA, nDim, nDim, pL, pU, pP,
- nPermutCounter, bIsInvertable);
- if (bOk)
- {
- if (!bIsInvertable)
- SetNoValue();
- else
- {
- USHORT nMatInd5;
- ScMatrix* pUInv = GetNewMat(nDim, nDim, nMatInd5);
- if (!pUInv)
- PushInt(0);
- else
- {
- bOk = MFastBackSubst(pU, pUInv, nDim, TRUE);
- if (!bOk)
- SetNoValue();
- else
- {
- ScMatrix* pPInv = pU;
- MFastTrans(pP, pPInv, nDim, nDim);
- ScMatrix* pPInvUInv = pP;
- MFastMult(pPInv, pUInv, pPInvUInv, nDim, nDim, nDim);
- ScMatrix* pLInv = pPInv;
- MFastBackSubst(pL, pLInv, nDim, FALSE);
- if (nDim == nC)
- MFastMult(pPInvUInv, pLInv, pMat, nDim, nDim, nDim);
- else
- {
- MFastMult(pPInvUInv, pLInv, pL, nDim, nDim, nDim);
- for (USHORT i = 0; i < nC; i++)
- for (USHORT j = 0; j < nC; j++)
- pMat->PutDouble(pL->GetDouble(i, j), i, j);
- }
- PushMatrix(pMat);
- if (nMatInd != MAX_ANZ_MAT) // vorher neue Matrix
- nRetMat = nMatInd; // sonst nRetMat wie vorher
- ResetNewMat(nMatInd5);
- delete pUInv;
- }
- }
- }
- }
- else
- {
- SetError(errCodeOverflow);
- PushInt(0);
- }
- ResetNewMat(nMatInd4);
- ResetNewMat(nMatInd3);
- ResetNewMat(nMatInd2);
- ResetNewMat(nMatInd1);
- if (nC != nDim)
- delete pA;
- delete pP;
- delete pL;
- delete pU;
- }
- }
- }
- void ScInterpreter::ScMatMult()
- {
- if ( MustHaveParamCount( GetByte(), 2 ) )
- {
- USHORT nMatInd1, nMatInd2;
- ScMatrix* pMat2 = GetMatrix(nMatInd2);
- ScMatrix* pMat1 = GetMatrix(nMatInd1);
- ScMatrix* pRMat;
- if (pMat1 && pMat2)
- {
- if ( pMat1->IsNumeric() && pMat2->IsNumeric() )
- {
- USHORT nC1, nR1, nC2, nR2;
- pMat1->GetDimensions(nC1, nR1);
- pMat2->GetDimensions(nC2, nR2);
- if (nC1 != nR2)
- SetIllegalParameter();
- else
- {
- USHORT nMatInd;
- pRMat = GetNewMat(nC2, nR1, nMatInd); // Matrixabsicherung
- if (pRMat)
- {
- double sum;
- for (USHORT i = 0; i < nR1; i++)
- {
- for (USHORT j = 0; j < nC2; j++)
- {
- sum = 0.0;
- for (USHORT k = 0; k < nC1; k++)
- {
- sum += pMat1->GetDouble(k,i)*pMat2->GetDouble(j,k);
- }
- pRMat->PutDouble(sum, j, i);
- }
- }
- PushMatrix(pRMat);
- nRetMat = nMatInd;
- }
- else
- SetNoValue();
- }
- }
- else
- SetNoValue();
- }
- else
- SetIllegalParameter();
- }
- }
- void ScInterpreter::ScMatTrans()
- {
- if ( MustHaveParamCount( GetByte(), 1 ) )
- {
- USHORT nMatInd, nMatInd1;
- ScMatrix* pMat = GetMatrix(nMatInd);
- ScMatrix* pRMat;
- if (pMat)
- {
- USHORT nC, nR;
- pMat->GetDimensions(nC, nR);
- pRMat = GetNewMat(nR, nC, nMatInd1);
- pMat->MatTrans(*pRMat);
- PushMatrix(pRMat);
- nRetMat = nMatInd1;
- }
- else
- SetIllegalParameter();
- }
- }
- /*N*/ ScMatrix* ScInterpreter::MatAdd(ScMatrix* pMat1, ScMatrix* pMat2)
- /*N*/ {
- /*N*/ USHORT nC1, nR1, nC2, nR2, nMinC, nMinR, i, j;
- /*N*/ pMat1->GetDimensions(nC1, nR1);
- /*N*/ pMat2->GetDimensions(nC2, nR2);
- /*N*/ if (nC1 < nC2)
- /*N*/ nMinC = nC1;
- /*N*/ else
- /*N*/ nMinC = nC2;
- /*N*/ if (nR1 < nR2)
- /*N*/ nMinR = nR1;
- /*N*/ else
- /*N*/ nMinR = nR2;
- /*N*/ USHORT nMatInd;
- /*N*/ ScMatrix* pResMat = GetNewMat(nMinC, nMinR, nMatInd);
- /*N*/ if (pResMat)
- /*N*/ {
- /*N*/ for (i = 0; i < nMinC; i++)
- /*N*/ {
- /*N*/ for (j = 0; j < nMinR; j++)
- /*N*/ {
- /*N*/ if (pMat1->IsValueOrEmpty(i,j) && pMat2->IsValueOrEmpty(i,j))
- /*N*/ pResMat->PutDouble( ::rtl::math::approxAdd( pMat1->GetDouble(i,j),
- /*N*/ pMat2->GetDouble(i,j)), i, j);
- /*N*/ else
- /*?*/ pResMat->PutString(ScGlobal::GetRscString(
- /*N*/ STR_NO_VALUE), i, j);
- /*N*/ }
- /*N*/ }
- /*N*/ nRetMat = nMatInd;
- /*N*/ }
- /*N*/ return pResMat;
- /*N*/ }
- ScMatrix* ScInterpreter::MatSub(ScMatrix* pMat1, ScMatrix* pMat2)
- {
- USHORT nC1, nR1, nC2, nR2, nMinC, nMinR, i, j;
- pMat1->GetDimensions(nC1, nR1);
- pMat2->GetDimensions(nC2, nR2);
- if (nC1 < nC2)
- nMinC = nC1;
- else
- nMinC = nC2;
- if (nR1 < nR2)
- nMinR = nR1;
- else
- nMinR = nR2;
- USHORT nMatInd;
- ScMatrix* pResMat = GetNewMat(nMinC, nMinR, nMatInd);
- if (pResMat)
- {
- for (i = 0; i < nMinC; i++)
- {
- for (j = 0; j < nMinR; j++)
- {
- if (pMat1->IsValueOrEmpty(i,j) && pMat2->IsValueOrEmpty(i,j))
- pResMat->PutDouble( ::rtl::math::approxSub( pMat1->GetDouble(i,j),
- pMat2->GetDouble(i,j)), i, j);
- else
- pResMat->PutString(ScGlobal::GetRscString(
- STR_NO_VALUE), i, j);
- }
- }
- nRetMat = nMatInd;
- }
- return pResMat;
- }
- /*N*/ ScMatrix* ScInterpreter::MatMul(ScMatrix* pMat1, ScMatrix* pMat2)
- /*N*/ {
- /*N*/ USHORT nC1, nR1, nC2, nR2, nMinC, nMinR, i, j;
- /*N*/ pMat1->GetDimensions(nC1, nR1);
- /*N*/ pMat2->GetDimensions(nC2, nR2);
- /*N*/ if (nC1 < nC2)
- /*N*/ nMinC = nC1;
- /*N*/ else
- /*N*/ nMinC = nC2;
- /*N*/ if (nR1 < nR2)
- /*N*/ nMinR = nR1;
- /*N*/ else
- /*N*/ nMinR = nR2;
- /*N*/ USHORT nMatInd;
- /*N*/ ScMatrix* pResMat = GetNewMat(nMinC, nMinR, nMatInd);
- /*N*/ if (pResMat)
- /*N*/ {
- /*N*/ for (i = 0; i < nMinC; i++)
- /*N*/ {
- /*N*/ for (j = 0; j < nMinR; j++)
- /*N*/ {
- /*N*/ if (pMat1->IsValueOrEmpty(i,j) && pMat2->IsValueOrEmpty(i,j))
- /*N*/ pResMat->PutDouble(pMat1->GetDouble(i,j) *
- /*N*/ pMat2->GetDouble(i,j), i, j);
- /*N*/ else
- /*?*/ pResMat->PutString(ScGlobal::GetRscString(
- /*N*/ STR_NO_VALUE), i, j);
- /*N*/ }
- /*N*/ }
- /*N*/ nRetMat = nMatInd;
- /*N*/ }
- /*N*/ return pResMat;
- /*N*/ }
- ScMatrix* ScInterpreter::MatDiv(ScMatrix* pMat1, ScMatrix* pMat2)
- {
- USHORT nC1, nR1, nC2, nR2, nMinC, nMinR, i, j;
- pMat1->GetDimensions(nC1, nR1);
- pMat2->GetDimensions(nC2, nR2);
- if (nC1 < nC2)
- nMinC = nC1;
- else
- nMinC = nC2;
- if (nR1 < nR2)
- nMinR = nR1;
- else
- nMinR = nR2;
- USHORT nMatInd;
- ScMatrix* pResMat = GetNewMat(nMinC, nMinR, nMatInd);
- if (pResMat)
- {
- for (i = 0; i < nMinC; i++)
- {
- for (j = 0; j < nMinR; j++)
- {
- if (pMat1->IsValueOrEmpty(i,j) && pMat2->IsValueOrEmpty(i,j))
- pResMat->PutDouble(pMat1->GetDouble(i,j) /
- pMat2->GetDouble(i,j), i, j);
- else
- pResMat->PutString(ScGlobal::GetRscString(
- STR_NO_VALUE), i, j);
- }
- }
- nRetMat = nMatInd;
- }
- return pResMat;
- }
- ScMatrix* ScInterpreter::MatPow(ScMatrix* pMat1, ScMatrix* pMat2)
- {
- USHORT nC1, nR1, nC2, nR2, nMinC, nMinR, i, j;
- pMat1->GetDimensions(nC1, nR1);
- pMat2->GetDimensions(nC2, nR2);
- if (nC1 < nC2)
- nMinC = nC1;
- else
- nMinC = nC2;
- if (nR1 < nR2)
- nMinR = nR1;
- else
- nMinR = nR2;
- USHORT nMatInd;
- ScMatrix* pResMat = GetNewMat(nMinC, nMinR, nMatInd);
- if (pResMat)
- {
- for (i = 0; i < nMinC; i++)
- {
- for (j = 0; j < nMinR; j++)
- {
- if (pMat1->IsValueOrEmpty(i,j) && pMat2->IsValueOrEmpty(i,j))
- pResMat->PutDouble(pow(pMat1->GetDouble(i,j),
- pMat2->GetDouble(i,j)), i, j);
- else
- pResMat->PutString(ScGlobal::GetRscString(
- STR_NO_VALUE), i, j);
- }
- }
- nRetMat = nMatInd;
- }
- return pResMat;
- }
- ScMatrix* ScInterpreter::MatConcat(ScMatrix* pMat1, ScMatrix* pMat2)
- {
- USHORT nC1, nR1, nC2, nR2, nMinC, nMinR, i, j;
- pMat1->GetDimensions(nC1, nR1);
- pMat2->GetDimensions(nC2, nR2);
- if (nC1 < nC2)
- nMinC = nC1;
- else
- nMinC = nC2;
- if (nR1 < nR2)
- nMinR = nR1;
- else
- nMinR = nR2;
- USHORT nMatInd;
- ScMatrix* pResMat = GetNewMat(nMinC, nMinR, nMatInd);
- if (pResMat)
- {
- for (i = 0; i < nMinC; i++)
- {
- for (j = 0; j < nMinR; j++)
- {
- if (pMat1->IsString(i,j) && pMat2->IsString(i,j))
- {
- String aTmp( pMat1->GetString(i,j) );
- aTmp += pMat2->GetString(i,j);
- pResMat->PutString( aTmp , i, j);
- }
- …
Large files files are truncated, but you can click here to view the full file