From 2f47a523915bf7a76ab7d39fff1f6fc672759e77 Mon Sep 17 00:00:00 2001 From: Tim Haines Date: Thu, 19 Jul 2012 17:09:43 -0500 Subject: [PATCH] Add propagation of badflag with .= (Ops::assgn) for sf.net bug 3543056. --- Basic/Ops/ops.pd | 18 +++++++++++++++--- t/ops.t | 15 ++++++++++++++- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/Basic/Ops/ops.pd b/Basic/Ops/ops.pd index 20c387e06..d9cfcf95a 100644 --- a/Basic/Ops/ops.pd +++ b/Basic/Ops/ops.pd @@ -378,14 +378,26 @@ sub PDL::log10 { # pp_def( 'assgn', -# HandleBad => 1, + HandleBad => 1, Pars => 'a(); [o]b();', Code => '$b() = $a();', -# BadCode => -# 'if ( $ISBAD(a()) ) { $SETBAD(b()); } else { $b() = $a(); }', + BadCode => + 'if ( $ISBAD(a()) ) { $SETBAD(b()); } else { $b() = $a(); }', Doc => 'Plain numerical assignment. This is used to implement the ".=" operator', + BadDoc => +'If C is a child piddle (e.g., the result of a slice) and bad values are generated in C, +the bad value flag is set in C, but it is B automatically propagated back to the parent of C. +The following idiom ensures that the badflag is propagated back to the parent of C: + + $pdl->slice(":,(1)") .= PDL::Bad_aware_func(); + $pdl->badflag(1); + $pdl->check_badflag(); + +This is unnecessary if $pdl->badflag is known to be 1 before the slice is performed. + +See http://pdl.perl.org/PDLdocs/BadValues.html#dataflow_of_the_badflag for details.' ); # pp_def assgn #pp_export_nothing(); diff --git a/t/ops.t b/t/ops.t index a3d8fd0e2..577a1cf40 100644 --- a/t/ops.t +++ b/t/ops.t @@ -1,5 +1,6 @@ -use Test::More tests => 53; +use Test::More tests => 54; use PDL::LiteF; +use PDL::Config; kill INT,$$ if $ENV{UNDER_DEBUGGER}; # Useful for debugging. sub tapprox { @@ -173,3 +174,15 @@ $USHORT_MAX = 65535; ok byte($BYTE_MAX)%1 == 0; ok ushort($USHORT_MAX)%1 == 0; + +SKIP: { +skip 'No BADVAL', 1 if !$PDL::Config{WITH_BADVAL}; +# Check badflag propagation with .= (Ops::assgn) sf.net bug 3543056 +$a = sequence(10); +$b = sequence(5); +$b->inplace->setvaltobad(3); +$a->slice('0:4') .= $b; +$a->badflag(1); +$a->check_badflag(); +ok($a->badflag == 1 && $a->nbad == 1); +}