00001 
00013 #ifndef DISCR_H
00014 #define DISCR_H
00015 
00016 
00017 #include "../shared_ptr.h"
00018 #include "../base/bdmbase.h"
00019 #include "../math/chmat.h"
00020 
00021 namespace bdm
00022 {
00023 
00027         class rectangular_support: public root {
00028                 protected:
00030                         Array<vec> ranges;
00032                         ivec gridsizes;
00034                         int dim;
00036                         int Npoints;
00038                         vec actvec;
00040                         vec actvec_ind;
00042                         vec steps;
00043                 public:
00045                         rectangular_support() : dim(0), Npoints(0) {
00046                         }
00047                         
00049                         void set_parameters(const Array<vec> &ranges0, const ivec &gridsize0){
00050                                 ranges=ranges0;
00051                                 gridsizes=gridsize0;
00052                                 initialize();
00053                         }
00055                         void initialize() {
00056                                 dim = ranges.length();
00057                                 bdm_assert(gridsizes.length() == dim, "Incompatible dimensions of input");
00058                                 Npoints = prod(gridsizes);
00059                                 bdm_assert(Npoints > 0, "Wrong input parameters");
00060                                 
00061                                 
00062                                 steps.set_size(dim);
00063                                 for ( int j = 0; j < dim; j++ ) {
00064                                         steps ( j ) = ( ranges ( j ) ( 1 ) - ranges(j)(0) ) / gridsizes ( j );
00065                                 }
00066                                 actvec.set_size(dim);
00067                                 actvec_ind.set_size(dim);
00068                         }
00070                         vec get_vec(const ivec &inds){
00071                                 vec v ( dim );
00072                                 for ( int j = 0; j < dim; j++ ) {
00073                                         bdm_assert_debug(inds(j) < gridsizes(j), "Index out of bounds");
00074                                         v ( j ) = ranges(j)(0) + (0.5+inds(j))*steps(j);
00075                                 }
00076                                 return v;
00077                         }
00078 
00080                         long linear_index (const ivec inds){
00081                                 long ind=0;
00082                                 bdm_assert_debug(inds.length() == dim, "Improper indices inds");
00083                                 int dim_skips=1; 
00084                                                 
00085                                 for (int j=0; j<dim; j++){ 
00086                                         ind += dim_skips*(inds(j)); 
00087                                         dim_skips*=gridsizes(j);  
00088                                 }
00089                                 return ind;
00090                         } 
00092                         const vec& first_vec(){
00093                                 for ( int j = 0; j < dim; j++ ) {
00094                                         actvec ( j ) = ranges(j)(0) + 0.5*steps(j);
00095                                         actvec_ind(j) = 0;
00096                                 }
00097                                 return actvec;
00098                         }
00100                         const vec& next_vec() {
00101                                 
00102                                 int j=0;
00103                                 while (j<dim) {
00104                                         if ( actvec_ind ( j ) == gridsizes ( j ) - 1 ) { 
00105                                                 actvec_ind ( j ) = 0; 
00106                                                 actvec ( j ) = ranges ( j ) ( 0 ) + 0.5*steps(j);
00107                                                 j++;
00108                                         } else {
00109                                                 actvec_ind ( j ) ++;
00110                                                 actvec ( j ) += steps ( j );
00111                                                 break;
00112                                         }
00113                                 }
00114                                 return actvec;
00115                         } 
00116                         
00117                         ivec nearest_point(const vec &val){
00118                                 ivec inds;
00119                                 inds.set_size(dim);
00120                                 for(int j=0; j<dim; j++){
00121                                         if (val(j)<ranges(j)(0))
00122                                                 inds(j) = 0;
00123                                         else {
00124                                                 if (val(j)>ranges(j)(1))
00125                                                         inds(j) = gridsizes(j)-1;
00126                                                 else {
00127                                                         inds(j) = ::round(val(j) - ranges(j)(0)/ steps(j));
00128                                                 }
00129                                         }
00130                                 }
00131                                 return inds;
00132                         }
00133 
00135                         int points() const {return Npoints;}
00136                         
00138                         const vec& _steps() const {return steps;}
00139                         
00140                         void from_setting (const Setting &set) {
00141                                 UI::get (ranges , set, "ranges", UI::compulsory);
00142                                 UI::get (gridsizes, set, "gridsizes", UI::compulsory);
00143                                 initialize();
00144                         }
00145         };
00146         UIREGISTER(rectangular_support);
00147         
00149         class discrete_support: public root{
00150                 protected:
00152                         Array<vec> Spoints;
00154                         int idx;
00155                 public:
00157                         discrete_support() : Spoints(0), idx(0){}
00159                         int points() const {return Spoints.length();}
00161                         const vec& first_vec(){bdm_assert_debug(Spoints.length()>0,"Empty support");idx=0; return Spoints(idx);}
00163                         const vec& next_vec(){bdm_assert_debug(Spoints.length()>idx-1,"Out of support points"); return Spoints(++idx);}
00164                         
00174                         void from_setting (const Setting &set) {
00175                                 UI::get (Spoints, set, "points", UI::compulsory);
00176                                 if (points()<1){
00177                                         int npoints;
00178                                         shared_ptr<epdf> ep= UI::build<epdf>(set, "epdf", UI::compulsory);
00179                                         if (!UI::get(npoints,set,"npoints",UI::optional)){npoints=100;}
00180                                         
00181                                         
00182                                         Spoints.set_size(npoints);
00183                                         for(int i=0; i<points(); i++){Spoints(i)=ep->sample();}
00184                                 }
00185                         }
00187                         Array<vec> & _Spoints() {return Spoints;}
00188         };
00189         UIREGISTER(discrete_support);
00190         
00191         class grid_fnc: public fnc{
00192                 protected:
00193                         rectangular_support sup;
00194                         vec values;
00195                 public:
00197                         void set_support(rectangular_support &sup0){sup=sup0; values=zeros(sup.points());}
00199                         void set_values(double (*evalptr)(const vec&)){
00200                                 if (sup.points()>0){
00201                                         values(0) = (*evalptr)(sup.first_vec());
00202                                         for (int j=1; j<sup.points(); j++){ 
00203                                                 values(j)=(*evalptr)(sup.next_vec());
00204                                         }
00205                                 }
00206                         } 
00208                         double nearest_val(const vec &val){return values( sup.linear_index(sup.nearest_point(val)));}
00209                         
00210                         vec eval(const vec &val){return vec_1(nearest_val(val));}
00211         };
00212         UIREGISTER(grid_fnc);
00213 
00217         class egrid: public epdf{
00218                 protected:
00219                         rectangular_support sup;
00220                         vec values;
00221                 public:
00223                         double evallog(const vec &val){return log(values( sup.linear_index(sup.nearest_point(val))));}
00224                         
00225         };
00226 }
00227 #endif //DISCR_H