Mercurial > hg > octave-nkf
diff liboctave/oct-lookup.h @ 7671:4fbaba9abec1
implement compiled binary lookup
author | Jaroslav Hajek <highegg@gmail.com> |
---|---|
date | Fri, 28 Mar 2008 15:53:09 -0400 |
parents | |
children | 6848970153ba |
line wrap: on
line diff
new file mode 100644 --- /dev/null +++ b/liboctave/oct-lookup.h @@ -0,0 +1,174 @@ +/* + +Copyright (C) 2008 VZLU Prague, a.s., Czech Republic + +This file is part of Octave. + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 3 of the License, or (at your +option) any later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with Octave; see the file COPYING. If not, see +<http://www.gnu.org/licenses/>. + +*/ + +// Author: Jaroslav Hajek <highegg@gmail.com> + +#if !defined (octave_oct_lookup) +#define octave_oct_lookup 1 + +#include <algorithm> +#include <functional> + +#include "oct-types.h" + +// a simple binary lookup +template<typename T, typename bpred> +octave_idx_type +bin_lookup (const T *table, octave_idx_type size, + const T& val, + bpred comp) +{ + return std::upper_bound (table, table + size, val, comp) - table; +} + +// version using < operator +template<typename T> +octave_idx_type +bin_lookup (const T *table, octave_idx_type size, + const T& val) +{ + return std::upper_bound (table, table + size, val) - table; +} + +// a unary functor that checks whether a value is outside [a,b) range +template<class T, class bpred> +class out_range : public std::unary_function<T, bool> +{ +public: + out_range (const T& aa, const T& bb, const bpred& ccomp) + : a(aa), b(bb), comp(ccomp) { } + + bool operator() (const T& x) { return comp (x, a) || ! comp (x, b); } + +private: + T a; + T b; + + bpred comp; +}; + +// conveniently constructs the above functor +// NOTE: with SGI extensions, this can be written as +// compose2 (logical_and<bool>(), +// bind2nd (less<T>(), a), +// not1 (bind2nd (less<T>(), b))) +template<class T, class bpred> +out_range<T, bpred> +chk_out_range (const T& a, const T& b, bpred comp) +{ + return out_range<T, bpred> (a, b, comp); +} + +template<typename T, typename bpred> +void +seq_lookup (const T *table, octave_idx_type offset, octave_idx_type size, + const T *vals, octave_idx_type nvals, + octave_idx_type *idx, bpred comp) +{ + const T *begin = table + offset; + + if (size == 0) + // the trivial case of empty table + std::fill_n (idx, nvals, offset); + else + { + const T *vcur = vals; + const T *vend = vals + nvals; + + const T *cur = begin; + const T *end = begin + size; + + while (vcur < vend) + { + // determine the enclosing interval for next value, trying + // ++cur as a special case; + if (cur == end || comp (*vcur, *cur)) + cur = std::upper_bound (begin, cur, *vcur, comp); + else + { + ++cur; + if (cur < end && ! comp (*vcur, *cur)) + cur = std::upper_bound (cur + 1, end, *vcur, comp); + } + + // store index of the current interval. + *(idx++) = (cur - table); + ++vcur; + + // find first value not in current subrange + const T *vnew; + if (cur < end) + if (cur > begin) + // inner interval + vnew = std::find_if (vcur, vend, + chk_out_range (*(cur-1), *cur, comp)); + + else + // special case: lowermost range (-Inf, min) + vnew = std::find_if (vcur, vend, + not1 (bind2nd (comp, *cur))); + else + // special case: uppermost range [max, Inf) + vnew = std::find_if (vcur, vend, + bind2nd (comp, *(cur-1))); + + // store index of the current interval. + idx = std::fill_n (idx, vnew - vcur, cur - table); + vcur = vnew; + + } + } +} + +// overload using < operator +template<typename T, typename bpred> +void +seq_lookup (const T *table, octave_idx_type offset, octave_idx_type size, + const T *vals, octave_idx_type nvals, + octave_idx_type *idx) +{ + seq_lookup (table, offset, size, vals, nvals, idx, std::less<T>()); +} + +// helper functions - determine whether an array is descending +template<typename T> +bool +is_descending (const T *table, octave_idx_type size) +{ + return size > 1 && table[size-1] < table[0]; +} + +template<typename T, typename bpred> +bool +is_descending (const T *table, octave_idx_type size, + bpred comp) +{ + return size > 1 && comp (table[size-1], table[0]); +} + +#endif + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/