diff --git a/src/internal_modules/roc_core/mov_quantile.h b/src/internal_modules/roc_core/mov_quantile.h index 58cc0d53d..36b2c1660 100644 --- a/src/internal_modules/roc_core/mov_quantile.h +++ b/src/internal_modules/roc_core/mov_quantile.h @@ -22,26 +22,32 @@ namespace core { template class MovQuantile { public: const size_t win_len_; - const size_t k_; + const size_t percentile_; + size_t k_; + size_t heap_size_; size_t elem_index_; bool win_filled_; + bool valid_; Array heap_; Array elem_index_heap_index_; Array heap_index_elem_index_; - MovQuantile(IArena& arena, const size_t win_len, const size_t k) + MovQuantile(IArena& arena, const size_t win_len, const size_t percentile) : win_len_(win_len) - , k_(k) + , percentile_(percentile) + , k_(0) + , heap_size_(0) , elem_index_(0) - , win_filled_ (false) - , heap_ (arena) + , win_filled_(false) + , valid_(false) + , heap_(arena) , elem_index_heap_index_(arena) , heap_index_elem_index_(arena) { if (win_len == 0) { roc_panic("mov quantile: window length must be greater than 0"); } - if (k_ > win_len_){ - roc_panic("smallest element index should be less than window size"); + if (percentile > 100){ + roc_panic("mov quantile: percentile should be between 0 and 100"); } if (!heap_.resize(win_len)) { return; @@ -55,22 +61,26 @@ template class MovQuantile { for(size_t i = 0 ; i < win_len; i++){ elem_index_heap_index_[i] = i; heap_index_elem_index_[i] = i; - } + } + valid_ = true; } bool is_valid(){ - return (win_len_ == 5); + return valid_; } void swap(size_t index_1, size_t index_2){ - T temp = heap_[index_1]; - size_t temp_index = heap_index_elem_index_[index_1]; - heap_[index_1] = heap_[index_2]; - heap_index_elem_index_[index_1] = heap_index_elem_index_[index_2]; - heap_[index_2] = temp; - heap_index_elem_index_[index_2] = temp_index; + size_t elem_index_1 = heap_index_elem_index_[index_1]; + size_t elem_index_2 = heap_index_elem_index_[index_2]; - elem_index_heap_index_[heap_index_elem_index_[index_1]] = index_2; - elem_index_heap_index_[heap_index_elem_index_[index_2]] = index_1; + T temp = heap_[index_1]; + heap_[index_1] = heap_[index_2]; + heap_[index_2] = temp; + + heap_index_elem_index_[index_1] = elem_index_2; + heap_index_elem_index_[index_2] = elem_index_1; + + elem_index_heap_index_[elem_index_1] = index_2; + elem_index_heap_index_[elem_index_2] = index_1; } void heapify_up(size_t heap_index){ @@ -85,30 +95,30 @@ template class MovQuantile { } } - void heapify_down(size_t heap_index, size_t heap_size){ + void heapify_down(size_t heap_index){ size_t largest = heap_index; size_t left = 2*heap_index + 1; - if(left < heap_size && heap_[left] < heap_[largest]) + if(left < heap_size_ && heap_[left] < heap_[largest]) largest = left; size_t right = 2*heap_index + 2; - if(right < heap_size && heap_[right] < heap_[largest]) + if(right < heap_size_ && heap_[right] < heap_[largest]) largest = right; if(largest != heap_index){ swap(heap_index,largest); - heapify_down(largest,heap_size); + heapify_down(largest); } } - void heapify(size_t heap_index, size_t heap_size){ + void heapify(size_t heap_index){ size_t parent = (heap_index-1)/2; if(heap_index!=0 && heap_[parent] > heap_[heap_index]){ heapify_up(heap_index); return; } else{ - heapify_down(heap_index,heap_size); + heapify_down(heap_index); return; } } @@ -116,20 +126,27 @@ template class MovQuantile { void add(const T& x){ if ((elem_index_ + 1) == win_len_) win_filled_ = true; - size_t heap_size = elem_index_ + 1; + heap_size_ = elem_index_ + 1; + if(win_filled_){ - heap_size = win_len_; + heap_size_ = win_len_; } + elem_index_ = (elem_index_) % win_len_; + k_ = (percentile_ * heap_size_)/100; size_t heap_index = elem_index_heap_index_[elem_index_]; heap_[heap_index] = x; - heapify(heap_index,heap_size); - elem_index_ = (elem_index_ + 1) % win_len_; + heapify(heap_index); + elem_index_ = elem_index_ + 1; } - + T sliding_minimum(){ return heap_[0]; } + + size_t k_value(){ + return k_; + } }; diff --git a/src/tests/roc_core/test_mov_quantile.cpp b/src/tests/roc_core/test_mov_quantile.cpp index c9471ebf6..bd151c8c3 100644 --- a/src/tests/roc_core/test_mov_quantile.cpp +++ b/src/tests/roc_core/test_mov_quantile.cpp @@ -20,21 +20,28 @@ TEST_GROUP(movquantile){ TEST(movquantile, testing_code){ const size_t n = 7; - MovQuantile quant(arena,n,2); - quant.add(5); - quant.add(4); - quant.add(2); + MovQuantile quant(arena,n,62); quant.add(5); + quant.add(4); + quant.add(2); + quant.add(6); quant.add(6); int64_t x = quant.sliding_minimum(); + size_t k1 = quant.k_value(); LONGS_EQUAL((int64_t)2,x); - + CHECK_EQUAL((size_t)3,k1); quant.add(10); quant.add(12); + LONGS_EQUAL((int64_t)2,quant.sliding_minimum()); quant.add(4); + LONGS_EQUAL((int64_t)2,quant.sliding_minimum()); + quant.add(1); + quant.add(8); int64_t x1 = quant.sliding_minimum(); - LONGS_EQUAL((int64_t)4,x1); + size_t k2 = quant.k_value(); + CHECK_EQUAL((size_t)4,k2); + LONGS_EQUAL((int64_t)1,x1); } } }