Re: [eigen] Sign function

[ Thread Index | Date Index | More Archives ]

Hi, sorry for re-opening this old thread *g*

On 08.12.2012 14:08, Gael Guennebaud wrote:
You can do something like:

A += (B.array()>0).select(MatType::Constant(k),-k);

Unfortunately the following cannot work because we have to know the matrix
type returned by select from at least one of its arguments:

A += (B.array()>0).select(k,-k);

I would have expected this to be an array, since (B.array()>0) is an array expression. Actually, I don't see many cases where select() actually makes sense with matrix-expressions as select itself is a component-wise, i.e. array-expression. Of course, there are cases where you want to convert arrays to matrices and back, and you could still do, -k).matrix() if you need it.

Another thing: I guess what Carlos actually needs is a copysign function, which could be implemented with pure bitwise operations

A(i)+= copysign(k, B(i));
// or
A(i)+= k | (B(i) & -0.0); // for positive k, otherwise (k & ~(-0.0)),
                          // which if k is known can be optimized away.

i.e. sth like this using Eigens packet operators:
padd(A.packet(i), por(pset1(k), pand(B.packet(i), pset1(-0.0)));

If you really want k*sign(B), that would be k ^ (B(i) & -0.0).
The only difference compared to the select method is different handling of NaNs and distinguishing between +0.0 and -0.0; and, afaik, CMPccPS/D has a rather high latency compared to simple bit operations (however, in this simple case memory-throughput might be the bottle-neck anyways).


You can also use B.unaryExpr(std::ptr_fun(sign)) to reproduce "sign(B)".


On Sat, Dec 8, 2012 at 12:26 PM, Carlos Becker <carlosbecker@xxxxxxxxx>wrote:

Hello everyone,

I am wondering which would be the fast way to compute the sign of every
element in a vector or matrix, since I have to do the following

A = A + k * sign(B)

where A and B are double matrices and k is a scalar.

I was trying to find some information in the docs but so far I didn't
I know I can do a boolean operation and then cast to double, multiply by 2
and subtract 1, but that doesn't seem very efficient.

Maybe some kind of custom element-wise processing, since it would be
enough to compute the sign and then add k or -k to each element of A ?


Dipl.-Inf., Dipl.-Math. Christoph Hertzberg
Cartesium 0.049
Universität Bremen
Enrique-Schmidt-Straße 5
28359 Bremen

Tel: +49 (421) 218-64252

Mail converted by MHonArc 2.6.19+