Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

300 lines
7.8 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name:
  4. meancomp.cpp
  5. Abstract:
  6. SIS Groveler mean comparitor
  7. Authors:
  8. John Douceur, 1998
  9. Environment:
  10. User Mode
  11. Revision History:
  12. --*/
  13. #include "all.hxx"
  14. const int MeanComparator::max_sample_table_size = 20;
  15. MeanComparator::PTableDescriptor
  16. MeanComparator::p_list = {-1.0, 0, 0, &p_list, &p_list, 0};
  17. MeanComparator::MeanComparator(
  18. int num_clans,
  19. int sample_group_size,
  20. double acceptance_p_value,
  21. double rejection_p_value,
  22. double tolerance)
  23. {
  24. ASSERT(this != 0);
  25. ASSERT(num_clans > 0);
  26. ASSERT(sample_group_size > 0);
  27. ASSERT(acceptance_p_value >= 0.0);
  28. ASSERT(acceptance_p_value <= 1.0);
  29. ASSERT(rejection_p_value >= 0.0);
  30. ASSERT(rejection_p_value <= 1.0);
  31. ASSERT(tolerance >= 0.0);
  32. ASSERT(tolerance <= 1.0);
  33. this->num_clans = num_clans;
  34. this->sample_group_size = sample_group_size;
  35. this->tolerance = tolerance;
  36. sample_table_size = __min(sample_group_size, max_sample_table_size);
  37. acceptance_table = add_p_value(acceptance_p_value, sample_table_size);
  38. ASSERT(acceptance_table != 0);
  39. rejection_table = add_p_value(rejection_p_value, sample_table_size);
  40. ASSERT(rejection_table != 0);
  41. samples = new Sample[sample_group_size];
  42. compare_values = new double[num_clans];
  43. current_offset = 0;
  44. current_group_size = 0;
  45. }
  46. MeanComparator::~MeanComparator()
  47. {
  48. ASSERT(this != 0);
  49. ASSERT(acceptance_table != 0);
  50. remove_p_value(acceptance_table);
  51. acceptance_table = 0;
  52. ASSERT(rejection_table != 0);
  53. remove_p_value(rejection_table);
  54. rejection_table = 0;
  55. ASSERT(samples != 0);
  56. delete[] samples;
  57. samples = 0;
  58. ASSERT(compare_values != 0);
  59. delete[] compare_values;
  60. compare_values = 0;
  61. }
  62. void
  63. MeanComparator::reset()
  64. {
  65. ASSERT(this != 0);
  66. ASSERT(current_group_size >= 0);
  67. ASSERT(current_group_size <= sample_group_size);
  68. current_group_size = 0;
  69. }
  70. void
  71. MeanComparator::sample(
  72. int clan,
  73. double value)
  74. {
  75. ASSERT(this != 0);
  76. ASSERT(current_group_size >= 0);
  77. ASSERT(current_group_size <= sample_group_size);
  78. ASSERT(current_offset >= 0);
  79. ASSERT(current_offset < sample_group_size);
  80. current_offset--;
  81. if (current_offset < 0)
  82. {
  83. current_offset += sample_group_size;
  84. }
  85. current_group_size = __min(current_group_size + 1, sample_group_size);
  86. ASSERT(current_offset >= 0);
  87. ASSERT(current_offset < sample_group_size);
  88. samples[current_offset].clan = clan;
  89. samples[current_offset].value = value;
  90. }
  91. bool
  92. MeanComparator::within(
  93. double compare_value,
  94. ...)
  95. {
  96. ASSERT(this != 0);
  97. ASSERT(num_clans > 0);
  98. ASSERT(current_group_size >= 0);
  99. ASSERT(current_group_size <= sample_group_size);
  100. ASSERT(current_offset >= 0);
  101. ASSERT(current_offset < sample_group_size);
  102. va_list ap;
  103. va_start(ap, compare_value);
  104. compare_values[0] = compare_value;
  105. for (int index = 1; index < num_clans; index++)
  106. {
  107. compare_values[index] = va_arg(ap, double);
  108. }
  109. va_end(ap);
  110. int sample_count = 0;
  111. int below_count = 0;
  112. int *p_table = acceptance_table->p_table;
  113. ASSERT(p_table != 0);
  114. for (index = 0;
  115. index < current_group_size && sample_count < sample_table_size;
  116. index++)
  117. {
  118. int loc = (index + current_offset) % sample_group_size;
  119. int clan = samples[loc].clan;
  120. double value = samples[loc].value;
  121. double cv = compare_values[clan];
  122. if (fabs(value - cv) > tolerance * cv)
  123. {
  124. sample_count++;
  125. if (value < cv)
  126. {
  127. below_count++;
  128. if (below_count > p_table[sample_count-1])
  129. {
  130. return true;
  131. }
  132. }
  133. }
  134. }
  135. return false;
  136. }
  137. bool
  138. MeanComparator::exceeds(
  139. double compare_value,
  140. ...)
  141. {
  142. ASSERT(this != 0);
  143. ASSERT(num_clans > 0);
  144. ASSERT(current_group_size >= 0);
  145. ASSERT(current_group_size <= sample_group_size);
  146. ASSERT(current_offset >= 0);
  147. ASSERT(current_offset < sample_group_size);
  148. va_list ap;
  149. va_start(ap, compare_value);
  150. compare_values[0] = compare_value;
  151. for (int index = 1; index < num_clans; index++)
  152. {
  153. compare_values[index] = va_arg(ap, double);
  154. }
  155. va_end(ap);
  156. int sample_count = 0;
  157. int above_count = 0;
  158. int *p_table = rejection_table->p_table;
  159. ASSERT(p_table != 0);
  160. for (index = 0;
  161. index < current_group_size && sample_count < sample_table_size;
  162. index++)
  163. {
  164. int loc = (index + current_offset) % sample_group_size;
  165. int clan = samples[loc].clan;
  166. double value = samples[loc].value;
  167. double cv = compare_values[clan];
  168. if (fabs(value - cv) > tolerance * cv)
  169. {
  170. sample_count++;
  171. if (value > cv)
  172. {
  173. above_count++;
  174. if (above_count > p_table[sample_count-1])
  175. {
  176. return true;
  177. }
  178. }
  179. }
  180. }
  181. return false;
  182. }
  183. MeanComparator::PTableDescriptor *
  184. MeanComparator::add_p_value(
  185. double p_value,
  186. int sample_table_size)
  187. {
  188. ASSERT(p_list.next != 0);
  189. ASSERT(p_list.prev != 0);
  190. PTableDescriptor *ptd = p_list.next;
  191. while (ptd != &p_list && ptd->p_value < p_value)
  192. {
  193. ASSERT(ptd->next == &p_list || ptd->next->p_value > ptd->p_value);
  194. ptd = ptd->next;
  195. }
  196. ASSERT(ptd != 0);
  197. if (ptd->p_value == p_value)
  198. {
  199. ASSERT(ptd != &p_list);
  200. ASSERT(ptd->table_size > 0);
  201. ASSERT(ptd->table_size <= max_sample_table_size);
  202. if (ptd->table_size >= sample_table_size)
  203. {
  204. ptd->ref_count++;
  205. return ptd;
  206. }
  207. ASSERT(ptd->p_table != 0);
  208. delete[] ptd->p_table;
  209. ptd->p_table = 0;
  210. }
  211. else
  212. {
  213. PTableDescriptor *new_ptd = new PTableDescriptor;
  214. new_ptd->p_value = p_value;
  215. new_ptd->p_table = 0;
  216. new_ptd->next = ptd;
  217. new_ptd->prev = ptd->prev;
  218. ptd->prev->next = new_ptd;
  219. ptd->prev = new_ptd;
  220. new_ptd->ref_count = 0;
  221. ptd = new_ptd;
  222. }
  223. ASSERT(ptd->prev == &p_list || ptd->prev->p_value < p_value);
  224. ASSERT(ptd->next == &p_list || ptd->next->p_value > p_value);
  225. int *p_table = new int[sample_table_size];
  226. ptd->table_size = sample_table_size;
  227. double threshold = p_value;
  228. for (int n = 1; n <= sample_table_size; n++)
  229. {
  230. threshold *= 2.0;
  231. if (1.0 > threshold)
  232. {
  233. p_table[n - 1] = n;
  234. continue;
  235. }
  236. __int64 numerator = 1;
  237. __int64 denominator = 1;
  238. __int64 sum = 1;
  239. for (int r = 1; r <= n; r++)
  240. {
  241. numerator *= n - r + 1;
  242. ASSERT(numerator > 0);
  243. denominator *= r;
  244. ASSERT(denominator > 0);
  245. sum += numerator / denominator;
  246. ASSERT(sum > 0);
  247. if (double(sum) > threshold)
  248. {
  249. break;
  250. }
  251. }
  252. p_table[n - 1] = n - r;
  253. }
  254. ptd->p_table = p_table;
  255. ptd->ref_count++;
  256. return ptd;
  257. }
  258. bool
  259. MeanComparator::remove_p_value(
  260. PTableDescriptor *ptd)
  261. {
  262. ASSERT(ptd != 0);
  263. ptd->ref_count--;
  264. ASSERT(ptd->ref_count >= 0);
  265. if (ptd->ref_count == 0)
  266. {
  267. ASSERT(ptd->p_table != 0);
  268. delete[] ptd->p_table;
  269. ptd->p_table = 0;
  270. ptd->prev->next = ptd->next;
  271. ptd->next->prev = ptd->prev;
  272. delete ptd;
  273. ptd = 0;
  274. }
  275. return true;
  276. }