Re: [eigen] State of eigen support for small integers(16 bit, signed/unsigned)

[ Thread Index | Date Index | More Archives ]

OK, let me try to put all my answers in 1 mail:

2009/8/20 Rohit Garg <rpg.314@xxxxxxxxx>:
> I have been adding stuff for both short and unsigned short so far.
> Mainly because I need right shifts for unsigned shorts, which are
> logical bit shifts, instead of algebraic bit shifts. I turns out that
> there are a few missing intrinsics in sse2, as usual, for signed and
> unsigned stuff. So it will perhaps be easier to just do short instead
> of unsigned short too. There is no unsigned int in eigen for instance.

Feel free to add unsigned int! So far we had no use for it. but I
understand that as one works with shorter int types, the benefit of
unsigned gets bigger, so there's a need for uint8 and uint16, and then
for consistency it makes sense to add uint32.

Especially if you start a new module SmallIntegers, it really doesn't
hurt to add more types.

> But since I need, unsigned shorts, I propose, that we offer both
> algebraic, logical bit shifting as a template parameter option.
> Comments?

I dont have an opinion as I didnt think much about it, just go ahead
with your plans, he who codes decides :)

> Yes, int and short do share an sse type. :(
> Now what?

Now I can see 2 options.

a) you make the packet types like Packet4f be structs containing a
typedef to the standard SSE type --- instead of being that typedef
themselves. In this way, you make sure that they are treated as
different types even if the underlying SSE type is the same.


b) you rework our design here, ei_unpacket_traits doesnt work so you
come up with a design to do without it. That would mean that the
functions that are template only in the packet type and then use
ei_unpacket_traits to find back the scalar type, should be modified to
be template in the scalar type and use ei_packet_traits to find the
packet type.

Perhaps try b first (just my gut feeling) and fall back to a if it
gets too cumbersome.

>There is a Functors.h in both array and core. I looked at both. The
>array one provides a EIGEN_FUNCTOR_PLUGIN. But I dont know how to put
>it to use. Suggestions?

at the moment it escapes me why EIGEN_FUNCTOR_PLUGIN is needed and i
don't understand the comment there anymore :(

Let's explain.

Binary shifting is an operation that applies to every coeff of a
single matrix. That is what we call a "coefficient-wise unary
operation". Since such expressions share a lot of generic code, we
unified them in a CwiseUnaryOp class. See Core/CwiseUnaryOp.h. That
class is template in the matrix type (to which the operation is
applied) and also in another type describing the operation : that is
called the functor type. Whenever you want to add another such
operation, all you need to do is:
1) add the corresponding functor
2) add a specialization of ei_functor_traits for this functor
3) expose this operation in class MatrixBase or in class Cwise (the
latter means that the user will have to write .cwise() to use your
operation: in your case, I think that's what we want)

Here's an example. Let's look at the implementation between .cwise().abs().

Go to Core/Functors.h line 164:

/** \internal
  * \brief Template functor to compute the absolute value of a scalar
  * \sa class CwiseUnaryOp, Cwise::abs
template<typename Scalar> struct ei_scalar_abs_op EIGEN_EMPTY_STRUCT {
  typedef typename NumTraits<Scalar>::Real result_type;
  EIGEN_STRONG_INLINE const result_type operator() (const Scalar& a)
const { return ei_abs(a); }
template<typename Scalar>
struct ei_functor_traits<ei_scalar_abs_op<Scalar> >
  enum {
    Cost = NumTraits<Scalar>::AddCost,
    PacketAccess = false // this could actually be vectorized with SSSE3.

as you can see we define the functor class ei_scalar_abs_op, it
contains 2 informations: the result type, and an operator() doing the
computation, making objects of this class behave like functions --
whence the name functor. Note the EIGEN_EMPTY_STRUCT, it helps some
compiler generate better code by adding a dummy member. Then comes the
specialization of ei_functor_traits, where we give a rough estimate of
the cost of the operation, and we tell whether the operation could be

Note that if the operation could be vectorized, the functor should
provide a packetOp() method. Here's an example, line 30 in the same

/** \internal
  * \brief Template functor to compute the sum of two scalars
  * \sa class CwiseBinaryOp, MatrixBase::operator+, class
PartialRedux, MatrixBase::sum()
template<typename Scalar> struct ei_scalar_sum_op EIGEN_EMPTY_STRUCT {
  EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a, const
Scalar& b) const { return a + b; }
  template<typename PacketScalar>
  EIGEN_STRONG_INLINE const PacketScalar packetOp(const PacketScalar&
a, const PacketScalar& b) const
  { return ei_padd(a,b); }
template<typename Scalar>
struct ei_functor_traits<ei_scalar_sum_op<Scalar> > {
  enum {
    Cost = NumTraits<Scalar>::AddCost,
    PacketAccess = ei_packet_traits<Scalar>::size>1

Here we say that there is "packet access" i.e. vectorizability if the
scalar type has the property that packets contain more than one
scalar. That's a standard way of saying whether a scalar type is

Notice how the packetOp method is templated in the packet type! That's
a little discrepancy with the operator(), i admit.

OK, then how is this exposed in the API ? Go to Core/CwiseUnaryOp.h line 130:

/** \returns an expression of the coefficient-wise absolute value of \c *this
  * Example: \include Cwise_abs.cpp
  * Output: \verbinclude Cwise_abs.out
  * \sa abs2()
template<typename ExpressionType>
Cwise<ExpressionType>::abs() const
  return _expression();

so this is a method in class Cwise, in practice the user constructs an
object of class Cwise by calling .cwise(), that's why the resulting
API is .cwise().abs().

> I am through modding Numtraits.h, MathFunctions .h to add shorts. In
> the PacketMath.h there are these 3 functions whose purpose I did not
> understand.
> ei_palign_impl
> ei_preduxp
> ei_predux

Have a look at Core/GenericPacketMath.h, this is where all the comments are ;)


Mail converted by MHonArc 2.6.19+