00001 #ifndef BIT_ALGO_HH
00002 #define BIT_ALGO_HH
00003
00004 #include "bit/exceptions.hh"
00005 #include "bit/base.hh"
00006
00007 namespace bit {
00008
00010 template <class A>
00011 u32 max(const A &array)
00012 {
00013 u32 max = 0;
00014 for (u64 i = 0; i < array.num_elems(); i++) {
00015 u32 value = array.get(i);
00016 if (value > max)
00017 max = value;
00018 }
00019 return max;
00020 }
00021
00032 template <class A>
00033 u64 binary_search(const A &array, u32 value, u64 first, u64 limit)
00034 {
00035 u64 bound = lower_bound(array, value, first, limit);
00036 if (bound < limit && array.get(bound) == value)
00037 return bound;
00038 return limit;
00039 }
00040
00052 template <class A>
00053 u64 lower_bound(const A &array, u32 value, u64 first, u64 limit)
00054 {
00055 if (first > limit)
00056 throw bit::invalid_argument(
00057 "bit::lower_bound(): negative range");
00058 if (limit > array.num_elems())
00059 throw bit::out_of_range("bit::lower_bound(): out of range");
00060
00061 u64 middle;
00062 u64 half;
00063 u64 len = limit - first;
00064
00065 while (len > 5) {
00066 half = len / 2;
00067 middle = first + half;
00068
00069
00070 u32 cur_value = array.get(middle);
00071
00072
00073 if (cur_value >= value) {
00074 limit = middle;
00075 len = limit - first;
00076 }
00077
00078
00079 else {
00080 first = middle + 1;
00081 len = limit - first;
00082 }
00083 }
00084
00085 while (first < limit) {
00086 u32 cur_value = array.get(first);
00087 if (cur_value >= value)
00088 break;
00089 first++;
00090 }
00091
00092 return first;
00093 }
00094
00105 template <class A>
00106 u64 last_leq(const A &array, u32 value)
00107 {
00108 return last_leq(array, value, 0, array.num_elems());
00109 }
00110
00126 template <class A>
00127 u64 last_leq(const A &array, u32 value, u64 first, u64 limit)
00128 {
00129 if (first > limit)
00130 throw bit::invalid_argument("bit::last_leq() negative range");
00131 if (limit > array.num_elems())
00132 throw bit::out_of_range("bit::last_leq() limit out of range");
00133
00134 u64 middle;
00135 u64 half;
00136 u64 len = limit - first;
00137
00138 while (len > 5) {
00139 half = len / 2;
00140 middle = first + half;
00141
00142
00143 u32 cur_value = array.get(middle);
00144
00145
00146 if (cur_value <= value) {
00147 first = middle;
00148 len = limit - first;
00149 }
00150
00151
00152 else {
00153 limit = middle;
00154 len = limit - first;
00155 }
00156 }
00157
00158 u64 orig_first = first;
00159 while (first < limit) {
00160 u32 cur_value = array.get(first);
00161 if (cur_value > value)
00162 break;
00163 first++;
00164 }
00165
00166 if (first == orig_first)
00167 return max_u64;
00168
00169 return first - 1;
00170 }
00171
00172 template <class A>
00173 u64 last_leq_naive(const A &array, u32 value, u64 first, u64 limit)
00174 {
00175 if (first > limit)
00176 throw bit::invalid_argument("bit::last_leq() negative range");
00177 if (limit > array.num_elems())
00178 throw bit::out_of_range("bit::last_leq() limit out of range");
00179
00180 u64 i;
00181 for (i = first; i < limit; i++) {
00182 if (array.get(i) > value) {
00183 break;
00184 }
00185 }
00186 if (i == first)
00187 return max_u64;
00188 return i - 1;
00189 }
00190
00191 };
00192
00193 #endif