00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #ifndef MTL_ZIPPED_SORT_INCLUDE
00013 #define MTL_ZIPPED_SORT_INCLUDE
00014
00015
00016
00017
00018 #include <iterator>
00019
00020 namespace mtl { namespace utility {
00021
00022 template <typename T, typename U> struct zip_ref;
00023 template <typename T, typename U> struct zip_it;
00024 template <typename T, typename U> struct zip_value;
00025
00026 struct less_0
00027 {
00028 template <typename T, typename U>
00029 bool operator()(const zip_ref<T, U>& x, const zip_ref<T, U>& y) const
00030 {
00031 return x.a[x.p] < y.a[y.p];
00032 }
00033
00034 template <typename T, typename U>
00035 bool operator()(const zip_ref<T, U>& x, const zip_value<T, U>& y) const
00036 {
00037 return x.a[x.p] < y.x;
00038 }
00039
00040 template <typename T, typename U>
00041 bool operator()(const zip_value<T, U>& x, const zip_ref<T, U>& y) const
00042 {
00043 return x.x < y.a[y.p];
00044 }
00045 };
00046
00047 template <typename T, typename U>
00048 struct zip_it
00049 {
00050 typedef zip_ref<T, U> ref_type;
00051
00052 explicit zip_it(T* a, U* v, int p) : a(a), v(v), p(p) {}
00053
00054 ref_type operator*() { return ref_type(a, v, p); }
00055 zip_it& operator++() { p++; return *this;}
00056 zip_it& operator--() { p--; return *this;}
00057 zip_it operator--(int) { zip_it tmp(a, v, p); p--; return tmp;}
00058
00059 void check(const zip_it& other) const { assert(a == other.a); assert(v == other.v); }
00060
00061 bool operator==(const zip_it& other) const { check(other); return p == other.p; }
00062 bool operator!=(const zip_it& other) const { check(other); return p != other.p; }
00063 bool operator<(const zip_it& other) const { check(other); return p < other.p; }
00064 int operator-(const zip_it& other) const { check(other); return p - other.p; }
00065 zip_it operator+(int i) const { return zip_it(a, v, p+i); }
00066 zip_it operator-(int i) const { return zip_it(a, v, p-i); }
00067 zip_it& operator=(const zip_it& other) { check(other); p= other.p; return *this; }
00068
00069 T* a;
00070 U* v;
00071 int p;
00072 };
00073
00074
00075 template <typename T, typename U>
00076 struct zip_ref
00077 {
00078 typedef zip_ref self;
00079
00080 zip_ref(T* a, U* v, int p) : a(a), v(v), p(p) {}
00081
00082 void check(const zip_ref& other) const { assert(a == other.a); assert(v == other.v); }
00083
00084 bool operator<(const zip_ref& r) const { check(r); return a[p] < r.a[r.p]; }
00085 zip_ref& operator=(const zip_ref& r)
00086 {
00087 check(r);
00088 if (p == r.p)
00089 return *this;
00090 a[p]= r.a[r.p]; v[p]= r.v[r.p];
00091 p= r.p;
00092 return *this;
00093 }
00094
00095 zip_ref& operator=(const zip_value<T, U>& zv)
00096 {
00097 a[p]= zv.x; v[p]= zv.y;
00098 return *this;
00099 }
00100
00101 friend inline void swap(self x, self y)
00102 {
00103 swap(x.a[x.p], y.a[y.p]);
00104 swap(x.v[x.p], y.v[y.p]);
00105 }
00106
00107 T *a;
00108 U *v;
00109 int p;
00110
00111 };
00112
00113 template <typename T, typename U>
00114 struct zip_value
00115 {
00116 zip_value(const zip_ref<T, U>& r) : x(r.a[r.p]), y(r.v[r.p]) {}
00117
00118 T x;
00119 U y;
00120 };
00121
00122 }}
00123
00124 namespace std {
00125 template <typename T, typename U>
00126 struct iterator_traits<mtl::utility::zip_it<T, U> >
00127 {
00128 typedef mtl::utility::zip_ref<T, U> ref_type;
00129 typedef mtl::utility::zip_value<T, U> value_type;
00130 typedef ref_type& reference;
00131 typedef ref_type* pointer;
00132 typedef int difference_type;
00133 typedef random_access_iterator_tag iterator_category;
00134 };
00135 }
00136
00137
00138
00139
00140
00141 #endif // MTL_ZIPPED_SORT_INCLUDE