Skip to content

Commit d279bb7

Browse files
committed
badflag now not propagated back to inputs if set on outputs - #517
1 parent 5e88f37 commit d279bb7

File tree

7 files changed

+45
-27
lines changed

7 files changed

+45
-27
lines changed

Changes

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
- add Ops::csqrt{,_up} (#524) - thanks @wlmb
2525
- Core::upd_data now sets DATACHANGED so will work for flowing ops
2626
- remove CopyBadStatusCode key from PP (#517)
27+
- badflag now not propagated back to inputs if set on outputs (#517)
2728

2829
2.098 2025-01-03
2930
- fix Windows build problems

lib/PDL/Bad.pd

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -820,9 +820,7 @@ EOF
820820
$GENERIC(b) a_val = $a();
821821
$b() = PDL_IF_BAD($ISBADVAR(a_val,a) ? replace : ,) a_val;
822822
%}
823-
char input_was_bad = !!$PDLSTATEISBAD(a);
824-
PDL->propagate_badflag( $PDL(b), 0 ); /* always make sure the output is "good" */
825-
if (input_was_bad && $PDL(a) != $PDL(b)) $PDLSTATESETBAD(a);
823+
PDL->propagate_badflag_dir($PDL(b), 0, 1, 1); /* always make sure the output is "good" */
826824
},
827825
NewXSFindBadStatusNS => <<'EOF',
828826
PDL_RETERROR(PDL_err, PDL->trans_check_pdls(__privtrans));

lib/PDL/Core.xs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1171,8 +1171,11 @@ badflag(x,newval=0)
11711171
pdl *x
11721172
int newval
11731173
CODE:
1174-
if (items>1)
1175-
pdl_propagate_badflag( x, newval );
1174+
if (items>1) {
1175+
if (x->trans_parent)
1176+
pdl_propagate_badflag_dir(x, newval, 0, 1);
1177+
pdl_propagate_badflag_dir(x, newval, 1, 1);
1178+
}
11761179
RETVAL = ((x->state & PDL_BADVAL) > 0);
11771180
OUTPUT:
11781181
RETVAL

lib/PDL/Core/pdlapi.c

Lines changed: 34 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ extern Core PDL; /* for PDL_TYPENAME */
2424
PDLDEBUG_f(printf("VTOD " #func " child=%p turning off datachanged, before=", child); pdl_dump_flags_fixspace(child->state, 0, PDL_FLAGS_PDL)); \
2525
if (is_fwd) child->state &= ~PDL_PARENTDATACHANGED; \
2626
if (child && (child->state & PDL_BADVAL)) \
27-
pdl_propagate_badflag(child, !!(child->state & PDL_BADVAL)); \
27+
pdl_propagate_badflag_dir(child, !!(child->state & PDL_BADVAL), is_fwd, 1); \
2828
} \
2929
} while (0)
3030
#define READDATA(trans) VTABLE_OR_DEFAULT(PDL_ACCUMERROR, trans, 1, readdata, readdata_affine)
@@ -1029,30 +1029,45 @@ pdl_error pdl_sever(pdl *src)
10291029
return PDL_err;
10301030
}
10311031

1032-
#define PDL_MAYBE_PROPAGATE_BADFLAG(t, newval) \
1033-
for ( i = 0; i < (t)->vtable->npdls; i++ ) { \
1034-
pdl *tpdl = (t)->pdls[i]; \
1035-
/* make sure we propagate if changed */ \
1036-
if (!!newval != !!(tpdl->state & PDL_BADVAL)) \
1037-
pdl_propagate_badflag( tpdl, newval ); \
1038-
}
1039-
1032+
#define PDL_MAYBE_PROPAGATE_BADFLAG(t, newval, is_fwd) do { \
1033+
pdl_transvtable *vtable = (t)->vtable; \
1034+
PDL_Indx i, istart = is_fwd ? vtable->nparents : 0, iend = is_fwd ? vtable->npdls : vtable->nparents; \
1035+
for (i = istart; i < iend; i++) { \
1036+
pdl *tpdl = (t)->pdls[i]; \
1037+
/* make sure we propagate if changed */ \
1038+
if (!!newval != !!(tpdl->state & PDL_BADVAL)) \
1039+
pdl_propagate_badflag_dir(tpdl, newval, is_fwd, recurse_count + 1); \
1040+
} \
1041+
} while (0)
10401042
/* newval = 1 means set flag, 0 means clear it */
1041-
void pdl_propagate_badflag( pdl *it, int newval ) {
1042-
PDLDEBUG_f(printf("pdl_propagate_badflag pdl=%p newval=%d\n", it, newval));
1043-
PDL_Indx i, j;
1044-
if (newval)
1045-
it->state |= PDL_BADVAL;
1046-
else
1047-
it->state &= ~PDL_BADVAL;
1043+
pdl_error pdl_propagate_badflag_dir(pdl *it, int newval, char is_fwd, int recurse_count) {
1044+
PDL_RECURSE_CHECK(recurse_count);
1045+
PDLDEBUG_f(printf("pdl_propagate_badflag_dir pdl=%p newval=%d is_fwd=%d\n", it, newval, (int)is_fwd));
1046+
pdl_error PDL_err = {0, NULL, 0};
1047+
if (newval)
1048+
it->state |= PDL_BADVAL;
1049+
else
1050+
it->state &= ~PDL_BADVAL;
1051+
if (!is_fwd) {
10481052
if (it->trans_parent)
1049-
PDL_MAYBE_PROPAGATE_BADFLAG(it->trans_parent, newval)
1053+
PDL_MAYBE_PROPAGATE_BADFLAG(it->trans_parent, newval, 0);
1054+
} else {
1055+
PDL_Indx j;
1056+
if (
1057+
(it->state & (PDL_OPT_VAFFTRANSOK|PDL_ALLOCATED)) == PDL_OPT_VAFFTRANSOK && /* pure vaff */
1058+
newval /* expansive - if slice gets badflag, whole does */
1059+
)
1060+
pdl_propagate_badflag_dir(it->vafftrans->from, newval, 1, recurse_count + 1);
10501061
for (j = 0; j < it->ntrans_children_allocated; j++) {
10511062
pdl_trans *trans = it->trans_children[j];
10521063
if (!trans) continue;
1053-
trans->bvalflag = !!newval;
1054-
PDL_MAYBE_PROPAGATE_BADFLAG(trans, newval)
1064+
PDL_MAYBE_PROPAGATE_BADFLAG(trans, newval, 1);
10551065
}
1066+
}
1067+
return PDL_err;
1068+
}
1069+
void pdl_propagate_badflag(pdl *it, int newval) { /* CORE21 get rid */
1070+
return; /* nerfed as replaced with directional version */
10561071
}
10571072

10581073
/*CORE21 use pdl_error, replace fprintf*/

lib/PDL/Core/pdlcore.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,7 @@ void pdl_dump_anyval(PDL_Anyval v);
159159
X(unpackpdls, SV*, ( pdl **, PDL_Indx npdls )) \
160160
X(packstrings, char **, ( SV* sv, PDL_Indx *nstrings )) \
161161
X(prealloc_trans_children, pdl_error, (pdl *it, PDL_Indx howmany)) \
162+
X(propagate_badflag_dir, pdl_error, (pdl *it, int newval, char is_fwd, int recurse_count)) \
162163

163164
/*************** Function prototypes *********************/
164165
#define X(sym, rettype, args) \

lib/PDL/Ops.pd

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -371,8 +371,8 @@ pp_def(
371371
Code => pp_line_numbers(__LINE__-1, q{
372372
PDL_IF_BAD(char anybad = 0;,)
373373
broadcastloop %{
374-
PDL_IF_BAD(if ( $ISBAD(a()) ) { anybad = 1; $SETBAD(b()); } else,)
375-
$b() = $a();
374+
PDL_IF_BAD(if ($ISBAD(a())) { anybad = 1; $SETBAD(b()); continue; },)
375+
$b() = $a();
376376
%}
377377
PDL_IF_BAD(if (anybad) $PDLSTATESETBAD(b);,)
378378
}),

t/bad.t

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ is_pdl $s[2], pdl(66.5), "setbadif/stats test 3";
184184
is_pdl $s[3], pdl(22), "setbadif/stats test 4";
185185
is_pdl $s[4], pdl(98), "setbadif/stats test 5";
186186
is_pdl $s[6], pdl(26.7312), abstol("setbadif/stats test 6");
187-
ok $x->badflag, 'badflag wrongly set on input after setbadif';
187+
ok !$x->badflag, 'badflag not set on input after setbadif';
188188

189189
# how about setbadtoval
190190
empty()->setbadtoval(20); # shouldn't segfault

0 commit comments

Comments
 (0)