Main Page   Namespace List   Class Hierarchy   Compound List   File List   Namespace Members   Compound Members   File Members  

histogram.h

Go to the documentation of this file.
00001 
00007 #ifndef __HISTOGRAM_H__
00008 #define __HISTOGRAM_H__
00009 
00010 
00011 #include <iterator>
00012 #include <functional>
00013 #include <vector>
00014 #include <numeric>
00015 #include <complex>
00016 
00017 #include "../src/index_iterator.h"
00018 #include "../src/genericalgs.h"
00019 #include "../src/generic_stdlib.h"
00020 #include "../src/bounded.h"
00021 #include "../src/mathconstants.h"
00022 
00023 
00024 namespace  Histo {
00025 
00026 
00036 template<class Count=int, class Value=double>
00037 class OneDBinList {
00038 protected:
00039   std::vector<Count> counts;
00040   std::vector<Value> values;
00041   Count total_c;
00042   Value total_v;
00043 
00044   template<class C, class V>  
00045   friend OneDBinList<C,V> operator-(const OneDBinList<C,V> &A, const OneDBinList<C,V> &B);
00046   
00047 private:
00048   typedef Generic::index_iterator< std::vector<Value>, Scale::Linear<Value> > index_i;
00049   typedef Scale::Linear<Value> ScaleType;
00050   
00051 public:
00052   typedef typename std::vector<Value>::size_type size_type;
00053   typedef Value value_type;
00054 
00056   typedef Bounded::Magnitude Magnitude;
00057 
00060   typedef std::complex<Value> Vector;
00061 
00062   static size_type num_bins_default;
00063 
00066   OneDBinList(const size_type num_bins=num_bins_default)
00067     : counts(num_bins), values(num_bins), total_c(0), total_v(0),
00068       cached_vector_sum_count(0), cached_vector_sum(0,0),
00069       cached_sum_value_count(0),  cached_sum_value(0)
00070     {  assert(num_bins>0);  }
00071 
00072 
00074   // Could specify as h[bin]+=val instead
00075   OneDBinList& add(size_type bin, Value val=1){
00076     total_c++;
00077     total_v+=val;
00078     counts[bin]++;
00079     values[bin]+=val;
00080     return *this;
00081   }
00082 
00093   OneDBinList& keep_peak(size_type bin, Value val) {
00094     total_c++;
00095     total_v+=val;
00096     counts[bin]++;
00097     if (val > values[bin]) values[bin]=val; 
00098     return *this;
00099   }
00100 
00106   inline size_type num_bins() const {  return counts.size();  }
00107 
00116   inline Value sum_value() const {
00117     if (total_count() != cached_sum_value_count) {
00118       cached_sum_value = std::accumulate(ISEQ(values),Value(0));
00119       cached_sum_value_count = total_count();
00120     }
00121     return cached_sum_value;
00122   }
00123   
00125   inline Count sum_count()    const {  return std::accumulate(ISEQ(counts),Count(0));  }
00126 
00128   inline Value average_value()const {  return sum_value()/Value(num_bins());  }
00129 
00131   Value max_value()    const {  return *(std::max_element(ISEQ(values)));  }
00132   Value min_value()    const {  return *(std::min_element(ISEQ(values)));  }
00133   Count max_count()    const {  return *(std::max_element(ISEQ(counts)));  }
00134   Count min_count()    const {  return *(std::min_element(ISEQ(counts)));  }
00135 
00137   size_type max_value_bin() const
00138     {  return std::max_element(ISEQ(values))-values.begin();  }
00139 
00141   //Magnitude max_value_bin_mag() const {  return bin_mag(max_value_bin());  }
00142   
00155   inline Magnitude relative_selectivity() const {
00156     /* With only one bin, one is always fully selective; special
00157        case to avoid divide-by-zero errors.  */
00158     if (num_bins()<=1) return 1.0;
00159     const Magnitude proportion = safe_divide(value(max_value_bin()),sum_value());
00160     const Magnitude offset = 1.0/num_bins();
00161     const Magnitude scaled = (proportion-offset)/(1.0-offset);
00162     /* Since we take the peak, negative selectivities shouldn't be
00163        possible, but just in case... */
00164     return Generic::crop(Magnitude(0.0),Magnitude(1.0),scaled);
00165     return scaled;
00166   }
00167 
00169   Value weighted_sum() const
00170     {  return std::inner_product(ISEQ(values),index_i(values.begin()),Value(0));  }
00171 
00177   inline Magnitude weighted_average() const
00178     {  return safe_divide((safe_divide(weighted_sum(),sum_value())),Value(num_bins()-1));  }
00179 
00180 
00186   inline static size_type undefined_values() {  return undefined_vals;  }
00187   inline static void      undefined_values_reset(size_type val=0) {  undefined_vals=val;  }
00188   
00192   inline Value total_value()  const {  return total_v;  }
00193   
00198   inline Count total_count()  const {  return total_c;  }
00199   
00201   
00202 
00203   
00220   Vector vector_sum() const {
00221     if (total_count() != cached_vector_sum_count) {
00222       cached_vector_sum = std::inner_product
00223         (ISEQ(values), index_i(values.begin(),ScaleType(2*(Math::pi)/Value(num_bins()))),
00224          Vector(0,0),
00225 
00226 /* Workaround for bug in at least egcs-1.1.2, possibly GCC 2.95 as well */       
00227 #if (__GNUC__ && (__GNUC__ < 3))
00228          plus<Vector>(),
00229 #else
00230          std::plus<Vector>(),
00231 #endif
00232          
00233          Generic::Polar<Value>());
00234       cached_vector_sum_count = total_count();
00235     }
00236     
00237     return cached_vector_sum;
00238   }
00239 
00242   inline Vector vector_average() const {  return vector_sum()/Value(num_bins());  }
00243 
00260   inline Magnitude vector_direction() const {
00261     if (std::abs(vector_sum())==0) undefined_vals++; /* Optional check */
00262     return Generic::wrap(0.0,1.0,std::arg(vector_sum())/(2*(Math::pi)));
00263   }
00264 
00281   inline Magnitude vector_selectivity() const
00282     {  return safe_divide(std::abs(vector_sum()),sum_value());  }
00284 
00285 
00286   
00293   inline Value         value(size_type i) const {  return values[i];  }
00294   inline Count         count(size_type i) const {  return counts[i];  }
00295   inline Magnitude value_mag(size_type i) const {  return safe_divide(values[i]*1.0,total_value());  }
00296   inline Magnitude count_mag(size_type i) const {  return safe_divide(Magnitude(counts[i]),Magnitude(total_count()));  }
00297 
00298 
00306   Magnitude relative_value(size_type bin) const
00307     {  return safe_divide(value(bin),sum_value());  }
00309 
00310   
00329   size_type bin_number(Magnitude binmag) {
00330     return Generic::crop(size_type(0),size_type(num_bins())-size_type(1),
00331                          size_type(binmag*num_bins()+float_adjust));
00332   }
00333 
00334 
00339   size_type bin_number_inclusive(Magnitude binmag) {
00340     return Generic::crop(size_type(0),size_type(num_bins()),
00341                          size_type(binmag*(num_bins()-1)+float_adjust));
00342   }
00343   
00344 
00347   Magnitude bin_mag(size_type bin) {  return Magnitude(bin)/Magnitude(num_bins());  }
00349 
00350 private:
00351 
00355   template <class T>
00356   inline T safe_divide(const T numerator, const T denominator) const 
00357     {  return (denominator==0? undefined_vals++, 0 : numerator/denominator);  }
00358 
00359   static size_type undefined_vals;
00360 
00364   mutable Count  cached_vector_sum_count;
00365   mutable Vector cached_vector_sum;
00366   mutable Count  cached_sum_value_count;
00367   mutable Value  cached_sum_value;
00369 
00370   static const value_type float_adjust; 
00371 };
00372 
00373 
00374 
00375 /* Static variables */
00376 template<class Count, class Value> typename OneDBinList<Count,Value>::size_type
00377 OneDBinList<Count,Value>::num_bins_default=1;  
00378 template<class Count, class Value> typename OneDBinList<Count,Value>::size_type
00379 OneDBinList<Count,Value>::undefined_vals=0;
00380 
00384 template<class Count, class Value> const typename OneDBinList<Count,Value>::value_type
00385 OneDBinList<Count,Value>::float_adjust=1E-14; 
00386 
00387 
00393 template<class Count, class Value>
00394 OneDBinList<Count,Value> operator-(const OneDBinList<Count,Value> &A, const OneDBinList<Count,Value> &B)
00395 {
00396   typename OneDBinList<Count,Value>::size_type N = A.num_bins();
00397   assert(N==B.num_bins());
00398 
00399   OneDBinList<Count,Value> tmp(N);
00400 
00401   for (typename OneDBinList<Count,Value>::size_type i=0; i<N; i++) {
00402     tmp.values[i] = A.values[i] - B.values[i];
00403     tmp.counts[i] = A.counts[i] - B.counts[i];
00404   }
00405   
00406   tmp.total_v = A.total_v + B.total_v;
00407   tmp.total_c = A.total_c + B.total_c;
00408   
00409   return tmp;
00410 }
00411 
00412 
00413 
00423 template<class Count=int, class Value=double>
00424 class OneDHistogram : public OneDBinList<Count,Value> {
00425 public:
00426   typedef typename OneDBinList<Count,Value>::size_type size_type;
00427   OneDHistogram(const size_type num_bins)
00428     : OneDBinList<Count,Value>(num_bins) { }
00429 };
00430 
00431 
00432  
00434 template<class Count=int, class Value=double>
00435 class OneDHistogramDifference : public OneDBinList<Count,Value> {
00436 public:
00437   OneDHistogramDifference(const OneDBinList<Count,Value> &A,
00438                           const OneDBinList<Count,Value> &B)
00439     : OneDBinList<Count,Value>(A-B) { }
00440 };
00441  
00442 
00443  
00444 } /* namespace Histo */
00445 #endif /* __HISTOGRAM_H__ */

Generated on Mon Jan 20 02:35:44 2003 for RF-LISSOM by doxygen1.3-rc2