Guest User

VectorFuncRange

a guest
Feb 9th, 2016
112
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 11.59 KB | None | 0 0
  1. /**
  2.     Author: Djeefther Souza Albuquerque (djeefther@gmail.com)
  3.     Created at 20/09/2015
  4.     Version 0.2
  5. */
  6.  
  7. #ifndef VECTOR_FUNC_RANGE_H_
  8. #define VECTOR_FUNC_RANGE_H_
  9.  
  10. #include <vector>
  11. #include <functional>
  12. #include <assert.h>
  13.  
  14. inline size_t div2ceil(size_t n) {
  15.     return (n >> 1) + (n & 1);
  16. }
  17.  
  18. template<class T, class Func = std::function<T(const T&, const T&)>>
  19. class VectorFuncRange {
  20.     std::vector<std::vector<T>> data_;
  21.     size_t last_level_;
  22.     Func func_;
  23.     T neutral_element_;
  24.  
  25.     //last_level_ is the index of last valid level in data_.
  26.     //After that index are just levels keeped to avoid reallocations.
  27.     //data_ should always have at least last_level_ allocated, and when reduced the number of levels
  28.     //should not reduce its size, but just clear the folling do not used levels
  29.     //the size of data_ (or levels allocated) should be reduced just in shring_to_fit method.
  30.  
  31. public:
  32.     class GetSetT {
  33.     protected:
  34.         VectorFuncRange * p_container_;
  35.         size_t index_;
  36.         GetSetT(VectorFuncRange * p_container, size_t index) : p_container_(p_container), index_(index) {
  37.         }
  38.         GetSetT(const GetSetT&) = delete;
  39.         GetSetT(const GetSetT&& obj) : p_container_(obj.p_container_), index_(index_) {}
  40.     public:
  41.         inline operator const T&() const {
  42.             return p_container_->get(index_);
  43.         }
  44.         inline const T& get() const {
  45.             return this->operator const T &();
  46.         }
  47.         inline typename const T& operator=(const T& data) {
  48.             p_container_->set(index_, data);
  49.             return p_container_->get(index_);
  50.         }
  51.         friend VectorFuncRange;
  52.     };
  53.  
  54.     VectorFuncRange() : data_(1), last_level_(0), neutral_element_() {
  55.     }
  56.     ~VectorFuncRange() {
  57.     }
  58.     const Func& func() const {
  59.         return func_;
  60.     }
  61.     const Func& func(const Func& func) {
  62.         func_ = func;
  63.         _update(0, 0, size());
  64.         return func_;
  65.     }
  66.     const Func& func(Func&& func) {
  67.         func_ = func;
  68.         _update(0, 0, size());
  69.         return func_;
  70.     }
  71.     inline const T& neutral_element() const {
  72.         return neutral_element_;
  73.     }
  74.     inline void neutral_element(const T& neutral_element) {
  75.         neutral_element_ = neutral_element;
  76.     }
  77.     inline void neutral_element(T&& neutral_element) {
  78.         neutral_element_ = neutral_element;
  79.     }
  80.     void push_back(const T& obj) {
  81.         data_.front().push_back(obj);
  82.         _update_and_resize(0, data_.front().size() - 1);
  83.     }
  84.     void push_back(T&& obj) {
  85.         data_.front().push_back(obj);
  86.         _update_and_resize(0, data_.front().size() - 1);
  87.     }
  88.     void set(size_t index, const T& obj) {
  89.         data_.front()[index] = obj;
  90.         _update(0, index);
  91.     }
  92.     void set(size_t index, T&& obj) {
  93.         data_.front()[index] = obj;
  94.         updata(0, index);
  95.     }
  96.     inline size_t size() const {
  97.         return data_.front().size();
  98.     }
  99.     void resize(const size_t size) {
  100.         size_t old_size = data_.front().size();
  101.  
  102.         if (old_size == size) {
  103.             return;
  104.         }
  105.  
  106.         data_.front().resize(size);
  107.  
  108.         _base_resize(old_size,size);
  109.     }
  110.     void resize(const size_t size, const T& value) {
  111.         size_t old_size = data_.front().size();
  112.  
  113.         if (old_size == size) {
  114.             return;
  115.         }
  116.  
  117.         data_.front().resize(size, value);
  118.  
  119.         _base_resize(old_size,size);
  120.     }
  121.     inline GetSetT operator[](size_t index) {
  122.         return GetSetT(this, index);
  123.     }
  124.     inline const T& operator[](size_t index) const {
  125.         return get(index);
  126.     }
  127.     inline const T& get(size_t index) const {
  128.         return data_.front()[index];
  129.     }
  130.     T range_func(size_t first_index, size_t last_index) const {
  131.         if (first_index == last_index) {
  132.             return neutral_element_;
  133.         }
  134.  
  135.         T accumulate_element_left = neutral_element_;
  136.         T accumulate_element_right = neutral_element_;
  137.  
  138.         last_index--;
  139.         //the intern process of this function is considering a close range [first_index, last_index],
  140.         //but the usage of this function follows the C++ idiomatic of [first_index,last_index)
  141.         size_t level = 0;
  142.  
  143.         while (true) {
  144.             if (first_index < last_index) {
  145.                 //Need some elements
  146.                 //will have a next level with diferent bounders
  147.  
  148.                 //first_index
  149.                 if (_is_right_children(first_index)) {
  150.                     //If this index is a right children his _father accumulate one element outside the range, so accumulate this one and change the _father
  151.                     accumulate_element_left = func_(accumulate_element_left, data_[level][first_index]);
  152.                     first_index = _father(first_index) + 1;
  153.                 }
  154.                 else {
  155.                     //His _father just accumulate the range
  156.                     first_index = _father(first_index);
  157.                 }
  158.  
  159.                 //last index
  160.                 if (_is_left_children(last_index)) {
  161.                     //In oposite direction the same  as above
  162.                     accumulate_element_right = func_(data_[level][last_index], accumulate_element_right);
  163.                     last_index = _father(last_index) - 1;
  164.                 }
  165.                 else {
  166.                     //In oposite direction the same  as above
  167.                     last_index = _father(last_index);
  168.                 }
  169.  
  170.                 //next_level
  171.                 level++;
  172.             }
  173.             else if (first_index == last_index) {
  174.                 //Just one element
  175.                 accumulate_element_left = func_(accumulate_element_left, data_[level][first_index]);
  176.                 break;
  177.             }
  178.             else {
  179.                 //Do not need any other accumulation
  180.                 break;
  181.             }
  182.  
  183.  
  184.         }
  185.  
  186.         return func_(accumulate_element_left, accumulate_element_right);
  187.     }
  188.     T range_func_dumb(size_t first_index, size_t last_index) const {
  189.         T accumulate_element = neutral_element_;
  190.         for (size_t i = first_index; i < last_index; i++) {
  191.             accumulate_element = func_(accumulate_element, data_.front()[i]);
  192.         }
  193.         return accumulate_element;
  194.     }
  195.     inline const T& all_range_func() const {
  196.         if (size() == 0) {
  197.             return neutral_element_;
  198.         }
  199.         return data_[last_level_].front();
  200.     }
  201.     void shrink_to_fit() {
  202.         data_.resize(last_level_+1);
  203.         data_.shrink_to_fit();
  204.         for (auto &i : data_) {
  205.             i.shrink_to_fit();
  206.         }
  207.     }
  208.     void clear() {
  209.         _num_levels(1);
  210.         data_.front().clear();
  211.     }
  212.     void pop_back() {
  213.         for (size_t level_index = 0; level_index <= last_level_; level_index++) {
  214.             size_t current_back_index = data_[level_index].size() - 1;
  215.  
  216.             data_[level_index].pop_back();
  217.  
  218.             if (data_[level_index].size() == 1) {
  219.                 //if this level now have size of one, it is the new root (final level)
  220.                 _num_levels(level_index + 1);
  221.                 break;
  222.             }
  223.             else if (_is_right_children(current_back_index)) {
  224.                 _update(level_index, current_back_index - 1);
  225.                 break;
  226.                 //this level is a right_children, so the next level still have a other children (left one)
  227.                 //after the pop_back and all the next levels should be keeped
  228.             }
  229.         }
  230.     }
  231. private:
  232.     static inline size_t _father(size_t index) {
  233.         return index / 2;
  234.     }
  235.     static inline bool _is_left_children(size_t index) {
  236.         return !(index & 1);
  237.     }
  238.     static inline bool _is_right_children(size_t index) {
  239.         return index & 1;
  240.     }
  241.     void _no_recursive_update(size_t level, size_t index) {
  242.         //_father
  243.         size_t father_level = level + 1;
  244.         size_t father_index = _father(index);
  245.  
  246.         auto data_level_it = data_[level].cbegin();//should be const!
  247.  
  248.         if (father_level < _num_levels()) {
  249.             if (2 * father_index + 1 < data_[level].size()) { //Have two childrens
  250.                 data_[father_level][father_index] = func_(data_level_it[2 * father_index], data_level_it[2 * father_index + 1]);
  251.             }
  252.             else { //Have just one, so copy the data
  253.                 data_[father_level][father_index] = data_level_it[index];
  254.             }
  255.         }
  256.     }
  257.     void _update(size_t level, size_t index) {
  258.         //_father
  259.         size_t father_level = level + 1;
  260.         size_t father_index = _father(index);
  261.  
  262.         auto data_level_it = data_[level].cbegin();//should be const!
  263.  
  264.         if (father_level < _num_levels()) {
  265.             if (2 * father_index + 1 < data_[level].size()) { //Have two childrens
  266.                 data_[father_level][father_index] = func_(data_level_it[2 * father_index], data_level_it[2 * father_index + 1]);
  267.             }
  268.             else { //Have just one, so copy the data
  269.                 data_[father_level][father_index] = data_level_it[index];
  270.             }
  271.  
  272.             _update(father_level, father_index);
  273.         }
  274.     }
  275.     void _update(size_t level, size_t first_index, size_t last_index) {
  276.         if (first_index < last_index) {
  277.             size_t last_i;
  278.             for (size_t i = first_index; i < last_index; i += 2) {
  279.                 _update(level, i);
  280.                 last_i = i;
  281.             }
  282.             if (last_i != (last_index - 1) && _is_left_children(last_index - 1)) {
  283.                 //If the last one is a left children and it was not _update by itselft should be
  284.                 _update(level, last_index - 1);
  285.             }
  286.         }
  287.     }
  288.     /**
  289.         Should be used for a level-index pair already allocated and set, but with fathers maybe not allocated maybe yet.
  290.     */
  291.     void _update_and_resize(size_t level, size_t index) {
  292.         if (data_[level].size() <= 1) {
  293.             _no_recursive_update(level, index);
  294.         }
  295.         else {
  296.             size_t father_level = level + 1;
  297.             size_t father_index = _father(index);
  298.  
  299.             if (_num_levels() <= father_level) {
  300.                 _emplace_back_level(father_index + 1);
  301.             }
  302.             else if (father_index >= data_[father_level].size()) {
  303.                 data_[father_level].resize(father_index + 1);
  304.             }
  305.  
  306.             _no_recursive_update(level, index);
  307.             _update_and_resize(father_level, father_index);
  308.         }
  309.     }
  310.     inline size_t _num_levels() {
  311.         return last_level_ + 1;
  312.     }
  313.     inline void _emplace_back_level(size_t size_new_level) {
  314.         assert(last_level_ < data_.size());
  315.         //The current last_level_ should always be allocated!
  316.  
  317.         last_level_++;//new level
  318.  
  319.         if (last_level_ == data_.size()) { //New level not allocated yet, should allocated
  320.             data_.emplace_back(size_new_level);
  321.         }
  322.         else { //New level existed, but should have the correct size
  323.             data_[last_level_].resize(size_new_level);
  324.         }
  325.     }
  326.     inline void _pop_back_level() {
  327.         assert(last_level_ != 0); //should have more than one level
  328.  
  329.         data_[last_level_].clear();
  330.         last_level_--;
  331.     }
  332.     inline void _num_levels(size_t new_num_levels) {
  333.         if (new_num_levels < _num_levels()) {
  334.             //less than corrected used levels, should clear not used anymore levels
  335.             for (auto it = data_.begin() + new_num_levels; it != data_.begin() + last_level_ + 1; it++) {
  336.                 it->clear();
  337.             }
  338.         }
  339.         else if (new_num_levels > data_.size()) {
  340.             //more levels than currenct allocated, should reallocate
  341.             data_.resize(new_num_levels);
  342.         }
  343.  
  344.         last_level_ = new_num_levels - 1;
  345.     }
  346.  
  347. protected:
  348.     inline void _base_resize(size_t old_size,size_t size) {
  349.         size_t level = 0;
  350.         size_t size_it = size;
  351.  
  352.         while (size_it > 1) {
  353.             level++;
  354.             size_it = div2ceil(size_it);
  355.  
  356.             if (_num_levels() <= level) { //this level did not exist yet
  357.                 //data_.emplace_back(size_it);
  358.                 _emplace_back_level(size_it);
  359.             }
  360.             else {
  361.                 data_[level].resize(size_it);
  362.             }
  363.         }
  364.  
  365.         //data_.resize(level + 1); //If level is greather than need, resize to shrink or keep the same
  366.         _num_levels(level + 1);
  367.  
  368.                                  //Update new values
  369.         if (old_size < size) {
  370.             //size_t last_i;
  371.             //for (int i = old_size; i < size; i += 2) {
  372.             //  _update(0, i);
  373.             //  last_i = i;
  374.             //}
  375.             //if (last_i != (size-1) && _is_left_children(size-1)) {
  376.             //  //If the last one is a left children and it was not _update by itselft should be
  377.             //  _update(0, size - 1);
  378.             //}
  379.             _update(0, old_size, size);
  380.         }
  381.         else if (_is_left_children(data_[0].size() - 1)) {
  382.             _update(0, data_[0].size() - 1); //_update the last one remaining if they are a left children
  383.         }
  384.     }
  385.  
  386. public:
  387.     void print_debug() {
  388.         size_t i_index = 0;
  389.         for (const auto& i : data_) {
  390.             for (const auto& j : i) {
  391.                 std::cout << j << " ";
  392.             }
  393.  
  394.             if (i_index == last_level_) {
  395.                 std::cout << " (last level)\n";
  396.             }
  397.             else {
  398.                 std::cout << " <<\n";
  399.             }
  400.  
  401.             i_index++;
  402.         }
  403.         std::cout << "_________________________\n";
  404.     }
  405.     void print_debug_ref() {
  406.         size_t i_index = 0;
  407.         for (const auto& i : data_) {
  408.             for (const auto& j : i) {
  409.                 std::cout << (*j) << " ";
  410.             }
  411.  
  412.             if (i_index == last_level_) {
  413.                 std::cout << " (last level)\n";
  414.             }
  415.             else {
  416.                 std::cout << " <<\n";
  417.             }
  418.  
  419.             i_index++;
  420.         }
  421.         std::cout << "_________________________\n";
  422.     }
  423. };
  424.  
  425. #endif
Add Comment
Please, Sign In to add comment