Advertisement
Guest User

Untitled

a guest
Apr 26th, 2018
58
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.22 KB | None | 0 0
  1.  
  2. #ifndef _ii_hpp
  3. #define _ii_hpp
  4.  
  5. #include <iostream>
  6. #include <memory>
  7. #include <vector>
  8. #include <queue>
  9. #include <iterator>
  10. #include <algorithm>
  11.  
  12. namespace ii_impl {
  13.  
  14. using namespace std;
  15.  
  16. uint8_t * encode(uint64_t n, uint8_t * buf)
  17. {
  18.     do {
  19.         // get last 7 bits
  20.         uint8_t x = static_cast<uint8_t>(n & 0x7F);
  21.         n = n >> 7;
  22.         if (n > 0) {
  23.             // add continuing bit
  24.             x = x | 0x80;
  25.         }
  26.         *buf = x;
  27.         ++buf;
  28.     } while (n > 0);
  29.     return buf;
  30. }
  31.  
  32. const uint8_t * decode(uint64_t & n, const uint8_t * buf) {
  33.     uint64_t x = 0;
  34.     uint8_t i = 0;
  35.     n = 0;
  36.     do {
  37.         x = static_cast<uint64_t>(*buf);
  38.         uint64_t pd = x & 0x7F;
  39.         n = n | (pd << (7 * i));
  40.         ++i;
  41.         ++buf;
  42.     } while ((x & 0x80) != 0);
  43.  
  44.     return buf;
  45. }
  46.  
  47. class Feature {
  48.     const uint64_t size;
  49.     const uint8_t * data_start;
  50.  
  51.     class iterator :
  52.         public std::iterator<std::forward_iterator_tag, uint64_t> {
  53.         uint64_t size;
  54.         uint64_t idx;
  55.         uint64_t cur;
  56.         const uint8_t * buf;
  57.  
  58.     public:
  59.  
  60.         uint64_t operator*() const {
  61.             return cur;
  62.         }
  63.  
  64.         iterator& operator++() {
  65.             ++idx;
  66.             uint64_t diff = 0;
  67.             // check if idx is valid so that decode does not access invalid memory
  68.             if (idx < size)
  69.                 buf = decode(diff, buf);
  70.             cur += diff;
  71.             return *this;
  72.         }
  73.  
  74.         bool operator== (const iterator & a) const {
  75.             return idx == a.idx;
  76.         }
  77.  
  78.         bool operator!= (const iterator & a) const {
  79.             return idx != a.idx;
  80.         }
  81.  
  82.         iterator(const Feature &f, bool end)
  83.         {
  84.             size = f.size;
  85.             if (end) {
  86.                 idx = f.size;
  87.                 return;
  88.             }
  89.             idx = 0;
  90.             cur = 0;
  91.             buf = f.data_start;
  92.             if (idx < f.size)
  93.                 buf = decode(cur, buf);
  94.         }
  95.     };
  96.  
  97. public:
  98.     // feature starts with uint64_t size value
  99.     Feature(const uint64_t * p)
  100.         : size(*p) {
  101.         data_start = (const uint8_t *)(p + 1);
  102.     }
  103.  
  104.     iterator begin() {
  105.         return iterator(*this, false);
  106.     }
  107.  
  108.     iterator end() {
  109.         return iterator(*this, true);
  110.     }
  111. };
  112.  
  113. }
  114.  
  115. namespace ii
  116. {
  117.  
  118. template<typename Truncate, typename FeatureObjectLists>
  119. void create (Truncate&& truncate, FeatureObjectLists&& features)
  120. {
  121.     //TODO: replace this with your implementation
  122.     /*
  123.     std::cerr << "number of features: " << features.size() << std::endl;
  124.     for (size_t i = 0; i < features.size(); ++i) {
  125.         std::cerr << "objects that contain feature " << i << ": ";
  126.         for (auto&&cur : features[i]) {
  127.             std::cerr << cur << ' ';
  128.         }
  129.         std::cerr << std::endl;
  130.     }
  131.     std::cerr << std::endl;
  132.     //*/
  133.  
  134.     // max_b is a tight upper bound on the number of bytes that will be used
  135.     // 3 * features.size() is space for:
  136.     //  - offset table
  137.     //  - count of objects in each feature
  138.     //  - aligning before next feature
  139.     uint64_t max_b = 5 * 8 * features.size();
  140.  
  141.     for (size_t i = 0; i < features.size(); ++i) {
  142.         uint64_t last = 0;
  143.         for (auto&&cur : features[i]) {
  144.             uint64_t diff = cur - last;
  145.             while (diff > 0) {
  146.                 ++max_b;
  147.                 diff >>= 7;
  148.             }
  149.             last = cur;
  150.         }
  151.     }
  152.  
  153.     // + 8 to take ceil of the division
  154.     uint64_t * seg_start = (uint64_t *)truncate((max_b + 8) / 8);
  155.     uint64_t * data = seg_start + features.size();
  156.    
  157.     for (size_t i = 0; i < features.size(); ++i) {
  158.         // set offset in the table
  159.         seg_start[i] = data - seg_start;
  160.         // + 1 -- reserving space for count
  161.         uint8_t * buf = (uint8_t *)(data + 1);
  162.         uint64_t last = 0;
  163.         uint64_t count = 0;
  164.  
  165.         for (auto&&cur : features[i]) {
  166.             buf = ii_impl::encode(cur - last, buf);
  167.             last = cur;
  168.             ++count;
  169.         }
  170.  
  171.         // store count of objects of this feature
  172.         *data = count;
  173.  
  174.         size_t foo = SIZE_MAX;
  175.         void * void_buf = (void *)buf;
  176.         data = (uint64_t *) std::align(alignof(uint64_t), sizeof(uint64_t), void_buf, foo);
  177.     }
  178.  
  179.     truncate(data - seg_start);
  180. }
  181.  
  182.  
  183. template<class Fs, class OutFn>
  184. void search(const uint64_t*segment, size_t size, Fs&& fs, OutFn&& callback)
  185. {
  186.     std::queue<ii_impl::Feature> q_orig;
  187.     std::queue<std::vector<uint64_t>> q_intrm;
  188.     for (auto&&f : fs) {
  189.         q_orig.push(ii_impl::Feature(segment + segment[f]));
  190.     }
  191.  
  192.     std::vector<uint64_t> res;
  193.     while (!q_orig.empty() || !q_intrm.empty()) {
  194.         if (q_orig.size() >= 2) {
  195.             auto f1 = q_orig.front(); q_orig.pop();
  196.             auto f2 = q_orig.front(); q_orig.pop();
  197.             std::vector<uint64_t> intrm_res;
  198.             std::set_intersection(f1.begin(), f1.end(), f2.begin(), f2.end(), std::back_inserter(intrm_res));
  199.             q_intrm.push(std::move(intrm_res));
  200.         }
  201.         else if (q_orig.size() == 1) {
  202.             auto f1 = q_orig.front(); q_orig.pop();
  203.             if (q_intrm.empty()) {  // single-feature query, just copy to result
  204.                 for (auto&& x : f1)
  205.                     res.push_back(x);
  206.             }
  207.             else {
  208.                 auto f2 = std::move(q_intrm.front()); q_intrm.pop();
  209.                 std::vector<uint64_t> intrm_res;
  210.                 std::set_intersection(f1.begin(), f1.end(), f2.begin(), f2.end(), std::back_inserter(intrm_res));
  211.  
  212.                 q_intrm.push(std::move(intrm_res));
  213.             }
  214.         }
  215.         else if (q_intrm.size() >= 2) {
  216.             auto f1 = std::move(q_intrm.front()); q_intrm.pop();
  217.             auto f2 = std::move(q_intrm.front()); q_intrm.pop();
  218.             std::vector<uint64_t> intrm_res;
  219.             std::set_intersection(f1.begin(), f1.end(), f2.begin(), f2.end(), std::back_inserter(intrm_res));
  220.             q_intrm.push(std::move(intrm_res));
  221.         }
  222.         else if (q_intrm.size() == 1) {
  223.             res = std::move(q_intrm.front()); q_intrm.pop();
  224.         }
  225.     }
  226.  
  227.     for (auto && x : res)
  228.         callback(x);
  229. }
  230.  
  231. }; //namespace ii
  232.  
  233.  
  234. #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement