#include "QFramework/TQMultiObservable.h"
#include "TROOT.h"
#include <limits>
#include <stdexcept>

#include "QFramework/TQSample.h"

// uncomment the following line to enable debug printouts
// #define _DEBUG_
// you can perform debug printouts with statements like this
// DEBUG("error number %d occurred",someInteger);

//change (temporary) value to 1 to run with lazy evaluation support for Subobservables
//note: this may lead to significantly increase memory usage!
// (therefore for now disabled by default by means of this flag)
bool TQMultiObservable::gEvaluateSubObservablesLazily(false);

// be careful to not move the _DEBUG_ flag behind the following line
// otherwise, it will show no effect
#include "QFramework/TQLibrary.h"

////////////////////////////////////////////////////////////////////////////////////////////////
//
// TQMultiObservable
//
// The TQMultiObservable is a sort of meta-observable that will act
// upon other observables and combine their respective
// output. Creation of such an observable can be triggered by
// prepending 'Multi:' to any expression, or by using brackets [...]
// in such a way that they enclose an unquoted string. Each segment
// enclosed in such brackets will be interpreted as the name of some
// other observable, which will be evaluated and inserted in this
// expression at runtime. Please note that TQMultiObservable does not
// provide any direct data access, which means that you shall not use
// any branch names in this expression directly, but only other
// observable names.
//
////////////////////////////////////////////////////////////////////////////////////////////////


/*@observable: [TQMultiObservable] The TQMultiObservable allows for combination of the values 
     provided by other (Sub)Observables in the form of any arithmetic expression that TFormula
     can handle. It is automatically created uppon encountering square brackets in an expression
     in between which any non-integer substring is contained. Please note that the TQMultiObservable
     does not provide any direct data access and fully relies on its Subobservables. Therefore, e.g.,
     when combining a custom Observable with a TTreeFormula expression (e.g. a branch name), both parts
     need to be separatelly enclosed in square brackets. Examples: '[myCustomObs] * [leadingElectronPt]',
     '[myOtherCustomObs] * [EventEM[0].part(0).pt()]'
*/

ClassImp(TQMultiObservable)

//______________________________________________________________________________________________

TQMultiObservable::TQMultiObservable(){
  // default constructor
  DEBUGclass("default constructor called");
}

//______________________________________________________________________________________________

TQMultiObservable::~TQMultiObservable(){
  // default destructor
  DEBUGclass("destructor called");
} 

//______________________________________________________________________________________________

int TQMultiObservable::getNevaluations() const {
  // returns the number of valid evaluations of this observable for the current event
  // returns -1 if a problem is found. It is left to the calling code to decide if an error should be thrown
  DEBUGclass("getNevaluations called");
  if (this->fObservableType != TQObservable::ObservableType::vector) return 1; //for non-vector valued instances we know the number of evaluations
  int nEvals = -1;
  for (size_t i=0; i<this->fObservables.size(); ++i) {
    if (this->fObservables[i]->getObservableType() != TQObservable::ObservableType::vector) continue;
    int iEvals = this->fObservables[i]->getNevaluations();
    if (nEvals < 0) nEvals = iEvals;
    if (nEvals != iEvals) return -1; //this should not happen, only combinations with vector observables of equal "length" are allowed!
  }
  DEBUGclass("returning");
  return nEvals; //might be -1, which means we have an error, e.g. this instance is marked as a vector observable but none of its sub observables is.
}

//______________________________________________________________________________________________

double TQMultiObservable::getValueAt(int index) const {
  // retrieve the value of this observable
  DEBUGclass("entering function");
  if (!this->isInitialized()) {
    throw std::runtime_error( TString::Format("caught attempt to evaluate uninitialized instance of TQMultiObservable with name '%s', expression '%s'. Make sure that its 'initialize(TQSample* s)' method is called before trying to evaluate it! (How elese should the Observable know what it should operate on?)",this->GetName(),this->getExpression().Data()).Data() );
    return -999.;
  }
  if (index!=0 && this->fObservableType != TQObservable::ObservableType::vector) {throw std::runtime_error("Attempt to retrieve value from illegal index in observable."); return -999.;} //protection for scalar variants
  const int nEntries = this->getNevaluations();
  if (index>=nEntries) throw std::runtime_error(TString::Format("Requested index '%d' is not available for TQMultiObservable with expression '%s' (%d entries available)",index,this->getExpression().Data(),nEntries).Data());
    
  const int entry = this->getCurrentEntry();
  if(entry < 0 || entry != this->fCachedEntry){
    DEBUGclass("calculating value of '%s'",this->getActiveExpression().Data());
    
    if (nEntries < 0) throw std::runtime_error(TString::Format("Illegal number of evaluations for TQMultiObservable with expression '%s'. Are you sure all vector observables are guaranteed to have the same number of evaluations?",this->getExpression().Data()).Data() );
    
    this->fCachedValue.resize(std::max(nEntries,(int)this->fCachedValue.size())); //ensure that the caching vector is sufficiently large
    //calculate+cache all elements of the results vector
    for (int myIndex = 0; myIndex<nEntries; myIndex++) {
#if ROOT_VERSION_CODE >= ROOT_VERSION(6,06,00)
      if (TQMultiObservable::gEvaluateSubObservablesLazily) {
        this->fCachedValue[myIndex] = this->fFormula->Eval(myIndex);//the x[0] value is used as the vector index for the evaluation of the sub-observables. Parameters p[i] are included in the expression that was passed to cling indicating if the particular observable i should be evaluated in a scalar sense (p[i]==0, hence index=x[0]*p[i]=0) or a vector sense (p[i]==1, hence index=x[0]*p[i]=x[0])
      } else {
        for(size_t i=0; i<this->fObservables.size(); ++i){
          DEBUGclass("evaluating observable %d: %s",(int)(i),this->fObservables[i]->getActiveExpression().Data());
          this->fFormula->SetParameter(i,this->fObservables[i]->getValueAt( this->fObservables[i]->getObservableType() == TQObservable::ObservableType::vector ? myIndex : 0 ));
          DEBUGclass("setting parameter [%d]=%g (from '%s')",(int)(i),this->fObservables[i]->getValueAt(this->fObservables[i]->getObservableType() == TQObservable::ObservableType::vector ? myIndex : 0),this->fObservables[i]->getActiveExpression().Data());
        }
        this->fCachedValue[myIndex] = this->fFormula->Eval(0.);
      }
#else
      for(size_t i=0; i<this->fObservables.size(); ++i){
        DEBUGclass("evaluating observable %d: %s",(int)(i),this->fObservables[i]->getActiveExpression().Data());
        this->fFormula->SetParameter(i,this->fObservables[i]->getValueAt( this->fObservables[i]->getObservableType() == TQObservable::ObservableType::vector ? myIndex : 0 ));
        DEBUGclass("setting parameter [%d]=%g (from '%s')",(int)(i),this->fObservables[i]->getValueAt(this->fObservables[i]->getObservableType() == TQObservable::ObservableType::vector ? myIndex : 0),this->fObservables[i]->getActiveExpression().Data());
      }
      this->fCachedValue[myIndex] = this->fFormula->Eval(0.);
#endif      
      DEBUGclass("value of '%s' is %g",this->fFormula->GetTitle(),this->fCachedValue[myIndex]);
    }
    this->fCachedEntry = entry; 
  } else {
    DEBUGclass("skipping reevalution for event %d",entry);
  }
  return this->fCachedValue.at(index);
  
}



double TQMultiObservable::getValue() const {
  //forward to the implementation capable of handling multiple values.
  if (this->fObservableType != TQObservable::ObservableType::vector) return this->getValueAt(0);
  else throw std::runtime_error(TString::Format( "Caught attempt to perform scalar evaluation on vector valued instance of TQMultiObservable with expression '%s'",this->getExpression().Data() ).Data());
}

//______________________________________________________________________________________________

bool TQMultiObservable::initializeSelf(){
  // initialize this observable
  DEBUGclass("starting initialization");
  this->fActiveExpression = TQObservable::unreplaceBools(this->compileExpression(this->fExpression,this->fSample,true));
  DEBUGclass("initializing observable with expression '%s'",this->fActiveExpression.Data()); 
  this->parseExpression(this->fActiveExpression);
  bool retval = true;
  if(!this->fParsedExpression.IsNull()){
    if(!gAllowErrorMessages) TQLibrary::redirect_stdout("/dev/null");
    //printf("\n<TQMultiObservalbe::initializeSelf>   expr = %s\n\n", expr.Data());
#if ROOT_VERSION_CODE >= ROOT_VERSION(6,06,00)
    TString expr;
    if (TQMultiObservable::gEvaluateSubObservablesLazily) {
      expr = this->fParsedExpression;
      this->fFormula = new TFormula(this->GetName(),expr,1,this->fObservables.size(),false);
    } else {
      expr = this->compileExpression(this->fParsedExpression,this->fSample,true); //why do we compile the parsed expression again????
      this->fFormula = new TFormula(this->GetName(),expr);
    }
#else
    TString expr(this->compileExpression(this->fParsedExpression,this->fSample,true)); //why do we compile the parsed expression again????
    this->fFormula = new TFormula(this->GetName(),expr);
#endif    
    if(!gAllowErrorMessages) TQLibrary::restore_stdout();
#if ROOT_VERSION_CODE >= ROOT_VERSION(6,04,00) 
    if(!this->fFormula->IsValid()){
      throw std::runtime_error(TString::Format("unable to initialize formula with expression '%s'",expr.Data()).Data());
      return false;
    }
#endif
  } else {
    WARNclass("observable '%s' has Null-Expression!",this->GetName());
    return false;
  }
  this->fObservableType = TQObservable::ObservableType::scalar; //default after initialization, is set to ::vector in the following if needed
  for(size_t i=0; i<this->fObservables.size(); ++i){
    if(!this->fObservables[i]->initialize(this->fSample)) {
      ERRORclass("Failed to initialize sub-observable created from expression '%s'",this->fObservables[i]->getExpression().Data());
      retval = false;
    }
    if (this->fObservables[i]->getObservableType() == TQObservable::ObservableType::vector) {
      this->fObservableType = TQObservable::ObservableType::vector; //if at least one sub-observable is a vector observable then this also becomes a vector observable.
#if ROOT_VERSION_CODE >= ROOT_VERSION(6,06,00)
      if (TQMultiObservable::gEvaluateSubObservablesLazily) {
        this->fFormula->SetParameter(i,1.);
      } else {
        this->fFormula->SetParameter(i,0.);
      }
#endif
    }
  }
  this->fCachedEntry = -999;
  DEBUGclass("successfully initialized");
  return retval;
}

//______________________________________________________________________________________________

bool TQMultiObservable::finalizeSelf(){
  // initialize this observable
  DEBUGclass("finalizing '%s'",this->GetName());
  bool ok = true;
  for(size_t i=0; i<this->fObservables.size(); ++i){
    if(!(this->fObservables[i]->finalize())){
      ok = false;
    }
  }
  if(this->fFormula) delete this->fFormula;
  this->fFormula = NULL;
  this->fActiveExpression.Clear();
  this->fObservables.clear();
  return ok;
}

//______________________________________________________________________________________________

Long64_t TQMultiObservable::getCurrentEntry() const {
  // retrieve the current entry from the tree
  if(this->fObservables.size() == 0) return -1;
  for (size_t i = 0; i<this->fObservables.size(); i++) {
    if (this->fObservables[i]->getCurrentEntry() >= 0) return this->fObservables[i]->getCurrentEntry();
  }
  return -1;
}

//______________________________________________________________________________________________
TObjArray* TQMultiObservable::getBranchNames() const {
  // retrieve the list of branch names for this observable
  // ownership of the list belongs to the caller of the function
  DEBUGclass("retrieving branch names");
  TObjArray* bnames = new TObjArray();
  for(size_t i=0; i<this->fObservables.size(); ++i){
    TQObservable* obs =this->fObservables[i];
    if(!obs) throw std::runtime_error("encountered invalid sub-observable!");
    DEBUGclass("retrieving branches of observable '%s' of class '%s'",obs->getExpression().Data(),obs->ClassName());
    TCollection* c = obs->getBranchNames();
    if(c){
      c->SetOwner(false);
      bnames->AddAll(c);
      delete c;
    }
  }
  DEBUGclass("returning");
  return bnames;
}

//______________________________________________________________________________________________

TQMultiObservable::TQMultiObservable(const TString& expression):
  TQObservable(expression)
{
  // constructor with expression argument
  DEBUGclass("constructor called with '%s'",expression.Data());
  // the predefined string member "expression" allows your observable to store an expression of your choice
  // this string will be the verbatim argument you passed to the constructor of your observable
  // you can use it to choose between different modes or pass configuration options to your observable
  this->SetName(TQObservable::makeObservableName(expression));
  this->setExpression(expression);
}

//______________________________________________________________________________________________

const TString& TQMultiObservable::getExpression() const {
  // retrieve the expression associated with this observable
  return this->fExpression;
}

//______________________________________________________________________________________________

bool TQMultiObservable::hasExpression() const {
  // check if this observable type knows expressions
  return true;
}

//______________________________________________________________________________________________

void TQMultiObservable::setExpression(const TString& expr){
  // set the expression to a given string
  this->fExpression = expr;
}
//______________________________________________________________________________________________

bool TQMultiObservable::parseExpression(const TString& expr){
  // parse the expression
  this->clearParsedExpression();
#if ROOT_VERSION_CODE >= ROOT_VERSION(6,06,00)
  if (TQMultiObservable::gEvaluateSubObservablesLazily) {
    this->fParsedExpression="[](double* x, double* p) -> double { return (";
  }
#endif
  TString expression(expr);
  int parcnt = 0;
  while(!expression.IsNull()){
    DEBUGclass("entering next parsing cycle: expr='%s', remainder='%s'",this->fParsedExpression.Data(),expression.Data());
    TQStringUtils::readUpTo(expression,this->fParsedExpression,"[");
    if(expression.IsNull()) break;
    TString subExpr = "";
    if(TQStringUtils::readBlock(expression,subExpr,"[]") < 1){
      throw std::runtime_error(TString::Format("no sub expression block [...] found in '%s'",expression.Data()).Data());
      return false;
    }
    TQObservable* obs = TQObservable::getObservable(subExpr,this->fSample);
    if(obs){
#if ROOT_VERSION_CODE >= ROOT_VERSION(6,06,00)
      if (TQMultiObservable::gEvaluateSubObservablesLazily) {
        //logic here: one parameter for each sub-observable, used to steer if vector indices are always 0 or whatever index value x[0] is set to.  
        this->fParsedExpression.Append(TString::Format("(reinterpret_cast<TQObservable*>(%p)->getValueAt(x[0]*p[%d]))",(void*)obs,parcnt));
      } else {
        this->fParsedExpression.Append(TString::Format("[%d]",parcnt));
      }
#else
      this->fParsedExpression.Append(TString::Format("[%d]",parcnt));
#endif
      this->fObservables.push_back(obs);
      parcnt++;
    } else {
      this->fParsedExpression.Append(TString::Format("0."));
      throw std::runtime_error(TString::Format("cannot parse expression '%s', unable to retrieve observable with expression '%s'",this->fParsedExpression.Data(),subExpr.Data()).Data());
    }
    DEBUGclass("result of parsing cycle: expr='%s', subExpr='%s', remainder='%s'",this->fParsedExpression.Data(),subExpr.Data(),expression.Data());
  }
  if(!expression.IsNull()){
    throw std::runtime_error(TString::Format("there was an undefined error while parsing expression '%s'",this->fParsedExpression.Data()).Data());
    return false;
  }
#if ROOT_VERSION_CODE >= ROOT_VERSION(6,06,00)
  if (TQMultiObservable::gEvaluateSubObservablesLazily) {
    //close lambda function
    this->fParsedExpression.Append("); }");
  }
#endif
  return true;
}

//______________________________________________________________________________________________

void TQMultiObservable::clearParsedExpression(){
  // clear the current expression
  this->fParsedExpression.Clear();
  this->fObservables.clear();
}

//______________________________________________________________________________________________

TString TQMultiObservable::getParsedExpression(){
  // clear the current expression
  return this->fParsedExpression;
}

//______________________________________________________________________________________________

TString TQMultiObservable::getActiveExpression() const {
  // retrieve the expression associated with this incarnation
  return this->fActiveExpression;
}

//______________________________________________________________________________________________

TQObservable* TQMultiObservable::getObservable(int idx){
  // return the sub-observable with the given index
  return this->fObservables.at(idx);
}

//______________________________________________________________________________________________

DEFINE_OBSERVABLE_FACTORY(TQMultiObservable,TString expression){
  // try to create an instance of this observable from the given expression
  if(TQStringUtils::removeLeadingText(expression,"Multi:") ||
     TQStringUtils::hasTFormulaParameters(expression)) { //check if there are [] with non-numerical characters (0-9) in between
    return new TQMultiObservable(expression);
  }
  return NULL;
}

 TQMultiObservable.cxx:1
 TQMultiObservable.cxx:2
 TQMultiObservable.cxx:3
 TQMultiObservable.cxx:4
 TQMultiObservable.cxx:5
 TQMultiObservable.cxx:6
 TQMultiObservable.cxx:7
 TQMultiObservable.cxx:8
 TQMultiObservable.cxx:9
 TQMultiObservable.cxx:10
 TQMultiObservable.cxx:11
 TQMultiObservable.cxx:12
 TQMultiObservable.cxx:13
 TQMultiObservable.cxx:14
 TQMultiObservable.cxx:15
 TQMultiObservable.cxx:16
 TQMultiObservable.cxx:17
 TQMultiObservable.cxx:18
 TQMultiObservable.cxx:19
 TQMultiObservable.cxx:20
 TQMultiObservable.cxx:21
 TQMultiObservable.cxx:22
 TQMultiObservable.cxx:23
 TQMultiObservable.cxx:24
 TQMultiObservable.cxx:25
 TQMultiObservable.cxx:26
 TQMultiObservable.cxx:27
 TQMultiObservable.cxx:28
 TQMultiObservable.cxx:29
 TQMultiObservable.cxx:30
 TQMultiObservable.cxx:31
 TQMultiObservable.cxx:32
 TQMultiObservable.cxx:33
 TQMultiObservable.cxx:34
 TQMultiObservable.cxx:35
 TQMultiObservable.cxx:36
 TQMultiObservable.cxx:37
 TQMultiObservable.cxx:38
 TQMultiObservable.cxx:39
 TQMultiObservable.cxx:40
 TQMultiObservable.cxx:41
 TQMultiObservable.cxx:42
 TQMultiObservable.cxx:43
 TQMultiObservable.cxx:44
 TQMultiObservable.cxx:45
 TQMultiObservable.cxx:46
 TQMultiObservable.cxx:47
 TQMultiObservable.cxx:48
 TQMultiObservable.cxx:49
 TQMultiObservable.cxx:50
 TQMultiObservable.cxx:51
 TQMultiObservable.cxx:52
 TQMultiObservable.cxx:53
 TQMultiObservable.cxx:54
 TQMultiObservable.cxx:55
 TQMultiObservable.cxx:56
 TQMultiObservable.cxx:57
 TQMultiObservable.cxx:58
 TQMultiObservable.cxx:59
 TQMultiObservable.cxx:60
 TQMultiObservable.cxx:61
 TQMultiObservable.cxx:62
 TQMultiObservable.cxx:63
 TQMultiObservable.cxx:64
 TQMultiObservable.cxx:65
 TQMultiObservable.cxx:66
 TQMultiObservable.cxx:67
 TQMultiObservable.cxx:68
 TQMultiObservable.cxx:69
 TQMultiObservable.cxx:70
 TQMultiObservable.cxx:71
 TQMultiObservable.cxx:72
 TQMultiObservable.cxx:73
 TQMultiObservable.cxx:74
 TQMultiObservable.cxx:75
 TQMultiObservable.cxx:76
 TQMultiObservable.cxx:77
 TQMultiObservable.cxx:78
 TQMultiObservable.cxx:79
 TQMultiObservable.cxx:80
 TQMultiObservable.cxx:81
 TQMultiObservable.cxx:82
 TQMultiObservable.cxx:83
 TQMultiObservable.cxx:84
 TQMultiObservable.cxx:85
 TQMultiObservable.cxx:86
 TQMultiObservable.cxx:87
 TQMultiObservable.cxx:88
 TQMultiObservable.cxx:89
 TQMultiObservable.cxx:90
 TQMultiObservable.cxx:91
 TQMultiObservable.cxx:92
 TQMultiObservable.cxx:93
 TQMultiObservable.cxx:94
 TQMultiObservable.cxx:95
 TQMultiObservable.cxx:96
 TQMultiObservable.cxx:97
 TQMultiObservable.cxx:98
 TQMultiObservable.cxx:99
 TQMultiObservable.cxx:100
 TQMultiObservable.cxx:101
 TQMultiObservable.cxx:102
 TQMultiObservable.cxx:103
 TQMultiObservable.cxx:104
 TQMultiObservable.cxx:105
 TQMultiObservable.cxx:106
 TQMultiObservable.cxx:107
 TQMultiObservable.cxx:108
 TQMultiObservable.cxx:109
 TQMultiObservable.cxx:110
 TQMultiObservable.cxx:111
 TQMultiObservable.cxx:112
 TQMultiObservable.cxx:113
 TQMultiObservable.cxx:114
 TQMultiObservable.cxx:115
 TQMultiObservable.cxx:116
 TQMultiObservable.cxx:117
 TQMultiObservable.cxx:118
 TQMultiObservable.cxx:119
 TQMultiObservable.cxx:120
 TQMultiObservable.cxx:121
 TQMultiObservable.cxx:122
 TQMultiObservable.cxx:123
 TQMultiObservable.cxx:124
 TQMultiObservable.cxx:125
 TQMultiObservable.cxx:126
 TQMultiObservable.cxx:127
 TQMultiObservable.cxx:128
 TQMultiObservable.cxx:129
 TQMultiObservable.cxx:130
 TQMultiObservable.cxx:131
 TQMultiObservable.cxx:132
 TQMultiObservable.cxx:133
 TQMultiObservable.cxx:134
 TQMultiObservable.cxx:135
 TQMultiObservable.cxx:136
 TQMultiObservable.cxx:137
 TQMultiObservable.cxx:138
 TQMultiObservable.cxx:139
 TQMultiObservable.cxx:140
 TQMultiObservable.cxx:141
 TQMultiObservable.cxx:142
 TQMultiObservable.cxx:143
 TQMultiObservable.cxx:144
 TQMultiObservable.cxx:145
 TQMultiObservable.cxx:146
 TQMultiObservable.cxx:147
 TQMultiObservable.cxx:148
 TQMultiObservable.cxx:149
 TQMultiObservable.cxx:150
 TQMultiObservable.cxx:151
 TQMultiObservable.cxx:152
 TQMultiObservable.cxx:153
 TQMultiObservable.cxx:154
 TQMultiObservable.cxx:155
 TQMultiObservable.cxx:156
 TQMultiObservable.cxx:157
 TQMultiObservable.cxx:158
 TQMultiObservable.cxx:159
 TQMultiObservable.cxx:160
 TQMultiObservable.cxx:161
 TQMultiObservable.cxx:162
 TQMultiObservable.cxx:163
 TQMultiObservable.cxx:164
 TQMultiObservable.cxx:165
 TQMultiObservable.cxx:166
 TQMultiObservable.cxx:167
 TQMultiObservable.cxx:168
 TQMultiObservable.cxx:169
 TQMultiObservable.cxx:170
 TQMultiObservable.cxx:171
 TQMultiObservable.cxx:172
 TQMultiObservable.cxx:173
 TQMultiObservable.cxx:174
 TQMultiObservable.cxx:175
 TQMultiObservable.cxx:176
 TQMultiObservable.cxx:177
 TQMultiObservable.cxx:178
 TQMultiObservable.cxx:179
 TQMultiObservable.cxx:180
 TQMultiObservable.cxx:181
 TQMultiObservable.cxx:182
 TQMultiObservable.cxx:183
 TQMultiObservable.cxx:184
 TQMultiObservable.cxx:185
 TQMultiObservable.cxx:186
 TQMultiObservable.cxx:187
 TQMultiObservable.cxx:188
 TQMultiObservable.cxx:189
 TQMultiObservable.cxx:190
 TQMultiObservable.cxx:191
 TQMultiObservable.cxx:192
 TQMultiObservable.cxx:193
 TQMultiObservable.cxx:194
 TQMultiObservable.cxx:195
 TQMultiObservable.cxx:196
 TQMultiObservable.cxx:197
 TQMultiObservable.cxx:198
 TQMultiObservable.cxx:199
 TQMultiObservable.cxx:200
 TQMultiObservable.cxx:201
 TQMultiObservable.cxx:202
 TQMultiObservable.cxx:203
 TQMultiObservable.cxx:204
 TQMultiObservable.cxx:205
 TQMultiObservable.cxx:206
 TQMultiObservable.cxx:207
 TQMultiObservable.cxx:208
 TQMultiObservable.cxx:209
 TQMultiObservable.cxx:210
 TQMultiObservable.cxx:211
 TQMultiObservable.cxx:212
 TQMultiObservable.cxx:213
 TQMultiObservable.cxx:214
 TQMultiObservable.cxx:215
 TQMultiObservable.cxx:216
 TQMultiObservable.cxx:217
 TQMultiObservable.cxx:218
 TQMultiObservable.cxx:219
 TQMultiObservable.cxx:220
 TQMultiObservable.cxx:221
 TQMultiObservable.cxx:222
 TQMultiObservable.cxx:223
 TQMultiObservable.cxx:224
 TQMultiObservable.cxx:225
 TQMultiObservable.cxx:226
 TQMultiObservable.cxx:227
 TQMultiObservable.cxx:228
 TQMultiObservable.cxx:229
 TQMultiObservable.cxx:230
 TQMultiObservable.cxx:231
 TQMultiObservable.cxx:232
 TQMultiObservable.cxx:233
 TQMultiObservable.cxx:234
 TQMultiObservable.cxx:235
 TQMultiObservable.cxx:236
 TQMultiObservable.cxx:237
 TQMultiObservable.cxx:238
 TQMultiObservable.cxx:239
 TQMultiObservable.cxx:240
 TQMultiObservable.cxx:241
 TQMultiObservable.cxx:242
 TQMultiObservable.cxx:243
 TQMultiObservable.cxx:244
 TQMultiObservable.cxx:245
 TQMultiObservable.cxx:246
 TQMultiObservable.cxx:247
 TQMultiObservable.cxx:248
 TQMultiObservable.cxx:249
 TQMultiObservable.cxx:250
 TQMultiObservable.cxx:251
 TQMultiObservable.cxx:252
 TQMultiObservable.cxx:253
 TQMultiObservable.cxx:254
 TQMultiObservable.cxx:255
 TQMultiObservable.cxx:256
 TQMultiObservable.cxx:257
 TQMultiObservable.cxx:258
 TQMultiObservable.cxx:259
 TQMultiObservable.cxx:260
 TQMultiObservable.cxx:261
 TQMultiObservable.cxx:262
 TQMultiObservable.cxx:263
 TQMultiObservable.cxx:264
 TQMultiObservable.cxx:265
 TQMultiObservable.cxx:266
 TQMultiObservable.cxx:267
 TQMultiObservable.cxx:268
 TQMultiObservable.cxx:269
 TQMultiObservable.cxx:270
 TQMultiObservable.cxx:271
 TQMultiObservable.cxx:272
 TQMultiObservable.cxx:273
 TQMultiObservable.cxx:274
 TQMultiObservable.cxx:275
 TQMultiObservable.cxx:276
 TQMultiObservable.cxx:277
 TQMultiObservable.cxx:278
 TQMultiObservable.cxx:279
 TQMultiObservable.cxx:280
 TQMultiObservable.cxx:281
 TQMultiObservable.cxx:282
 TQMultiObservable.cxx:283
 TQMultiObservable.cxx:284
 TQMultiObservable.cxx:285
 TQMultiObservable.cxx:286
 TQMultiObservable.cxx:287
 TQMultiObservable.cxx:288
 TQMultiObservable.cxx:289
 TQMultiObservable.cxx:290
 TQMultiObservable.cxx:291
 TQMultiObservable.cxx:292
 TQMultiObservable.cxx:293
 TQMultiObservable.cxx:294
 TQMultiObservable.cxx:295
 TQMultiObservable.cxx:296
 TQMultiObservable.cxx:297
 TQMultiObservable.cxx:298
 TQMultiObservable.cxx:299
 TQMultiObservable.cxx:300
 TQMultiObservable.cxx:301
 TQMultiObservable.cxx:302
 TQMultiObservable.cxx:303
 TQMultiObservable.cxx:304
 TQMultiObservable.cxx:305
 TQMultiObservable.cxx:306
 TQMultiObservable.cxx:307
 TQMultiObservable.cxx:308
 TQMultiObservable.cxx:309
 TQMultiObservable.cxx:310
 TQMultiObservable.cxx:311
 TQMultiObservable.cxx:312
 TQMultiObservable.cxx:313
 TQMultiObservable.cxx:314
 TQMultiObservable.cxx:315
 TQMultiObservable.cxx:316
 TQMultiObservable.cxx:317
 TQMultiObservable.cxx:318
 TQMultiObservable.cxx:319
 TQMultiObservable.cxx:320
 TQMultiObservable.cxx:321
 TQMultiObservable.cxx:322
 TQMultiObservable.cxx:323
 TQMultiObservable.cxx:324
 TQMultiObservable.cxx:325
 TQMultiObservable.cxx:326
 TQMultiObservable.cxx:327
 TQMultiObservable.cxx:328
 TQMultiObservable.cxx:329
 TQMultiObservable.cxx:330
 TQMultiObservable.cxx:331
 TQMultiObservable.cxx:332
 TQMultiObservable.cxx:333
 TQMultiObservable.cxx:334
 TQMultiObservable.cxx:335
 TQMultiObservable.cxx:336
 TQMultiObservable.cxx:337
 TQMultiObservable.cxx:338
 TQMultiObservable.cxx:339
 TQMultiObservable.cxx:340
 TQMultiObservable.cxx:341
 TQMultiObservable.cxx:342
 TQMultiObservable.cxx:343
 TQMultiObservable.cxx:344
 TQMultiObservable.cxx:345
 TQMultiObservable.cxx:346
 TQMultiObservable.cxx:347
 TQMultiObservable.cxx:348
 TQMultiObservable.cxx:349
 TQMultiObservable.cxx:350
 TQMultiObservable.cxx:351
 TQMultiObservable.cxx:352
 TQMultiObservable.cxx:353
 TQMultiObservable.cxx:354
 TQMultiObservable.cxx:355
 TQMultiObservable.cxx:356
 TQMultiObservable.cxx:357
 TQMultiObservable.cxx:358
 TQMultiObservable.cxx:359
 TQMultiObservable.cxx:360
 TQMultiObservable.cxx:361
 TQMultiObservable.cxx:362
 TQMultiObservable.cxx:363
 TQMultiObservable.cxx:364
 TQMultiObservable.cxx:365
 TQMultiObservable.cxx:366
 TQMultiObservable.cxx:367
 TQMultiObservable.cxx:368
 TQMultiObservable.cxx:369
 TQMultiObservable.cxx:370
 TQMultiObservable.cxx:371
 TQMultiObservable.cxx:372
 TQMultiObservable.cxx:373
 TQMultiObservable.cxx:374
 TQMultiObservable.cxx:375
 TQMultiObservable.cxx:376
 TQMultiObservable.cxx:377
 TQMultiObservable.cxx:378
 TQMultiObservable.cxx:379