// @(#)root/unuran:$Id$
// Authors: L. Moneta, J. Leydold Wed Feb 28 2007

/**********************************************************************
 *                                                                    *
 * Copyright (c) 2006  LCG ROOT Math Team, CERN/PH-SFT                *
 *                                                                    *
 *                                                                    *
 **********************************************************************/

// Implementation file for class TUnuranDiscrDist

#include "TUnuranDiscrDist.h"

#include "Math/IFunction.h"
#include "TF1.h"
#include "Math/WrappedTF1.h"


#include <cassert>


TUnuranDiscrDist::TUnuranDiscrDist (const ROOT::Math::IGenFunction & func, bool copyFunc) :
   fPmf(&func),
   fCdf(0),
   fXmin(1),
   fXmax(-1),
   fMode(0),
   fSum(0),
   fHasDomain(0),
   fHasMode(0),
   fHasSum(0),
   fOwnFunc(copyFunc)
{
   //Constructor from a generic function object
   if (fOwnFunc) {
      fPmf = fPmf->Clone();
      //if (fCdf) fCdf->Clone();
   }
}


TUnuranDiscrDist::TUnuranDiscrDist (TF1 * func) :
   fPmf( (func) ? new ROOT::Math::WrappedTF1 ( *func) : 0 ),
   fCdf(0),
   fXmin(1),
   fXmax(-1),
   fMode(0),
   fSum(0),
   fHasDomain(0),
   fHasMode(0),
   fHasSum(0),
   fOwnFunc(true)
{
   //Constructor from a TF1 objects
}


TUnuranDiscrDist::TUnuranDiscrDist(const TUnuranDiscrDist & rhs) :
   TUnuranBaseDist(),
   fPmf(0),
   fCdf(0)
{
   // Implementation of copy ctor using aassignment operator
   operator=(rhs);
}

TUnuranDiscrDist & TUnuranDiscrDist::operator = (const TUnuranDiscrDist &rhs)
{
   // Implementation of assignment operator (copy only the function pointer not the function itself)
   if (this == &rhs) return *this;  // time saving self-test
   fPVec = rhs.fPVec;
   fPVecSum = rhs.fPVecSum;
   fXmin = rhs.fXmin;
   fXmax = rhs.fXmax;
   fMode = rhs.fMode;
   fSum  = rhs.fSum;
   fHasDomain = rhs.fHasDomain;
   fHasMode   = rhs.fHasMode;
   fHasSum    = rhs.fHasSum;
   fOwnFunc   = rhs.fOwnFunc;
   if (!fOwnFunc) {
      fPmf   = rhs.fPmf;
      fCdf   = rhs.fCdf;
   }
   else {
      if (fPmf) delete fPmf;
      if (fCdf) delete fCdf;
      fPmf  = (rhs.fPmf)  ? rhs.fPmf->Clone()  : 0;
      fCdf  = (rhs.fCdf)  ? rhs.fCdf->Clone()  : 0;
   }

   return *this;
}

TUnuranDiscrDist::~TUnuranDiscrDist() {
   // destructor implementation
   if (fOwnFunc) {
      if (fPmf) delete fPmf;
      if (fCdf) delete fCdf;
   }
}

void TUnuranDiscrDist::SetCdf(const ROOT::Math::IGenFunction & cdf) {
   //  set cdf distribution using a generic function interface
   fCdf = (fOwnFunc) ? cdf.Clone() : &cdf;
}

void TUnuranDiscrDist::SetCdf(TF1 *  cdf) {
   // set cumulative distribution function from a TF1
   if (!fOwnFunc && fPmf) {
      // need to manage also the pmf
      fPmf = fPmf->Clone();
   }
   else
      if (fCdf) delete fCdf;

   fCdf = (cdf) ? new ROOT::Math::WrappedTF1 ( *cdf) : 0;
   fOwnFunc = true;
}

double TUnuranDiscrDist::Pmf ( int x) const {
   // evaluate the distribution
   if (!fPmf) {
      if (x < static_cast<int>(fPVec.size()) || x >= static_cast<int>(fPVec.size()) ) return 0;
      return fPVec[x];
   }
   return (*fPmf)(double(x));
}

double TUnuranDiscrDist::Cdf ( int x) const {
   // evaluate the cumulative distribution
   // otherwise evaluate from the sum of the probabilities
   if (fHasDomain && x < fXmin) return 0;

   if (fCdf) {
      return (*fCdf)(double(x));
   }

   //estimation from sum of probability
   int vsize = fPVecSum.size();
   if ( x < vsize )
      return fPVecSum[x];

   // calculate the sum
   int x0 = ( fHasDomain) ? fXmin : 0;
   int i0 = vsize;     // starting index
   int iN = x - x0 + 1;  // maximum index
   fPVecSum.resize(iN);
   double sum = ( i0 > 0 ) ? fPVecSum.back() : 0;
   for (int i = i0; i < iN; ++i) {
      sum += Pmf(i + x0);
      fPVecSum[i] =  sum;
   }

   return fPVecSum.back();

}





 TUnuranDiscrDist.cxx:1
 TUnuranDiscrDist.cxx:2
 TUnuranDiscrDist.cxx:3
 TUnuranDiscrDist.cxx:4
 TUnuranDiscrDist.cxx:5
 TUnuranDiscrDist.cxx:6
 TUnuranDiscrDist.cxx:7
 TUnuranDiscrDist.cxx:8
 TUnuranDiscrDist.cxx:9
 TUnuranDiscrDist.cxx:10
 TUnuranDiscrDist.cxx:11
 TUnuranDiscrDist.cxx:12
 TUnuranDiscrDist.cxx:13
 TUnuranDiscrDist.cxx:14
 TUnuranDiscrDist.cxx:15
 TUnuranDiscrDist.cxx:16
 TUnuranDiscrDist.cxx:17
 TUnuranDiscrDist.cxx:18
 TUnuranDiscrDist.cxx:19
 TUnuranDiscrDist.cxx:20
 TUnuranDiscrDist.cxx:21
 TUnuranDiscrDist.cxx:22
 TUnuranDiscrDist.cxx:23
 TUnuranDiscrDist.cxx:24
 TUnuranDiscrDist.cxx:25
 TUnuranDiscrDist.cxx:26
 TUnuranDiscrDist.cxx:27
 TUnuranDiscrDist.cxx:28
 TUnuranDiscrDist.cxx:29
 TUnuranDiscrDist.cxx:30
 TUnuranDiscrDist.cxx:31
 TUnuranDiscrDist.cxx:32
 TUnuranDiscrDist.cxx:33
 TUnuranDiscrDist.cxx:34
 TUnuranDiscrDist.cxx:35
 TUnuranDiscrDist.cxx:36
 TUnuranDiscrDist.cxx:37
 TUnuranDiscrDist.cxx:38
 TUnuranDiscrDist.cxx:39
 TUnuranDiscrDist.cxx:40
 TUnuranDiscrDist.cxx:41
 TUnuranDiscrDist.cxx:42
 TUnuranDiscrDist.cxx:43
 TUnuranDiscrDist.cxx:44
 TUnuranDiscrDist.cxx:45
 TUnuranDiscrDist.cxx:46
 TUnuranDiscrDist.cxx:47
 TUnuranDiscrDist.cxx:48
 TUnuranDiscrDist.cxx:49
 TUnuranDiscrDist.cxx:50
 TUnuranDiscrDist.cxx:51
 TUnuranDiscrDist.cxx:52
 TUnuranDiscrDist.cxx:53
 TUnuranDiscrDist.cxx:54
 TUnuranDiscrDist.cxx:55
 TUnuranDiscrDist.cxx:56
 TUnuranDiscrDist.cxx:57
 TUnuranDiscrDist.cxx:58
 TUnuranDiscrDist.cxx:59
 TUnuranDiscrDist.cxx:60
 TUnuranDiscrDist.cxx:61
 TUnuranDiscrDist.cxx:62
 TUnuranDiscrDist.cxx:63
 TUnuranDiscrDist.cxx:64
 TUnuranDiscrDist.cxx:65
 TUnuranDiscrDist.cxx:66
 TUnuranDiscrDist.cxx:67
 TUnuranDiscrDist.cxx:68
 TUnuranDiscrDist.cxx:69
 TUnuranDiscrDist.cxx:70
 TUnuranDiscrDist.cxx:71
 TUnuranDiscrDist.cxx:72
 TUnuranDiscrDist.cxx:73
 TUnuranDiscrDist.cxx:74
 TUnuranDiscrDist.cxx:75
 TUnuranDiscrDist.cxx:76
 TUnuranDiscrDist.cxx:77
 TUnuranDiscrDist.cxx:78
 TUnuranDiscrDist.cxx:79
 TUnuranDiscrDist.cxx:80
 TUnuranDiscrDist.cxx:81
 TUnuranDiscrDist.cxx:82
 TUnuranDiscrDist.cxx:83
 TUnuranDiscrDist.cxx:84
 TUnuranDiscrDist.cxx:85
 TUnuranDiscrDist.cxx:86
 TUnuranDiscrDist.cxx:87
 TUnuranDiscrDist.cxx:88
 TUnuranDiscrDist.cxx:89
 TUnuranDiscrDist.cxx:90
 TUnuranDiscrDist.cxx:91
 TUnuranDiscrDist.cxx:92
 TUnuranDiscrDist.cxx:93
 TUnuranDiscrDist.cxx:94
 TUnuranDiscrDist.cxx:95
 TUnuranDiscrDist.cxx:96
 TUnuranDiscrDist.cxx:97
 TUnuranDiscrDist.cxx:98
 TUnuranDiscrDist.cxx:99
 TUnuranDiscrDist.cxx:100
 TUnuranDiscrDist.cxx:101
 TUnuranDiscrDist.cxx:102
 TUnuranDiscrDist.cxx:103
 TUnuranDiscrDist.cxx:104
 TUnuranDiscrDist.cxx:105
 TUnuranDiscrDist.cxx:106
 TUnuranDiscrDist.cxx:107
 TUnuranDiscrDist.cxx:108
 TUnuranDiscrDist.cxx:109
 TUnuranDiscrDist.cxx:110
 TUnuranDiscrDist.cxx:111
 TUnuranDiscrDist.cxx:112
 TUnuranDiscrDist.cxx:113
 TUnuranDiscrDist.cxx:114
 TUnuranDiscrDist.cxx:115
 TUnuranDiscrDist.cxx:116
 TUnuranDiscrDist.cxx:117
 TUnuranDiscrDist.cxx:118
 TUnuranDiscrDist.cxx:119
 TUnuranDiscrDist.cxx:120
 TUnuranDiscrDist.cxx:121
 TUnuranDiscrDist.cxx:122
 TUnuranDiscrDist.cxx:123
 TUnuranDiscrDist.cxx:124
 TUnuranDiscrDist.cxx:125
 TUnuranDiscrDist.cxx:126
 TUnuranDiscrDist.cxx:127
 TUnuranDiscrDist.cxx:128
 TUnuranDiscrDist.cxx:129
 TUnuranDiscrDist.cxx:130
 TUnuranDiscrDist.cxx:131
 TUnuranDiscrDist.cxx:132
 TUnuranDiscrDist.cxx:133
 TUnuranDiscrDist.cxx:134
 TUnuranDiscrDist.cxx:135
 TUnuranDiscrDist.cxx:136
 TUnuranDiscrDist.cxx:137
 TUnuranDiscrDist.cxx:138
 TUnuranDiscrDist.cxx:139
 TUnuranDiscrDist.cxx:140
 TUnuranDiscrDist.cxx:141
 TUnuranDiscrDist.cxx:142
 TUnuranDiscrDist.cxx:143
 TUnuranDiscrDist.cxx:144
 TUnuranDiscrDist.cxx:145
 TUnuranDiscrDist.cxx:146
 TUnuranDiscrDist.cxx:147
 TUnuranDiscrDist.cxx:148
 TUnuranDiscrDist.cxx:149
 TUnuranDiscrDist.cxx:150
 TUnuranDiscrDist.cxx:151
 TUnuranDiscrDist.cxx:152
 TUnuranDiscrDist.cxx:153
 TUnuranDiscrDist.cxx:154
 TUnuranDiscrDist.cxx:155
 TUnuranDiscrDist.cxx:156
 TUnuranDiscrDist.cxx:157
 TUnuranDiscrDist.cxx:158
 TUnuranDiscrDist.cxx:159
 TUnuranDiscrDist.cxx:160
 TUnuranDiscrDist.cxx:161
 TUnuranDiscrDist.cxx:162
 TUnuranDiscrDist.cxx:163