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