diff options
Diffstat (limited to 'utils')
-rwxr-xr-x | utils/agenda.h | 86 | ||||
-rwxr-xr-x | utils/best.h | 15 | ||||
-rw-r--r-- | utils/d_ary_heap.h | 107 | ||||
-rwxr-xr-x | utils/hash.h | 12 | ||||
-rwxr-xr-x | utils/intern_pool.h | 54 | ||||
-rw-r--r-- | utils/logval.h | 8 | ||||
-rwxr-xr-x | utils/lvalue_pmap.h | 8 | ||||
-rwxr-xr-x | utils/max_plus.h | 13 | ||||
-rwxr-xr-x | utils/show.h | 25 | ||||
-rwxr-xr-x | utils/utoa.h | 2 | ||||
-rwxr-xr-x | utils/value_array.h | 24 | ||||
-rw-r--r-- | utils/warning_compiler.h | 3 | ||||
-rw-r--r-- | utils/warning_push.h | 2 |
13 files changed, 270 insertions, 89 deletions
diff --git a/utils/agenda.h b/utils/agenda.h index 639f35a9..1937ad1a 100755 --- a/utils/agenda.h +++ b/utils/agenda.h @@ -1,6 +1,7 @@ #ifndef AGENDA_H #define AGENDA_H +#define DBG_AGENDA(x) x /* a priority queue where you expect to queue the same item at different priorities several times before finally popping it. higher priority = better. @@ -48,54 +49,71 @@ template <class P> struct priority_traits { typedef typename P::priority_type priority_type; }; - -// P p has priority_traits<P>::type &p->agenda_priority() and unsigned &p->agenda_location(), and bool & p->agenda_done() -// this is really 4 functors in 1 (or lvalue property maps); you can supply your own as the Prio type in Agenda<...> below ; state is allowed. -template <class P> -struct AdjustablePriority { - typedef AdjustablePriority<P> Self; - typedef typename priority_traits<P>::priority_type Priority; - Priority & priority(P const &x) { - return x->agenda_priority(); - } - unsigned & location(P const &x) { // this gets updated by push, pop, and adjust - return x->agenda_location(); - } - void is_done(P const& x) const { - return x->agenda_done(); - } - void set_done(P const& x) const { - x->agenda_done()=true; - } -}; */ typedef best_t agenda_best_t; +typedef unsigned agenda_location_t; -PMAP_MEMBER_INDIRECT(LocationMap,unsigned,location) -PMAP_MEMBER_INDIRECT(PriorityMap,best_t,priority) +PMAP_MEMBER_INDIRECT(LocationMap,agenda_location_t,location) +PMAP_MEMBER_INDIRECT(PriorityMap,agenda_best_t,priority) + +struct Less { + typedef bool result_type; + template <class A,class B> + bool operator()(A const& a,B const& b) const { return a<b; } +}; // LocMap and PrioMap are boost property maps put(locmap,key,size_t), Better(get(priomap,k1),get(priomap,k2)) means k1 should be above k2 (be popped first). Locmap and PrioMap may have state; the rest are assumed stateless functors -template <class Item,class Better=std::less<Item>, /* intern_pool args */ class KeyF=get_key<Item>,class HashKey=boost::hash<typename KeyF::return_type>,class EqKey=std::equal_to<typename KeyF::return_type>, class Pool=boost::object_pool<Item> > -struct Agenda : intern_pool<Item,KeyF,EqKey,Pool> { +template <class Item,class Better=Less, /* intern_pool args */ class KeyF=get_key<Item>,class HashKey=boost::hash<typename KeyF::result_type>,class EqKey=std::equal_to<typename KeyF::result_type>, class Pool=boost::object_pool<Item> > +struct Agenda : intern_pool<Item,KeyF,HashKey,EqKey,Pool> { + typedef intern_pool<Item,KeyF,HashKey,EqKey,Pool> Intern; // inherited because I want to use construct() /* this is less generic than it could be, because I want to use a single hash mapping to intern to canonical mutable object pointers, where the property maps are just lvalue accessors */ - typedef intern_pool<Item,KeyF,EqKey,Pool> Intern; // inherited because I want to use construct() + typedef typename KeyF::result_type Key; typedef Item * Handle; typedef LocationMap<Handle> LocMap; typedef PriorityMap<Handle> PrioMap; LocMap locmap; - PrioMap priomap; - //NOT NEEDED: initialize function object state (there is none) + PrioMap priomap; // note: priomap[item] is set by caller before giving us the item; then tracks best (for canonicalized item) thereafter + Better better; + //NOT NEEDED: initialize function object state (there is none) -/* - typedef Item *CanonItem; + typedef Item *ItemC; //canonicalized pointer + typedef Item *ItemP; static const std::size_t heap_arity=4; // might be fastest possible (depends on key size probably - cache locality is bad w/ arity=2) - typedef std::vector<CanonItem> HeapStorage; - typedef boost::detail::d_ary_heap_indirect<Key,heap_arity,LocMap,PrioMap,Better,HeapStorage> Heap; - HASH_SET<Key,Hash,Equal> queued; - Agenda(LocMap const& lm=LocMap(),PrioMap const& pm=PrioMap()) : locmap(lm), priomap(pm) { } -*/ + typedef std::vector<ItemC> HeapStorage; + typedef d_ary_heap_indirect<Handle,heap_arity,LocMap,PrioMap,Better,HeapStorage,agenda_location_t> Heap; + Heap q; + + // please don't call q.push etc. directly. + void add(ItemP i) { + bool fresh=interneq(i); + DBG_AGENDA(assert(fresh && !q.contains(i))); + q.push(i); + } + bool improve(ItemP i) { + ItemP c=i; + bool fresh=interneq(c); + if (fresh) + return add(c); + DBG_AGENDA(assert(q.contains(c))); + return q.maybe_improve(priomap[i]); + } + inline bool empty() { + return q.empty(); + } + // no need to destroy the canon. item because we want to remember the best cost and reject more expensive ways of using it). + ItemC pop() { + DBG_AGENDA(assert(!empty())); + ItemC r=q.top(); + q.pop(); + return r; + } + agenda_best_t best() const { + return priomap[q.top()]; //TODO: cache/track the global best? + } + + Agenda(unsigned reserve=1000000,LocMap const& lm=LocMap(),PrioMap const& pm=PrioMap(),EqKey const& eq=EqKey(),Better const& better=Better()) : locmap(lm), priomap(pm), better(better), q(priomap,locmap,better,reserve) { } }; #endif diff --git a/utils/best.h b/utils/best.h index 8ff896bb..689e7600 100755 --- a/utils/best.h +++ b/utils/best.h @@ -8,6 +8,21 @@ typedef MaxPlus<double> best_t; inline bool operator <(best_t const& a,best_t const& b) { return a.v_>b.v_; // intentionally reversed, so default min-heap, sort, etc. put best first. } +struct BetterP { + inline bool operator ()(best_t const& a,best_t const& b) const { + return a.v_>b.v_; // intentionally reversed, so default min-heap, sort, etc. put best first. + } +}; +inline void maybe_improve(best_t &a,best_t const& b) { + if (a.v_>b.v_) + a.v_=b.v_; +} + +template <class O> +inline void maybe_improve(best_t &a,O const& b) { + if (a.v_>b.v_) + a.v_=b.v_; +} #endif diff --git a/utils/d_ary_heap.h b/utils/d_ary_heap.h index 15bde583..da99902c 100644 --- a/utils/d_ary_heap.h +++ b/utils/d_ary_heap.h @@ -106,7 +106,7 @@ std::size_t Arity, typename IndexInHeapPropertyMap, typename DistanceMap, - typename Compare = std::less<Value>, + typename Better = std::less<Value>, typename Container = std::vector<Value>, typename Size = typename Container::size_type, typename Equal = std::equal_to<Value> > @@ -120,16 +120,16 @@ typedef Value value_type; typedef typename Container::const_iterator const_iterator; typedef const_iterator iterator; - // The distances being compared using compare and that are stored in the + // The distances being compared using better and that are stored in the // distance map typedef typename boost::property_traits<DistanceMap>::value_type distance_type; - d_ary_heap_indirect(DistanceMap distance, - IndexInHeapPropertyMap index_in_heap, - const Compare& compare = Compare(), + d_ary_heap_indirect(DistanceMap const& distance, + IndexInHeapPropertyMap const& index_in_heap, + const Better& better = Better(), size_type container_reserve = 100000, Equal const& equal = Equal() ) - : compare(compare), data(), distance(distance), + : better(better), data(), distance(distance), index_in_heap(index_in_heap) { data.reserve(container_reserve); } @@ -210,8 +210,9 @@ void clear() { #if D_ARY_TRACK_OUT_OF_HEAP - for (typename Container::iterator i=data.begin(),e=data.end();i!=e;++i) - put(index_in_heap,*i,D_ARY_HEAP_NULL_INDEX); + using boost::put; + for (typename Container::iterator i=data.begin(),e=data.end();i!=e;++i) + put(index_in_heap,*i,D_ARY_HEAP_NULL_INDEX); #endif data.clear(); } @@ -224,6 +225,7 @@ } else { size_type index = data.size(); data.push_back(v); + using boost::put; put(index_in_heap, v, index); preserve_heap_property_up(index); } @@ -239,6 +241,7 @@ } void pop() { + using boost::put; if(D_ARY_TRACK_OUT_OF_HEAP) put(index_in_heap, data[0], D_ARY_HEAP_NULL_INDEX); if (data.size() != 1) { @@ -261,22 +264,40 @@ // (distance has become smaller, so it may need to rise toward top(). // i.e. decrease-key in a min-heap void update(const Value& v) { + using boost::get; size_type index = get(index_in_heap, v); - preserve_heap_property_up(index); + preserve_heap_property_up(v,index); verify_heap(); } + // return true if improved. + bool maybe_improve(const Value& v,distance_type dbetter) { + using boost::get; + if (better(dbetter,get(distance,v))) { + preserve_heap_property_up_dist(v,dbetter); + return true; + } + return false; + } + + +#include "warning_push.h" +#pragma GCC diagnostic ignored "-Wtype-limits" + // because maybe size_type is signed or unsigned inline bool contains(const Value &v,size_type i) const { return D_ARY_TRACK_OUT_OF_HEAP ? (i != D_ARY_HEAP_NULL_INDEX) : i>=0 && i<data.size() && equal(v,data[i]); // note: size_type may be signed (don't recommend it, though) - thus i>=0 check to catch uninit. data } +#include "warning_pop.h" inline bool contains(const Value& v) const { + using boost::get; return contains(v,get(index_in_heap, v)); } void push_or_update(const Value& v) { /* insert if not present, else update */ + using boost::get; size_type index = get(index_in_heap, v); if (D_ARY_PUSH_GRAEHL) { if (contains(v,index)) @@ -287,6 +308,7 @@ if (!contains(v,index)) { index = data.size(); data.push_back(v); + using boost::put; put(index_in_heap, v, index); } preserve_heap_property_up(index); @@ -296,7 +318,7 @@ private: Equal equal; - Compare compare; + Better better; Container data; DistanceMap distance; IndexInHeapPropertyMap index_in_heap; @@ -318,11 +340,13 @@ Value value_b = data[index_b]; data[index_a] = value_b; data[index_b] = value_a; + using boost::put; put(index_in_heap, value_a, index_b); put(index_in_heap, value_b, index_a); } inline void move_heap_element(Value const& v,size_type ito) { + using boost::put; put(index_in_heap,v,ito); data[ito]=v; //todo: move assign? } @@ -332,8 +356,9 @@ // This is a very expensive test so it should be disabled even when // NDEBUG is not defined #if D_ARY_VERIFY_HEAP + using boost::get; for (size_t i = 1; i < data.size(); ++i) { - if (compare(get(distance,data[i]), get(distance,data[parent(i)]))) { + if (better(get(distance,data[i]), get(distance,data[parent(i)]))) { assert (!"Element is smaller than its parent"); } } @@ -341,28 +366,47 @@ } // we have a copy of the key, so we don't need to do that stupid find # of levels to move then move. we act as though data[index]=currently_being_moved, but in fact it's an uninitialized "hole", which we fill at the very end - void preserve_heap_property_up(Value const& currently_being_moved,size_type index) { - size_type orig_index = index; - distance_type currently_being_moved_dist = - get(distance, currently_being_moved); - for (;;) { - if (index == 0) break; // Stop at root - size_type parent_index = parent(index); - Value const& parent_value = data[parent_index]; - if (compare(currently_being_moved_dist, get(distance, parent_value))) { - move_heap_element(parent_value,index); - index = parent_index; - } else { - break; // Heap property satisfied + inline void preserve_heap_property_up(Value const& currently_being_moved,size_type index) { + using boost::get; + preserve_heap_property_up(currently_being_moved,index,get(distance,currently_being_moved)); + } + + inline void preserve_heap_property_up_set_dist(Value const& currently_being_moved,distance_type dbetter) { + using boost::get; + using boost::put; + put(distance,currently_being_moved,dbetter); + preserve_heap_property_up(currently_being_moved,get(index_in_heap,currently_being_moved),dbetter); + verify_heap(); + } + + void preserve_heap_property_up(Value const& currently_being_moved,size_type index,distance_type currently_being_moved_dist) { + using boost::put; + using boost::get; + if (D_ARY_UP_GRAEHL) { + for (;;) { + if (index == 0) break; // Stop at root + size_type parent_index = parent(index); + Value const& parent_value = data[parent_index]; + if (better(currently_being_moved_dist, get(distance, parent_value))) { + move_heap_element(parent_value,index); + index = parent_index; + } else { + break; // Heap property satisfied + } } + //finish "swap chain" by filling hole w/ currently_being_moved + move_heap_element(currently_being_moved,index); // note: it's ok not to return early on index==0 at start, even if self-assignment isn't supported by Value - because currently_being_moved is a copy. + } else { + put(index_in_heap,currently_being_moved,index); + put(distance,currently_being_moved,currently_being_moved_dist); + preserve_heap_property_up(index); } - //finish "swap chain" by filling hole w/ currently_being_moved - move_heap_element(currently_being_moved,index); // note: it's ok not to return early on index==0 at start, even if self-assignment isn't supported by Value - because currently_being_moved is a copy. } // Starting at a node, move up the tree swapping elements to preserve the // heap property. doesn't actually use swap; uses hole void preserve_heap_property_up(size_type index) { + using boost::get; if (index == 0) return; // Do nothing on root if (D_ARY_UP_GRAEHL) { Value copyi=data[index]; @@ -381,7 +425,7 @@ if (index == 0) break; // Stop at root size_type parent_index = parent(index); Value parent_value = data[parent_index]; - if (compare(currently_being_moved_dist, get(distance, parent_value))) { + if (better(currently_being_moved_dist, get(distance, parent_value))) { ++num_levels_moved; index = parent_index; continue; @@ -392,6 +436,7 @@ // Actually do the moves -- move num_levels_moved elements down in the // tree, then put currently_being_moved at the top index = orig_index; + using boost::put; for (size_type i = 0; i < num_levels_moved; ++i) { size_type parent_index = parent(index); Value parent_value = data[parent_index]; @@ -409,6 +454,7 @@ // are any parent-child pairs that violate the heap property. v is placed at data[i], but then pushed down (note: data[i] won't be read explicitly; it will instead be overwritten by percolation). this also means that v must be a copy of data[i] if it was already at i. // e.g. v=data.back(), i=0, sz=data.size()-1 for pop(), implicitly swapping data[i], data.back(), and doing data.pop_back(), then adjusting from 0 down w/ swaps. updates index_in_heap for v. inline void preserve_heap_property_down(Value const& currently_being_moved,size_type i,size_type heap_size) { + using boost::get; distance_type currently_being_moved_dist=get(distance,currently_being_moved); Value* data_ptr = &data[0]; size_type index = 0; // hole at index - currently_being_moved to be put here when we find the final hole spot @@ -423,7 +469,7 @@ #undef D_ARY_MAYBE_IMPROVE_CHILD_I #define D_ARY_MAYBE_IMPROVE_CHILD_I \ distance_type i_dist = get(distance, child_base_ptr[i]); \ - if (compare(i_dist, smallest_child_dist)) { \ + if (better(i_dist, smallest_child_dist)) { \ smallest_child_index = i; \ smallest_child_dist = i_dist; \ } @@ -439,7 +485,7 @@ } //end: know best child - if (compare(smallest_child_dist, currently_being_moved_dist)) { + if (better(smallest_child_dist, currently_being_moved_dist)) { // instead of swapping, move. move_heap_element(child_base_ptr[smallest_child_index],index); // move up index=first_child_index+smallest_child_index; // descend - hole is now here @@ -456,6 +502,7 @@ } void preserve_heap_property_down() { + using boost::get; if (data.empty()) return; if (D_ARY_DOWN_GRAEHL) { // this *should* be more efficient because i avoid swaps. Value copy0=data[0]; @@ -484,7 +531,7 @@ D_ARY_MAYBE_IMPROVE_CHILD_I } } - if (compare(smallest_child_dist, currently_being_moved_dist)) { + if (better(smallest_child_dist, currently_being_moved_dist)) { swap_heap_elements(smallest_child_index + first_child_index, index); index = smallest_child_index + first_child_index; continue; diff --git a/utils/hash.h b/utils/hash.h index 17f150ff..2062578f 100755 --- a/utils/hash.h +++ b/utils/hash.h @@ -32,9 +32,9 @@ const unsigned GOLDEN_MEAN_FRACTION=2654435769U; template <class C> struct murmur_hash { - typedef MurmurInt return_type; + typedef MurmurInt result_type; typedef C /*const&*/ argument_type; - return_type operator()(argument_type const& c) const { + result_type operator()(argument_type const& c) const { return MurmurHash((void*)&c,sizeof(c)); } }; @@ -43,9 +43,9 @@ struct murmur_hash template <> struct murmur_hash<std::string> { - typedef MurmurInt return_type; + typedef MurmurInt result_type; typedef std::string /*const&*/ argument_type; - return_type operator()(argument_type const& c) const { + result_type operator()(argument_type const& c) const { return MurmurHash(c.data(),c.size()); } }; @@ -54,9 +54,9 @@ struct murmur_hash<std::string> template <class C> struct murmur_hash_array { - typedef MurmurInt return_type; + typedef MurmurInt result_type; typedef C /*const&*/ argument_type; - return_type operator()(argument_type const& c) const { + result_type operator()(argument_type const& c) const { return MurmurHash(&*c.begin(),c.size()*sizeof(*c.begin())); } }; diff --git a/utils/intern_pool.h b/utils/intern_pool.h index c85c9881..d9890ae6 100755 --- a/utils/intern_pool.h +++ b/utils/intern_pool.h @@ -14,26 +14,48 @@ template <class I> struct get_key { // default accessor for I = like pair<key,val> - typedef typename I::first_type const& return_type; + typedef typename I::first_type const& result_type; typedef I const& argument_type; - return_type operator()(I const& i) const { + result_type operator()(I const& i) const { return i.first; } }; +// Arg type should be the non-pointer version. this saves me from using boost type traits to remove_pointer. f may be binary or unary template <class KeyF,class F,class Arg=typename KeyF::argument_type> struct compose_indirect { - typedef Arg *argument_type; // also Arg + typedef Arg *argument_type; // we also accept Arg & KeyF kf; F f; - typedef typename F::return_type return_type; - return_type operator()(Arg p) const { + typedef typename F::result_type result_type; + result_type operator()(Arg const& p) const { return f(kf(p)); } - template <class V> - return_type operator()(Arg *p) const { + result_type operator()(Arg & p) const { + return f(kf(p)); + } + result_type operator()(Arg * p) const { return f(kf(*p)); } + template <class V> + result_type operator()(V const& v) const { + return f(kf(*v)); + } + + result_type operator()(Arg const& a1,Arg const& a2) const { + return f(kf(a1),kf(a2)); + } + result_type operator()(Arg & a1,Arg & a2) const { + return f(kf(a1),kf(a2)); + } + result_type operator()(Arg * a1,Arg * a2) const { + return f(kf(*a1),kf(*a2)); + } + template <class V,class W> + result_type operator()(V const& v,W const&w) const { + return f(kf(*v),kf(*w)); + } + }; @@ -43,27 +65,29 @@ template <class F> struct indirect_function { F f; explicit indirect_function(F const& f=F()) : f(f) {} - typedef typename F::return_type return_type; + typedef typename F::result_type result_type; template <class V> - return_type operator()(V *p) const { + result_type operator()(V *p) const { return f(*p); } }; */ -template <class Item,class KeyF=get_key<Item>,class HashKey=boost::hash<typename KeyF::return_type>,class EqKey=std::equal_to<typename KeyF::return_type>, class Pool=boost::object_pool<Item> > +template <class Item,class KeyF=get_key<Item>,class HashKey=boost::hash<typename KeyF::result_type>,class EqKey=std::equal_to<typename KeyF::result_type>, class Pool=boost::object_pool<Item> > struct intern_pool : Pool { KeyF key; - typedef typename KeyF::return_type Key; + typedef typename KeyF::result_type Key; typedef Item *Handle; - typedef compose_indirect<KeyF,HashKey,Handle> HashDeep; - typedef compose_indirect<KeyF,EqKey,Handle> EqDeep; + typedef compose_indirect<KeyF,HashKey,Item> HashDeep; + typedef compose_indirect<KeyF,EqKey,Item> EqDeep; typedef HASH_SET<Handle,HashDeep,EqDeep> Canonical; typedef typename Canonical::iterator CFind; typedef std::pair<CFind,bool> CInsert; Canonical canonical; - void interneq(Handle &i) { - i=intern(i); + bool interneq(Handle &i) { // returns true if i is newly interned, false if it already existed + CInsert i_new=canonical.insert(i); + i=*i_new.first; + return i_new.second; } // inherited: Handle construct(...) Handle construct_fresh() { return Pool::construct(); } diff --git a/utils/logval.h b/utils/logval.h index 4605d919..da0aa2b0 100644 --- a/utils/logval.h +++ b/utils/logval.h @@ -10,11 +10,18 @@ #include <limits> #include <cassert> #include "semiring.h" +#include "show.h" //TODO: template for supporting negation or not - most uses are for nonnegative "probs" only; probably some 10-20% speedup available template <class T> class LogVal { public: + void print(std::ostream &o) const { + if (s_) o<<"(-)"; + o<<v_; + } + PRINT_SELF(LogVal<T>) + typedef LogVal<T> Self; LogVal() : s_(), v_(LOGVAL_LOG0) {} @@ -143,6 +150,7 @@ class LogVal { bool s_; T v_; + }; template <class T> diff --git a/utils/lvalue_pmap.h b/utils/lvalue_pmap.h index 03ddf5e7..5b9403c0 100755 --- a/utils/lvalue_pmap.h +++ b/utils/lvalue_pmap.h @@ -3,7 +3,7 @@ #include <boost/property_map/property_map.hpp> -// i checked: boost provides get and put given [] +// i checked: boost provides get and put given [] - but it's not being found by ADL so instead i define them myself // lvalue property map pmapname<P> that is: P p; valtype &v=p->name; #define PMAP_MEMBER_INDIRECT(pmapname,valtype,name) template <class P> struct pmapname { \ @@ -12,6 +12,9 @@ typedef value_type & reference; \ typedef boost::lvalue_property_map_tag category; \ reference operator[](key_type p) const { return p->name; } \ + typedef pmapname<P> self_type; \ + friend inline value_type const& get(self_type const&,key_type p) { return p->name; } \ + friend inline void put(self_type &,key_type p,value_type const& v) { p->name = v; } \ }; #define PMAP_MEMBER_INDIRECT_2(pmapname,name) template <class P,class R> struct pmapname { \ @@ -20,6 +23,9 @@ typedef value_type & reference; \ typedef boost::lvalue_property_map_tag category; \ reference operator[](key_type p) const { return p->name; } \ + typedef pmapname<P,R> self_type; \ + friend inline value_type const& get(self_type const&,key_type p) { return p->name; } \ + friend inline void put(self_type &,key_type p,value_type const& v) { p->name = v; } \ }; #endif diff --git a/utils/max_plus.h b/utils/max_plus.h index 2c55b33c..2e56f85e 100755 --- a/utils/max_plus.h +++ b/utils/max_plus.h @@ -19,10 +19,23 @@ #include <cassert> #include <limits> #include "semiring.h" +#include "show.h" +//#include "logval.h" template <class T> class MaxPlus { public: + void print(std::ostream &o) const { + o<<v_; + } + PRINT_SELF(MaxPlus<T>) + template <class O> + void operator=(O const& o) { + v_=o.v_; + } + template <class O> + MaxPlus(O const& o) : v_(o.v_) { } + typedef MaxPlus<T> Self; MaxPlus() : v_(LOGVAL_LOG0) {} explicit MaxPlus(double x) : v_(std::log(x)) {} diff --git a/utils/show.h b/utils/show.h index 6f601d47..1b645c83 100755 --- a/utils/show.h +++ b/utils/show.h @@ -6,6 +6,29 @@ #define SHOWS std::cerr #endif + +#define SELF_TYPE_PRINT \ + template <class Char,class Traits> \ + inline friend std::basic_ostream<Char,Traits> & operator <<(std::basic_ostream<Char,Traits> &o, self_type const& me) \ + { me.print(o);return o; } \ + typedef self_type has_print; + +#define SELF_TYPE_PRINT_ANY_STREAM \ + template <class O> \ + friend inline O & operator <<(O &o, self_type const& me) \ + { me.print(o);return o; } \ + typedef self_type has_print; + +#define SELF_TYPE_PRINT_OSTREAM \ + friend inline std::ostream & operator <<(std::ostream &o, self_type const& me) \ + { me.print(o);return o; } \ + typedef self_type has_print; + +#define PRINT_SELF(self) typedef self self_type; SELF_TYPE_PRINT_OSTREAM + +#undef SHOWALWAYS +#define SHOWALWAYS(x) x + /* usage: #if DEBUG # define IFD(x) x @@ -36,6 +59,7 @@ careful: none of this is wrapped in a block. so you can't use one of these macr #define SHOW4(IF,x,y0,y1,y2) SHOW1(IF,x) SHOW3(IF,y0,y1,y2) #define SHOW5(IF,x,y0,y1,y2,y3) SHOW1(IF,x) SHOW4(IF,y0,y1,y2,y3) #define SHOW6(IF,x,y0,y1,y2,y3,y4) SHOW1(IF,x) SHOW5(IF,y0,y1,y2,y3,y4) +#define SHOW7(IF,x,y0,y1,y2,y3,y4,y5) SHOW1(IF,x) SHOW6(IF,y0,y1,y2,y3,y4,y5) #define SHOWM(IF,m,x) SHOWP(IF,m<<": ") SHOW(IF,x) #define SHOWM2(IF,m,x0,x1) SHOWP(IF,m<<": ") SHOW2(IF,x0,x1) @@ -43,5 +67,6 @@ careful: none of this is wrapped in a block. so you can't use one of these macr #define SHOWM4(IF,m,x0,x1,x2,x3) SHOWP(IF,m<<": ") SHOW4(IF,x0,x1,x2,x3) #define SHOWM5(IF,m,x0,x1,x2,x3,x4) SHOWP(IF,m<<": ") SHOW5(IF,x,x0,x1,x2,x3,x4) #define SHOWM6(IF,m,x0,x1,x2,x3,x4,x5) SHOWP(IF,m<<": ") SHOW6(IF,x0,x1,x2,x3,x4,x5) +#define SHOWM7(IF,m,x0,x1,x2,x3,x4,x5,x6) SHOWP(IF,m<<": ") SHOW7(IF,x0,x1,x2,x3,x4,x5,x6) #endif diff --git a/utils/utoa.h b/utils/utoa.h index 5de490ba..8b54987b 100755 --- a/utils/utoa.h +++ b/utils/utoa.h @@ -137,7 +137,7 @@ char *utoa_drop_trailing_0(char *buf,Uint_ n_, unsigned &n_skipped) { } //#include "warning_push.h" -//#pragma GCC diagnostic ignore "-Wtype-limits" // because sign check on itoa<unsigned> is annoying +//#pragma GCC diagnostic ignored "-Wtype-limits" // because sign check on itoa<unsigned> is annoying // desired feature: itoa(unsigned) = utoa(unsigned) // positive sign: 0 -> +0, 1-> +1. obviously -n -> -n diff --git a/utils/value_array.h b/utils/value_array.h index a10f754f..f1cc2a84 100755 --- a/utils/value_array.h +++ b/utils/value_array.h @@ -305,6 +305,21 @@ bool operator==(ValueArray<T,A> const& v1, ValueArray<T,A> const& v2) std::equal(v1.begin(),v1.end(),v2.begin()); } +template <class A> +bool operator==(ValueArray<char,A> const& v1, ValueArray<char,A> const& v2) +{ + typename ValueArray<char,A>::size_type sz=v1.size(); + return sz == v2.size() && + 0==std::memcmp(v1.begin(),v2.begin(),sizeof(char)*sz); +} + +template <class A> +bool operator==(ValueArray<unsigned char,A> const& v1, ValueArray<unsigned char,A> const& v2) +{ + typename ValueArray<char,A>::size_type sz=v1.size(); + return sz == v2.size() && + 0==std::memcmp(v1.begin(),v2.begin(),sizeof(char)*sz); +} template <class T,class A> bool operator< (ValueArray<T,A> const& v1, ValueArray<T,A> const& v2) @@ -315,6 +330,15 @@ bool operator< (ValueArray<T,A> const& v1, ValueArray<T,A> const& v2) , v2.end() ); } +template <class A> +bool operator<(ValueArray<unsigned char,A> const& v1, ValueArray<unsigned char,A> const& v2) +{ + typename ValueArray<char,A>::size_type sz=v1.size(); + return sz == v2.size() && + std::memcmp(v1.begin(),v2.begin(),sizeof(char)*sz)<0; +} + + template <class T,class A> void memcpy(void *out,ValueArray<T,A> const& v) { std::memcpy(out,v.begin(),v.size()*sizeof(T)); diff --git a/utils/warning_compiler.h b/utils/warning_compiler.h index 2052cff3..b981ac0f 100644 --- a/utils/warning_compiler.h +++ b/utils/warning_compiler.h @@ -5,7 +5,8 @@ #undef HAVE_DIAGNOSTIC_PUSH #if __GNUC__ > 4 || __GNUC__==4 && __GNUC_MINOR__ > 3 # define HAVE_GCC_4_4 1 -# define HAVE_DIAGNOSTIC_PUSH 1 +# define HAVE_DIAGNOSTIC_PUSH 0 +// weird, they took it out of 4.5? #else # define HAVE_GCC_4_4 0 # define HAVE_DIAGNOSTIC_PUSH 0 diff --git a/utils/warning_push.h b/utils/warning_push.h index 086fd524..29d04e76 100644 --- a/utils/warning_push.h +++ b/utils/warning_push.h @@ -3,6 +3,6 @@ #else #include "warning_compiler.h" #if HAVE_DIAGNOSTIC_PUSH -# pragma GCC diagnostic push +#pragma GCC diagnostic push #endif #endif |