Main Page · Modules · All Classes · Class Hierarchy
MCSamples.hpp
1 /*
2  * This file is part of the AiBO+ project
3  *
4  * Copyright (C) 2005-2016 Csaba Kertész (csaba.kertesz@gmail.com)
5  *
6  * AiBO+ is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * AiBO+ is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
19  *
20  */
21 
22 #pragma once
23 
24 #include "MCDefs.hpp"
25 
26 #include <string>
27 #include <vector>
28 
29 template <typename T>
31 
37 namespace MC
38 {
40 template <typename T>
41 struct Statistic
42 {
44 typedef std::vector<MCSampleStatistic<T>* > List;
45 };
46 }
47 
51 template <typename T>
52 struct MCSamples
53 {
54 public:
63  explicit MCSamples(int size, MCSampleStatistic<T>& statistic) : Samples(nullptr), Weights(nullptr),
64  Size(size < 2 ? 2 : size), Valid(false), LastElementIndex(-1)
65  {
66  AddStatistic(statistic);
67  }
68 
76  MCSamples(const MCSamples& other) : Samples(nullptr), Weights(nullptr), Size(-1)
77  {
78  operator=(other);
79  }
80 
82  virtual ~MCSamples()
83  {
84  ClearStatistics();
85  delete[] Samples;
86  Samples = nullptr;
87  delete[] Weights;
88  Weights = nullptr;
89  }
90 
98  int GetSize() const
99  {
100  return Size;
101  }
102 
110  inline bool IsEmpty() const
111  {
112  return LastElementIndex == -1;
113  }
114 
124  bool IsValid() const
125  {
126  return Valid;
127  }
128 
136  int GetSampleCount() const
137  {
138  if (unlikely(IsEmpty()))
139  {
140  return 0;
141  }
142  if (likely(Valid))
143  {
144  return Size;
145  }
146  return LastElementIndex+1;
147  }
148 
160  {
161  Statistics.push_back(&statistic);
162  statistic.SetSize(Size);
163  statistic.SetStorage(Samples);
164  statistic.Reset();
165  }
166 
175  {
176  return *Statistics[0];
177  }
178 
188  MCSampleStatistic<T>* GetStatistic(const std::string& statistic_name)
189  {
190  for (auto& statistic : Statistics)
191  {
192  if (statistic->GetName() == statistic_name)
193  return statistic;
194  }
195  return nullptr;
196  }
197 
209  {
210  for (auto& statistic_iter : Statistics)
211  {
212  if (*statistic_iter == &statistic)
213  {
214  statistic_iter = Statistics.erase(statistic_iter);
215  return;
216  }
217  }
218  }
219 
227  void Reset()
228  {
229  Valid = false;
230  LastElementIndex = -1;
231  // Reset the statistics
232  for (auto& statistic : Statistics)
233  {
234  statistic->Reset();
235  }
236  }
237 
244  {
245  for (auto& statistic : Statistics)
246  {
247  delete statistic;
248  }
249  Statistics.clear();
250  }
251 
259  template <typename U>
260  void AddValues(const U& container)
261  {
262  for (auto& value : container)
263  {
264  *this << (T)value;
265  }
266  }
267 
278  {
279  if (unlikely(Size != other.Size))
280  {
281  Size = other.Size;
282  Valid = other.Valid;
283  LastElementIndex = other.LastElementIndex;
284  delete[] Samples;
285  delete[] Weights;
286  }
287  // Clear the statistics
288  ClearStatistics();
289  // Clone the statistics
290  for (auto& statistic : other.Statistics)
291  {
292  Statistics.push_back(statistic->Clone());
293  }
294  // Copy the sample cache
295  if (other.Samples)
296  {
297  Samples = new T[Size];
298  for (int i = 0; i < Size; ++i)
299  Samples[i] = other.Samples[i];
300  // Set the new storage references
301  for (auto& statistic : Statistics)
302  statistic->SetStorage(Samples);
303  }
304  // Copy the weight cache
305  if (other.Weights)
306  {
307  Weights = new float[Size];
308  for (int i = 0; i < Size; ++i)
309  Weights[i] = other.Weights[i];
310  }
311  return *this;
312  }
313 
323  bool operator==(const MCSamples<T>& other) const
324  {
325  if (Size != other.Size || !Samples || !Weights || !other.Samples || !other.Weights)
326  {
327  return false;
328  }
329  for (int i = 0; i < Size; ++i)
330  {
331  if (Samples[i] != other.Samples[i])
332  return false;
333  }
334  for (int i = 0; i < Size; ++i)
335  {
336  if (Weights[i] != other.Weights[i])
337  return false;
338  }
339  return true;
340  }
341 
351  bool operator!=(const MCSamples<T>& other) const
352  {
353  return !operator==(other);
354  }
355 
368  MCSamples<T>& operator<<(const T value)
369  {
370  return operator+=(value);
371  }
372 
385  MCSamples<T>& operator<<(const std::vector<T>& container)
386  {
387  return operator+=(container);
388  }
389 
390 
403  MCSamples<T>& operator<<(const std::pair<const T, float>& value)
404  {
405  return operator+=(value);
406  }
407 
420  const MCSamples<T> operator+(const T value) const
421  {
422  return MCSamples<T>(*this) += value;
423  }
424 
437  const MCSamples<T> operator+(const std::pair<const T, float>& value) const
438  {
439  return MCSamples<T>(*this) += value;
440  }
441 
454  MCSamples<T>& operator+=(const T value)
455  {
456  return operator+=(std::pair<T, float>(value, 0.0));
457  }
458 
471  MCSamples<T>& operator+=(const std::vector<T>& container)
472  {
473  for (auto& value : container)
474  {
475  *this << (T)value;
476  }
477  return *this;
478  }
479 
480 
493  MCSamples<T>& operator+=(const std::pair<const T, float>& value)
494  {
495  // Delayed memory allocation
496  if (!Samples)
497  {
498  Samples = new T[Size];
499  Weights = new float[Size];
500  // Set the new storage references
501  for (auto& statistic : Statistics)
502  statistic->SetStorage(Samples);
503  }
504  int OldIndex = LastElementIndex;
505  int NewIndex;
506  int NewerIndex;
507 
508  LastElementIndex++;
509  NewIndex = LastElementIndex % Size;
510  NewerIndex = (NewIndex+1) % Size;
511  // Making the cache valid if possible
512  if (unlikely(!Valid && LastElementIndex == Size-1))
513  Valid = true;
514 
515  // Remove the old value from the statistics
516  for (auto& statistic : Statistics)
517  {
518  if (likely(statistic->IsValid()))
519  statistic->RemoveValue(Samples[NewIndex], Weights[NewIndex], Samples[NewerIndex], Weights[NewerIndex]);
520  }
521 
522  // Replace the old sample with the new
523  Samples[NewIndex] = value.first;
524  Weights[NewIndex] = value.second;
525  LastElementIndex = NewIndex;
526 
527  // Add the new value to the statistics
528  for (auto& statistic : Statistics)
529  {
530  if (unlikely(OldIndex == -1))
531  {
532  statistic->AddValue(value.first, value.second, (T)0, MCFloatInfinity());
533  } else {
534  statistic->AddValue(value.first, value.second, Samples[OldIndex], Weights[OldIndex]);
535  }
536  }
537  return *this;
538  }
539 
540 private:
544  float* Weights;
546  int Size;
548  bool Valid;
553 };
554 
558 template <typename T>
559 class MCSampleStatistic
560 {
561  friend class MCSamples<T>;
562 
563 public:
564 
572  MCSampleStatistic(const std::string& name) : Name(name), Size(0), Storage(nullptr), Samples(0), Valid(false)
573  { }
574  virtual ~MCSampleStatistic() { }
575 
583  inline const std::string& GetName() const
584  {
585  return Name;
586  }
587 
595  inline bool IsValid()
596  {
597  return Valid;
598  }
599 
607  virtual float GetResult() = 0;
608 
616  virtual MCSampleStatistic<T>* Clone() = 0;
617 
618 protected:
619 
630  void AddValue(const T value, const float weight, const T prev_value, const float prev_weight)
631  {
632  // The value was not valid for the statistic -> Return
633  if (!Add(value, weight, prev_value, prev_weight))
634  return;
635 
636  if (unlikely(!Valid))
637  {
638  Samples++;
639  if (Samples % Size == 0)
640  Valid = true;
641  }
642  }
643 
654  void RemoveValue(const T value, const float weight, const T prev_value, const float prev_weight)
655  {
656  Remove(value, weight, prev_value, prev_weight);
657  }
658 
659 private:
660 
673  virtual bool Add(const T value, const float weight, const T prev_value, const float prev_weight) = 0;
674 
685  virtual void Remove(const T value, const float weight, const T next_value, const float next_weight) = 0;
686 
687 public:
688 
696  virtual void SetSize(int size)
697  {
698  Size = size;
699  }
700 
708  inline void SetStorage(const T* storage)
709  {
710  Storage = storage;
711  }
712 
718  virtual void Reset()
719  {
720  Samples = 0;
721  Valid = false;
722  }
723 
724 protected:
726  std::string Name;
728  int Size;
730  const T* Storage;
732  int Samples;
734  bool Valid;
735 };
736 
MCSamples< T > & operator=(const MCSamples< T > &other)
Copy assignment operator.
Definition: MCSamples.hpp:277
float * Weights
Weight storage.
Definition: MCSamples.hpp:544
Sample cache class.
Definition: MCSamples.hpp:52
int GetSampleCount() const
Get the sample count in the cache.
Definition: MCSamples.hpp:136
MCSampleStatistic< T > & GetDefaultStatistic()
Get the default (first) statistic.
Definition: MCSamples.hpp:174
bool operator==(const MCSamples< T > &other) const
Equality (==) operator.
Definition: MCSamples.hpp:323
MCSamples(int size, MCSampleStatistic< T > &statistic)
Class constructor.
Definition: MCSamples.hpp:63
MCSamples(const MCSamples &other)
Class copy constructor.
Definition: MCSamples.hpp:76
int LastElementIndex
Last element index in the cache.
Definition: MCSamples.hpp:550
bool Valid
Whenever the sample cache has been filled at least once to do calculations.
Definition: MCSamples.hpp:548
void RemoveValue(const T value, const float weight, const T prev_value, const float prev_weight)
Remove a value.
Definition: MCSamples.hpp:654
bool Valid
Whenever the statistic is valid after the first complete sample storage.
Definition: MCSamples.hpp:734
const T * Storage
Pointer to the sample storage.
Definition: MCSamples.hpp:730
const std::string & GetName() const
Get the statistic name.
Definition: MCSamples.hpp:583
int GetSize() const
Get the size of the sample cache.
Definition: MCSamples.hpp:98
virtual void Reset()
Reset the statistic to a default state.
Definition: MCSamples.hpp:718
bool IsEmpty() const
Check if the sample cache is empty.
Definition: MCSamples.hpp:110
virtual void SetSize(int size)
Set the sample vector size for the calculation.
Definition: MCSamples.hpp:696
bool operator!=(const MCSamples< T > &other) const
Inequality (!=) operator.
Definition: MCSamples.hpp:351
int Size
The size of the sample cache.
Definition: MCSamples.hpp:546
int Samples
Counted samples in the calculations.
Definition: MCSamples.hpp:732
MCSamples< T > & operator+=(const std::pair< const T, float > &value)
Addition assignment (+=) operator.
Definition: MCSamples.hpp:493
Sample statistic base class.
Definition: MCSamples.hpp:30
void SetStorage(const T *storage)
Set the sample storage pointer.
Definition: MCSamples.hpp:708
bool IsValid()
Check if the statistic is valid.
Definition: MCSamples.hpp:595
bool IsValid() const
Check if the sample cache is valid for calculations.
Definition: MCSamples.hpp:124
MCSampleStatistic< T > * GetStatistic(const std::string &statistic_name)
Get a statistic by name.
Definition: MCSamples.hpp:188
A wrapper class because of the template typedefs.
Definition: MCSamples.hpp:41
std::string Name
Statistic name.
Definition: MCSamples.hpp:726
void RemoveStatistic(MCSampleStatistic< T > &statistic)
Remove a statistic calculation.
Definition: MCSamples.hpp:208
T * Samples
Sample storage.
Definition: MCSamples.hpp:542
void AddValue(const T value, const float weight, const T prev_value, const float prev_weight)
Add an input value.
Definition: MCSamples.hpp:630
MCSamples< T > & operator+=(const std::vector< T > &container)
Addition assignment (+=) operator.
Definition: MCSamples.hpp:471
int Size
Sample storage size.
Definition: MCSamples.hpp:728
float MCFloatInfinity()
Get float infinity.
Definition: MCDefs.cpp:110
MCSamples< T > & operator+=(const T value)
Addition assignment (+=) operator.
Definition: MCSamples.hpp:454
const MCSamples< T > operator+(const T value) const
Increment (+) operator.
Definition: MCSamples.hpp:420
void ClearStatistics()
Clear the statistics of the sample cache.
Definition: MCSamples.hpp:243
virtual ~MCSamples()
Class destructor.
Definition: MCSamples.hpp:82
MC::Statistic< T >::List Statistics
The list of the calculated statistics for the sample cache.
Definition: MCSamples.hpp:552
void AddValues(const U &container)
Put a whole container into the cache.
Definition: MCSamples.hpp:260
std::vector< MCSampleStatistic< T > * > List
Statistic list type.
Definition: MCSamples.hpp:44
const MCSamples< T > operator+(const std::pair< const T, float > &value) const
Increment (+) operator.
Definition: MCSamples.hpp:437
MCSampleStatistic(const std::string &name)
Class constructor.
Definition: MCSamples.hpp:572
void Reset()
Get the size of the sample cache.
Definition: MCSamples.hpp:227
void AddStatistic(MCSampleStatistic< T > &statistic)
Add a statistic calculation.
Definition: MCSamples.hpp:159