SigUtil  0.95
Utility modules for modern C++
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
histgram.hpp
Go to the documentation of this file.
1 /*
2 Copyright© 2014 Akihiro Nishimura
3 
4 This software is released under the MIT License.
5 http://opensource.org/licenses/mit-license.php
6 */
7 
8 #ifndef SIG_UTIL_HISTGRAM_HPP
9 #define SIG_UTIL_HISTGRAM_HPP
10 
11 #include "../sigutil.hpp"
12 #include <fstream>
13 #include <array>
14 
15 
17 
18 namespace sig
19 {
20 
22 
52 template <class T, size_t Bin>
53 class Histgram
54 {
55  T const min_;
56  T const max_;
57  double const delta_;
58  std::array<uint, Bin + 2> count_; //[0]: x < min, [Bin-1]: max <= x
59  uint num_;
60 
61 private:
62  void print_base_(std::ostream& ofs) const
63  {
64  //auto IsPlus = [](double v){ return v < 0 ? false : true; };
65 
66  auto IntDigit = [](double v){ return static_cast<int>(std::log10(v) + 1); };
67 
68  auto FirstZero = [](double v){
69  uint keta = 0;
70  if (equal(v, 0)) return keta;
71  while (static_cast<int>(v * std::pow(10, keta)) == 0) ++keta;
72  return keta;
73  };
74 
75  auto Space = [](int num){
76  std::string space;
77  for (int i = 0; i < num; ++i) space.append(" ");
78  return space;
79  };
80 
81  auto Precision = [](double v)
82  {
83  uint keta = 0;
84  double dv = v - int(v);
85 
86  while (true){
87  if (equal(dv, 0) || keta >= 15) break;
88  v *= 10;
89  dv = v - int(v);
90  ++keta;
91  }
92 
93  return keta;
94  };
95 
96  int const rketa = IntDigit(max_);
97  int const disp_precision = typename std::conditional<std::is_integral<T>::value, std::true_type, std::false_type>::type{}
98  ? 0
99  : IntDigit(delta_) > 1
100  ? 0
101  : FirstZero(delta_) +1;
102  int const keta = std::max(rketa, std::min((int) Precision(delta_), disp_precision) + 2);
103  int const ctketa = log10(*std::max_element(count_.begin(), count_.end())) + 1;
104  T const dbar = num_ < 100 ? 1.0 : num_*0.01;
105 
106  /*
107  std::string offset1, offset2;
108  if (keta < 3) offset1.append(2 - keta, ' ');
109  else offset2.append(keta - 3, ' ');*/
110 
111  ofs << "\n-- Histgram --\n";
112  for (uint i = 0; i < Bin + 2; ++i){
113  auto low = delta_*(i - 1) + min_;
114  auto high = delta_*i + min_;
115 
116  if (i == 0) ofs << std::fixed << std::setprecision(disp_precision) << "\n[-∞" << Space(keta - 2) << "," << std::setw(keta + 1) << high << ")" << ":" << std::setw(ctketa) << count_[i] << " ";
117  else if (i == Bin + 1) ofs << std::fixed << std::setprecision(disp_precision) << "\n[" << std::setw(keta + 1) << low << ",+∞" << Space(keta - 2) << ")" << ":" << std::setw(ctketa) << count_[i] << " ";
118  else ofs << std::fixed << std::setprecision(disp_precision) << "\n[" << std::setw(keta + 1) << low << "," << std::setw(keta + 1) << high << ")" << ":" << std::setw(ctketa) << count_[i] << " ";
119 
120  for (uint j = 1; dbar*j <= count_[i]; ++j) ofs << "|";
121  }
122  ofs << std::resetiosflags(std::ios_base::floatfield) << "\n\n";
123  }
124 
125 public:
127 
131  Histgram(T min, T max) : min_(min), max_(max), delta_(((double) max - min) / Bin), num_(0)
132  {
133  if (!(delta_ > 0)){
134  std::cout << "error: max - min = " << delta_ << std::endl;
135  std::terminate();
136  }
137  for (auto& ct : count_) ct = 0;
138  }
139 
141  void count(T value)
142  {
143  for (uint i = 0; i < Bin + 1; ++i){
144  if (value < delta_*i + min_){
145  ++num_;
146  ++count_[i];
147  return;
148  }
149  }
150  ++count_[Bin + 1];
151  }
152 
153  template <class C, typename std::enable_if<impl::container_traits<C>::exist>::type*& = enabler>
154  void count(C const& values){
155  for (auto const& e : values) count(e);
156  }
157 
159  bool is_over_range() const{ return count_[0] || count_[Bin + 1]; }
160 
161  //double GetAverage() const{ return std::accumulate(count_.begin(), count_.end(), 0, [](T total, T next){ return total + next; }) / static_cast<double>(num_); }
162 
164  auto get_count() const -> std::array<uint, Bin>
165  {
166  std::array<uint, Bin> tmp;
167  for (uint i = 0; i < Bin; ++i) tmp[i] = count_[i + 1];
168  return tmp;
169  }
170 
172 
177  auto get_count(uint bin) const ->Maybe<std::tuple<uint, int, int>>
178  {
179  return bin < Bin
180  ? Just<std::tuple<uint, int, int>>(std::make_tuple(count_[bin + 1], delta_*bin + min_, delta_*(bin + 1) + min_))
181  : Nothing(std::make_tuple(static_cast<uint>(0u), 0, 0));
182  }
183 
185  void print() const{ print_base_(std::cout); }
186 
188  void print(FilepassString const& file_pass) const
189  {
190  std::ofstream ofs(file_pass);
191  print_base_(ofs);
192  }
193 };
194 
195 }
196 #endif
auto get_count() const -> std::array< uint, Bin >
頻度を取得
Definition: histgram.hpp:164
void print() const
標準出力へ出力
Definition: histgram.hpp:185
bool is_over_range() const
bin外の要素が存在したか
Definition: histgram.hpp:159
auto get_count(uint bin) const -> Maybe< std::tuple< uint, int, int >>
bin番目(0 ~ Bin-1)の頻度を取得
Definition: histgram.hpp:177
ヒストグラム
Definition: histgram.hpp:53
Histgram(T min, T max)
コンストラクタ
Definition: histgram.hpp:131
void * enabler
auto Nothing() -> typename impl::SameIf< T, void, typename boost::none_t, Maybe< T >>::type
値コンストラクタ
Definition: maybe.hpp:67
bool equal(T1 &&v1, T2 &&v2)
数値の簡易等値比較(厳密な計算でない場合の使用を想定)
void count(C const &values)
Definition: histgram.hpp:154
void count(T value)
要素をbinに振り分けてカウント
Definition: histgram.hpp:141
STLライクな静的配列
Definition: array.hpp:27
auto min(T v) -> T
void print(FilepassString const &file_pass) const
ファイルへ出力
Definition: histgram.hpp:188
auto max(T v) -> T
Definition: array.hpp:15