average.h 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. // This file is part of BOINC.
  2. // http://boinc.berkeley.edu
  3. // Copyright (C) 2010 University of California
  4. //
  5. // BOINC is free software; you can redistribute it and/or modify it
  6. // under the terms of the GNU Lesser General Public License
  7. // as published by the Free Software Foundation,
  8. // either version 3 of the License, or (at your option) any later version.
  9. //
  10. // BOINC is distributed in the hope that it will be useful,
  11. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  13. // See the GNU Lesser General Public License for more details.
  14. //
  15. // You should have received a copy of the GNU Lesser General Public License
  16. // along with BOINC. If not, see <http://www.gnu.org/licenses/>.
  17. // structure for tracking the recent average
  18. // of a distribution that may change over time
  19. //
  20. struct AVERAGE {
  21. double n; // double to avoid integer overflow
  22. double avg;
  23. inline void clear() {
  24. n = avg = 0;
  25. }
  26. // return true if sample exceeded limit and was truncated
  27. //
  28. inline bool update(
  29. double sample,
  30. double n_threshold,
  31. // after this many samples, use exponential average
  32. double sample_weight,
  33. // new samples get this weight in exp avg
  34. double sample_limit
  35. // truncate samples at avg*limit
  36. ) {
  37. double delta;
  38. bool truncated = false;
  39. if (sample < 0) return true;
  40. if (n && avg) {
  41. if (sample > avg*sample_limit) {
  42. sample = avg*sample_limit;
  43. truncated = true;
  44. }
  45. }
  46. n++;
  47. delta = sample - avg;
  48. if (n < n_threshold) {
  49. avg += delta/n;
  50. } else {
  51. avg += sample_weight*delta;
  52. }
  53. return truncated;
  54. }
  55. inline double get_avg() {
  56. return avg;
  57. }
  58. };
  59. // same, but variance also
  60. //
  61. struct AVERAGE_VAR : AVERAGE {
  62. double var;
  63. double q;
  64. inline bool update_var(
  65. double sample,
  66. double n_threshold,
  67. // after this many samples, use exponential average
  68. double sample_weight,
  69. // new samples get this weight in exp avg
  70. double sample_limit
  71. // truncate samples at avg*limit
  72. ) {
  73. double delta;
  74. bool truncated = false;
  75. if (sample < 0) return true;
  76. if (n && avg) {
  77. if (sample > avg*sample_limit) {
  78. sample = avg*sample_limit;
  79. truncated = true;
  80. }
  81. }
  82. n++;
  83. delta = sample - avg;
  84. if (n < n_threshold) {
  85. avg += delta/n;
  86. q += delta*(sample - avg);
  87. var = q/n;
  88. } else {
  89. avg += sample_weight*delta;
  90. double vdelta = (delta*delta - var);
  91. var += sample_weight*vdelta;
  92. }
  93. return truncated;
  94. }
  95. inline double get_var() {
  96. return var;
  97. }
  98. inline void clear() {
  99. AVERAGE::clear();
  100. var = 0;
  101. q = 0;
  102. }
  103. };