00001
00002 #ifndef _GK_CDF_H
00003 #define _GK_CDF_H
00004
00005 #include "Sampler.h"
00006
00007
00008 namespace gk {
00009
00010
00011 class Cdf
00012 {
00013 std::vector<float> m_cdf;
00014 float m_total;
00015
00016 public:
00017
00018 Cdf( const int reserve= 0 )
00019 :
00020 m_cdf(),
00021 m_total(0.f)
00022 {
00023 if(reserve > 0)
00024 m_cdf.reserve(reserve);
00025 }
00026
00027
00028 void insert( const float v )
00029 {
00030 assert( v!= 0.f );
00031
00032
00033 m_total= m_total + v;
00034 m_cdf.push_back(m_total);
00035 }
00036
00037 #if 0
00038
00039
00040 float sampleSlow( int& id ) const
00041 {
00042 assert(m_cdf.empty() == false);
00043
00044
00045 const float r= drand48() * m_total;
00046
00047 int i;
00048 const int count= (int) m_cdf.size();
00049 for(i= 0; i < count; i++)
00050 if(r < m_cdf[i])
00051 break;
00052
00053 if(i < count)
00054 id= i;
00055 else
00056 id= i -1;
00057
00058
00059 if(id > 0)
00060 return (m_cdf[id] - m_cdf[id -1]) / m_total;
00061 else
00062 return m_cdf[0] / m_total;
00063 }
00064 #endif
00065
00066
00067
00068 float sample( Sampler& sampler, int& id ) const
00069 {
00070 assert(m_cdf.empty() == false);
00071
00072
00073 const float r= sampler.uniformFloat() * m_total;
00074
00075 int p= 0;
00076 int q= (int) m_cdf.size();
00077 while(p < q)
00078 {
00079 const int m= (p+q) / 2;
00080 if(m_cdf[m] < r)
00081 p= m+1;
00082 else
00083 q= m;
00084 }
00085 assert(p >= 0 && p < (int) m_cdf.size());
00086
00087
00088 id= p;
00089 if(p > 0)
00090 return (m_cdf[p] - m_cdf[p -1]) / m_total;
00091 else
00092 return m_cdf[0] / m_total;
00093 }
00094
00095
00096 float pdf( const int id ) const
00097 {
00098 assert(m_cdf.empty() == false);
00099
00100 if(id == 0)
00101 return m_cdf[0] / m_total;
00102 else
00103 return (m_cdf[id] - m_cdf[id -1]) / m_total;
00104 }
00105
00106
00107 float sampleUniform( Sampler& sampler, int &id ) const
00108 {
00109 assert(m_cdf.empty() == false);
00110
00111 id= drand48() * ((int) m_cdf.size() -1);
00112 assert(id < (int) m_cdf.size());
00113
00114 return 1.f / (float) m_cdf.size();
00115 }
00116
00117
00118 float pdfUniform( const int id ) const
00119 {
00120 assert(m_cdf.empty() == false);
00121 return 1.f / (float) m_cdf.size();
00122 }
00123 };
00124
00125 }
00126
00127 #endif