[vsipl++] [selgen]
Jules Bergmann
jules at codesourcery.com
Tue Sep 27 22:18:13 UTC 2005
Stefan Seefeld wrote:
> The attached patch implements all functions from section 9.4 ([selgen])
> of the spec, i.e.
>
> * first()
> * indexbool()
> * gather()
> * scatter()
> * clip()
> * invclip()
> * swap()
>
> together with unit tests. It also contains some bits and pieces I
> submitted earlier today to cleanup header dependencies etc., as I
> wasn't able to easily separate the two.
Stefan,
Looks good. I have one suggestion for indexbool to make it a little
more robust, otherwise it looks ready to check in.
Also, were the unit tests included in the patch?
thanks,
-- Jules
>
> /***********************************************************************
> @@ -30,6 +31,29 @@
> namespace impl
> {
>
> +template <typename T, typename B1, typename B2>
> +length_type
> +indexbool(const_Vector<T, B1> source, Vector<Index<1>, B2> indices)
> +{
> + index_type cursor = 0;
> + for (index_type i = 0; i != source.size(); ++i)
> + if (source.get(i))
> + indices.put(cursor++, Index<1>(i));
> + return cursor;
> +}
I'm trying to think if we can do better error checking here. This
doesn't check if cursor < indices.size(0), but the put does, so that's
good. It would be good to have an assertion in indexbool so that the
failure is more obvious.
However, I don't think the specification of indexbool makes it very
useful. It should handle an overflow more gracefully than either
aborting or corrupting memory. Since the overflow condition is
data-dependent, it forces me to size indices for the absolute worst
case. Hypotheticaly, if I'm doing target detection on an IR sensor and
a flare goes off, I'm going to have way more detections for a few frames
until I have a chance to adapt my thresholds. As a system engineer, I
would probably choose to drop some detections for a few frames rather
than size my detection buffer for the absolute worst-case. I certainly
don't want the application to crash or corrupt itself!
This is a future opportunity here to design a better interface (such as
a stateful one that avoids overflow by getting the next N detections
from source, where N is the size of indices).
In the short term, let's check that cursor is less than indices.size()
before doing the put, i.e.:
index_type cursor = 0;
for (index_type i = 0; i != source.size(); ++i)
if (source.get(i) && cursor++ < indices.size())
indices.put(cursor-1, Index<1>(i));
return cursor;
The returned value (cursor) is still the "number of non-false values in
source" (as required by the spec) and we avoid overwriting memory. A
concerned user can check if the returned value is greater than
indices.size().
> +
> +template <typename T, typename B1, typename B2>
> +length_type
> +indexbool(const_Matrix<T, B1> source, Vector<Index<2>, B2> indices)
> +{
> + index_type cursor = 0;
> + for (index_type r = 0; r != source.size(0); ++r)
> + for (index_type c = 0; c != source.size(1); ++c)
> + if (source.get(r, c))
> + indices.put(cursor++, Index<2>(r, c));
> + return cursor;
> +}
Let's do the same as above.
>
> +namespace impl
> +{
> +template <typename Tout, typename Tin1>
> +struct clip_wrapper
> +{
> + template <typename Tin0>
> + struct clip_functor
> + {
> + typedef Tout result_type;
> + result_type operator()(Tin0 t) const
> + {
> + return t <= lower_threshold ? lower_clip_value
> + : t < upper_threshold ? t
> + : upper_clip_value;
> + }
> +
> + Tin1 lower_threshold;
> + Tin1 upper_threshold;
> + result_type lower_clip_value;
> + result_type upper_clip_value;
> + };
> + template <typename Tin0>
> + struct invclip_functor
> + {
> + typedef Tout result_type;
> + result_type operator()(Tin0 t) const
> + {
> + return t < lower_threshold ? t
> + : t < middle_threshold ? lower_clip_value
> + : t <= upper_threshold ? upper_clip_value
> + : t;
> + }
> +
> + Tin1 lower_threshold;
> + Tin1 middle_threshold;
> + Tin1 upper_threshold;
> + result_type lower_clip_value;
> + result_type upper_clip_value;
> + };
> +};
> +
Why are clip_functor and invclip_functor nested in clip_wrapper? (I'm
just curious, I'm not suggesting that it should be changed)
> +
> +namespace impl
> +{
> +/// Generic swapping of the content of two blocks.
> +template <typename Block1, typename Block2>
> +struct Swap
> +{
> + static void apply(Block1 &block1, Block2 &block2)
> + {
> + assert(block1.size() == block2.size());
> + for (index_type i = 0; i != block1.size(); ++i)
> + {
> + typename Block1::value_type tmp = block1.get(i);
> + block1.put(i, block2.get(i));
> + block2.put(i, tmp);
> + }
> +
> + }
> +};
Looks good. We can plug in specializations to Swap for things like
swapping pointers (if we decide it's worth doing).
More information about the vsipl++
mailing list