diff options
Diffstat (limited to 'utils')
-rwxr-xr-x | utils/hash.h | 27 | ||||
-rwxr-xr-x | utils/indices_after.h | 61 | ||||
-rwxr-xr-x | utils/named_enum.h | 5 | ||||
-rw-r--r-- | utils/small_vector.h | 24 |
4 files changed, 110 insertions, 7 deletions
diff --git a/utils/hash.h b/utils/hash.h index e89b1863..b0b1c43e 100755 --- a/utils/hash.h +++ b/utils/hash.h @@ -58,4 +58,31 @@ typename H::mapped_type & get_default(H &ht,K const& k,typename H::mapped_type c return const_cast<typename H::mapped_type &>(ht.insert(typename H::value_type(k,v)).first->second); } +// the below could also return a ref to the mapped max/min. they have the advantage of not falsely claiming an improvement when an equal value already existed. otherwise you could just modify the get_default and if equal assume new. +template <class H,class K> +bool improve_mapped_max(H &ht,K const& k,typename H::mapped_type const& v) { + std::pair<typename H::iterator,bool> inew=ht.insert(typename H::value_type(k,v)); + if (inew.second) return true; + typedef typename H::mapped_type V; + V &oldv=const_cast<V&>(inew.first->second); + if (oldv<v) { + oldv=v; + return true; + } + return false; +} + +template <class H,class K> +bool improve_mapped_min(H &ht,K const& k,typename H::mapped_type const& v) { + std::pair<typename H::iterator,bool> inew=ht.insert(typename H::value_type(k,v)); + if (inew.second) return true; + typedef typename H::mapped_type V; + V &oldv=const_cast<V&>(inew.first->second); + if (v<oldv) { // the only difference from above + oldv=v; + return true; + } + return false; +} + #endif diff --git a/utils/indices_after.h b/utils/indices_after.h index 2b662d5c..2891563c 100755 --- a/utils/indices_after.h +++ b/utils/indices_after.h @@ -1,6 +1,9 @@ #ifndef INDICES_AFTER_REMOVING_H #define INDICES_AFTER_REMOVING_H +//TODO: instead of making REMOVED a constant, make it class state (defaults to -1 as before, of course). + +#include <assert.h> #include <boost/config.hpp> // STATIC_CONSTANT #include <algorithm> //swap #include <iterator> @@ -48,19 +51,50 @@ unsigned new_indices(KEEP keep,O out) { return new_indices(keep.begin(),keep.end(),out); } +template <class V,class Out,class Permi> +void copy_perm_to(Out o,V const& from,Permi i,Permi e) { + for (;i!=e;++i) + *o++=from[*i]; +} + +//to cannot be same as from, for most permutations. for to==from, use indices_after::init_inverse_order instead. +template <class Vto,class Vfrom,class Perm> +void remap_perm_to(Vto &to,Vfrom const& from,Perm const& p) { + to.resize(p.size()); + copy_perm_to(to.begin(),from,p.begin(),p.end()); +} + // given a vector and a parallel sequence of bools where true means keep, keep only the marked elements while maintaining order. // this is done with a parallel sequence to the input, marked with positions the kept items would map into in a destination array, with removed items marked with the index -1. the reverse would be more compact (parallel to destination array, index of input item that goes into it) but would require the input sequence be random access. struct indices_after { BOOST_STATIC_CONSTANT(unsigned,REMOVED=(unsigned)-1); unsigned *map; // map[i] == REMOVED if i is deleted - unsigned n_kept; + unsigned n_kept; // important to init this. unsigned n_mapped; template <class AB,class ABe> indices_after(AB i, ABe end) { init(i,end); } + template <class Order> + void init_inverse_order(unsigned from_sz,Order const& order) { + init_inverse_order(from_sz,order.begin(),order.end()); + } + template <class OrderI> + void init_inverse_order(unsigned from_sz,OrderI i,OrderI end) { + init_alloc(from_sz); + unsigned d=0; + n_kept=0; + for(;i!=end;++i) { + assert(d<from_sz); + map[d++]=*i; + ++n_kept; + } + for(;d<from_sz;++d) + map[d]=REMOVED; + } + template <class Vec,class R> void init_keep_if(Vec v,R const& r) { @@ -69,6 +103,25 @@ struct indices_after map=(unsigned *)::operator new(sizeof(unsigned)*n_mapped); n_kept=new_indices_keep_if_n(n_mapped,r,map); } + // contents uninit. + void init_alloc(unsigned n) { + free(); + n_mapped=n; + map=n_mapped>0 ? + (unsigned *)::operator new(sizeof(unsigned)*n_mapped) + : 0; + } + void init_const(unsigned n,unsigned map_all_to) { + init_alloc(n); + for (unsigned i=0;i<n;++i) + map[i]=map_all_to; + n_kept=(map_all_to==REMOVED)?0:n; + } + + void init_keep_none(unsigned n) { + init_const(n,REMOVED); + n_kept=0; + } template <class AB,class ABe> void init(AB i, ABe end) { @@ -93,9 +146,14 @@ struct indices_after indices_after() : n_mapped(0) {} ~indices_after() { + free(); + } + void free() { if (n_mapped) ::operator delete((void*)map); + n_mapped=0; } + bool removing(unsigned i) const { return map[i] == REMOVED; @@ -127,7 +185,6 @@ struct indices_after { using std::swap; assert(v.size()==n_mapped); - unsigned r=n_mapped; unsigned i=0; for (;i<n_mapped&&keeping(i);++i) ; for(;i<n_mapped;++i) diff --git a/utils/named_enum.h b/utils/named_enum.h index 447dff78..675ec868 100755 --- a/utils/named_enum.h +++ b/utils/named_enum.h @@ -2,13 +2,16 @@ #define NAMED_ENUM_H #ifndef NAMED_ENUM_USE_OPTIONAL -# define NAMED_ENUM_USE_OPTIONAL 1 +# define NAMED_ENUM_USE_OPTIONAL 0 #endif //TODO: efficiency - supply map type (e.g. std::map or tr1::unordered_map) for string->int (int->string already fast w/ switch) - then implement iterators that don't assume contiguous ids. //TODO: hidden (can't convert string->id, but can do reverse) sentinel values. XX (hidden) and XY (can convert to) //TODO: bitfield "A|B" strings - note: slightly complicates int->string, as well. //TODO: option for case-insensitive compare (ctype tolower?) +//TODO: program_options validate method so you can declare po::value<MyEnum> instead of po::value<string>? +//TODO: cout << MyEnum ? +//impossible: (without wrapping in struct) MyEnum(string) /* named enum (string<->int). note: inefficient linear search for string->int diff --git a/utils/small_vector.h b/utils/small_vector.h index 077a524a..8c1c3bfe 100644 --- a/utils/small_vector.h +++ b/utils/small_vector.h @@ -15,6 +15,8 @@ #include <new> #include <stdint.h> #include "swap_pod.h" +#include <boost/functional/hash.hpp> + //sizeof(T)/sizeof(T*)>1?sizeof(T)/sizeof(T*):1 template <class T,int SV_MAX=2> @@ -250,6 +252,15 @@ public: swap_pod(*this,o); } + inline std::size_t hash() const { + using namespace boost; + if (size_==0) return 0; + if (size_==1) return hash_value(data_.vals[0]); + if (size<= SV_MAX) + return hash_range(data_.vals,data_.vals+size_); + return hash_range(data_.ptr,data_.ptr+size_); + } + private: union StorageType { T vals[SV_MAX]; @@ -260,15 +271,20 @@ public: uint16_t capacity_; // only defined when size_ > __SV_MAX_STATIC }; -template <class T,int SV_MAX> -inline void swap(SmallVector<T,SV_MAX> &a,SmallVector<T,SV_MAX> &b) { +template <class T,int M> +std::size_t hash_value(SmallVector<T,M> const& x) { + return x.hash(); +} + +template <class T,int M> +inline void swap(SmallVector<T,M> &a,SmallVector<T,M> &b) { a.swap(b); } typedef SmallVector<int,2> SmallVectorInt; -template <class T,int N> -void memcpy(void *out,SmallVector<T,N> const& v) { +template <class T,int M> +void memcpy(void *out,SmallVector<T,M> const& v) { std::memcpy(out,v.begin(),v.size()*sizeof(T)); } |