blob: f4db0e1e49c3005fac3d63a858dbaa3c915c430f [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
#ifndef SC_JUMPMATRIX_HXX
#define SC_JUMPMATRIX_HXX
#include "formula/token.hxx"
#include "formula/errorcodes.hxx"
#include <tools/solar.h>
#include <vector>
#include "scmatrix.hxx"
typedef ::std::vector< formula::FormulaToken*> ScTokenVec;
struct ScJumpMatrixEntry
{
double fBool; // 0:= false 1:= true also if no-path
// other values may contain error conditions like NAN and INF
short nStart; // start of path (actually start-1, see formula::FormulaTokenIterator)
short nNext; // next after path
// jump path exists if nStart != nNext, else no path
short nStop; // optional stop of path (nPC < nStop)
void SetJump( double fBoolP, short nStartP, short nNextP, short nStopP )
{
fBool = fBoolP;
nStart = nStartP;
nNext = nNextP;
nStop = nStopP;
}
void GetJump( double& rBool, short& rStart, short& rNext, short& rStop )
{
rBool = fBool;
rStart = nStart;
rNext = nNext;
rStop = nStop;
}
};
class ScJumpMatrix
{
ScJumpMatrixEntry* pJump; // the jumps
ScMatrixRef pMat; // the results
ScTokenVec* pParams; // parameter stack
SCSIZE nCols;
SCSIZE nRows;
SCSIZE nCurCol;
SCSIZE nCurRow;
SCSIZE nResMatCols;
SCSIZE nResMatRows;
bool bStarted;
// not implemented, prevent usage
ScJumpMatrix( const ScJumpMatrix& );
ScJumpMatrix& operator=( const ScJumpMatrix& );
public:
ScJumpMatrix( SCSIZE nColsP, SCSIZE nRowsP )
: pJump( new ScJumpMatrixEntry[ nColsP * nRowsP ] )
, pMat( new ScMatrix( nColsP, nRowsP) )
, pParams( NULL )
, nCols( nColsP )
, nRows( nRowsP )
, nCurCol( 0 )
, nCurRow( 0 )
, nResMatCols( nColsP )
, nResMatRows( nRowsP )
, bStarted( false )
{
// Initialize result matrix in case of
// a premature end of the interpreter
// due to errors.
pMat->FillDouble( CreateDoubleError(
NOTAVAILABLE), 0, 0, nCols-1,
nRows-1);
/*! pJump not initialized */
}
~ScJumpMatrix()
{
if ( pParams )
{
for ( ScTokenVec::iterator i =
pParams->begin(); i !=
pParams->end(); ++i )
{
(*i)->DecRef();
}
delete pParams;
}
delete [] pJump;
}
void GetDimensions( SCSIZE& rCols, SCSIZE& rRows ) const
{
rCols = nCols;
rRows = nRows;
}
void SetJump( SCSIZE nCol, SCSIZE nRow, double fBool,
short nStart, short nNext,
short nStop = SHRT_MAX )
{
pJump[ (sal_uLong)nCol * nRows + nRow ].
SetJump( fBool, nStart, nNext, nStop);
}
void GetJump( SCSIZE nCol, SCSIZE nRow, double& rBool,
short& rStart, short& rNext,
short& rStop ) const
{
if (nCols == 1 && nRows == 1)
{
nCol = 0;
nRow = 0;
}
else if (nCols == 1 && nRow < nRows)
nCol = 0;
else if (nRows == 1 && nCol < nCols)
nRow = 0;
else if (nCols <= nCol || nRows <= nRow)
{
DBG_ERROR("ScJumpMatrix::GetJump: dimension error");
nCol = 0;
nRow = 0;
}
pJump[ (sal_uLong)nCol * nRows + nRow ].
GetJump( rBool, rStart, rNext, rStop);
}
void SetAllJumps( double fBool,
short nStart, short nNext,
short nStop = SHRT_MAX )
{
sal_uLong n = (sal_uLong)nCols * nRows;
for ( sal_uLong j=0; j<n; ++j )
{
pJump[ j ].SetJump( fBool, nStart,
nNext, nStop);
}
}
void SetJumpParameters( ScTokenVec* p )
{ pParams = p; }
const ScTokenVec* GetJumpParameters() const { return pParams; }
ScMatrix* GetResultMatrix() const { return pMat; }
void GetPos( SCSIZE& rCol, SCSIZE& rRow ) const
{
rCol = nCurCol;
rRow = nCurRow;
}
bool Next( SCSIZE& rCol, SCSIZE& rRow )
{
if ( !bStarted )
{
bStarted = true;
nCurCol = nCurRow = 0;
}
else
{
if ( ++nCurRow >= nResMatRows )
{
nCurRow = 0;
++nCurCol;
}
}
GetPos( rCol, rRow );
return nCurCol < nResMatCols;
}
void GetResMatDimensions( SCSIZE& rCols, SCSIZE& rRows )
{
rCols = nResMatCols;
rRows = nResMatRows;
}
void SetNewResMat( SCSIZE nNewCols, SCSIZE nNewRows )
{
if ( nNewCols > nResMatCols || nNewRows > nResMatRows )
{
pMat = pMat->CloneAndExtend( nNewCols, nNewRows );
if ( nResMatCols < nNewCols )
{
pMat->FillDouble( CreateDoubleError(
NOTAVAILABLE), nResMatCols, 0, nNewCols-1,
nResMatRows-1);
}
if ( nResMatRows < nNewRows )
{
pMat->FillDouble( CreateDoubleError(
NOTAVAILABLE), 0, nResMatRows, nNewCols-1,
nNewRows-1);
}
if ( nRows == 1 && nCurCol != 0 )
{
nCurCol = 0;
nCurRow = nResMatRows - 1;
}
nResMatCols = nNewCols;
nResMatRows = nNewRows;
}
}
};
#endif // SC_JUMPMATRIX_HXX