18 #ifndef FUNNEL_H_INCLUDED__ 19 #define FUNNEL_H_INCLUDED__ 37 inline height_t
logc(order_t k)
40 for( order_t i=k-1; i; h++, i/=order );
54 for( ; h; h--, k*=order );
78 { i = rhs.i;
return *
this; }
80 {
return i == rhs.i; }
82 {
return i != rhs.i; }
83 inline void child(basic_order_t ch)
84 { i =
static_cast<order_t
>(order*(i-1)+ch+2); }
86 { i =
static_cast<order_t
>((i-2)/order+1); }
88 {
return static_cast<basic_order_t
>((i+order-2) % order); }
96 static const int alpha = 16;
98 template<
class diff_type>
100 {
return static_cast<order_t
>(std::sqrt(static_cast<double>(N)/alpha)); }
101 template<
class diff_type>
103 { assert(
false );
return static_cast<order_t
>(std::sqrt(static_cast<double>(N)/alpha)); }
105 {
return static_cast<size_t>(alpha*(order+1)*(order+1)); }
106 static inline height_t
split(height_t h)
109 {
return static_cast<size_t>(alpha*k*k); }
112 template<
class FwIt>
struct nop_refill {
template<
class Merger>
inline bool operator()(
const Merger*, FwIt, FwIt)
116 template<
class,
int,
class,
class,
class,
class>
119 template<
class RanIt,
int Order=2,
class Splitter = default_splitter<Order>,
class Pred = std::less<
typename std::iterator_traits<RanIt>::value_type>,
class Refiller = nop_refill<RanIt>,
class Alloc = std::allocator<
typename std::iterator_traits<RanIt>::value_type> >
122 friend class special_<RanIt,Order,Splitter,Pred,Refiller,Alloc>;
128 typedef typename std::iterator_traits<RanIt>::value_type
value_type;
132 template<
class NewRefiller>
137 typedef typename allocator::pointer TPtr;
138 typedef typename allocator::size_type size_type;
140 typedef typename nallocator::pointer NPtr;
145 typedef typename allocator::pointer
TPtr;
147 typedef typename nallocator::pointer
NPtr;
148 inline void construct(order_t k, height_t height,
size_t *buf_size, allocator alloc, nallocator nalloc);
149 inline void destroy(allocator alloc, nallocator nalloc);
151 typename allocator::pointer head,
tail, begin, end;
153 static inline void fill_dflt(TPtr b, TPtr e, allocator alloc);
155 inline void construct(order_t k, height_t height,
size_t *buf_size, allocator alloc, nallocator nalloc);
156 inline void destroy(allocator alloc, nallocator nalloc);
158 typedef std::pair<RanIt,RanIt> stream_t;
160 typedef typename sallocator::pointer SPtr;
164 inline merge_tree(order_t k,
const allocator& alloc) : k(k), cold(true), alloc(alloc), salloc(alloc), nalloc(alloc)
178 {
return pair->first; }
180 {
return pair->second; }
189 {
return static_cast<order_t
>(ptr-rhs.ptr); }
193 { ++ptr;
return *
this; }
201 {
return ptr == rhs.ptr; }
203 {
return ptr != rhs.ptr; }
207 { *last_stream++ = std::make_pair(begin,end); }
219 inline FwIt
empty(FwIt begin, FwIt end)
220 {
return empty_buffers(root, begin, end); }
221 template<
class OutIt>
223 {
return empty_buffers(root, begin); }
226 inline It operator()(It begin, It end);
227 template<
class OutIt>
228 inline OutIt operator()(OutIt begin);
232 static inline FwIt empty_buffers(NPtr n, FwIt begin, FwIt end);
233 template<
class OutIt>
234 static inline OutIt empty_buffers(NPtr n, OutIt begin);
236 static void compute_buffer_sizes(size_type *b, size_type *e);
237 void construct(order_t k);
248 template<
class OutIt>
254 inline FwIt fill_root(FwIt begin, FwIt end)
256 template<
class OutIt>
257 inline OutIt fill_root(OutIt begin)
269 SPtr input_streams, last_stream;
283 template<
int Order,
class Splitter,
class Pred,
class Refiller,
class Alloc>
284 class merge_tree<typename Alloc::pointer, Order, Splitter, Pred, Refiller, Alloc>
286 typedef typename Alloc::pointer RanIt;
287 friend class special_<typename Alloc::pointer,Order,Splitter,Pred,Refiller,Alloc>;
289 typedef unsigned int order_t;
293 typedef typename std::iterator_traits<typename Alloc::pointer>::value_type
value_type;
302 typedef typename allocator::pointer TPtr;
303 typedef typename allocator::size_type size_type;
305 typedef typename nallocator::pointer NPtr;
310 typedef typename allocator::pointer
TPtr;
312 typedef typename nallocator::pointer
NPtr;
313 inline Edge** construct(order_t k, height_t height,
size_t *buf_size, Edge** edge_list, allocator alloc, nallocator nalloc);
314 inline void destroy(allocator alloc, nallocator nalloc);
316 typename allocator::pointer head,
tail, begin, end;
318 static inline void fill_dflt(TPtr b, TPtr e, allocator alloc);
320 inline Edge** construct(order_t k, height_t height,
size_t *buf_size, Edge** edge_list, allocator alloc, nallocator nalloc);
321 inline void destroy(allocator alloc, nallocator nalloc);
323 typedef typename Node::Edge* stream_t;
325 typedef typename sallocator::pointer SPtr;
329 inline merge_tree(order_t k,
const allocator& alloc) : k(k), cold(true), alloc(alloc), salloc(alloc), nalloc(alloc)
341 inline stream(stream_t edge) : edge(edge) { }
342 inline typename allocator::pointer&
begin()
343 {
return edge->head; }
344 inline typename allocator::pointer&
end()
345 {
return edge->tail; }
347 class stream_iterator
354 {
return static_cast<order_t
>(ptr-rhs.ptr); }
356 {
return stream(*ptr); }
358 { ++ptr;
return *
this; }
361 stream_iterator ret = stream_iterator(ptr);
366 {
return ptr == rhs.ptr; }
368 {
return ptr != rhs.ptr; }
371 inline void add_stream(
typename Alloc::pointer begin,
typename Alloc::pointer end)
372 { (*last_stream)->head = begin, (*last_stream)->tail = end, ++last_stream; }
374 {
return input_streams; }
375 inline stream_iterator
end()
376 {
return last_stream; }
384 inline FwIt
empty(FwIt begin, FwIt end)
385 {
return empty_buffers(root, begin, end); }
386 template<
class OutIt>
388 {
return empty_buffers(root, begin); }
391 inline FwIt operator()(FwIt begin, FwIt end);
392 template<
class OutIt>
393 inline OutIt operator()(OutIt begin);
396 static inline FwIt empty_buffers(NPtr n, FwIt begin, FwIt end);
397 template<
class OutIt>
398 static inline OutIt empty_buffers(NPtr n, OutIt begin);
400 void construct(order_t k);
401 static void compute_buffer_sizes(size_type *b, size_type *e);
403 static inline void go_down(
typename Node::Edge& e, Pred comp);
404 static inline void go_down_cold(
typename Node::Edge& e, Pred comp);
406 static void warmup(NPtr n,
typename Node::Edge& output, Pred comp);
408 template<
class OutIt>
409 static inline OutIt copy(
typename Node::Edge& de, OutIt begin, Pred comp);
411 static inline FwIt copy(
typename Node::Edge& de, FwIt begin, FwIt end, Pred comp, std::forward_iterator_tag);
413 static inline RIt copy(
typename Node::Edge& de, RIt begin, RIt end, Pred comp, std::random_access_iterator_tag);
415 template<
class OutIt>
416 static inline OutIt fill(NPtr n, OutIt begin, Pred comp)
419 static inline FwIt fill(NPtr n, FwIt begin, FwIt end, Pred comp)
426 SPtr input_streams, last_stream;
437 #endif // FUNNEL_H_INCLUDED__
order_t operator-(const stream_iterator &rhs)
bool operator==(const stream_iterator &rhs)
static height_t split(height_t h)
merge_tree(order_t k, const allocator &alloc)
FwIt empty(FwIt begin, FwIt end)
order_t pow_of_order< 2 >(height_t h)
bool operator!=(const stream_iterator &rhs)
allocator::pointer & begin()
order_t pow_of_order< 8 >(height_t h)
allocator::template rebind< Node >::other nallocator
static order_t min_order()
allocator::pointer & end()
nallocator::pointer child
bool operator==(const bfs_index< order > &rhs) const
static size_t switch_to_cache_aware()
stream_iterator & operator++()
order_t pow_of_order(height_t h)
static order_t prefered_order_output(diff_type N)
static order_t min_order()
void child(basic_order_t ch)
stream_iterator & operator++(int)
FwIt empty(FwIt begin, FwIt end)
const Refiller & get_refiller() const
std::iterator_traits< RanIt >::value_type value_type
unsigned short basic_order_t
bool operator()(const Merger *, FwIt, FwIt)
bool operator==(const stream_iterator &rhs)
void add_stream(RanIt begin, RanIt end)
std::iterator_traits< typename Alloc::pointer >::value_type value_type
stream_iterator & operator++()
void set_refiller(const Refiller &r)
void set_refiller(const Refiller &r)
const Refiller & get_refiller() const
order_t operator-(const stream_iterator &rhs)
static order_t prefered_order_input(diff_type N)
bfs_index< order > operator=(const bfs_index< order > &rhs)
stream_iterator & operator++(int)
merge_tree(order_t k, const allocator &alloc)
allocator::template rebind< Node >::other::pointer child
allocator::template rebind< Node >::other nallocator
bool operator!=(const stream_iterator &rhs)
static size_t out_buffer_size(order_t k)
order_t pow_of_order< 4 >(height_t h)
basic_order_t child_index() const
order_t pow_of_order< 16 >(height_t h)
bool operator!=(const bfs_index< order > &rhs) const
merge_tree< iterator, order, splitter, predicate, NewRefiller, allocator > other
void add_stream(typename Alloc::pointer begin, typename Alloc::pointer end)
stream_iterator(SPtr ptr)
stream_iterator(SPtr ptr)