1BADVALUES(1)          User Contributed Perl Documentation         BADVALUES(1)
2
3
4

NAME

6       PDL::BadValues - Discussion of bad value support in PDL
7

DESCRIPTION

9   What are bad values and why should I bother with them?
10       Sometimes it's useful to be able to specify a certain value is 'bad' or
11       'missing'; for example CCDs used in astronomy produce 2D images which
12       are not perfect since certain areas contain invalid data due to
13       imperfections in the detector.  Whilst PDL's powerful index routines
14       and all the complicated business with dataflow, slices, etc etc mean
15       that these regions can be ignored in processing, it's awkward to do. It
16       would be much easier to be able to say "$c = $x + $y" and leave all the
17       hassle to the computer.
18
19       If you're not interested in this, then you may (rightly) be concerned
20       with how this affects the speed of PDL, since the overhead of checking
21       for a bad value at each operation can be large.  Because of this, the
22       code has been written to be as fast as possible - particularly when
23       operating on piddles which do not contain bad values.  In fact, you
24       should notice essentially no speed difference when working with piddles
25       which do not contain bad values.
26
27       However, if you do not want bad values, then PDL's "WITH_BADVAL"
28       configuration option comes to the rescue; if set to 0 or undef, the
29       bad-value support is ignored.  About the only time I think you'll need
30       to use this - I admit, I'm biased ;) - is if you have limited disk or
31       memory space, since the size of the code is increased (see below).
32
33       You may also ask 'well, my computer supports IEEE NaN, so I already
34       have this'.  Well, yes and no - many routines, such as "y=sin(x)", will
35       propagate NaN's without the user having to code differently, but
36       routines such as "qsort", or finding the median of an array, need to be
37       re-coded to handle bad values.  For floating-point datatypes, "NaN" and
38       "Inf" are used to flag bad values IF the option "BADVAL_USENAN" is set
39       to 1 in your config file.  Otherwise special values are used (Default
40       bad values).  I do not have any benchmarks to see which option is
41       faster.
42
43       There is an experimental feature "BADVAL_PER_PDL" which, if set, allows
44       you to have different bad values for separate piddles of the same type.
45       This currently does not work with the "BADVAL_USENAN" option; if both
46       are set then PDL will ignore the "BADVAL_USENAN" value.
47
48   Code increase due to bad values
49       The following comparison is out of date!
50
51       On an i386 machine running Linux and Perl 5.005_03, I measured the
52       following sizes (the Slatec code was compiled in, but none of the other
53       options: e.g., FFTW, GSL, and TriD were):
54
55       WITH_BADVAL = 0
56           Size of blib directory after a successful make = 4963 kb: blib/arch
57           = 2485 kb and blib/lib = 1587 kb.
58
59       WITH_BADVAL = 1
60           Size of blib directory after a successful make = 5723 kb: blib/arch
61           = 3178 kb and blib/lib = 1613 kb.
62
63       So, the overall increase is only 15% - not much to pay for all the
64       wonders that bad values provides ;)
65
66       The source code used for this test had the vast majority of the core
67       routines (eg those in Basic/) converted to use bad values, whilst very
68       few of the 'external' routines (i.e. everything else in the PDL
69       distribution) had been changed.
70
71   A quick overview
72        pdl> p $PDL::Bad::Status
73        1
74        pdl> $x = sequence(4,3);
75        pdl> p $x
76        [
77         [ 0  1  2  3]
78         [ 4  5  6  7]
79         [ 8  9 10 11]
80        ]
81        pdl> $x = $x->setbadif( $x % 3 == 2 )
82        pdl> p $x
83        [
84         [  0   1 BAD   3]
85         [  4 BAD   6   7]
86         [BAD   9  10 BAD]
87        ]
88        pdl> $x *= 3
89        pdl> p $x
90        [
91         [  0   3 BAD   9]
92         [ 12 BAD  18  21]
93         [BAD  27  30 BAD]
94        ]
95        pdl> p $x->sum
96        120
97
98       "demo bad" and "demo bad2" within perldl or pdl2 gives a demonstration
99       of some of the things possible with bad values.  These are also
100       available on PDL's web-site, at http://pdl.perl.org/demos/.  See
101       PDL::Bad for useful routines for working with bad values and t/bad.t to
102       see them in action.
103
104       The intention is to:
105
106       •   not significantly affect PDL for users who don't need bad value
107           support
108
109       •   be as fast as possible when bad value support is installed
110
111       If you never want bad value support, then you set "WITH_BADVAL" to 0 in
112       perldl.conf; PDL then has no bad value support compiled in, so will be
113       as fast as it used to be.
114
115       However, in most cases, the bad value support has a negligible affect
116       on speed, so you should set "WITH_CONFIG" to 1! One exception is if you
117       are low on memory, since the amount of code produced is larger (but
118       only by about 15% - see "Code increase due to bad values").
119
120       To find out if PDL has been compiled with bad value support, look at
121       the values of either $PDL::Config{WITH_BADVAL} or $PDL::Bad::Status -
122       if true then it has been.
123
124       To find out if a routine supports bad values, use the "badinfo" command
125       in perldl or pdl2 or the "-b" option to pdldoc.  This facility is
126       currently a 'proof of concept' (or, more realistically, a quick hack)
127       so expect it to be rough around the edges.
128
129       Each piddle contains a flag - accessible via "$pdl->badflag" - to say
130       whether there's any bad data present:
131
132       •   If false/0, which means there's no bad data here, the code supplied
133           by the "Code" option to "pp_def()" is executed. This means that the
134           speed should be very close to that obtained with "WITH_BADVAL=0",
135           since the only overhead is several accesses to a bit in the piddles
136           state variable.
137
138       •   If true/1, then this says there MAY be bad data in the piddle, so
139           use the code in the "BadCode" option (assuming that the "pp_def()"
140           for this routine has been updated to have a BadCode key).  You get
141           all the advantages of threading, as with the "Code" option, but it
142           will run slower since you are going to have to handle the presence
143           of bad values.
144
145       If you create a piddle, it will have its bad-value flag set to 0. To
146       change this, use "$pdl->badflag($new_bad_status)", where
147       $new_bad_status can be 0 or 1.  When a routine creates a piddle, its
148       bad-value flag will depend on the input piddles: unless over-ridden
149       (see the "CopyBadStatusCode" option to "pp_def"), the bad-value flag
150       will be set true if any of the input piddles contain bad values.  To
151       check that a piddle really contains bad data, use the "check_badflag"
152       method.
153
154       NOTE: propagation of the badflag
155
156       If you change the badflag of a piddle, this change is propagated to all
157       the children of a piddle, so
158
159          pdl> $x = zeroes(20,30);
160          pdl> $y = $x->slice('0:10,0:10');
161          pdl> $c = $y->slice(',(2)');
162          pdl> print ">>c: ", $c->badflag, "\n";
163          >>c: 0
164          pdl> $x->badflag(1);
165          pdl> print ">>c: ", $c->badflag, "\n";
166          >>c: 1
167
168       No change is made to the parents of a piddle, so
169
170          pdl> print ">>a: ", $x->badflag, "\n";
171          >>a: 1
172          pdl> $c->badflag(0);
173          pdl> print ">>a: ", $x->badflag, "\n";
174          >>a: 1
175
176       Thoughts:
177
178       •   the badflag can ONLY be cleared IF a piddle has NO parents, and
179           that this change will propagate to all the children of that piddle.
180           I am not so keen on this anymore (too awkward to code, for one).
181
182       •   "$x->badflag(1)" should propagate the badflag to BOTH parents and
183           children.
184
185       This shouldn't be hard to implement (although an initial attempt
186       failed!).  Does it make sense though? There's also the issue of what
187       happens if you change the badvalue of a piddle - should these propagate
188       to children/parents (yes) or whether you should only be able to change
189       the badvalue at the 'top' level - i.e. those piddles which do not have
190       parents.
191
192       The "orig_badvalue()" method returns the compile-time value for a given
193       datatype. It works on piddles, PDL::Type objects, and numbers - eg
194
195         $pdl->orig_badvalue(), byte->orig_badvalue(), and orig_badvalue(4).
196
197       It also has a horrible name...
198
199       To get the current bad value, use the "badvalue()" method - it has the
200       same syntax as "orig_badvalue()".
201
202       To change the current bad value, supply the new number to badvalue - eg
203
204         $pdl->badvalue(2.3), byte->badvalue(2), badvalue(5,-3e34).
205
206       Note: the value is silently converted to the correct C type, and
207       returned - i.e. "byte->badvalue(-26)" returns 230 on my Linux machine.
208       It is also a "nop" for floating-point types when "BADVAL_USENAN" is
209       true.
210
211       Note that changes to the bad value are NOT propagated to previously-
212       created piddles - they will still have the bad value set, but suddenly
213       the elements that were bad will become 'good', but containing the old
214       bad value.  See discussion below.  It's not a problem for floating-
215       point types which use NaN, since you can not change their badvalue.
216
217   Bad values and boolean operators
218       For those boolean operators in PDL::Ops, evaluation on a bad value
219       returns the bad value.  Whilst this means that
220
221        $mask = $img > $thresh;
222
223       correctly propagates bad values, it will cause problems for checks such
224       as
225
226        do_something() if any( $img > $thresh );
227
228       which need to be re-written as something like
229
230        do_something() if any( setbadtoval( ($img > $thresh), 0 ) );
231
232       When using one of the 'projection' functions in PDL::Ufunc - such as
233       orover - bad values are skipped over (see the documentation of these
234       functions for the current (poor) handling of the case when all elements
235       are bad).
236
237   A bad value for each piddle, and related issues
238       An experimental option "BADVAL_PER_PDL" has been added to perldl.conf
239       to allow per-piddle bad values. The documentation has not been updated
240       to account for this change.
241
242       The following is relevant only for integer types, and for floating-
243       point types if "BADVAL_USENAN" was not set when PDL was built.
244
245       Currently, there is one bad value for each datatype. The code is
246       written so that we could have a separate bad value for each piddle
247       (stored in the pdl structure) - this would then remove the current
248       problem of:
249
250        pdl> $x = byte( 1, 2, byte->badvalue, 4, 5 );
251        pdl> p $x;
252        [1 2 255 4 5]
253        pdl> $x->badflag(1)
254        pdl> p $x;
255        [1 2 BAD 4 5]
256        pdl> byte->badvalue(0);
257        pdl> p $x;
258        [1 2 255 4 5]
259
260       ie the bad value in $a has lost its bad status using the current
261       implementation.  It would almost certainly cause problems elsewhere
262       though!
263

IMPLEMENTATION DETAILS

265       PDL code just needs to access the %PDL::Config array (e.g.
266       Basic/Bad/bad.pd) to find out whether bad-value support is required.
267
268       A new flag has been added to the state of a piddle - "PDL_BADVAL". If
269       unset, then the piddle does not contain bad values, and so all the
270       support code can be ignored. If set, it does not guarantee that bad
271       values are present, just that they should be checked for. Thanks to
272       Christian, "badflag()" - which sets/clears this flag (see
273       Basic/Bad/bad.pd) - will update ALL the children/grandchildren/etc of a
274       piddle if its state changes (see "badflag" in Basic/Bad/bad.pd and
275       "propagate_badflag" in Basic/Core/Core.xs.PL).  It's not clear what to
276       do with parents: I can see the reason for propagating a 'set badflag'
277       request to parents, but I think a child should NOT be able to clear the
278       badflag of a parent.  There's also the issue of what happens when you
279       change the bad value for a piddle.
280
281       The "pdl_trans" structure has been extended to include an integer
282       value, "bvalflag", which acts as a switch to tell the code whether to
283       handle bad values or not. This value is set if any of the input piddles
284       have their "PDL_BADVAL" flag set (although this code can be replaced by
285       setting "FindBadStateCode" in pp_def).  The logic of the check is going
286       to get a tad more complicated if I allow routines to fall back to using
287       the "Code" section for floating-point types (i.e. those routines with
288       "NoBadifNaN => 1" when "BADVAL_USENAN" is true).
289
290       The bad values for the integer types are now stored in a structure
291       within the Core PDL structure - "PDL.bvals" (eg
292       Basic/Core/pdlcore.h.PL); see also "typedef badvals" in
293       Basic/Core/pdl.h.PL and the BOOT code of Basic/Core/Core.xs.PL where
294       the values are initialised to (hopefully) sensible values.  See
295       PDL/Bad/bad.pd for read/write routines to the values.
296
297       The addition of the "BADVAL_PER_PDL" option has resulted in additional
298       changes to the internals of piddles. These changes are not documented
299       yet.
300
301   Why not make a PDL subclass?
302       The support for bad values could have been done as a PDL sub-class.
303       The advantage of this approach would be that you only load in the code
304       to handle bad values if you actually want to use them.  The downside is
305       that the code then gets separated: any bug fixes/improvements have to
306       be done to the code in two different files.  With the present approach
307       the code is in the same "pp_def" function (although there is still the
308       problem that both "Code" and "BadCode" sections need updating).
309
310   Default bad values
311       The default/original bad values are set to (taken from the Starlink
312       distribution):
313
314         #include <limits.h>
315
316         PDL_Byte    ==  UCHAR_MAX
317         PDL_Short   ==   SHRT_MIN
318         PDL_Ushort  ==  USHRT_MAX
319         PDL_Long    ==    INT_MIN
320
321       If "BADVAL_USENAN == 0", then we also have
322
323         PDL_Float   ==   -FLT_MAX
324         PDL_Double  ==   -DBL_MAX
325
326       otherwise all of "NaN", "+Inf", and "-Inf" are taken to be bad for
327       floating-point types.  In this case, the bad value can't be changed,
328       unlike the integer types.
329
330   How do I change a routine to handle bad values?
331       Examples can be found in most of the *.pd files in Basic/ (and
332       hopefully many more places soon!).  Some of the logic might appear a
333       bit unclear - that's probably because it is! Comments appreciated.
334
335       All routines should automatically propagate the bad status flag to
336       output piddles, unless you declare otherwise.
337
338       If a routine explicitly deals with bad values, you must provide this
339       option to pp_def:
340
341          HandleBad => 1
342
343       This ensures that the correct variables are initialised for the $ISBAD
344       etc macros. It is also used by the automatic document-creation routines
345       to provide default information on the bad value support of a routine
346       without the user having to type it themselves (this is in its early
347       stages).
348
349       To flag a routine as NOT handling bad values, use
350
351          HandleBad => 0
352
353       This should cause the routine to print a warning if it's sent any
354       piddles with the bad flag set. Primitive's "intover" has had this set -
355       since it would be awkward to convert - but I've not tried it out to see
356       if it works.
357
358       If you want to handle bad values but not set the state of all the
359       output piddles, or if it's only one input piddle that's important, then
360       look at the PP rules "NewXSFindBadStatus" and "NewXSCopyBadStatus" and
361       the corresponding "pp_def" options:
362
363       FindBadStatusCode
364           By default, "FindBadStatusCode" creates code which sets
365           "$PRIV(bvalflag)" depending on the state of the bad flag of the
366           input piddles: see "findbadstatus" in Basic/Gen/PP.pm.  User-
367           defined code should also store the value of "bvalflag" in the
368           "$BADFLAGCACHE()" variable.
369
370       CopyBadStatusCode
371           The default code here is a bit simpler than for
372           "FindBadStatusCode": the bad flag of the output piddles are set if
373           "$BADFLAGCACHE()" is true after the code has been evaluated.
374           Sometimes "CopyBadStatusCode" is set to an empty string, with the
375           responsibility of setting the badflag of the output piddle left to
376           the "BadCode" section (e.g. the "xxxover" routines in
377           Basic/Primitive/primitive.pd).
378
379           Prior to PDL 2.4.3 we used "$PRIV(bvalflag)" instead of
380           "$BADFLAGCACHE()". This is dangerous since the "$PRIV()" structure
381           is not guaranteed to be valid at this point in the code.
382
383       If you have a routine that you want to be able to use as in-place, look
384       at the routines in bad.pd (or ops.pd) which use the "in-place" option
385       to see how the bad flag is propagated to children using the
386       "xxxBadStatusCode" options.  I decided not to automate this as rules
387       would be a little complex, since not every in-place op will need to
388       propagate the badflag (eg unary functions).
389
390       If the option
391
392          HandleBad => 1
393
394       is given, then many things happen.  For integer types, the readdata
395       code automatically creates a variable called "<pdl name>_badval", which
396       contains the bad value for that piddle (see "get_xsdatapdecl()" in
397       Basic/Gen/PP/PdlParObjs.pm).  However, do not hard code this name into
398       your code!  Instead use macros (thanks to Tuomas for the suggestion):
399
400         '$ISBAD(a(n=>1))'  expands to '$a(n=>1) == a_badval'
401         '$ISGOOD(a())'                '$a()     != a_badval'
402         '$SETBAD(bob())'              '$bob()    = bob_badval'
403
404       well, the "$a(...)" is expanded as well. Also, you can use a "$" before
405       the pdl name, if you so wish, but it begins to look like line noise -
406       eg "$ISGOOD($a())".
407
408       If you cache a piddle value in a variable -- eg "index" in slices.pd --
409       the following routines are useful:
410
411          '$ISBADVAR(c_var,pdl)'       'c_var == pdl_badval'
412          '$ISGOODVAR(c_var,pdl)'      'c_var != pdl_badval'
413          '$SETBADVAR(c_var,pdl)'      'c_var  = pdl_badval'
414
415       The following have been introduced, They may need playing around with
416       to improve their use.
417
418         '$PPISBAD(CHILD,[i])          'CHILD_physdatap[i] == CHILD_badval'
419         '$PPISGOOD(CHILD,[i])         'CHILD_physdatap[i] != CHILD_badval'
420         '$PPSETBAD(CHILD,[i])         'CHILD_physdatap[i]  = CHILD_badval'
421
422       If "BADVAL_USENAN" is set, then it's a bit different for "float" and
423       "double", where we consider "NaN", "+Inf", and "-Inf" all to be bad. In
424       this case:
425
426         ISBAD   becomes   finite(piddle) == 0
427         ISGOOD            finite(piddle) != 0
428         SETBAD            piddle          = NaN
429
430       where the value for NaN is discussed below in Handling NaN values.
431
432       This all means that you can change
433
434          Code => '$a() = $b() + $c();'
435
436       to
437
438          BadCode => 'if ( $ISBAD(b()) || $ISBAD(c()) ) {
439                        $SETBAD(a());
440                      } else {
441                        $a() = $b() + $c();
442                      }'
443
444       leaving Code as it is. PP::PDLCode will then create a loop something
445       like
446
447          if ( __trans->bvalflag ) {
448               threadloop over BadCode
449          } else {
450               threadloop over Code
451          }
452
453       (it's probably easier to just look at the .xs file to see what goes
454       on).
455
456   Going beyond the Code section
457       Similar to "BadCode", there's "BadBackCode", and "BadRedoDimsCode".
458
459       Handling "EquivCPOffsCode" is a bit different: under the assumption
460       that the only access to data is via the "$EQUIVCPOFFS(i,j)" macro, then
461       we can automatically create the 'bad' version of it; see the
462       "[EquivCPOffsCode]" and "[Code]" rules in PDL::PP.
463
464   Macro access to the bad flag of a piddle
465       Macros have been provided to provide access to the bad-flag status of a
466       pdl:
467
468         '$PDLSTATEISBAD(a)'    -> '($PDL(a)->state & PDL_BADVAL) > 0'
469         '$PDLSTATEISGOOD(a)'      '($PDL(a)->state & PDL_BADVAL) == 0'
470
471         '$PDLSTATESETBAD(a)'      '$PDL(a)->state |= PDL_BADVAL'
472         '$PDLSTATESETGOOD(a)'     '$PDL(a)->state &= ~PDL_BADVAL'
473
474       For use in "xxxxBadStatusCode" (+ other stuff that goes into the INIT:
475       section) there are:
476
477         '$SETPDLSTATEBAD(a)'       -> 'a->state |= PDL_BADVAL'
478         '$SETPDLSTATEGOOD(a)'      -> 'a->state &= ~PDL_BADVAL'
479
480         '$ISPDLSTATEBAD(a)'        -> '((a->state & PDL_BADVAL) > 0)'
481         '$ISPDLSTATEGOOD(a)'       -> '((a->state & PDL_BADVAL) == 0)'
482
483       In PDL 2.4.3 the "$BADFLAGCACHE()" macro was introduced for use in
484       "FindBadStatusCode" and "CopyBadStatusCode".
485
486   Handling NaN values
487       There are two issues:
488
489       NaN as the bad value
490           which is done.  To select, set "BADVAL_USENAN" to 1 in perldl.conf;
491           a value of 0 falls back to treating the floating-point types the
492           same as the integers.  I need to do some benchmarks to see which is
493           faster, and whether it's dependent on machines (Linux seems to slow
494           down much more than my Sparc machine in some very simple tests I
495           did).
496
497       Ignoring BadCode sections
498           which is not.
499
500       For simple routines processing floating-point numbers, we should let
501       the computer process the bad values (i.e. "NaN" and "Inf" values)
502       instead of using the code in the "BadCode" section.  Many such routines
503       have been labeled using "NoBadifNaN => 1"; however this is currently
504       ignored by PDL::PP.
505
506       For these routines, we want to use the "Code" section if
507
508         the piddle does not have its bad flag set
509         the datatype is a float or double
510
511       otherwise we use the "BadCode" section.  This is NOT IMPLEMENTED, as it
512       will require reasonable hacking of PP::PDLCode!
513
514       There's also the problem of how we handle 'exceptions' - since "$x =
515       pdl(2) / pdl(0)" produces a bad value but doesn't update the badflag
516       value of the piddle.  Can we catch an exception, or do we have to trap
517       for this (e.g. search for "exception" in Basic/Ops/ops.pd)?
518
519       Checking for "Nan", and "Inf" is done by using the "finite()" system
520       call.  If you want to set a value to the "NaN" value, the following bit
521       of code can be used (this can be found in both Basic/Core/Core.xs.PL
522       and Basic/Bad/bad.pd):
523
524         /* for big-endian machines */
525         static union { unsigned char __c[4]; float __d; }
526               __pdl_nan = { { 0x7f, 0xc0, 0, 0 } };
527
528         /* for little-endian machines */
529         static union { unsigned char __c[4]; float __d; }
530               __pdl_nan = { { 0, 0, 0xc0, 0x7f } };
531
532       This approach should probably be replaced by library routines such as
533       "nan("")" or "atof("NaN")".
534
535       To find out whether a particular machine is big endian, use the routine
536       "PDL::Core::Dev::isbigendian()".
537

WHAT ABOUT DOCUMENTATION?

539       One of the strengths of PDL is its on-line documentation. The aim is to
540       use this system to provide information on how/if a routine supports bad
541       values: in many cases "pp_def()" contains all the information anyway,
542       so the function-writer doesn't need to do anything at all! For the
543       cases when this is not sufficient, there's the "BadDoc" option. For
544       code written at the Perl level - i.e. in a .pm file - use the "=for
545       bad" pod directive.
546
547       This information will be available via man/pod2man/html documentation.
548       It's also accessible from the "perldl" or "pdl2" shells - using the
549       "badinfo" command - and the "pdldoc" shell command - using the "-b"
550       option.
551
552       This support is at a very early stage - i.e. not much thought has gone
553       into it: comments are welcome; improvements to the code preferred ;)
554       One awkward problem is for *.pm code: you have to write a *.pm.PL file
555       which only inserts the "=for bad" directive (+ text) if bad value
556       support is compiled in. In fact, this is a pain when handling bad
557       values at the Perl, rather than PDL::PP, level: perhaps I should just
558       scrap the "WITH_BADVAL" option...
559

CURRENT ISSUES

561       There are a number of areas that need work, user input, or both!  They
562       are mentioned elsewhere in this document, but this is just to make sure
563       they don't get lost.
564
565   Trapping invalid mathematical operations
566       Should we add exceptions to the functions in "PDL::Ops" to set the
567       output bad for out-of-range input values?
568
569        pdl> p log10(pdl(10,100,-1))
570
571       I would like the above to produce "[1 2 BAD]", but this would slow down
572       operations on all piddles.  We could check for "NaN"/"Inf" values after
573       the operation, but I doubt that would be any faster.
574
575   Integration with NaN
576       When "BADVAL_USENAN" is true, the routines in "PDL::Ops" should just
577       fall through to the "Code" section - i.e. don't use "BadCode" - for
578       "float" and "double" data types.
579
580   Global versus per-piddle bad values
581       I think all that's needed is to change the routines in
582       "Basic/Core/pdlconv.c.PL", although there's bound to be complications.
583       It would also mean that the pdl structure would need to have a variable
584       to store its bad value, which would mean binary incompatibility with
585       previous versions of PDL with bad value support.
586
587       As of 17 March 2006, PDL contains the experimental "BADVAL_PER_PDL"
588       configuration option which, if selected, adds per-piddle bad values.
589
590   Dataflow of the badflag
591       Currently changes to the bad flag are propagated to the children of a
592       piddle, but perhaps they should also be passed on to the parents as
593       well. With the advent of per-piddle bad values we need to consider how
594       to handle changes to the value used to represent bad items too.
595

EVERYTHING ELSE

597       The build process has been affected. The following files are now
598       created during the build:
599
600         Basic/Core/pdlcore.h      pdlcore.h.PL
601                    pdlcore.c      pdlcore.c.PL
602                    pdlapi.c       pdlapi.c.PL
603                    Core.xs        Core.xs.PL
604                    Core.pm        Core.pm.PL
605
606       Several new files have been added:
607
608         Basic/Pod/BadValues.pod (i.e. this file)
609
610         t/bad.t
611
612         Basic/Bad/
613         Basic/Bad/Makefile.PL
614                   bad.pd
615
616       etc
617

TODO/SUGGESTIONS

619       •   Look at using per-piddle bad values.  Would mean a change to the
620           pdl structure (i.e. binary incompatibility) and the routines in
621           "Basic/Core/pdlconv.c.PL" would need changing to handle this.  Most
622           other routines should not need to be changed ...
623
624           See the experimental "BADVAL_PER_PDL" option.
625
626       •   what to do about "$y = pdl(-2); $x = log10($y)" - $x should be set
627           bad, but it currently isn't.
628
629       •   Allow the operations in PDL::Ops to skip the check for bad values
630           when using NaN as a bad value and processing a floating-point
631           piddle.  Needs a fair bit of work to PDL::PP::PDLCode.
632
633       •   "$pdl->baddata()" now updates all the children of this piddle as
634           well. However, not sure what to do with parents, since:
635
636             $y = $x->slice();
637             $y->baddata(0)
638
639           doesn't mean that $x shouldn't have its badvalue cleared.  however,
640           after
641
642             $y->baddata(1)
643
644           it's sensible to assume that the parents now get flagged as
645           containing bad values.
646
647           PERHAPS you can only clear the bad value flag if you are NOT a
648           child of another piddle, whereas if you set the flag then all
649           children AND parents should be set as well?
650
651           Similarly, if you change the bad value in a piddle, should this be
652           propagated to parent & children? Or should you only be able to do
653           this on the 'top-level' piddle? Nasty...
654
655       •   get some code set up to do benchmarks to see how much things are
656           slowed down (and to check that I haven't messed things up if
657           "WITH_BADVAL" is 0/undef).
658
659       •   some of the names aren't appealing - I'm thinking of
660           "orig_badvalue()" in Basic/Bad/bad.pd in particular. Any
661           suggestions appreciated.
662

AUTHOR

664       Copyright (C) Doug Burke (djburke@cpan.org), 2000, 2006.
665
666       The per-piddle bad value support is by Heiko Klein (2006).
667
668       Commercial reproduction of this documentation in a different format is
669       forbidden.
670
671
672
673perl v5.32.1                      2021-02-15                      BADVALUES(1)
Impressum