<commit_before>////////////////////////////////////////////////////////////////////////
//
// Implementation of oscillations of neutrinos in matter in a
// three-neutrino framework with decoherence.
//
// This  class inherits from the PMNS_Fast class
//
// jcoelho@apc.in2p3.fr
////////////////////////////////////////////////////////////////////////

#include <iostream>
#include <cassert>
#include <stdlib.h>

#include "PMNS_Deco.h"

using namespace OscProb;

using namespace std;

//......................................................................
///
/// Constructor. \sa PMNS_Base::PMNS_Base
///
/// This class is restricted to 3 neutrino flavours.
///
PMNS_Deco::PMNS_Deco() : PMNS_Fast(), fGamma(),
fRho(3, row(3,0))
{
  SetStdPath();
  SetGamma(2,0);
  SetGamma(3,0);
  SetDecoAngle(0);
}

//......................................................................
///
/// Nothing to clean.
///
PMNS_Deco::~PMNS_Deco(){}

//......................................................................
///
/// Set the decoherence parameter \f$\Gamma_{j1}\f$.
///
/// This will check if value is changing to keep track of whether
/// the eigensystem needs to be recomputed.
///
/// Requires that j = 2 or 3. Will notify you if input is wrong.
///
/// @param j   - The first mass index
/// @param val - The absolute value of the parameter
///
void PMNS_Deco::SetGamma(int j, double val){

  if(j < 2 || j > 3){
    cout << "Gamma_" << j << 1 << " not valid for " << fNumNus;
    cout << " neutrinos. Doing nothing." << endl;
    return;
  }

  fGotES *= (fGamma[j-1] == val);

  fGamma[j-1] = val;

}

//......................................................................
///
/// Set the decoherence angle. This will define the relationship:
///
///   \f$
///   \Gamma_{32} = \Gamma_{31} + \Gamma_{21} \cos^2\theta -
///   \cos\theta \sqrt{\Gamma_{21} (4\Gamma_{31} - \Gamma_{21} (1 - \cos^2\theta))}
///   \f$
///
/// This will check if value is changing to keep track of whether
/// the eigensystem needs to be recomputed.
///
/// @param th - decoherence angle
///
void PMNS_Deco::SetDecoAngle(double th)
{

  double cosTh = cos(th);

  fGotES *= (fGamma[0] == cosTh);

  fGamma[0] = cosTh;

}

//......................................................................
///
/// Get any given decoherence parameter.
///
/// Requires that i > j. Will notify you if input is wrong.
/// If i < j, will assume reverse order and swap i and j.
///
/// @param i  - The first mass index
/// @param j  - The second mass index
///
double PMNS_Deco::GetGamma(int i, int j)
{

  if(i < j){
    cout << "First argument should be larger than second argument" << endl;
    cout << "Setting reverse order (Gamma_" << j << i << "). " << endl;
    int temp = i;
    i = j;
    j = temp;
  }
  if(i<1 || i>3 || i <= j || j < 1){
    cout << "Gamma_" << i << j << " not valid for " << fNumNus;
    cout << " neutrinos. Returning 0." << endl;
    return 0;
  }

  if(j == 1){
    return fGamma[i-1];
  }
  else {
    // Combine Gamma31, Gamma21 and an angle (fGamma[0] = cos(th)) to make Gamma32
    double arg = fGamma[1] * ( 4*fGamma[2] - fGamma[1]*(1 - pow(fGamma[0],2)) );

    return fGamma[2] + fGamma[1]*pow(fGamma[0],2) - fGamma[0] * sqrt(arg);

  }

}

//.....................................................................
/// Dot product of two matrices.
///
/// @param A - input matrix A
/// @param B - input matrix B
///
/// @return - matrix A.B
///
PMNS_Deco::matrix PMNS_Deco::Dot(matrix A, matrix B)
{

  matrix out(3, row(3,0));

  for(int i=0; i<3; i++){
  for(int j=0; j<3; j++){
  for(int k=0; k<3; k++){

    out[i][j] += A[i][k] * B[k][j];

  }}}

  return out;

}

//.....................................................................
/// Product of elements of two matrices.
///
/// @param A - input matrix A
/// @param B - input matrix B
///
/// @return - matrix A * B
///
PMNS_Deco::matrix PMNS_Deco::Mult(matrix A, matrix B)
{

  matrix out(3, row(3,0));

  for(int i=0; i<3; i++){
  for(int j=0; j<3; j++){

    out[i][j] += A[i][j] * B[i][j];

  }}

  return out;

}

//.....................................................................
/// Conjugate transpose matrix.
///
/// @param A - input matrix A
///
/// @return - \f$A^{\dagger}\f$
///
PMNS_Deco::matrix PMNS_Deco::CTransp(matrix A)
{

  matrix out(3, row(3,0));

  for(int i=0; i<3; i++){
  for(int j=0; j<3; j++){

    out[i][j] += conj(A[j][i]);

  }}

  return out;

}

//.....................................................................
///
/// Propagate the current neutrino state through a given path
///
/// @param p - A neutrino path segment
///
void PMNS_Deco::PropagatePath(NuPath p)
{

  // Set the neutrino path
  SetCurPath(p);

  // Solve for eigensystem
  SolveHam();

  // The code below is not pretty or optimised at all. Lots of matrix
  // multiplications are going on which could be otpimised due to
  // symmetry. The index sorting is also terrible. Needs improving.

  // Store rotation matrices
  matrix U = fEvec;
  matrix Ut = CTransp(fEvec);

  // Rotate to effective mass basis
  fRho = Dot(Ut, Dot(fRho, U));

  // Compute evolution matrix
  matrix evolve(3, row(3,1));

  // Some ugly way of matching gamma and dmsqr indices
  int maxdm = 0;
  if(fDm[1] > fDm[maxdm]) maxdm = 1;
  if(fDm[2] > fDm[maxdm]) maxdm = 2;

  int mindm = 0;
  if(fDm[1] < fDm[mindm]) mindm = 1;
  if(fDm[2] < fDm[mindm]) mindm = 2;

  int middm = 0;
  if(middm == maxdm || middm == mindm) middm = 1;
  if(middm == maxdm || middm == mindm) middm = 2;

  int maxev = 0;
  if(fEval[1] > fEval[maxev]) maxev = 1;
  if(fEval[2] > fEval[maxev]) maxev = 2;

  int minev = 0;
  if(fEval[1] < fEval[minev]) minev = 1;
  if(fEval[2] < fEval[minev]) minev = 2;

  int midev = 0;
  if(midev == maxev || midev == minev) midev = 1;
  if(midev == maxev || midev == minev) midev = 2;

  int idx[3];
  idx[minev] = mindm;
  idx[midev] = middm;
  idx[maxev] = maxdm;

  for(int j=0; j<3; j++){
  for(int i=0; i<j; i++){
    complex arg = complex(GetGamma(max(idx[i],idx[j])+1,min(idx[i],idx[j])+1) * kGeV2eV, fEval[i] - fEval[j]) * kKm2eV * p.length;
    evolve[i][j] = exp(-arg);
    evolve[j][i] = exp(-conj(arg));
  }}

  // Evolve density matrix
  fRho = Mult(fRho, evolve);

  // Rotate back to flavour basis
  fRho = Dot(U, Dot(fRho, Ut));

}

//......................................................................
///
/// Reset the neutrino state back to a pure flavour where it starts
///
/// Flavours are:
///

///   0 = nue, 1 = numu, 2 = nutau
///   3 = sterile_1, 4 = sterile_2, etc.
///

/// @param flv - The neutrino starting flavour.
///
void PMNS_Deco::ResetToFlavour(int flv)
{
  assert(flv>=0 && flv<fNumNus);
  for (int i=0; i<fNumNus; ++i){
  for (int j=0; j<fNumNus; ++j){
    if (i==flv && i==j) fRho[i][j] = one;
    else                fRho[i][j] = zero;
  }}
}

//......................................................................
///
/// Compute oscillation probability of flavour flv from current state
///
/// Flavours are:
///

///   0 = nue, 1 = numu, 2 = nutau
///   3 = sterile_1, 4 = sterile_2, etc.
///

/// @param flv - The neutrino final flavour.
///
/// @return Neutrino oscillation probability
///
double PMNS_Deco::P(int flv)
{
  assert(flv>=0 && flv<fNumNus);
  return sqrt(norm(fRho[flv][flv]));
}

////////////////////////////////////////////////////////////////////////
<commit_msg>Use std::abs for probability from density matrix<commit_after>////////////////////////////////////////////////////////////////////////
//
// Implementation of oscillations of neutrinos in matter in a
// three-neutrino framework with decoherence.
//
// This  class inherits from the PMNS_Fast class
//
// jcoelho@apc.in2p3.fr
////////////////////////////////////////////////////////////////////////

#include <iostream>
#include <cassert>
#include <stdlib.h>

#include "PMNS_Deco.h"

using namespace OscProb;

using namespace std;

//......................................................................
///
/// Constructor. \sa PMNS_Base::PMNS_Base
///
/// This class is restricted to 3 neutrino flavours.
///
PMNS_Deco::PMNS_Deco() : PMNS_Fast(), fGamma(),
fRho(3, row(3,0))
{
  SetStdPath();
  SetGamma(2,0);
  SetGamma(3,0);
  SetDecoAngle(0);
}

//......................................................................
///
/// Nothing to clean.
///
PMNS_Deco::~PMNS_Deco(){}

//......................................................................
///
/// Set the decoherence parameter \f$\Gamma_{j1}\f$.
///
/// This will check if value is changing to keep track of whether
/// the eigensystem needs to be recomputed.
///
/// Requires that j = 2 or 3. Will notify you if input is wrong.
///
/// @param j   - The first mass index
/// @param val - The absolute value of the parameter
///
void PMNS_Deco::SetGamma(int j, double val){

  if(j < 2 || j > 3){
    cout << "Gamma_" << j << 1 << " not valid for " << fNumNus;
    cout << " neutrinos. Doing nothing." << endl;
    return;
  }

  fGotES *= (fGamma[j-1] == val);

  fGamma[j-1] = val;

}

//......................................................................
///
/// Set the decoherence angle. This will define the relationship:
///
///   \f$
///   \Gamma_{32} = \Gamma_{31} + \Gamma_{21} \cos^2\theta -
///   \cos\theta \sqrt{\Gamma_{21} (4\Gamma_{31} - \Gamma_{21} (1 - \cos^2\theta))}
///   \f$
///
/// This will check if value is changing to keep track of whether
/// the eigensystem needs to be recomputed.
///
/// @param th - decoherence angle
///
void PMNS_Deco::SetDecoAngle(double th)
{

  double cosTh = cos(th);

  fGotES *= (fGamma[0] == cosTh);

  fGamma[0] = cosTh;

}

//......................................................................
///
/// Get any given decoherence parameter.
///
/// Requires that i > j. Will notify you if input is wrong.
/// If i < j, will assume reverse order and swap i and j.
///
/// @param i  - The first mass index
/// @param j  - The second mass index
///
double PMNS_Deco::GetGamma(int i, int j)
{

  if(i < j){
    cout << "First argument should be larger than second argument" << endl;
    cout << "Setting reverse order (Gamma_" << j << i << "). " << endl;
    int temp = i;
    i = j;
    j = temp;
  }
  if(i<1 || i>3 || i <= j || j < 1){
    cout << "Gamma_" << i << j << " not valid for " << fNumNus;
    cout << " neutrinos. Returning 0." << endl;
    return 0;
  }

  if(j == 1){
    return fGamma[i-1];
  }
  else {
    // Combine Gamma31, Gamma21 and an angle (fGamma[0] = cos(th)) to make Gamma32
    double arg = fGamma[1] * ( 4*fGamma[2] - fGamma[1]*(1 - pow(fGamma[0],2)) );

    return fGamma[2] + fGamma[1]*pow(fGamma[0],2) - fGamma[0] * sqrt(arg);

  }

}

//.....................................................................
/// Dot product of two matrices.
///
/// @param A - input matrix A
/// @param B - input matrix B
///
/// @return - matrix A.B
///
PMNS_Deco::matrix PMNS_Deco::Dot(matrix A, matrix B)
{

  matrix out(3, row(3,0));

  for(int i=0; i<3; i++){
  for(int j=0; j<3; j++){
  for(int k=0; k<3; k++){

    out[i][j] += A[i][k] * B[k][j];

  }}}

  return out;

}

//.....................................................................
/// Product of elements of two matrices.
///
/// @param A - input matrix A
/// @param B - input matrix B
///
/// @return - matrix A * B
///
PMNS_Deco::matrix PMNS_Deco::Mult(matrix A, matrix B)
{

  matrix out(3, row(3,0));

  for(int i=0; i<3; i++){
  for(int j=0; j<3; j++){

    out[i][j] += A[i][j] * B[i][j];

  }}

  return out;

}

//.....................................................................
/// Conjugate transpose matrix.
///
/// @param A - input matrix A
///
/// @return - \f$A^{\dagger}\f$
///
PMNS_Deco::matrix PMNS_Deco::CTransp(matrix A)
{

  matrix out(3, row(3,0));

  for(int i=0; i<3; i++){
  for(int j=0; j<3; j++){

    out[i][j] += conj(A[j][i]);

  }}

  return out;

}

//.....................................................................
///
/// Propagate the current neutrino state through a given path
///
/// @param p - A neutrino path segment
///
void PMNS_Deco::PropagatePath(NuPath p)
{

  // Set the neutrino path
  SetCurPath(p);

  // Solve for eigensystem
  SolveHam();

  // The code below is not pretty or optimised at all. Lots of matrix
  // multiplications are going on which could be otpimised due to
  // symmetry. The index sorting is also terrible. Needs improving.

  // Store rotation matrices
  matrix U = fEvec;
  matrix Ut = CTransp(fEvec);

  // Rotate to effective mass basis
  fRho = Dot(Ut, Dot(fRho, U));

  // Compute evolution matrix
  matrix evolve(3, row(3,1));

  // Some ugly way of matching gamma and dmsqr indices
  int maxdm = 0;
  if(fDm[1] > fDm[maxdm]) maxdm = 1;
  if(fDm[2] > fDm[maxdm]) maxdm = 2;

  int mindm = 0;
  if(fDm[1] < fDm[mindm]) mindm = 1;
  if(fDm[2] < fDm[mindm]) mindm = 2;

  int middm = 0;
  if(middm == maxdm || middm == mindm) middm = 1;
  if(middm == maxdm || middm == mindm) middm = 2;

  int maxev = 0;
  if(fEval[1] > fEval[maxev]) maxev = 1;
  if(fEval[2] > fEval[maxev]) maxev = 2;

  int minev = 0;
  if(fEval[1] < fEval[minev]) minev = 1;
  if(fEval[2] < fEval[minev]) minev = 2;

  int midev = 0;
  if(midev == maxev || midev == minev) midev = 1;
  if(midev == maxev || midev == minev) midev = 2;

  int idx[3];
  idx[minev] = mindm;
  idx[midev] = middm;
  idx[maxev] = maxdm;

  for(int j=0; j<3; j++){
  for(int i=0; i<j; i++){
    complex arg = complex(GetGamma(max(idx[i],idx[j])+1,min(idx[i],idx[j])+1) * kGeV2eV, fEval[i] - fEval[j]) * kKm2eV * p.length;
    evolve[i][j] = exp(-arg);
    evolve[j][i] = exp(-conj(arg));
  }}

  // Evolve density matrix
  fRho = Mult(fRho, evolve);

  // Rotate back to flavour basis
  fRho = Dot(U, Dot(fRho, Ut));

}

//......................................................................
///
/// Reset the neutrino state back to a pure flavour where it starts
///
/// Flavours are:
///

///   0 = nue, 1 = numu, 2 = nutau
///   3 = sterile_1, 4 = sterile_2, etc.
///

/// @param flv - The neutrino starting flavour.
///
void PMNS_Deco::ResetToFlavour(int flv)
{
  assert(flv>=0 && flv<fNumNus);
  for (int i=0; i<fNumNus; ++i){
  for (int j=0; j<fNumNus; ++j){
    if (i==flv && i==j) fRho[i][j] = one;
    else                fRho[i][j] = zero;
  }}
}

//......................................................................
///
/// Compute oscillation probability of flavour flv from current state
///
/// Flavours are:
///

///   0 = nue, 1 = numu, 2 = nutau
///   3 = sterile_1, 4 = sterile_2, etc.
///

/// @param flv - The neutrino final flavour.
///
/// @return Neutrino oscillation probability
///
double PMNS_Deco::P(int flv)
{
  assert(flv>=0 && flv<fNumNus);
  return std::abs(fRho[flv][flv]);
}

////////////////////////////////////////////////////////////////////////
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: drdefuno.hxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: vg $ $Date: 2001-09-18 15:15:52 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library 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 for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef SC_DRDEFUNO_HXX
#define SC_DRDEFUNO_HXX

#ifndef _SVX_UNOPOOL_HXX_
#include <svx/unopool.hxx>
#endif

#ifndef _SFXLSTNER_HXX
#include <svtools/lstner.hxx>
#endif

class ScDocShell;

class ScDrawDefaultsObj : public SvxUnoDrawPool, public SfxListener
{
private:
    ScDocShell*             pDocShell;

public:
                            ScDrawDefaultsObj(ScDocShell* pDocSh);
    virtual                 ~ScDrawDefaultsObj() throw ();

    virtual void            Notify( SfxBroadcaster& rBC, const SfxHint& rHint );

                            // from SvxUnoDrawPool
    virtual SfxItemPool*    getModelPool( sal_Bool bReadOnly ) throw();
};

#endif

<commit_msg>INTEGRATION: CWS ooo19126 (1.2.920); FILE MERGED 2005/09/05 15:00:45 rt 1.2.920.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: drdefuno.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 17:37:36 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library 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 for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef SC_DRDEFUNO_HXX
#define SC_DRDEFUNO_HXX

#ifndef _SVX_UNOPOOL_HXX_
#include <svx/unopool.hxx>
#endif

#ifndef _SFXLSTNER_HXX
#include <svtools/lstner.hxx>
#endif

class ScDocShell;

class ScDrawDefaultsObj : public SvxUnoDrawPool, public SfxListener
{
private:
    ScDocShell*             pDocShell;

public:
                            ScDrawDefaultsObj(ScDocShell* pDocSh);
    virtual                 ~ScDrawDefaultsObj() throw ();

    virtual void            Notify( SfxBroadcaster& rBC, const SfxHint& rHint );

                            // from SvxUnoDrawPool
    virtual SfxItemPool*    getModelPool( sal_Bool bReadOnly ) throw();
};

#endif

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: XMLTextListItemContext.hxx,v $
 *
 *  $Revision: 1.1.1.1 $
 *
 *  last change: $Author: hr $ $Date: 2000-09-18 17:07:06 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library 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 for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _XMLTEXTLISTITEMCONTEXT_HXX
#define _XMLTEXTLISTITEMCONTEXT_HXX

#ifndef _XMLOFF_XMLICTXT_HXX
#include "xmlictxt.hxx"
#endif

class XMLTextImportHelper;

class XMLTextListItemContext : public SvXMLImportContext
{
    XMLTextImportHelper& rTxtImport;

    sal_Int16                   nStartValue;

//  SwXMLImport& GetSwImport() { return (SwXMLImport&)GetImport(); }

public:

    TYPEINFO();

    XMLTextListItemContext(
            SvXMLImport& rImport,
            XMLTextImportHelper& rTxtImp, sal_uInt16 nPrfx,
            const ::rtl::OUString& rLName,
            const ::com::sun::star::uno::Reference<
            ::com::sun::star::xml::sax::XAttributeList > & xAttrList,
            sal_Bool bIsHeader = sal_False );
    virtual ~XMLTextListItemContext();

    virtual void EndElement();

    SvXMLImportContext *CreateChildContext( sal_uInt16 nPrefix,
                 const ::rtl::OUString& rLocalName,
                 const ::com::sun::star::uno::Reference<
                     ::com::sun::star::xml::sax::XAttributeList > & xAttrList );

    sal_Bool HasStartValue() const { return -1 != nStartValue; }
    sal_Int16 GetStartValue() const { return nStartValue; }
};

#endif
<commit_msg>INTEGRATION: CWS ooo19126 (1.1.1.1.654); FILE MERGED 2005/09/05 14:40:04 rt 1.1.1.1.654.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: XMLTextListItemContext.hxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 15:23:08 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library 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 for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _XMLTEXTLISTITEMCONTEXT_HXX
#define _XMLTEXTLISTITEMCONTEXT_HXX

#ifndef _XMLOFF_XMLICTXT_HXX
#include "xmlictxt.hxx"
#endif

class XMLTextImportHelper;

class XMLTextListItemContext : public SvXMLImportContext
{
    XMLTextImportHelper& rTxtImport;

    sal_Int16                   nStartValue;

//  SwXMLImport& GetSwImport() { return (SwXMLImport&)GetImport(); }

public:

    TYPEINFO();

    XMLTextListItemContext(
            SvXMLImport& rImport,
            XMLTextImportHelper& rTxtImp, sal_uInt16 nPrfx,
            const ::rtl::OUString& rLName,
            const ::com::sun::star::uno::Reference<
            ::com::sun::star::xml::sax::XAttributeList > & xAttrList,
            sal_Bool bIsHeader = sal_False );
    virtual ~XMLTextListItemContext();

    virtual void EndElement();

    SvXMLImportContext *CreateChildContext( sal_uInt16 nPrefix,
                 const ::rtl::OUString& rLocalName,
                 const ::com::sun::star::uno::Reference<
                     ::com::sun::star::xml::sax::XAttributeList > & xAttrList );

    sal_Bool HasStartValue() const { return -1 != nStartValue; }
    sal_Int16 GetStartValue() const { return nStartValue; }
};

#endif
<|endoftext|>


<commit_before>/*
 * Copyright 2013 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "BenchTimer.h"
#include "LazyDecodeBitmap.h"
#include "PictureBenchmark.h"
#include "PictureRenderer.h"
#include "SkBenchmark.h"
#include "SkForceLinking.h"
#include "SkGraphics.h"
#include "SkStream.h"
#include "SkString.h"
#include "SkTArray.h"
#include "TimerData.h"

static const int kNumNormalRecordings = SkBENCHLOOP(10);
static const int kNumRTreeRecordings = SkBENCHLOOP(10);
static const int kNumPlaybacks = SkBENCHLOOP(4);
static const size_t kNumBaseBenchmarks = 3;
static const size_t kNumTileSizes = 3;
static const size_t kNumBbhPlaybackBenchmarks = 3;
static const size_t kNumBenchmarks = kNumBaseBenchmarks + kNumBbhPlaybackBenchmarks;

enum BenchmarkType {
    kNormal_BenchmarkType = 0,
    kRTree_BenchmarkType,
};

struct Histogram {
    Histogram() {
        // Make fCpuTime negative so that we don't mess with stats:
        fCpuTime = SkIntToScalar(-1);
    }
    SkScalar fCpuTime;
    SkString fPath;
};

typedef void (*BenchmarkFunction)
    (BenchmarkType, const SkISize&, const SkString&, SkPicture*, BenchTimer*);

// Defined below.
static void benchmark_playback(
        BenchmarkType, const SkISize&, const SkString&, SkPicture*, BenchTimer*);
static void benchmark_recording(
        BenchmarkType, const SkISize&, const SkString&, SkPicture*, BenchTimer*);

/**
 * Acts as a POD containing information needed to run a benchmark.
 * Provides static methods to poll benchmark info from an index.
 */
struct BenchmarkControl {
    SkISize fTileSize;
    BenchmarkType fType;
    BenchmarkFunction fFunction;
    SkString fName;

    /**
     * Will construct a BenchmarkControl instance from an index between 0 an kNumBenchmarks.
     */
    static BenchmarkControl Make(size_t i) {
        SkASSERT(kNumBenchmarks > i);
        BenchmarkControl benchControl;
        benchControl.fTileSize = getTileSize(i);
        benchControl.fType = getBenchmarkType(i);
        benchControl.fFunction = getBenchmarkFunc(i);
        benchControl.fName = getBenchmarkName(i);
        return benchControl;
    }

    enum BaseBenchmarks {
        kNormalRecord = 0,
        kRTreeRecord,
        kNormalPlayback,
    };

    static SkISize fTileSizes[kNumTileSizes];

    static SkISize getTileSize(size_t i) {
        // Two of the base benchmarks don't need a tile size. But to maintain simplicity
        // down the pipeline we have to let a couple of values unused.
        if (i < kNumBaseBenchmarks) {
            return SkISize::Make(256, 256);
        }
        if (i >= kNumBaseBenchmarks && i < kNumBenchmarks) {
            return fTileSizes[i - kNumBaseBenchmarks];
        }
        SkASSERT(0);
        return SkISize::Make(0, 0);
    }

    static BenchmarkType getBenchmarkType(size_t i) {
        if (i < kNumBaseBenchmarks) {
            switch (i) {
                case kNormalRecord:
                    return kNormal_BenchmarkType;
                case kNormalPlayback:
                    return kNormal_BenchmarkType;
                case kRTreeRecord:
                    return kRTree_BenchmarkType;
            }
        }
        if (i < kNumBenchmarks) {
            return kRTree_BenchmarkType;
        }
        SkASSERT(0);
        return kRTree_BenchmarkType;
    }

    static BenchmarkFunction getBenchmarkFunc(size_t i) {
        // Base functions.
        switch (i) {
            case kNormalRecord:
                return benchmark_recording;
            case kNormalPlayback:
                return benchmark_playback;
            case kRTreeRecord:
                return benchmark_recording;
        }
        // RTree playbacks
        if (i < kNumBenchmarks) {
            return benchmark_playback;
        }
        SkASSERT(0);
        return NULL;
    }

    static SkString getBenchmarkName(size_t i) {
        // Base benchmark names
        switch (i) {
            case kNormalRecord:
                return SkString("normal_recording");
            case kNormalPlayback:
                return SkString("normal_playback");
            case kRTreeRecord:
                return SkString("rtree_recording");
        }
        // RTree benchmark names.
        if (i < kNumBenchmarks) {
            SkASSERT(i >= kNumBaseBenchmarks);
            SkString name;
            name.printf("rtree_playback_%dx%d",
                    fTileSizes[i - kNumBaseBenchmarks].fWidth,
                    fTileSizes[i - kNumBaseBenchmarks].fHeight);
            return name;

        } else {
            SkASSERT(0);
        }
        return SkString("");
    }

};

SkISize BenchmarkControl::fTileSizes[kNumTileSizes] = {
    SkISize::Make(256, 256),
    SkISize::Make(512, 512),
    SkISize::Make(1024, 1024),
};

static SkPicture* pic_from_path(const char path[]) {
    SkFILEStream stream(path);
    if (!stream.isValid()) {
        SkDebugf("-- Can't open '%s'\n", path);
        return NULL;
    }
    return SkPicture::CreateFromStream(&stream, &sk_tools::LazyDecodeBitmap);
}

/**
 * This function is the sink to which all work ends up going.
 * Renders the picture into the renderer. It may or may not use an RTree.
 * The renderer is chosen upstream. If we want to measure recording, we will
 * use a RecordPictureRenderer. If we want to measure rendering, we eill use a
 * TiledPictureRenderer.
 */
static void do_benchmark_work(sk_tools::PictureRenderer* renderer,
        int benchmarkType, const SkString& path, SkPicture* pic,
        const int numRepeats, const char *msg, BenchTimer* timer) {
    SkString msgPrefix;

    switch (benchmarkType){
        case kNormal_BenchmarkType:
            msgPrefix.set("Normal");
            renderer->setBBoxHierarchyType(sk_tools::PictureRenderer::kNone_BBoxHierarchyType);
            break;
        case kRTree_BenchmarkType:
            msgPrefix.set("RTree");
            renderer->setBBoxHierarchyType(sk_tools::PictureRenderer::kRTree_BBoxHierarchyType);
            break;
        default:
            SkASSERT(0);
            break;
    }

    renderer->init(pic);

    /**
     * If the renderer is not tiled, assume we are measuring recording.
     */
    bool isPlayback = (NULL != renderer->getTiledRenderer());

    SkDebugf("%s %s %s %d times...\n", msgPrefix.c_str(), msg, path.c_str(), numRepeats);
    for (int i = 0; i < numRepeats; ++i) {
        renderer->setup();
        // Render once to fill caches.
        renderer->render(NULL);
        // Render again to measure
        timer->start();
        bool result = renderer->render(NULL);
        timer->end();
        // We only care about a false result on playback. RecordPictureRenderer::render will always
        // return false because we are passing a NULL file name on purpose; which is fine.
        if(isPlayback && !result) {
            SkDebugf("Error rendering during playback.\n");
        }
    }
    renderer->end();
}

/**
 * Call do_benchmark_work with a tiled renderer using the default tile dimensions.
 */
static void benchmark_playback(
        BenchmarkType benchmarkType, const SkISize& tileSize,
        const SkString& path, SkPicture* pic, BenchTimer* timer) {
    sk_tools::TiledPictureRenderer renderer;

    SkString message("tiled_playback");
    message.appendf("_%dx%d", tileSize.fWidth, tileSize.fHeight);
    do_benchmark_work(&renderer, benchmarkType,
            path, pic, kNumPlaybacks, message.c_str(), timer);
}

/**
 * Call do_benchmark_work with a RecordPictureRenderer.
 */
static void benchmark_recording(
        BenchmarkType benchmarkType, const SkISize& tileSize,
        const SkString& path, SkPicture* pic, BenchTimer* timer) {
    sk_tools::RecordPictureRenderer renderer;
    int numRecordings = 0;
    switch(benchmarkType) {
        case kRTree_BenchmarkType:
            numRecordings = kNumRTreeRecordings;
            break;
        case kNormal_BenchmarkType:
            numRecordings = kNumNormalRecordings;
            break;
    }
    do_benchmark_work(&renderer, benchmarkType, path, pic, numRecordings, "recording", timer);
}

/**
 * Takes argc,argv along with one of the benchmark functions defined above.
 * Will loop along all skp files and perform measurments.
 *
 * Returns a SkScalar representing CPU time taken during benchmark.
 * As a side effect, it spits the timer result to stdout.
 * Will return -1.0 on error.
 */
static bool benchmark_loop(
        int argc,
        char **argv,
        const BenchmarkControl& benchControl,
        SkTArray<Histogram>& histogram) {
    static const SkString timeFormat("%f");
    TimerData timerData(argc - 1);
    for (int index = 1; index < argc; ++index) {
        BenchTimer timer;
        SkString path(argv[index]);
        SkAutoTUnref<SkPicture> pic(pic_from_path(path.c_str()));
        if (NULL == pic) {
            SkDebugf("Couldn't create picture. Ignoring path: %s\n", path.c_str());
            continue;
        }
        benchControl.fFunction(benchControl.fType, benchControl.fTileSize, path, pic, &timer);
        SkAssertResult(timerData.appendTimes(&timer));

        histogram[index - 1].fPath = path;
        histogram[index - 1].fCpuTime = SkDoubleToScalar(timer.fCpu);
    }

    const SkString timerResult = timerData.getResult(
            /*doubleFormat = */ timeFormat.c_str(),
            /*result = */ TimerData::kAvg_Result,
            /*configName = */ benchControl.fName.c_str(),
            /*timerFlags = */ TimerData::kCpu_Flag);

    const char findStr[] = "= ";
    int pos = timerResult.find(findStr);
    if (-1 == pos) {
        SkDebugf("Unexpected output from TimerData::getResult(...). Unable to parse.");
        return false;
    }

    SkScalar cpuTime = SkDoubleToScalar(atof(timerResult.c_str() + pos + sizeof(findStr) - 1));
    if (cpuTime == 0) {  // atof returns 0.0 on error.
        SkDebugf("Unable to read value from timer result.\n");
        return false;
    }
    return true;
}

int tool_main(int argc, char** argv);
int tool_main(int argc, char** argv) {
    SkAutoGraphics ag;
    SkString usage;
    usage.printf("Usage: filename [filename]*\n");

    if (argc < 2) {
        SkDebugf("%s\n", usage.c_str());
        return -1;
    }

    SkTArray<Histogram> histograms[kNumBenchmarks];

    for (size_t i = 0; i < kNumBenchmarks; ++i) {
        histograms[i].reset(argc - 1);
        bool success = benchmark_loop(
                argc, argv,
                BenchmarkControl::Make(i),
                histograms[i]);
        if (!success) {
            SkDebugf("benchmark_loop failed at index %d", i);
        }
    }

    // Output gnuplot readable histogram data..
    const char* pbTitle = "bbh_shootout_playback.dat";
    const char* recTitle = "bbh_shootout_record.dat";
    SkFILEWStream playbackOut(pbTitle);
    SkFILEWStream recordOut(recTitle);
    recordOut.writeText("# ");
    playbackOut.writeText("# ");
    for (size_t i = 0; i < kNumBenchmarks; ++i) {
        SkString out;
        out.printf("%s ", BenchmarkControl::getBenchmarkName(i).c_str());
        if (BenchmarkControl::getBenchmarkFunc(i) == &benchmark_recording) {
            recordOut.writeText(out.c_str());
        }
        if (BenchmarkControl::getBenchmarkFunc(i) == &benchmark_playback) {
            playbackOut.writeText(out.c_str());
        }
    }
    recordOut.writeText("\n");
    playbackOut.writeText("\n");

    for (int i = 0; i < argc - 1; ++i) {
        SkString pbLine;
        SkString recLine;
        // ==== Write record info
        recLine.printf("%d ", i);
        recLine.appendf("%f ", histograms[0][i].fCpuTime);  // Append normal_record time
        recLine.appendf("%f", histograms[1][i].fCpuTime);  // Append rtree_record time

        // ==== Write playback info
        pbLine.printf("%d ", i);
        pbLine.appendf("%f ", histograms[2][i].fCpuTime);  // Start with normal playback time.
        // Append all playback benchmark times.
        for (size_t j = kNumBbhPlaybackBenchmarks; j < kNumBenchmarks; ++j) {
            pbLine.appendf("%f ", histograms[j][i].fCpuTime);
        }
        pbLine.remove(pbLine.size() - 1, 1);  // Remove trailing space from line.
        pbLine.appendf("\n");
        recLine.appendf("\n");
        playbackOut.writeText(pbLine.c_str());
        recordOut.writeText(recLine.c_str());
    }
    SkDebugf("\nWrote data to gnuplot-readable files: %s %s\n", pbTitle, recTitle);

    return 0;
}

#if !defined(SK_BUILD_FOR_IOS) && !defined(SK_BUILD_FOR_NACL)
int main(int argc, char** argv) {
    return tool_main(argc, argv);
}
#endif
<commit_msg>Add correctness test to bbh_shootout.<commit_after>/*
 * Copyright 2013 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "BenchTimer.h"
#include "LazyDecodeBitmap.h"
#include "PictureBenchmark.h"
#include "PictureRenderer.h"
#include "SkBenchmark.h"
#include "SkForceLinking.h"
#include "SkGraphics.h"
#include "SkStream.h"
#include "SkString.h"
#include "SkTArray.h"
#include "TimerData.h"

static const int kNumNormalRecordings = SkBENCHLOOP(10);
static const int kNumRTreeRecordings = SkBENCHLOOP(10);
static const int kNumPlaybacks = SkBENCHLOOP(1);
static const size_t kNumBaseBenchmarks = 3;
static const size_t kNumTileSizes = 3;
static const size_t kNumBbhPlaybackBenchmarks = 3;
static const size_t kNumBenchmarks = kNumBaseBenchmarks + kNumBbhPlaybackBenchmarks;

enum BenchmarkType {
    kNormal_BenchmarkType = 0,
    kRTree_BenchmarkType,
};

struct Histogram {
    Histogram() {
        // Make fCpuTime negative so that we don't mess with stats:
        fCpuTime = SkIntToScalar(-1);
    }
    SkScalar fCpuTime;
    SkString fPath;
};

////////////////////////////////////////////////////////////////////////////////
// Defined below.
struct BenchmarkControl;

typedef void (*BenchmarkFunction)
    (const BenchmarkControl&, const SkString&, SkPicture*, BenchTimer*);

static void benchmark_playback(
    const BenchmarkControl&, const SkString&, SkPicture*, BenchTimer*);
static void benchmark_recording(
    const BenchmarkControl&, const SkString&, SkPicture*, BenchTimer*);
////////////////////////////////////////////////////////////////////////////////

/**
 * Acts as a POD containing information needed to run a benchmark.
 * Provides static methods to poll benchmark info from an index.
 */
struct BenchmarkControl {
    SkISize fTileSize;
    BenchmarkType fType;
    BenchmarkFunction fFunction;
    SkString fName;

    /**
     * Will construct a BenchmarkControl instance from an index between 0 an kNumBenchmarks.
     */
    static BenchmarkControl Make(size_t i) {
        SkASSERT(kNumBenchmarks > i);
        BenchmarkControl benchControl;
        benchControl.fTileSize = GetTileSize(i);
        benchControl.fType = GetBenchmarkType(i);
        benchControl.fFunction = GetBenchmarkFunc(i);
        benchControl.fName = GetBenchmarkName(i);
        return benchControl;
    }

    enum BaseBenchmarks {
        kNormalRecord = 0,
        kRTreeRecord,
        kNormalPlayback,
    };

    static SkISize fTileSizes[kNumTileSizes];

    static SkISize GetTileSize(size_t i) {
        // Two of the base benchmarks don't need a tile size. But to maintain simplicity
        // down the pipeline we have to let a couple of values unused.
        if (i < kNumBaseBenchmarks) {
            return SkISize::Make(256, 256);
        }
        if (i >= kNumBaseBenchmarks && i < kNumBenchmarks) {
            return fTileSizes[i - kNumBaseBenchmarks];
        }
        SkASSERT(0);
        return SkISize::Make(0, 0);
    }

    static BenchmarkType GetBenchmarkType(size_t i) {
        if (i < kNumBaseBenchmarks) {
            switch (i) {
            case kNormalRecord:
                return kNormal_BenchmarkType;
            case kNormalPlayback:
                return kNormal_BenchmarkType;
            case kRTreeRecord:
                return kRTree_BenchmarkType;
            }
        }
        if (i < kNumBenchmarks) {
            return kRTree_BenchmarkType;
        }
        SkASSERT(0);
        return kRTree_BenchmarkType;
    }

    static BenchmarkFunction GetBenchmarkFunc(size_t i) {
        // Base functions.
        switch (i) {
            case kNormalRecord:
                return benchmark_recording;
            case kNormalPlayback:
                return benchmark_playback;
            case kRTreeRecord:
                return benchmark_recording;
        }
        // RTree playbacks
        if (i < kNumBenchmarks) {
            return benchmark_playback;
        }
        SkASSERT(0);
        return NULL;
    }

    static SkString GetBenchmarkName(size_t i) {
        // Base benchmark names
        switch (i) {
            case kNormalRecord:
                return SkString("normal_recording");
            case kNormalPlayback:
                return SkString("normal_playback");
            case kRTreeRecord:
                return SkString("rtree_recording");
        }
        // RTree benchmark names.
        if (i < kNumBenchmarks) {
            SkASSERT(i >= kNumBaseBenchmarks);
            SkString name;
            name.printf("rtree_playback_%dx%d",
                    fTileSizes[i - kNumBaseBenchmarks].fWidth,
                    fTileSizes[i - kNumBaseBenchmarks].fHeight);
            return name;

        } else {
            SkASSERT(0);
        }
        return SkString("");
    }

};

SkISize BenchmarkControl::fTileSizes[kNumTileSizes] = {
    SkISize::Make(256, 256),
    SkISize::Make(512, 512),
    SkISize::Make(1024, 1024),
};

static SkPicture* pic_from_path(const char path[]) {
    SkFILEStream stream(path);
    if (!stream.isValid()) {
        SkDebugf("-- Can't open '%s'\n", path);
        return NULL;
    }
    return SkPicture::CreateFromStream(&stream, &sk_tools::LazyDecodeBitmap);
}

/**
 * Returns true when a tiled renderer with no bounding box hierarchy produces the given bitmap.
 */
static bool compare_picture(const SkString& path, const SkBitmap& inBitmap, SkPicture* pic) {
    SkBitmap* bitmap;
    sk_tools::TiledPictureRenderer renderer;
    renderer.setBBoxHierarchyType(sk_tools::PictureRenderer::kNone_BBoxHierarchyType);
    renderer.init(pic);
    renderer.setup();
    renderer.render(&path, &bitmap);
    SkAutoTDelete<SkBitmap> bmDeleter(bitmap);
    renderer.end();

    if (bitmap->getSize() != inBitmap.getSize()) {
        return false;
    }
    return !memcmp(bitmap->getPixels(), inBitmap.getPixels(), bitmap->getSize());
}

/**
 * This function is the sink to which all work ends up going.
 * Renders the picture into the renderer. It may or may not use an RTree.
 * The renderer is chosen upstream. If we want to measure recording, we will
 * use a RecordPictureRenderer. If we want to measure rendering, we will use a
 * TiledPictureRenderer.
 */
static void do_benchmark_work(sk_tools::PictureRenderer* renderer,
        int benchmarkType, const SkString& path, SkPicture* pic,
        const int numRepeats, const char *msg, BenchTimer* timer) {
    SkString msgPrefix;

    switch (benchmarkType){
        case kNormal_BenchmarkType:
            msgPrefix.set("Normal");
            renderer->setBBoxHierarchyType(sk_tools::PictureRenderer::kNone_BBoxHierarchyType);
            break;
        case kRTree_BenchmarkType:
            msgPrefix.set("RTree");
            renderer->setBBoxHierarchyType(sk_tools::PictureRenderer::kRTree_BBoxHierarchyType);
            break;
        default:
            SkASSERT(0);
            break;
    }

    renderer->init(pic);

    /**
     * If the renderer is not tiled, assume we are measuring recording.
     */
    bool isPlayback = (NULL != renderer->getTiledRenderer());
    // Will be non-null during RTree picture playback. For correctness test.
    SkBitmap* bitmap = NULL;

    SkDebugf("%s %s %s %d times...\n", msgPrefix.c_str(), msg, path.c_str(), numRepeats);
    for (int i = 0; i < numRepeats; ++i) {
        // Set up the bitmap.
        SkBitmap** out = NULL;
        if (i == 0 && kRTree_BenchmarkType == benchmarkType && isPlayback) {
            out = &bitmap;
        }

        renderer->setup();
        // Render once to fill caches.
        renderer->render(NULL);
        // Render again to measure
        timer->start();
        bool result = renderer->render(NULL, out);
        timer->end();

        // We only care about a false result on playback. RecordPictureRenderer::render will always
        // return false because we are passing a NULL file name on purpose; which is fine.
        if (isPlayback && !result) {
            SkDebugf("Error rendering during playback.\n");
        }
    }
    if (bitmap) {
        SkAutoTDelete<SkBitmap> bmDeleter(bitmap);
        if (!compare_picture(path, *bitmap, pic)) {
            SkDebugf("Error: RTree produced different bitmap\n");
        }
    }
}

/**
 * Call do_benchmark_work with a tiled renderer using the default tile dimensions.
 */
static void benchmark_playback(
        const BenchmarkControl& benchControl,
        const SkString& path, SkPicture* pic, BenchTimer* timer) {
    sk_tools::TiledPictureRenderer renderer;

    SkString message("tiled_playback");
    message.appendf("_%dx%d", benchControl.fTileSize.fWidth, benchControl.fTileSize.fHeight);
    do_benchmark_work(&renderer, benchControl.fType,
            path, pic, kNumPlaybacks, message.c_str(), timer);
}

/**
 * Call do_benchmark_work with a RecordPictureRenderer.
 */
static void benchmark_recording(
        const BenchmarkControl& benchControl,
        const SkString& path, SkPicture* pic, BenchTimer* timer) {
    sk_tools::RecordPictureRenderer renderer;
    int numRecordings = 0;
    switch(benchControl.fType) {
        case kRTree_BenchmarkType:
            numRecordings = kNumRTreeRecordings;
            break;
        case kNormal_BenchmarkType:
            numRecordings = kNumNormalRecordings;
            break;
    }
    do_benchmark_work(&renderer, benchControl.fType,
            path, pic, numRecordings, "recording", timer);
}

/**
 * Takes argc,argv along with one of the benchmark functions defined above.
 * Will loop along all skp files and perform measurments.
 *
 * Returns a SkScalar representing CPU time taken during benchmark.
 * As a side effect, it spits the timer result to stdout.
 * Will return -1.0 on error.
 */
static bool benchmark_loop(
        int argc,
        char **argv,
        const BenchmarkControl& benchControl,
        SkTArray<Histogram>& histogram) {
    static const SkString timeFormat("%f");
    TimerData timerData(argc - 1);
    for (int index = 1; index < argc; ++index) {
        BenchTimer timer;
        SkString path(argv[index]);
        SkAutoTUnref<SkPicture> pic(pic_from_path(path.c_str()));
        if (NULL == pic) {
            SkDebugf("Couldn't create picture. Ignoring path: %s\n", path.c_str());
            continue;
        }
        benchControl.fFunction(benchControl, path, pic, &timer);

        histogram[index - 1].fPath = path;
        histogram[index - 1].fCpuTime = SkDoubleToScalar(timer.fCpu);
    }

    const SkString timerResult = timerData.getResult(
            /*doubleFormat = */ timeFormat.c_str(),
            /*result = */ TimerData::kAvg_Result,
            /*configName = */ benchControl.fName.c_str(),
            /*timerFlags = */ TimerData::kCpu_Flag);

    const char findStr[] = "= ";
    int pos = timerResult.find(findStr);
    if (-1 == pos) {
        SkDebugf("Unexpected output from TimerData::getResult(...). Unable to parse.\n");
        return false;
    }

    SkScalar cpuTime = SkDoubleToScalar(atof(timerResult.c_str() + pos + sizeof(findStr) - 1));
    if (cpuTime == 0) {  // atof returns 0.0 on error.
        SkDebugf("Unable to read value from timer result.\n");
        return false;
    }
    return true;
}

int tool_main(int argc, char** argv);
int tool_main(int argc, char** argv) {
    SkAutoGraphics ag;
    SkString usage;
    usage.printf("Usage: filename [filename]*\n");

    if (argc < 2) {
        SkDebugf("%s\n", usage.c_str());
        return -1;
    }

    SkTArray<Histogram> histograms[kNumBenchmarks];

    for (size_t i = 0; i < kNumBenchmarks; ++i) {
        histograms[i].reset(argc - 1);
        bool success = benchmark_loop(
                argc, argv,
                BenchmarkControl::Make(i),
                histograms[i]);
        if (!success) {
            SkDebugf("benchmark_loop failed at index %d\n", i);
        }
    }

    // Output gnuplot readable histogram data..
    const char* pbTitle = "bbh_shootout_playback.dat";
    const char* recTitle = "bbh_shootout_record.dat";
    SkFILEWStream playbackOut(pbTitle);
    SkFILEWStream recordOut(recTitle);
    recordOut.writeText("# ");
    playbackOut.writeText("# ");
    for (size_t i = 0; i < kNumBenchmarks; ++i) {
        SkString out;
        out.printf("%s ", BenchmarkControl::GetBenchmarkName(i).c_str());
        if (BenchmarkControl::GetBenchmarkFunc(i) == &benchmark_recording) {
            recordOut.writeText(out.c_str());
        }
        if (BenchmarkControl::GetBenchmarkFunc(i) == &benchmark_playback) {
            playbackOut.writeText(out.c_str());
        }
    }
    recordOut.writeText("\n");
    playbackOut.writeText("\n");
    // Write to file, and save recording averages.
    SkScalar avgRecord = SkIntToScalar(0);
    SkScalar avgRecordRTree = SkIntToScalar(0);
    for (int i = 0; i < argc - 1; ++i) {
        SkString pbLine;
        SkString recLine;
        // ==== Write record info
        recLine.printf("%d ", i);
        SkScalar cpuTime = histograms[BenchmarkControl::kNormalRecord][i].fCpuTime;
        recLine.appendf("%f ", cpuTime);
        avgRecord += cpuTime;
        cpuTime = histograms[BenchmarkControl::kRTreeRecord][i].fCpuTime;
        recLine.appendf("%f", cpuTime);
        avgRecordRTree += cpuTime;

        // ==== Write playback info
        pbLine.printf("%d ", i);
        pbLine.appendf("%f ", histograms[2][i].fCpuTime);  // Start with normal playback time.
        // Append all playback benchmark times.
        for (size_t j = kNumBbhPlaybackBenchmarks; j < kNumBenchmarks; ++j) {
            pbLine.appendf("%f ", histograms[j][i].fCpuTime);
        }
        pbLine.remove(pbLine.size() - 1, 1);  // Remove trailing space from line.
        pbLine.appendf("\n");
        recLine.appendf("\n");
        playbackOut.writeText(pbLine.c_str());
        recordOut.writeText(recLine.c_str());
    }
    avgRecord /= argc - 1;
    avgRecordRTree /= argc - 1;
    SkDebugf("Average base recording time: %.3fms\n", avgRecord);
    SkDebugf("Average recording time with rtree: %.3fms\n", avgRecordRTree);
    SkDebugf("\nWrote data to gnuplot-readable files: %s %s\n", pbTitle, recTitle);

    return 0;
}

#if !defined(SK_BUILD_FOR_IOS) && !defined(SK_BUILD_FOR_NACL)
int main(int argc, char** argv) {
    return tool_main(argc, argv);
}
#endif
<|endoftext|>


<commit_before>#include <gtest/gtest.h>
#include <jni.h>
#include <qi/type/dynamicobjectbuilder.hpp>
#include <qi/property.hpp>
#include <jnitools.hpp>
#include <jobjectconverter.hpp>
#include <object.hpp>

qiLogCategory("qimessaging.jni.test");

int main(int argc, char** argv)
{
  // Avoid making a qi::Application. Real Java apps cannot do it.
  qi::log::addFilter("qimessaging.jni", qi::LogLevel_Debug);
  ::testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}

class QiJNI: public ::testing::Test
{
protected:
  static void SetUpTestCase()
  {
    JavaVMOption options[1];
    JavaVMInitArgs vm_args;
    long status;

    char classPathDefinition[] = "-Djava.class.path=.";
    options[0].optionString = classPathDefinition;
    memset(&vm_args, 0, sizeof(vm_args));
    vm_args.version = JNI_VERSION_1_6;
    vm_args.nOptions = 1;
    vm_args.options = options;
    status = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);

    if (status == JNI_ERR)
      throw std::runtime_error("Failed to set a JVM up");
    jvm->AttachCurrentThread((void**)&env, nullptr);

    // Real Java apps will always call this when loading the library.
    JNI_OnLoad(jvm, nullptr);

    Java_com_aldebaran_qi_EmbeddedTools_initTypeSystem(env, jclass{});
  }

  static void TearDownTestCase()
  {
    if (jvm)
      jvm->DestroyJavaVM();
  }

  static JNIEnv* env;
  static JavaVM* jvm;
};

JNIEnv* QiJNI::env = nullptr;
JavaVM* QiJNI::jvm = nullptr;

template <typename T>
qi::AnyObject makeObjectWithProperty(const std::string& propertyName, qi::Property<T>& property)
{
  qi::DynamicObjectBuilder objectBuilder;
  objectBuilder.advertiseProperty(propertyName, &property);
  return objectBuilder.object();
}

TEST_F(QiJNI, setProperty)
{
  const int initialValue = 12;
  const int newValue = 42;
  qi::Property<int> property{initialValue};

  const std::string propertyName = "serendipity";
  auto object = makeObjectWithProperty(propertyName, property);
  auto objectPtr = &object;

  qi::jni::JNIAttach attach{env};
  auto futureAddress = Java_com_aldebaran_qi_AnyObject_setProperty(
        env, jobject{},
        reinterpret_cast<jlong>(objectPtr),
        qi::jni::toJstring(propertyName),
        JObject_from_AnyValue(qi::AnyValue{newValue}.asReference()));

  auto future = reinterpret_cast<qi::Future<qi::AnyValue>*>(futureAddress);
  auto status = future->waitFor(qi::MilliSeconds{200});
  ASSERT_EQ(qi::FutureState_FinishedWithValue, status);
  ASSERT_EQ(newValue, object.property<int>(propertyName).value());
}

TEST_F(QiJNI, futureErrorIfSetPropertyThrows)
{
  using CustomException = std::exception;
  const int initialValue = 12;
  const int newValue = 42;
  qi::Property<int> property{initialValue, qi::Property<int>::Getter{}, [this](int&, const int&)->bool
  {
    throw CustomException{};
  }};

  const std::string propertyName = "serendipity";
  auto object = makeObjectWithProperty(propertyName, property);
  auto objectPtr = &object;

  qi::jni::JNIAttach attach{env};
  auto futureAddress = Java_com_aldebaran_qi_AnyObject_setProperty(
        env, jobject{},
        reinterpret_cast<jlong>(objectPtr),
        qi::jni::toJstring(propertyName),
        JObject_from_AnyValue(qi::AnyValue{newValue}.asReference()));

  auto future = reinterpret_cast<qi::Future<qi::AnyValue>*>(futureAddress);
  auto status = future->waitFor(qi::MilliSeconds{200});
  ASSERT_EQ(qi::FutureState_FinishedWithError, status);
  ASSERT_EQ(initialValue, object.property<int>(propertyName).value());
}
<commit_msg>JNI: new test demonstrates a simple use of DynamicObject.advertiseMethod<commit_after>#include <gtest/gtest.h>
#include <jni.h>
#include <qi/type/dynamicobjectbuilder.hpp>
#include <qi/property.hpp>
#include <jnitools.hpp>
#include <jobjectconverter.hpp>
#include <object.hpp>
#include <objectbuilder.hpp>

qiLogCategory("qimessaging.jni.test");

int main(int argc, char** argv)
{
  // Avoid making a qi::Application. Real Java apps cannot do it.
  qi::log::addFilter("qimessaging.jni", qi::LogLevel_Debug);
  ::testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}

class QiJNI: public ::testing::Test
{
protected:
  static void SetUpTestCase()
  {
    JavaVMOption options[1];
    JavaVMInitArgs vm_args;
    long status;

    char classPathDefinition[] = "-Djava.class.path=.";
    options[0].optionString = classPathDefinition;
    memset(&vm_args, 0, sizeof(vm_args));
    vm_args.version = JNI_VERSION_1_6;
    vm_args.nOptions = 1;
    vm_args.options = options;
    status = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);

    if (status == JNI_ERR)
      throw std::runtime_error("Failed to set a JVM up");
    jvm->AttachCurrentThread((void**)&env, nullptr);

    // Real Java apps will always call this when loading the library.
    JNI_OnLoad(jvm, nullptr);

    Java_com_aldebaran_qi_EmbeddedTools_initTypeSystem(env, jclass{});
  }

  static void TearDownTestCase()
  {
    if (jvm)
      jvm->DestroyJavaVM();
  }

  static JNIEnv* env;
  static JavaVM* jvm;
};

JNIEnv* QiJNI::env = nullptr;
JavaVM* QiJNI::jvm = nullptr;

template <typename T>
qi::AnyObject makeObjectWithProperty(const std::string& propertyName, qi::Property<T>& property)
{
  qi::DynamicObjectBuilder objectBuilder;
  objectBuilder.advertiseProperty(propertyName, &property);
  return objectBuilder.object();
}

TEST_F(QiJNI, setProperty)
{
  const int initialValue = 12;
  const int newValue = 42;
  qi::Property<int> property{initialValue};

  const std::string propertyName = "serendipity";
  auto object = makeObjectWithProperty(propertyName, property);
  auto objectPtr = &object;

  qi::jni::JNIAttach attach{env};
  auto futureAddress = Java_com_aldebaran_qi_AnyObject_setProperty(
        env, jobject{},
        reinterpret_cast<jlong>(objectPtr),
        qi::jni::toJstring(propertyName),
        JObject_from_AnyValue(qi::AnyValue{newValue}.asReference()));

  auto future = reinterpret_cast<qi::Future<qi::AnyValue>*>(futureAddress);
  auto status = future->waitFor(qi::MilliSeconds{200});
  ASSERT_EQ(qi::FutureState_FinishedWithValue, status);
  ASSERT_EQ(newValue, object.property<int>(propertyName).value());
}

TEST_F(QiJNI, futureErrorIfSetPropertyThrows)
{
  using CustomException = std::exception;
  const int initialValue = 12;
  const int newValue = 42;
  qi::Property<int> property{initialValue, qi::Property<int>::Getter{}, [this](int&, const int&)->bool
  {
    throw CustomException{};
  }};

  const std::string propertyName = "serendipity";
  auto object = makeObjectWithProperty(propertyName, property);
  auto objectPtr = &object;

  qi::jni::JNIAttach attach{env};
  auto futureAddress = Java_com_aldebaran_qi_AnyObject_setProperty(
        env, jobject{},
        reinterpret_cast<jlong>(objectPtr),
        qi::jni::toJstring(propertyName),
        JObject_from_AnyValue(qi::AnyValue{newValue}.asReference()));

  auto future = reinterpret_cast<qi::Future<qi::AnyValue>*>(futureAddress);
  auto status = future->waitFor(qi::MilliSeconds{200});
  ASSERT_EQ(qi::FutureState_FinishedWithError, status);
  ASSERT_EQ(initialValue, object.property<int>(propertyName).value());
}

TEST_F(QiJNI, dynamicObjectBuilderAdvertiseMethodVoidVoid)
{
  // Object.notify() is a typical example of function taking and returning nothing.
  const auto javaObjectClassName = "java/lang/Object";
  const auto javaObjectClass = env->FindClass(javaObjectClassName);
  const auto javaObjectConstructor = env->GetMethodID(javaObjectClass, "<init>", "()V");
  const auto javaObject = env->NewObject(javaObjectClass, javaObjectConstructor);

  // Let's make a Qi Object calling that method.
  const auto objectBuilderAddress = Java_com_aldebaran_qi_DynamicObjectBuilder_create(env, nullptr);
  env->ExceptionClear();
  Java_com_aldebaran_qi_DynamicObjectBuilder_advertiseMethod(
        env, jobject{},
        objectBuilderAddress,
        qi::jni::toJstring("notify::v()"), javaObject, // 'v' stands for "void"
        qi::jni::toJstring(javaObjectClassName),
        qi::jni::toJstring("Whatever"));
  ASSERT_FALSE(env->ExceptionCheck());
}
<|endoftext|>


<commit_before>/* -*- 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.
 *
 ************************************************************************/

#ifndef SC_MATRIX_HXX
#define SC_MATRIX_HXX

#include "global.hxx"
#include "formula/intruref.hxx"
#include "formula/errorcodes.hxx"
#include <tools/string.hxx>
#include "scdllapi.h"

class SvStream;
class ScInterpreter;
class SvNumberFormatter;
class ScMatrixImpl;

typedef BYTE ScMatValType;
const ScMatValType SC_MATVAL_VALUE     = 0x00;
const ScMatValType SC_MATVAL_BOOLEAN   = 0x01;
const ScMatValType SC_MATVAL_STRING    = 0x02;
const ScMatValType SC_MATVAL_EMPTY     = SC_MATVAL_STRING | 0x04; // STRING plus flag
const ScMatValType SC_MATVAL_EMPTYPATH = SC_MATVAL_EMPTY | 0x08;  // EMPTY plus flag
const ScMatValType SC_MATVAL_NONVALUE  = SC_MATVAL_EMPTYPATH;     // mask of all non-value bits

struct ScMatrixValue
{
    union {
        double fVal;
        const String* pS;
    };
    ScMatValType nType;

    /// Only valid if ScMatrix methods indicate so!
    const String& GetString() const { return pS ? *pS : EMPTY_STRING; }

    /// Only valid if ScMatrix methods indicate that this is no string!
    USHORT GetError() const         { return GetDoubleErrorValue( fVal); }

    /// Only valid if ScMatrix methods indicate that this is a boolean
    bool GetBoolean() const         { return fVal != 0.0; }

    ScMatrixValue() : pS(NULL), nType(SC_MATVAL_EMPTY) {}

    ScMatrixValue(const ScMatrixValue& r) : nType(r.nType)
    {
        switch (nType)
        {
            case SC_MATVAL_VALUE:
            case SC_MATVAL_BOOLEAN:
                fVal = r.fVal;
            break;
            default:
                pS = r.pS;
        }
    }

    bool operator== (const ScMatrixValue& r) const
    {
        if (nType != r.nType)
            return false;

        switch (nType)
        {
            case SC_MATVAL_VALUE:
            case SC_MATVAL_BOOLEAN:
                return fVal == r.fVal;
            break;
            default:
                ;
        }
        if (!pS)
            return r.pS == NULL;

        return GetString().Equals(r.GetString());
    }

    bool operator!= (const ScMatrixValue& r) const
    {
        return !operator==(r);
    }

    ScMatrixValue& operator= (const ScMatrixValue& r)
    {
        nType = r.nType;
        switch (nType)
        {
            case SC_MATVAL_VALUE:
            case SC_MATVAL_BOOLEAN:
                fVal = r.fVal;
            break;
            default:
                pS = r.pS;
        }
        return *this;
    }
};

/** Matrix representation of double values and strings.

    @ATTENTION: optimized for speed and double values.

    <p> Matrix elements are NOT initialized after construction!

    <p> All methods using an SCSIZE nIndex parameter and all Is...() methods do
    NOT check the range for validity! However, the Put...() and Get...()
    methods using nCol/nRow parameters do check the range.

    <p> Methods using nCol/nRow parameters do replicate a single row vector if
    nRow > 0 and nCol < nColCount, respectively a column vector if nCol
    > 0 and nRow < nRowCount.

    <p> GetString( SCSIZE nIndex ) does not check if there really is a string,
    do this with IsString() first. GetString( SCSIZE nC, SCSIZE nR ) does check
    it and returns and empty string if there is no string. Both GetDouble()
    methods don't check for a string, do this with IsNumeric() or IsString() or
    IsValue() first.

    <p> The GetString( SvNumberFormatter&, ...) methods return the matrix
    element's string if one is present, otherwise the numerical value is
    formatted as a string, or in case of an error the error string is returned.

    <p> PutDouble() does not reset an eventual string! Use
    PutDoubleAndResetString() if that is wanted. Also the FillDouble...()
    methods don't reset strings. As a consequence memory leaks may occur if
    used wrong.
 */
class SC_DLLPUBLIC ScMatrix
{
    ScMatrixImpl*   pImpl;
    mutable ULONG   nRefCnt;    // reference count

    // only delete via Delete()
    ~ScMatrix();

    // not implemented, prevent usage
    ScMatrix( const ScMatrix& );
    ScMatrix& operator=( const ScMatrix&);

public:
    enum DensityType
    {
        FILLED_ZERO,
        FILLED_EMPTY,
        SPARSE_ZERO,
        SPARSE_EMPTY
    };

    /// The maximum number of elements a matrix may have at runtime.
    inline static size_t GetElementsMax()
    {
        // Roughly 125MB in total, divided by 8+1 per element => 14M elements.
        const size_t nMemMax = 0x08000000 / (sizeof(ScMatrixValue) + sizeof(ScMatValType));
        // With MAXROWCOUNT==65536 and 128 columns => 8M elements ~72MB.
        const size_t nArbitraryLimit = (size_t)MAXROWCOUNT * 128;
        // Stuffed with a million rows would limit this to 14 columns.
        return nMemMax < nArbitraryLimit ? nMemMax : nArbitraryLimit;
    }

    /// Value or boolean.
    inline static bool IsValueType( ScMatValType nType )
    {
        return nType <= SC_MATVAL_BOOLEAN;
    }

    /// Boolean.
    inline static bool IsBooleanType( ScMatValType nType )
    {
        return nType == SC_MATVAL_BOOLEAN;
    }

    /// String, empty or empty path, but not value nor boolean.
    inline static bool IsNonValueType( ScMatValType nType )
    {
        return (nType & SC_MATVAL_NONVALUE) != 0;
    }

    /** String, but not empty or empty path or any other type.
        Not named IsStringType to prevent confusion because previously
        IsNonValueType was named IsStringType. */
    inline static bool IsRealStringType( ScMatValType nType )
    {
        return (nType & SC_MATVAL_NONVALUE) == SC_MATVAL_STRING;
    }

    /// Empty, but not empty path or any other type.
    inline static bool IsEmptyType( ScMatValType nType )
    {
        return (nType & SC_MATVAL_NONVALUE) == SC_MATVAL_EMPTY;
    }

    /// Empty path, but not empty or any other type.
    inline static bool IsEmptyPathType( ScMatValType nType )
    {
        return (nType & SC_MATVAL_NONVALUE) == SC_MATVAL_EMPTYPATH;
    }

    /** If nC*nR results in more than GetElementsMax() entries, a 1x1 matrix is
        created instead and a double error value (errStackOverflow) is set.
        Compare nC and nR with a GetDimensions() call to check. */
    ScMatrix( SCSIZE nC, SCSIZE nR, DensityType eType = FILLED_ZERO);

    /** Clone the matrix. */
    ScMatrix* Clone() const;
    ScMatrix* Clone( DensityType eType) const;

    /** Clone the matrix if mbCloneIfConst (immutable) is set, otherwise
        return _this_ matrix, to be assigned to a ScMatrixRef. */
    ScMatrix* CloneIfConst();

    /** Set the matrix to (im)mutable for CloneIfConst(), only the interpreter
        should do this and know the consequences. */
    void SetImmutable( bool bVal );

    /**
     * Resize the matrix to specified new dimension.  Note that this operation
     * clears all stored values.
     */
    void Resize( SCSIZE nC, SCSIZE nR);

    /** Clone the matrix and extend it to the new size. nNewCols and nNewRows
        MUST be at least of the size of the original matrix. */
    ScMatrix* CloneAndExtend( SCSIZE nNewCols, SCSIZE nNewRows, DensityType eType) const;

    /// Disable refcounting forever, may only be deleted via Delete() afterwards.
    inline  void    SetEternalRef()         { nRefCnt = ULONG_MAX; }
    inline  bool    IsEternalRef() const    { return nRefCnt == ULONG_MAX; }
    inline  void    IncRef() const
    {
        if ( !IsEternalRef() )
            ++nRefCnt;
    }
    inline  void    DecRef() const
    {
        if ( nRefCnt > 0 && !IsEternalRef() )
            if ( --nRefCnt == 0 )
                delete this;
    }
    inline  void    Delete()
    {
        if ( nRefCnt == 0 || IsEternalRef() )
            delete this;
        else
            --nRefCnt;
    }

    DensityType GetDensityType() const;
    void SetErrorInterpreter( ScInterpreter* p);
    void GetDimensions( SCSIZE& rC, SCSIZE& rR) const;
    SCSIZE GetElementCount() const;
    bool ValidColRow( SCSIZE nC, SCSIZE nR) const;
    SCSIZE CalcOffset( SCSIZE nC, SCSIZE nR) const;

    /** For a row vector or column vector, if the position does not point into
        the vector but is a valid column or row offset it is adapted such that
        it points to an element to be replicated, same column row 0 for a row
        vector, same row column 0 for a column vector. Else, for a 2D matrix,
        returns false.
     */
    bool ValidColRowReplicated( SCSIZE & rC, SCSIZE & rR ) const;

    /** Checks if the matrix position is within the matrix. If it is not, for a
        row vector or column vector the position is adapted such that it points
        to an element to be replicated, same column row 0 for a row vector,
        same row column 0 for a column vector. Else, for a 2D matrix and
        position not within matrix, returns false.
     */
    bool ValidColRowOrReplicated( SCSIZE & rC, SCSIZE & rR ) const;

    void PutDouble( double fVal, SCSIZE nC, SCSIZE nR);
    void PutDouble( double fVal, SCSIZE nIndex);
    void PutString( const String& rStr, SCSIZE nC, SCSIZE nR);
    void PutString( const String& rStr, SCSIZE nIndex);
    void PutEmpty( SCSIZE nC, SCSIZE nR);
    /// Jump FALSE without path
    void PutEmptyPath( SCSIZE nC, SCSIZE nR);
    void PutError( USHORT nErrorCode, SCSIZE nC, SCSIZE nR );
    void PutBoolean( bool bVal, SCSIZE nC, SCSIZE nR);

    void FillDouble( double fVal,
            SCSIZE nC1, SCSIZE nR1, SCSIZE nC2, SCSIZE nR2 );

    /** May be used before obtaining the double value of an element to avoid
        passing its NAN around.
        @ATTENTION: MUST NOT be used if the element is a string!
                    Use GetErrorIfNotString() instead if not sure.
        @returns 0 if no error, else one of err... constants */
    USHORT GetError( SCSIZE nC, SCSIZE nR) const;

    /** Use in ScInterpreter to obtain the error code, if any.
        @returns 0 if no error or string element, else one of err... constants */
    USHORT GetErrorIfNotString( SCSIZE nC, SCSIZE nR) const
        { return IsValue( nC, nR) ? GetError( nC, nR) : 0; }

    /// @return 0.0 if empty or empty path, else value or DoubleError.
    double GetDouble( SCSIZE nC, SCSIZE nR) const;
    /// @return 0.0 if empty or empty path, else value or DoubleError.
    double GetDouble( SCSIZE nIndex) const;

    /// @return empty string if empty or empty path, else string content.
    const String& GetString( SCSIZE nC, SCSIZE nR) const;
    /// @return empty string if empty or empty path, else string content.
    const String& GetString( SCSIZE nIndex) const;

    /** @returns the matrix element's string if one is present, otherwise the
        numerical value formatted as string, or in case of an error the error
        string is returned; an empty string for empty, a "FALSE" string for
        empty path. */
    String GetString( SvNumberFormatter& rFormatter, SCSIZE nC, SCSIZE nR) const;

    /// @ATTENTION: If bString the ScMatrixValue->pS may still be NULL to indicate
    /// an empty string!
    ScMatrixValue Get( SCSIZE nC, SCSIZE nR) const;

    /// @return <TRUE/> if string or empty or empty path, in fact non-value.
    BOOL IsString( SCSIZE nIndex ) const;

    /// @return <TRUE/> if string or empty or empty path, in fact non-value.
    BOOL IsString( SCSIZE nC, SCSIZE nR ) const;

    /// @return <TRUE/> if empty or empty path.
    BOOL IsEmpty( SCSIZE nC, SCSIZE nR ) const;

    /// @return <TRUE/> if empty path.
    BOOL IsEmptyPath( SCSIZE nC, SCSIZE nR ) const;

    /// @return <TRUE/> if value or boolean.
    BOOL IsValue( SCSIZE nIndex ) const;

    /// @return <TRUE/> if value or boolean.
    BOOL IsValue( SCSIZE nC, SCSIZE nR ) const;

    /// @return <TRUE/> if value or boolean or empty or empty path.
    BOOL IsValueOrEmpty( SCSIZE nC, SCSIZE nR ) const;

    /// @return <TRUE/> if boolean.
    BOOL IsBoolean( SCSIZE nC, SCSIZE nR ) const;

    /// @return <TRUE/> if entire matrix is numeric, including booleans, with no strings or empties
    BOOL IsNumeric() const;

    void MatTrans( ScMatrix& mRes) const;
    void MatCopy ( ScMatrix& mRes) const;

    // Convert ScInterpreter::CompareMat values (-1,0,1) to boolean values
    void CompareEqual();
    void CompareNotEqual();
    void CompareLess();
    void CompareGreater();
    void CompareLessEqual();
    void CompareGreaterEqual();

    double And();       // logical AND of all matrix values, or NAN
    double Or();        // logical OR of all matrix values, or NAN

    // All other matrix functions  MatMult, MInv, ...  are in ScInterpreter
    // to be numerically safe.
};

typedef formula::SimpleIntrusiveReference< class ScMatrix > ScMatrixRef;
typedef formula::SimpleIntrusiveReference< const class ScMatrix > ScConstMatrixRef;

#endif  // SC_MATRIX_HXX

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>Re-wrote header description for ScMatrix.<commit_after>/* -*- 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.
 *
 ************************************************************************/

#ifndef SC_MATRIX_HXX
#define SC_MATRIX_HXX

#include "global.hxx"
#include "formula/intruref.hxx"
#include "formula/errorcodes.hxx"
#include <tools/string.hxx>
#include "scdllapi.h"

class SvStream;
class ScInterpreter;
class SvNumberFormatter;
class ScMatrixImpl;

typedef BYTE ScMatValType;
const ScMatValType SC_MATVAL_VALUE     = 0x00;
const ScMatValType SC_MATVAL_BOOLEAN   = 0x01;
const ScMatValType SC_MATVAL_STRING    = 0x02;
const ScMatValType SC_MATVAL_EMPTY     = SC_MATVAL_STRING | 0x04; // STRING plus flag
const ScMatValType SC_MATVAL_EMPTYPATH = SC_MATVAL_EMPTY | 0x08;  // EMPTY plus flag
const ScMatValType SC_MATVAL_NONVALUE  = SC_MATVAL_EMPTYPATH;     // mask of all non-value bits

struct ScMatrixValue
{
    union {
        double fVal;
        const String* pS;
    };
    ScMatValType nType;

    /// Only valid if ScMatrix methods indicate so!
    const String& GetString() const { return pS ? *pS : EMPTY_STRING; }

    /// Only valid if ScMatrix methods indicate that this is no string!
    USHORT GetError() const         { return GetDoubleErrorValue( fVal); }

    /// Only valid if ScMatrix methods indicate that this is a boolean
    bool GetBoolean() const         { return fVal != 0.0; }

    ScMatrixValue() : pS(NULL), nType(SC_MATVAL_EMPTY) {}

    ScMatrixValue(const ScMatrixValue& r) : nType(r.nType)
    {
        switch (nType)
        {
            case SC_MATVAL_VALUE:
            case SC_MATVAL_BOOLEAN:
                fVal = r.fVal;
            break;
            default:
                pS = r.pS;
        }
    }

    bool operator== (const ScMatrixValue& r) const
    {
        if (nType != r.nType)
            return false;

        switch (nType)
        {
            case SC_MATVAL_VALUE:
            case SC_MATVAL_BOOLEAN:
                return fVal == r.fVal;
            break;
            default:
                ;
        }
        if (!pS)
            return r.pS == NULL;

        return GetString().Equals(r.GetString());
    }

    bool operator!= (const ScMatrixValue& r) const
    {
        return !operator==(r);
    }

    ScMatrixValue& operator= (const ScMatrixValue& r)
    {
        nType = r.nType;
        switch (nType)
        {
            case SC_MATVAL_VALUE:
            case SC_MATVAL_BOOLEAN:
                fVal = r.fVal;
            break;
            default:
                pS = r.pS;
        }
        return *this;
    }
};

/**
 * Matrix data type that can store values of mixed types.  Each element can
 * be one of the following types: numeric, string, boolean, empty, and empty
 * path.
 *
 * This class also supports four different density types: filled zero,
 * filled empty, sparse zero, and sparse empty.  The filled density type
 * allocates memory for every single element at all times, whereas the
 * sparse density types allocates memory only for non-default elements.
 */
class SC_DLLPUBLIC ScMatrix
{
    ScMatrixImpl*   pImpl;
    mutable ULONG   nRefCnt;    // reference count

    // only delete via Delete()
    ~ScMatrix();

    // not implemented, prevent usage
    ScMatrix( const ScMatrix& );
    ScMatrix& operator=( const ScMatrix&);

public:
    enum DensityType
    {
        FILLED_ZERO,
        FILLED_EMPTY,
        SPARSE_ZERO,
        SPARSE_EMPTY
    };

    /// The maximum number of elements a matrix may have at runtime.
    inline static size_t GetElementsMax()
    {
        // Roughly 125MB in total, divided by 8+1 per element => 14M elements.
        const size_t nMemMax = 0x08000000 / (sizeof(ScMatrixValue) + sizeof(ScMatValType));
        // With MAXROWCOUNT==65536 and 128 columns => 8M elements ~72MB.
        const size_t nArbitraryLimit = (size_t)MAXROWCOUNT * 128;
        // Stuffed with a million rows would limit this to 14 columns.
        return nMemMax < nArbitraryLimit ? nMemMax : nArbitraryLimit;
    }

    /// Value or boolean.
    inline static bool IsValueType( ScMatValType nType )
    {
        return nType <= SC_MATVAL_BOOLEAN;
    }

    /// Boolean.
    inline static bool IsBooleanType( ScMatValType nType )
    {
        return nType == SC_MATVAL_BOOLEAN;
    }

    /// String, empty or empty path, but not value nor boolean.
    inline static bool IsNonValueType( ScMatValType nType )
    {
        return (nType & SC_MATVAL_NONVALUE) != 0;
    }

    /** String, but not empty or empty path or any other type.
        Not named IsStringType to prevent confusion because previously
        IsNonValueType was named IsStringType. */
    inline static bool IsRealStringType( ScMatValType nType )
    {
        return (nType & SC_MATVAL_NONVALUE) == SC_MATVAL_STRING;
    }

    /// Empty, but not empty path or any other type.
    inline static bool IsEmptyType( ScMatValType nType )
    {
        return (nType & SC_MATVAL_NONVALUE) == SC_MATVAL_EMPTY;
    }

    /// Empty path, but not empty or any other type.
    inline static bool IsEmptyPathType( ScMatValType nType )
    {
        return (nType & SC_MATVAL_NONVALUE) == SC_MATVAL_EMPTYPATH;
    }

    /** If nC*nR results in more than GetElementsMax() entries, a 1x1 matrix is
        created instead and a double error value (errStackOverflow) is set.
        Compare nC and nR with a GetDimensions() call to check. */
    ScMatrix( SCSIZE nC, SCSIZE nR, DensityType eType = FILLED_ZERO);

    /** Clone the matrix. */
    ScMatrix* Clone() const;
    ScMatrix* Clone( DensityType eType) const;

    /** Clone the matrix if mbCloneIfConst (immutable) is set, otherwise
        return _this_ matrix, to be assigned to a ScMatrixRef. */
    ScMatrix* CloneIfConst();

    /** Set the matrix to (im)mutable for CloneIfConst(), only the interpreter
        should do this and know the consequences. */
    void SetImmutable( bool bVal );

    /**
     * Resize the matrix to specified new dimension.  Note that this operation
     * clears all stored values.
     */
    void Resize( SCSIZE nC, SCSIZE nR);

    /** Clone the matrix and extend it to the new size. nNewCols and nNewRows
        MUST be at least of the size of the original matrix. */
    ScMatrix* CloneAndExtend( SCSIZE nNewCols, SCSIZE nNewRows, DensityType eType) const;

    /// Disable refcounting forever, may only be deleted via Delete() afterwards.
    inline  void    SetEternalRef()         { nRefCnt = ULONG_MAX; }
    inline  bool    IsEternalRef() const    { return nRefCnt == ULONG_MAX; }
    inline  void    IncRef() const
    {
        if ( !IsEternalRef() )
            ++nRefCnt;
    }
    inline  void    DecRef() const
    {
        if ( nRefCnt > 0 && !IsEternalRef() )
            if ( --nRefCnt == 0 )
                delete this;
    }
    inline  void    Delete()
    {
        if ( nRefCnt == 0 || IsEternalRef() )
            delete this;
        else
            --nRefCnt;
    }

    DensityType GetDensityType() const;
    void SetErrorInterpreter( ScInterpreter* p);
    void GetDimensions( SCSIZE& rC, SCSIZE& rR) const;
    SCSIZE GetElementCount() const;
    bool ValidColRow( SCSIZE nC, SCSIZE nR) const;
    SCSIZE CalcOffset( SCSIZE nC, SCSIZE nR) const;

    /** For a row vector or column vector, if the position does not point into
        the vector but is a valid column or row offset it is adapted such that
        it points to an element to be replicated, same column row 0 for a row
        vector, same row column 0 for a column vector. Else, for a 2D matrix,
        returns false.
     */
    bool ValidColRowReplicated( SCSIZE & rC, SCSIZE & rR ) const;

    /** Checks if the matrix position is within the matrix. If it is not, for a
        row vector or column vector the position is adapted such that it points
        to an element to be replicated, same column row 0 for a row vector,
        same row column 0 for a column vector. Else, for a 2D matrix and
        position not within matrix, returns false.
     */
    bool ValidColRowOrReplicated( SCSIZE & rC, SCSIZE & rR ) const;

    void PutDouble( double fVal, SCSIZE nC, SCSIZE nR);
    void PutDouble( double fVal, SCSIZE nIndex);
    void PutString( const String& rStr, SCSIZE nC, SCSIZE nR);
    void PutString( const String& rStr, SCSIZE nIndex);
    void PutEmpty( SCSIZE nC, SCSIZE nR);
    /// Jump FALSE without path
    void PutEmptyPath( SCSIZE nC, SCSIZE nR);
    void PutError( USHORT nErrorCode, SCSIZE nC, SCSIZE nR );
    void PutBoolean( bool bVal, SCSIZE nC, SCSIZE nR);

    void FillDouble( double fVal,
            SCSIZE nC1, SCSIZE nR1, SCSIZE nC2, SCSIZE nR2 );

    /** May be used before obtaining the double value of an element to avoid
        passing its NAN around.
        @ATTENTION: MUST NOT be used if the element is a string!
                    Use GetErrorIfNotString() instead if not sure.
        @returns 0 if no error, else one of err... constants */
    USHORT GetError( SCSIZE nC, SCSIZE nR) const;

    /** Use in ScInterpreter to obtain the error code, if any.
        @returns 0 if no error or string element, else one of err... constants */
    USHORT GetErrorIfNotString( SCSIZE nC, SCSIZE nR) const
        { return IsValue( nC, nR) ? GetError( nC, nR) : 0; }

    /// @return 0.0 if empty or empty path, else value or DoubleError.
    double GetDouble( SCSIZE nC, SCSIZE nR) const;
    /// @return 0.0 if empty or empty path, else value or DoubleError.
    double GetDouble( SCSIZE nIndex) const;

    /// @return empty string if empty or empty path, else string content.
    const String& GetString( SCSIZE nC, SCSIZE nR) const;
    /// @return empty string if empty or empty path, else string content.
    const String& GetString( SCSIZE nIndex) const;

    /** @returns the matrix element's string if one is present, otherwise the
        numerical value formatted as string, or in case of an error the error
        string is returned; an empty string for empty, a "FALSE" string for
        empty path. */
    String GetString( SvNumberFormatter& rFormatter, SCSIZE nC, SCSIZE nR) const;

    /// @ATTENTION: If bString the ScMatrixValue->pS may still be NULL to indicate
    /// an empty string!
    ScMatrixValue Get( SCSIZE nC, SCSIZE nR) const;

    /// @return <TRUE/> if string or empty or empty path, in fact non-value.
    BOOL IsString( SCSIZE nIndex ) const;

    /// @return <TRUE/> if string or empty or empty path, in fact non-value.
    BOOL IsString( SCSIZE nC, SCSIZE nR ) const;

    /// @return <TRUE/> if empty or empty path.
    BOOL IsEmpty( SCSIZE nC, SCSIZE nR ) const;

    /// @return <TRUE/> if empty path.
    BOOL IsEmptyPath( SCSIZE nC, SCSIZE nR ) const;

    /// @return <TRUE/> if value or boolean.
    BOOL IsValue( SCSIZE nIndex ) const;

    /// @return <TRUE/> if value or boolean.
    BOOL IsValue( SCSIZE nC, SCSIZE nR ) const;

    /// @return <TRUE/> if value or boolean or empty or empty path.
    BOOL IsValueOrEmpty( SCSIZE nC, SCSIZE nR ) const;

    /// @return <TRUE/> if boolean.
    BOOL IsBoolean( SCSIZE nC, SCSIZE nR ) const;

    /// @return <TRUE/> if entire matrix is numeric, including booleans, with no strings or empties
    BOOL IsNumeric() const;

    void MatTrans( ScMatrix& mRes) const;
    void MatCopy ( ScMatrix& mRes) const;

    // Convert ScInterpreter::CompareMat values (-1,0,1) to boolean values
    void CompareEqual();
    void CompareNotEqual();
    void CompareLess();
    void CompareGreater();
    void CompareLessEqual();
    void CompareGreaterEqual();

    double And();       // logical AND of all matrix values, or NAN
    double Or();        // logical OR of all matrix values, or NAN

    // All other matrix functions  MatMult, MInv, ...  are in ScInterpreter
    // to be numerically safe.
};

typedef formula::SimpleIntrusiveReference< class ScMatrix > ScMatrixRef;
typedef formula::SimpleIntrusiveReference< const class ScMatrix > ScConstMatrixRef;

#endif  // SC_MATRIX_HXX

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>