algo.hh

Go to the documentation of this file.
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) { // NOTE: magic threshold to do linear search
00066       half = len / 2;
00067       middle = first + half;
00068 
00069       // Equal
00070       u32 cur_value = array.get(middle);
00071 
00072       // First half
00073       if (cur_value >= value) {
00074         limit = middle;
00075         len = limit - first;
00076       }
00077 
00078       // Second half
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) { // NOTE: magic threshold to do linear search
00139       half = len / 2;
00140       middle = first + half;
00141 
00142       // Equal
00143       u32 cur_value = array.get(middle);
00144 
00145       // First half
00146       if (cur_value <= value) {
00147         first = middle;
00148         len = limit - first;
00149       }
00150 
00151       // Second half
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 /* BIT_ALGO_HH */

Generated on Mon Jan 8 15:51:03 2007 for bit by  doxygen 1.4.6