00001 //---------------------------------------------------------------------------- 00002 /** @file SgStatisticsVlt.h 00003 Specialized versions of some classes in SgStatistics.h for volatile 00004 member variables. Previous versions of Fuego used instantiations like 00005 @c SgStatisticsBase<volatile double,volatile double>, but this has the 00006 effect that local variables in member functions and types in explicit 00007 conversions also use the volatile qualifier, and it caused a warning with 00008 Visual C++ (C4197: top-level volatile in cast is ignored). Unfortunately, 00009 the only way to avoid this is to create exact copies of the classes in 00010 SgStatistics with the only difference that the member variables are 00011 declared volatile. */ 00012 //---------------------------------------------------------------------------- 00013 00014 #ifndef SG_STATISTICSVLT_H 00015 #define SG_STATISTICSVLT_H 00016 00017 #include <cmath> 00018 #include <iostream> 00019 #include <limits> 00020 #include <map> 00021 #include <sstream> 00022 #include <string> 00023 #include <vector> 00024 #include "SgException.h" 00025 #include "SgWrite.h" 00026 00027 //---------------------------------------------------------------------------- 00028 00029 /** Specialized version of SgStatisticsBase for volatile member variables. 00030 @see SgStatisticsVlt.h SgStatisticsBase */ 00031 template<typename VALUE, typename COUNT> 00032 class SgStatisticsVltBase 00033 { 00034 public: 00035 SgStatisticsVltBase(); 00036 00037 /** Create statistics initialized with values. 00038 Note that value must be initialized to 0 if count is 0. 00039 Equivalent to creating a statistics and calling @c count times 00040 Add(val) */ 00041 SgStatisticsVltBase(VALUE val, COUNT count); 00042 00043 void Add(VALUE val); 00044 00045 void Remove(VALUE val); 00046 00047 /** Add a value n times */ 00048 void Add(VALUE val, COUNT n); 00049 00050 /** Remove a value n times. */ 00051 void Remove(VALUE val, COUNT n); 00052 00053 void Clear(); 00054 00055 COUNT Count() const; 00056 00057 /** Initialize with values. 00058 Equivalent to calling Clear() and calling @c count times 00059 Add(val) */ 00060 void Initialize(VALUE val, COUNT count); 00061 00062 /** Check if the mean value is defined. 00063 The mean value is defined, if the count if greater than zero. The 00064 result of this function is equivalent to <tt>Count() > 0</tt>, for 00065 integer count types and <tt>Count() > epsilon()</tt> for floating 00066 point count types. */ 00067 bool IsDefined() const; 00068 00069 VALUE Mean() const; 00070 00071 /** Write in human readable format. */ 00072 void Write(std::ostream& out) const; 00073 00074 /** Save in a compact platform-independent text format. 00075 The data is written in a single line, without trailing newline. */ 00076 void SaveAsText(std::ostream& out) const; 00077 00078 /** Load from text format. 00079 See SaveAsText() */ 00080 void LoadFromText(std::istream& in); 00081 00082 private: 00083 volatile COUNT m_count; 00084 00085 volatile VALUE m_mean; 00086 }; 00087 00088 template<typename VALUE, typename COUNT> 00089 inline SgStatisticsVltBase<VALUE,COUNT>::SgStatisticsVltBase() 00090 { 00091 Clear(); 00092 } 00093 00094 template<typename VALUE, typename COUNT> 00095 inline SgStatisticsVltBase<VALUE,COUNT>::SgStatisticsVltBase(VALUE val, COUNT count) 00096 : m_count(count), 00097 m_mean(val) 00098 { 00099 } 00100 00101 template<typename VALUE, typename COUNT> 00102 void SgStatisticsVltBase<VALUE,COUNT>::Add(VALUE val) 00103 { 00104 // Write order dependency: at least one class (SgUctSearch in lock-free 00105 // mode) uses SgStatisticsVltBase concurrently without locking and assumes 00106 // that m_mean is valid, if m_count is greater zero 00107 COUNT count = m_count; 00108 ++count; 00109 SG_ASSERT(! std::numeric_limits<COUNT>::is_exact 00110 || count > 0); // overflow 00111 val -= m_mean; 00112 m_mean += val / VALUE(count); 00113 m_count = count; 00114 } 00115 00116 template<typename VALUE, typename COUNT> 00117 void SgStatisticsVltBase<VALUE,COUNT>::Remove(VALUE val) 00118 { 00119 // Write order dependency: at least on class (SgUctSearch in lock-free 00120 // mode) uses SgStatisticsVltBase concurrently without locking and assumes 00121 // that m_mean is valid, if m_count is greater zero 00122 COUNT count = m_count; 00123 if (count > 1) 00124 { 00125 --count; 00126 m_mean += (m_mean - val) / VALUE(count); 00127 m_count = count; 00128 } 00129 else 00130 Clear(); 00131 } 00132 00133 template<typename VALUE, typename COUNT> 00134 void SgStatisticsVltBase<VALUE,COUNT>::Remove(VALUE val, COUNT n) 00135 { 00136 // Write order dependency: at least on class (SgUctSearch in lock-free 00137 // mode) uses SgStatisticsVltBase concurrently without locking and assumes 00138 // that m_mean is valid, if m_count is greater zero 00139 COUNT count = m_count; 00140 if (count > n) 00141 { 00142 count -= n; 00143 m_mean += VALUE(n) * (m_mean - val) / VALUE(count); 00144 m_count = count; 00145 } 00146 else 00147 Clear(); 00148 } 00149 00150 template<typename VALUE, typename COUNT> 00151 void SgStatisticsVltBase<VALUE,COUNT>::Add(VALUE val, COUNT n) 00152 { 00153 // Write order dependency: at least one class (SgUctSearch in lock-free 00154 // mode) uses SgStatisticsVltBase concurrently without locking and assumes 00155 // that m_mean is valid, if m_count is greater zero 00156 COUNT count = m_count; 00157 count += n; 00158 SG_ASSERT(! std::numeric_limits<COUNT>::is_exact 00159 || count > 0); // overflow 00160 val -= m_mean; 00161 m_mean += VALUE(n) * val / VALUE(count); 00162 m_count = count; 00163 } 00164 00165 template<typename VALUE, typename COUNT> 00166 inline void SgStatisticsVltBase<VALUE,COUNT>::Clear() 00167 { 00168 m_count = 0; 00169 m_mean = 0; 00170 } 00171 00172 template<typename VALUE, typename COUNT> 00173 inline COUNT SgStatisticsVltBase<VALUE,COUNT>::Count() const 00174 { 00175 return m_count; 00176 } 00177 00178 template<typename VALUE, typename COUNT> 00179 inline void SgStatisticsVltBase<VALUE,COUNT>::Initialize(VALUE val, COUNT count) 00180 { 00181 SG_ASSERT(count > 0); 00182 m_count = count; 00183 m_mean = val; 00184 } 00185 00186 template<typename VALUE, typename COUNT> 00187 inline bool SgStatisticsVltBase<VALUE,COUNT>::IsDefined() const 00188 { 00189 if (std::numeric_limits<COUNT>::is_exact) 00190 return m_count > 0; 00191 else 00192 return m_count > std::numeric_limits<COUNT>::epsilon(); 00193 } 00194 00195 template<typename VALUE, typename COUNT> 00196 void SgStatisticsVltBase<VALUE,COUNT>::LoadFromText(std::istream& in) 00197 { 00198 in >> m_count >> m_mean; 00199 } 00200 00201 template<typename VALUE, typename COUNT> 00202 inline VALUE SgStatisticsVltBase<VALUE,COUNT>::Mean() const 00203 { 00204 SG_ASSERT(IsDefined()); 00205 return m_mean; 00206 } 00207 00208 template<typename VALUE, typename COUNT> 00209 void SgStatisticsVltBase<VALUE,COUNT>::Write(std::ostream& out) const 00210 { 00211 if (IsDefined()) 00212 out << Mean(); 00213 else 00214 out << '-'; 00215 } 00216 00217 template<typename VALUE, typename COUNT> 00218 void SgStatisticsVltBase<VALUE,COUNT>::SaveAsText(std::ostream& out) const 00219 { 00220 out << m_count << ' ' << m_mean; 00221 } 00222 00223 //---------------------------------------------------------------------------- 00224 00225 #endif // SG_STATISTICSVLT_H