David, first of all thank your for your long and useful answer.
I give some comments with respect to your answers below, where I feel it may be helpful
to your understanding of my questions or that of the other list subscribers.

Louis

Quoting David Mertens <[email protected]>:

Louis -

First, from the looks of your code, your use of the cross product is
identical to a squared sum:

$result = sum(a**2);

No I think don't think so, the sum formula would result in PDL of dimension 1 by 1. Without the sum (i.e. $a**2) it would result in a every element of $a being squared, whereas transpose($a) x $a is the internal cross product and results in a square matrix of dimension n by n if $a is m by n (I think, I am still learning PDL and I am sometimes confused by the order of the dimension). Short of rewriting the matmult there is probably no substitute for the overloaded 'x' procedure. I need this product on many instances, the inverse of (transpose($a) x $a) is a fairly standard calculation which appears in the solution to sets of linear equations (among which is optimized least squares, also known as regression).


That should handle bad values just fine. You can also use sumover in place
of sum if you need to thread that over multiple dimensions. As for the code
you actually posted, you are using some slightly obfuscated code which I
believe bears some dissection. Here at least here is how I interpret it:

On Mon, Jan 2, 2012 at 8:43 AM, louis <[email protected]> wrote:

I am trying to understand how to handle BAD values, but can do with some
help. I want to know how to properly deal with this warning "WARNING:
routine does not handle bad values." Here is some sample code.

------
print (transpose($a) x $a);


This throws the warnings, right?

Yes it does throw a warning.




.
.
.



I'm not sure if you understand the return value of the following sub. You
might, but in case others miss it, I've added my understanding (but please
correct me if I'm wrong). If a function does not have an explicit return
statement, Perl returns the last executed statement. So...

sub mysub{
      my ($pdla) = @_;
      if (!$pdla->badflag()) { transpose($pdla) x $pdla;}


... if there is no bad flag, this function returns this cross product...


      else { my $pdlb=pdl(0)->inplace->setvaltobad( 0 );}


... and if there is a badflag, this function returns this value, which is
bad.


Absolutely right. Perl subs return the result of the last evaluation as a standard. So as Perl does lazy evaluation (it stops as soon as it can figure out the if clause, and never reaches the else part in this case) the else statement is not evaluated if $pdla does not have a bad flag set. If the flag is set, the last evaluation of the sub is in fact the line starting with: else { my $pdlb=pld(0)...etc... And yes, on rereading my code
it is obfuscated. Properly the lines might read:

      if (!$pdla->badflag()) { return (transpose($pdla) x $pdla);}
and
       my $pdlb;
       else { return ($pdlb=pdl(0)->inplace->setvaltobad( 0 ));}
which is what I was trying to avoid.



}
print mysub($a) ? "result is undefined\n" : "a is, $a";


Because PDL doesn't like boolean evaluations **except for single-element
piddles**, this expression will croak if $a is anything more than a
one-dimensional vector. Have you tried running that conditional when $a is
more complex? For example, if $a is a matrix, this will croak. Something I
didn't realize, but just learned messing with this, is that a single BAD
value is considered boolean false. That's more clever than I had expected.
:-)


Thanks for pointing that out it should be:
print $a->badflag() ? "result is undefined\n" : "a is, $a";
And this is Perl shorthand for a conditional statement.


------

If $a has a bad value the first line will give the correct answer with
bad values where you expect them, but gives a warning: "WARNING: routine
does not handle bad values."


For those following along, the cross product (the 'x' operator) is
PDL::matmult, defined in Basic/Primitive/primitive.pd. Craig implemented a
tiled version of that function a couple of years back (so that
multiplication of large matrices doesn't blow the processor cache). The
resulting code is a bit more complex than a naive C implementation of
matrix-matrix multiplication, and there is no BadCode section (yet?).
Anyway, the fact that BAD values show up in the right place is quite
surprising since there is no obvious reason to me why that should happen. I
would almost consider that to be a bug.


The sub will not give the warning but of course the answer is now
undefined.


No, it's a PDL with a single bad value, which evaluates to false in boolean
context. That's different from undef in some important ways. For exapmle,
if you add 1 to an undefined value, it becomes 1, but if you add 1 to a PDL
with a single bad value, its single value is still bad.


Yes, you are right, I was looking for a PDL with the bad flag set, which I understand
is not necessarily the same as a PDL with a single bad value.


1) How can I use the 'x' operator, with the correct propagation of the
bad values, but without the warning.


There is no way to avoid that warning unless you find a different
expression that does the same thing, but which handles bad values (like the
squared sum I used above). Which raises the question for PDL porters (not
for you): wouldn't it make sense if PDL created its own class of warnings
by using warnings::register? This way, users could turn off bad-value
warning messages, or even handle them with their own $SIG{__WARNING__}. For
those who care, checkout http://perldoc.perl.org/warnings.html


Thank for the link, I did not know that.


2) The line with "else { my $pdlb=pdl(0)->inplace->setvaltobad( 0 );}"
is fairly ugly, is there a shorter way to do the same?


In PDL 2.4.10, you should be able to return pdl('bad'). That's a recent
implementation of mine. :-) Alternatively, perhaps PDL should add BAD to
PDL::Constants (as well as INF, for that matter).


Neat, that was the return value I was looking for, unfortunately I run 2.4.7, so
I guess I will stick to my 'ugly' alternative.



Any help appreciated, I could not find the answer in the documentation
for PDL::Badbalues or in the PDL::Bad manpage. If avoidable I will stay
away from using the PP_def structures.


Sorry the bad docs are not very clear. I've struggled with them myself.
Thank you for reading the docs before asking your question!

Regards Louis


_______________________________________________
Perldl mailing list
[email protected]
http://mailman.jach.hawaii.edu/mailman/listinfo/perldl


Did that help?

Yes, thank you, I can proceed now. Your suggestion (to the porters) would
be a useful extension, for now I will find another way.



David

--
Sent via my carrier pigeon.





_______________________________________________
Perldl mailing list
[email protected]
http://mailman.jach.hawaii.edu/mailman/listinfo/perldl

Reply via email to