File Coverage

blib/lib/PDLA/Primitive.pm
Criterion Covered Total %
statement 293 390 75.1
branch 117 210 55.7
condition 30 82 36.5
subroutine 37 38 97.3
pod 8 30 26.6
total 485 750 64.6


line stmt bran cond sub pod time code
1              
2             #
3             # GENERATED WITH PDLA::PP! Don't modify!
4             #
5             package PDLA::Primitive;
6              
7             @EXPORT_OK = qw( PDLA::PP inner PDLA::PP outer matmult PDLA::PP matmult PDLA::PP innerwt PDLA::PP inner2 PDLA::PP inner2d PDLA::PP inner2t PDLA::PP crossp PDLA::PP norm PDLA::PP indadd PDLA::PP conv1d PDLA::PP in uniq uniqind uniqvec PDLA::PP hclip PDLA::PP lclip clip PDLA::PP clip PDLA::PP wtstat PDLA::PP statsover stats PDLA::PP histogram PDLA::PP whistogram PDLA::PP histogram2d PDLA::PP whistogram2d PDLA::PP fibonacci PDLA::PP append PDLA::PP axisvalues PDLA::PP random PDLA::PP randsym grandom vsearch PDLA::PP vsearch_sample PDLA::PP vsearch_insert_leftmost PDLA::PP vsearch_insert_rightmost PDLA::PP vsearch_match PDLA::PP vsearch_bin_inclusive PDLA::PP vsearch_bin_exclusive PDLA::PP interpolate interpol interpND one2nd PDLA::PP which PDLA::PP which_both where whereND whichND setops intersect );
8             %EXPORT_TAGS = (Func=>[@EXPORT_OK]);
9              
10 78     78   560 use PDLA::Core;
  78         169  
  78         477  
11 78     78   535 use PDLA::Exporter;
  78         159  
  78         421  
12 78     78   380 use DynaLoader;
  78         164  
  78         5419  
13              
14              
15              
16            
17             @ISA = ( 'PDLA::Exporter','DynaLoader' );
18             push @PDLA::Core::PP, __PACKAGE__;
19             bootstrap PDLA::Primitive ;
20              
21              
22              
23              
24              
25 78     78   46727 use PDLA::Slices;
  78         215  
  78         544  
26 78     78   613 use Carp;
  78         173  
  78         45654  
27              
28             =head1 NAME
29              
30             PDLA::Primitive - primitive operations for pdl
31              
32             =head1 DESCRIPTION
33              
34             This module provides some primitive and useful functions defined
35             using PDLA::PP and able to use the new indexing tricks.
36              
37             See L for how to use indices creatively.
38             For explanation of the signature format, see L.
39              
40             =head1 SYNOPSIS
41              
42             # Pulls in PDLA::Primitive, among other modules.
43             use PDLA;
44              
45             # Only pull in PDLA::Primitive:
46             use PDLA::Primitive;
47              
48             =cut
49              
50              
51              
52              
53              
54              
55              
56             =head1 FUNCTIONS
57              
58              
59              
60             =cut
61              
62              
63              
64              
65              
66              
67             =head2 inner
68              
69             =for sig
70              
71             Signature: (a(n); b(n); [o]c())
72              
73              
74              
75             =for ref
76              
77             Inner product over one dimension
78              
79             c = sum_i a_i * b_i
80              
81              
82              
83             =for bad
84              
85             =for bad
86              
87             If C contains only bad data,
88             C is set bad. Otherwise C will have its bad flag cleared,
89             as it will not contain any bad values.
90              
91              
92              
93             =cut
94              
95              
96              
97              
98              
99              
100             *inner = \&PDLA::inner;
101              
102              
103              
104              
105              
106             =head2 outer
107              
108             =for sig
109              
110             Signature: (a(n); b(m); [o]c(n,m))
111              
112              
113              
114             =for ref
115              
116             outer product over one dimension
117              
118             Naturally, it is possible to achieve the effects of outer
119             product simply by threading over the "C<*>"
120             operator but this function is provided for convenience.
121              
122              
123              
124             =for bad
125              
126             outer processes bad values.
127             It will set the bad-value flag of all output piddles if the flag is set for any of the input piddles.
128              
129              
130             =cut
131              
132              
133              
134              
135              
136              
137             *outer = \&PDLA::outer;
138              
139              
140              
141              
142             =head2 x
143              
144             =for sig
145              
146             Signature: (a(i,z), b(x,i),[o]c(x,z))
147              
148             =for ref
149              
150             Matrix multiplication
151              
152             PDLA overloads the C operator (normally the repeat operator) for
153             matrix multiplication. The number of columns (size of the 0
154             dimension) in the left-hand argument must normally equal the number of
155             rows (size of the 1 dimension) in the right-hand argument.
156              
157             Row vectors are represented as (N x 1) two-dimensional PDLAs, or you
158             may be sloppy and use a one-dimensional PDLA. Column vectors are
159             represented as (1 x N) two-dimensional PDLAs.
160              
161             Threading occurs in the usual way, but as both the 0 and 1 dimension
162             (if present) are included in the operation, you must be sure that
163             you don't try to thread over either of those dims.
164              
165             EXAMPLES
166              
167             Here are some simple ways to define vectors and matrices:
168              
169             pdla> $r = pdl(1,2); # A row vector
170             pdla> $c = pdl([[3],[4]]); # A column vector
171             pdla> $c = pdl(3,4)->(*1); # A column vector, using NiceSlice
172             pdla> $m = pdl([[1,2],[3,4]]); # A 2x2 matrix
173              
174             Now that we have a few objects prepared, here is how to
175             matrix-multiply them:
176              
177             pdla> print $r x $m # row x matrix = row
178             [
179             [ 7 10]
180             ]
181              
182             pdla> print $m x $r # matrix x row = ERROR
183             PDLA: Dim mismatch in matmult of [2x2] x [2x1]: 2 != 1
184              
185             pdla> print $m x $c # matrix x column = column
186             [
187             [ 5]
188             [11]
189             ]
190              
191             pdla> print $m x 2 # Trivial case: scalar mult.
192             [
193             [2 4]
194             [6 8]
195             ]
196              
197             pdla> print $r x $c # row x column = scalar
198             [
199             [11]
200             ]
201              
202             pdla> print $c x $r # column x row = matrix
203             [
204             [3 6]
205             [4 8]
206             ]
207              
208              
209             INTERNALS
210              
211             The mechanics of the multiplication are carried out by the
212             L method.
213              
214             =cut
215              
216              
217              
218              
219              
220             =head2 matmult
221              
222             =for sig
223              
224             Signature: (a(t,h); b(w,t); [o]c(w,h))
225              
226             =for ref
227              
228             Matrix multiplication
229              
230             Notionally, matrix multiplication $x x $y is equivalent to the
231             threading expression
232              
233             $x->dummy(1)->inner($y->xchg(0,1)->dummy(2),$c);
234              
235             but for large matrices that breaks CPU cache and is slow. Instead,
236             matmult calculates its result in 32x32x32 tiles, to keep the memory
237             footprint within cache as long as possible on most modern CPUs.
238              
239             For usage, see L, a description of the overloaded 'x' operator
240              
241              
242              
243             =for bad
244              
245             matmult ignores the bad-value flag of the input piddles.
246             It will set the bad-value flag of all output piddles if the flag is set for any of the input piddles.
247              
248              
249             =cut
250              
251              
252              
253              
254             sub PDLA::matmult {
255 20     20 0 935 my ($x,$y,$c) = @_;
256              
257 20 100       34 $y = pdl($y) unless eval { $y->isa('PDLA') };
  20         100  
258 20 100       41 $c = PDLA->null unless eval { $c->isa('PDLA') };
  20         89  
259              
260 20         77 while($x->getndims < 2) {$x = $x->dummy(-1)}
  2         8  
261 20         76 while($y->getndims < 2) {$y = $y->dummy(-1)}
  2         15  
262              
263 20 100 66     201 return ($c .= $x * $y) if( ($x->dim(0)==1 && $x->dim(1)==1) ||
      66        
      100        
264             ($y->dim(0)==1 && $y->dim(1)==1) );
265 18 100       65 if($y->dim(1) != $x->dim(0)) {
266 1         18 barf(sprintf("Dim mismatch in matmult of [%dx%d] x [%dx%d]: %d != %d",$x->dim(0),$x->dim(1),$y->dim(0),$y->dim(1),$x->dim(0),$y->dim(1)));
267             }
268 17         422 PDLA::_matmult_int($x,$y,$c);
269 17         68 $c;
270             }
271              
272              
273             *matmult = \&PDLA::matmult;
274              
275              
276              
277              
278              
279             =head2 innerwt
280              
281             =for sig
282              
283             Signature: (a(n); b(n); c(n); [o]d())
284              
285              
286              
287             =for ref
288              
289             Weighted (i.e. triple) inner product
290              
291             d = sum_i a(i) b(i) c(i)
292              
293              
294              
295             =for bad
296              
297             innerwt processes bad values.
298             It will set the bad-value flag of all output piddles if the flag is set for any of the input piddles.
299              
300              
301             =cut
302              
303              
304              
305              
306              
307              
308             *innerwt = \&PDLA::innerwt;
309              
310              
311              
312              
313              
314             =head2 inner2
315              
316             =for sig
317              
318             Signature: (a(n); b(n,m); c(m); [o]d())
319              
320              
321              
322             =for ref
323              
324             Inner product of two vectors and a matrix
325              
326             d = sum_ij a(i) b(i,j) c(j)
327              
328             Note that you should probably not thread over C and C since that would be
329             very wasteful. Instead, you should use a temporary for C.
330              
331              
332              
333             =for bad
334              
335             inner2 processes bad values.
336             It will set the bad-value flag of all output piddles if the flag is set for any of the input piddles.
337              
338              
339             =cut
340              
341              
342              
343              
344              
345              
346             *inner2 = \&PDLA::inner2;
347              
348              
349              
350              
351              
352             =head2 inner2d
353              
354             =for sig
355              
356             Signature: (a(n,m); b(n,m); [o]c())
357              
358              
359              
360             =for ref
361              
362             Inner product over 2 dimensions.
363              
364             Equivalent to
365              
366             $c = inner($x->clump(2), $y->clump(2))
367              
368              
369              
370             =for bad
371              
372             inner2d processes bad values.
373             It will set the bad-value flag of all output piddles if the flag is set for any of the input piddles.
374              
375              
376             =cut
377              
378              
379              
380              
381              
382              
383             *inner2d = \&PDLA::inner2d;
384              
385              
386              
387              
388              
389             =head2 inner2t
390              
391             =for sig
392              
393             Signature: (a(j,n); b(n,m); c(m,k); [t]tmp(n,k); [o]d(j,k)))
394              
395              
396              
397             =for ref
398              
399             Efficient Triple matrix product C
400              
401             Efficiency comes from by using the temporary C. This operation only
402             scales as C whereas threading using L would scale
403             as C.
404              
405             The reason for having this routine is that you do not need to
406             have the same thread-dimensions for C as for the other arguments,
407             which in case of large numbers of matrices makes this much more
408             memory-efficient.
409              
410             It is hoped that things like this could be taken care of as a kind of
411             closures at some point.
412              
413              
414              
415             =for bad
416              
417             inner2t processes bad values.
418             It will set the bad-value flag of all output piddles if the flag is set for any of the input piddles.
419              
420              
421             =cut
422              
423              
424              
425              
426              
427              
428             *inner2t = \&PDLA::inner2t;
429              
430              
431              
432              
433              
434             =head2 crossp
435              
436             =for sig
437              
438             Signature: (a(tri=3); b(tri); [o] c(tri))
439              
440              
441             =for ref
442              
443             Cross product of two 3D vectors
444              
445             After
446              
447             =for example
448              
449             $c = crossp $x, $y
450              
451             the inner product C<$c*$x> and C<$c*$y> will be zero, i.e. C<$c> is
452             orthogonal to C<$x> and C<$y>
453              
454              
455              
456             =for bad
457              
458             crossp does not process bad values.
459             It will set the bad-value flag of all output piddles if the flag is set for any of the input piddles.
460              
461              
462             =cut
463              
464              
465              
466              
467              
468              
469             *crossp = \&PDLA::crossp;
470              
471              
472              
473              
474              
475             =head2 norm
476              
477             =for sig
478              
479             Signature: (vec(n); [o] norm(n))
480              
481             =for ref
482              
483             Normalises a vector to unit Euclidean length
484              
485             =for bad
486              
487             norm processes bad values.
488             It will set the bad-value flag of all output piddles if the flag is set for any of the input piddles.
489              
490              
491             =cut
492              
493              
494              
495              
496              
497              
498             *norm = \&PDLA::norm;
499              
500              
501              
502              
503              
504             =head2 indadd
505              
506             =for sig
507              
508             Signature: (a(); indx ind(); [o] sum(m))
509              
510              
511              
512             =for ref
513              
514             Threaded Index Add: Add C to the C element of C, i.e:
515              
516             sum(ind) += a
517              
518             =for example
519              
520             Simple Example:
521              
522             $x = 2;
523             $ind = 3;
524             $sum = zeroes(10);
525             indadd($x,$ind, $sum);
526             print $sum
527             #Result: ( 2 added to element 3 of $sum)
528             # [0 0 0 2 0 0 0 0 0 0]
529              
530             Threaded Example:
531              
532             $x = pdl( 1,2,3);
533             $ind = pdl( 1,4,6);
534             $sum = zeroes(10);
535             indadd($x,$ind, $sum);
536             print $sum."\n";
537             #Result: ( 1, 2, and 3 added to elements 1,4,6 $sum)
538             # [0 1 0 0 2 0 3 0 0 0]
539              
540              
541              
542             =for bad
543              
544             =for bad
545              
546             The routine barfs if any of the indices are bad.
547              
548              
549              
550             =cut
551              
552              
553              
554              
555              
556              
557             *indadd = \&PDLA::indadd;
558              
559              
560              
561              
562              
563             =head2 conv1d
564              
565             =for sig
566              
567             Signature: (a(m); kern(p); [o]b(m); int reflect)
568              
569              
570             =for ref
571              
572             1D convolution along first dimension
573              
574             The m-th element of the discrete convolution of an input piddle
575             C<$a> of size C<$M>, and a kernel piddle C<$kern> of size C<$P>, is
576             calculated as
577              
578             n = ($P-1)/2
579             ====
580             \
581             ($a conv1d $kern)[m] = > $a_ext[m - n] * $kern[n]
582             /
583             ====
584             n = -($P-1)/2
585              
586             where C<$a_ext> is either the periodic (or reflected) extension of
587             C<$a> so it is equal to C<$a> on C< 0..$M-1 > and equal to the
588             corresponding periodic/reflected image of C<$a> outside that range.
589              
590              
591             =for example
592              
593             $con = conv1d sequence(10), pdl(-1,0,1);
594              
595             $con = conv1d sequence(10), pdl(-1,0,1), {Boundary => 'reflect'};
596              
597             By default, periodic boundary conditions are assumed (i.e. wrap around).
598             Alternatively, you can request reflective boundary conditions using
599             the C option:
600              
601             {Boundary => 'reflect'} # case in 'reflect' doesn't matter
602              
603             The convolution is performed along the first dimension. To apply it across
604             another dimension use the slicing routines, e.g.
605              
606             $y = $x->mv(2,0)->conv1d($kernel)->mv(0,2); # along third dim
607              
608             This function is useful for threaded filtering of 1D signals.
609              
610             Compare also L, L,
611             L, L,
612             L
613              
614             =for bad
615              
616             WARNING: C processes bad values in its inputs as
617             the numeric value of C<< $pdl->badvalue >> so it is not
618             recommended for processing pdls with bad values in them
619             unless special care is taken.
620              
621              
622              
623             =for bad
624              
625             conv1d ignores the bad-value flag of the input piddles.
626             It will set the bad-value flag of all output piddles if the flag is set for any of the input piddles.
627              
628              
629             =cut
630              
631              
632              
633              
634              
635              
636             sub PDLA::conv1d {
637 0 0   0 0 0 my $opt = pop @_ if ref($_[$#_]) eq 'HASH';
638 0 0 0     0 die 'Usage: conv1d( a(m), kern(p), [o]b(m), {Options} )'
639             if $#_<1 || $#_>2;
640 0         0 my($x,$kern) = @_;
641 0 0       0 my $c = $#_ == 2 ? $_[2] : PDLA->null;
642             &PDLA::_conv1d_int($x,$kern,$c,
643             !(defined $opt && exists $$opt{Boundary}) ? 0 :
644 0 0 0     0 lc $$opt{Boundary} eq "reflect");
645 0         0 return $c;
646             }
647              
648              
649              
650             *conv1d = \&PDLA::conv1d;
651              
652              
653              
654              
655              
656             =head2 in
657              
658             =for sig
659              
660             Signature: (a(); b(n); [o] c())
661              
662              
663             =for ref
664              
665             test if a is in the set of values b
666              
667             =for example
668              
669             $goodmsk = $labels->in($goodlabels);
670             print pdl(3,1,4,6,2)->in(pdl(2,3,3));
671             [1 0 0 0 1]
672              
673             C is akin to the I of set theory. In principle,
674             PDLA threading could be used to achieve its functionality by using a
675             construct like
676              
677             $msk = ($labels->dummy(0) == $goodlabels)->orover;
678              
679             However, C doesn't create a (potentially large) intermediate
680             and is generally faster.
681              
682              
683              
684             =for bad
685              
686             in does not process bad values.
687             It will set the bad-value flag of all output piddles if the flag is set for any of the input piddles.
688              
689              
690             =cut
691              
692              
693              
694              
695              
696              
697             *in = \&PDLA::in;
698              
699              
700              
701              
702             =head2 uniq
703              
704             =for ref
705              
706             return all unique elements of a piddle
707              
708             The unique elements are returned in ascending order.
709              
710             =for example
711              
712             PDLA> p pdl(2,2,2,4,0,-1,6,6)->uniq
713             [-1 0 2 4 6] # 0 is returned 2nd (sorted order)
714              
715             PDLA> p pdl(2,2,2,4,nan,-1,6,6)->uniq
716             [-1 2 4 6 nan] # NaN value is returned at end
717              
718             Note: The returned pdl is 1D; any structure of the input
719             piddle is lost. C values are never compare equal to
720             any other values, even themselves. As a result, they are
721             always unique. C returns the NaN values at the end
722             of the result piddle. This follows the Matlab usage.
723              
724             See L if you need the indices of the unique
725             elements rather than the values.
726              
727             =cut
728              
729              
730              
731              
732             =for bad
733              
734             Bad values are not considered unique by uniq and are ignored.
735              
736             $x=sequence(10);
737             $x=$x->setbadif($x%3);
738             print $x->uniq;
739             [0 3 6 9]
740              
741             =cut
742              
743              
744              
745              
746             *uniq = \&PDLA::uniq;
747             # return unique elements of array
748             # find as jumps in the sorted array
749             # flattens in the process
750             sub PDLA::uniq {
751 78     78   650 use PDLA::Core 'barf';
  78         196  
  78         413  
752 11     11 0 17 my ($arr) = @_;
753 11 50       29 return $arr if($arr->nelem == 0); # The null list is unique (CED)
754 11         25 my $srt = $arr->clump(-1)->where($arr==$arr)->qsort; # no NaNs or BADs for qsort
755 11         85 my $nans = $arr->clump(-1)->where($arr!=$arr);
756 11 50       236 my $uniq = ($srt->nelem > 0) ? $srt->where($srt != $srt->rotate(-1)) : $srt;
757             # make sure we return something if there is only one value
758 11         63 my $answ = $nans; # NaN values always uniq
759 11 50       56 if ( $uniq->nelem > 0 ) {
760 11         132 $answ = $uniq->append($answ);
761             } else {
762 0 0       0 $answ = ( ($srt->nelem == 0) ? $srt : PDLA::pdl( ref($srt), [$srt->index(0)] ) )->append($answ);
763             }
764 11         89 return $answ;
765             }
766              
767              
768              
769              
770             =head2 uniqind
771              
772             =for ref
773              
774             Return the indices of all unique elements of a piddle
775             The order is in the order of the values to be consistent
776             with uniq. C values never compare equal with any
777             other value and so are always unique. This follows the
778             Matlab usage.
779              
780             =for example
781              
782             PDLA> p pdl(2,2,2,4,0,-1,6,6)->uniqind
783             [5 4 1 3 6] # the 0 at index 4 is returned 2nd, but...
784              
785             PDLA> p pdl(2,2,2,4,nan,-1,6,6)->uniqind
786             [5 1 3 6 4] # ...the NaN at index 4 is returned at end
787              
788              
789             Note: The returned pdl is 1D; any structure of the input
790             piddle is lost.
791              
792             See L if you want the unique values instead of the
793             indices.
794              
795             =cut
796              
797              
798              
799              
800             =for bad
801              
802             Bad values are not considered unique by uniqind and are ignored.
803              
804             =cut
805              
806              
807              
808              
809             *uniqind = \&PDLA::uniqind;
810             # return unique elements of array
811             # find as jumps in the sorted array
812             # flattens in the process
813             sub PDLA::uniqind {
814 78     78   612 use PDLA::Core 'barf';
  78         186  
  78         352  
815 2     2 0 10 my ($arr) = @_;
816 2 50       10 return $arr if($arr->nelem == 0); # The null list is unique (CED)
817             # Different from uniq we sort and store the result in an intermediary
818 2         5 my $aflat = $arr->flat;
819 2         40 my $nanind = which($aflat!=$aflat); # NaN indexes
820 2         12 my $good = $aflat->sequence->long->where($aflat==$aflat); # good indexes
821 2         27 my $i_srt = $aflat->where($aflat==$aflat)->qsorti; # no BAD or NaN values for qsorti
822 2         30 my $srt = $aflat->where($aflat==$aflat)->index($i_srt);
823 2         8 my $uniqind;
824 2 50       14 if ($srt->nelem > 0) {
825 2         39 $uniqind = which($srt != $srt->rotate(-1));
826 2 100       19 $uniqind = $i_srt->slice('0') if $uniqind->isempty;
827             } else {
828 0         0 $uniqind = which($srt);
829             }
830             # Now map back to the original space
831 2         4 my $ansind = $nanind;
832 2 50       10 if ( $uniqind->nelem > 0 ) {
833 2         51 $ansind = ($good->index($i_srt->index($uniqind)))->append($ansind);
834             } else {
835 0         0 $ansind = $uniqind->append($ansind);
836             }
837 2         43 return $ansind;
838             }
839              
840              
841              
842              
843             =head2 uniqvec
844              
845             =for ref
846              
847             Return all unique vectors out of a collection
848              
849             NOTE: If any vectors in the input piddle have NaN values
850             they are returned at the end of the non-NaN ones. This is
851             because, by definition, NaN values never compare equal with
852             any other value.
853              
854             NOTE: The current implementation does not sort the vectors
855             containing NaN values.
856              
857             The unique vectors are returned in lexicographically sorted
858             ascending order. The 0th dimension of the input PDLA is treated
859             as a dimensional index within each vector, and the 1st and any
860             higher dimensions are taken to run across vectors. The return
861             value is always 2D; any structure of the input PDLA (beyond using
862             the 0th dimension for vector index) is lost.
863              
864             See also L for a unique list of scalars; and
865             L for sorting a list of vectors
866             lexicographcally.
867              
868             =cut
869              
870              
871              
872              
873             =for bad
874              
875             If a vector contains all bad values, it is ignored as in L.
876             If some of the values are good, it is treated as a normal vector. For
877             example, [1 2 BAD] and [BAD 2 3] could be returned, but [BAD BAD BAD]
878             could not. Vectors containing BAD values will be returned after any
879             non-NaN and non-BAD containing vectors, followed by the NaN vectors.
880              
881              
882             =cut
883              
884              
885              
886              
887             sub PDLA::uniqvec {
888              
889 9     9 0 1804 my($pdl) = shift;
890              
891 9 50 33     88 return $pdl if ( $pdl->nelem == 0 || $pdl->ndims < 2 );
892 9 100       36 return $pdl if ( $pdl->slice("(0)")->nelem < 2 ); # slice isn't cheap but uniqvec isn't either
893              
894 8         51 my $pdl2d = null;
895 8         65 $pdl2d = $pdl->mv(0,-1)->clump($pdl->ndims-1)->mv(-1,0); # clump all but dim(0)
896              
897 8         35 my $ngood = null;
898 8         32 $ngood = $pdl2d->ones->sumover;
899 8 50 33     119 $ngood = $pdl2d->ngoodover if ($PDLA::Bad::Status && $pdl->badflag); # number of good values each vector
900 8         35 my $ngood2 = null;
901 8         35 $ngood2 = $ngood->where($ngood); # number of good values with no all-BADs
902              
903 8         60 $pdl2d = $pdl2d->mv(0,-1)->dice($ngood->which)->mv(-1,0); # remove all-BAD vectors
904              
905              
906 8         39 my $numnan = null;
907 8         12714 $numnan = ($pdl2d!=$pdl2d)->sumover; # works since no all-BADs to confuse
908              
909 8         62 my $presrt = null;
910 8         292 $presrt = $pdl2d->mv(0,-1)->dice($numnan->not->which)->mv(0,-1); # remove vectors with any NaN values
911 8         45 my $nanvec = null;
912 8         85 $nanvec = $pdl2d->mv(0,-1)->dice($numnan->which)->mv(0,-1); # the vectors with any NaN values
913              
914             # use dice instead of nslice since qsortvec might be packing
915             # the badvals to the front of the array instead of the end like
916             # the docs say. If that is the case and it gets fixed, it won't
917             # bust uniqvec. DAL 14-March 2006
918              
919 8         41 my $srt = null;
920 8         50938 $srt = $presrt->qsortvec->mv(0,-1); # BADs are sorted by qsortvec
921 8         49 my $srtdice = $srt;
922 8         37 my $somebad = null;
923 8 50 33     86 if ($PDLA::Bad::Status && $srt->badflag) {
924 0         0 $srtdice = $srt->dice($srt->mv(0,-1)->nbadover->not->which);
925 0         0 $somebad = $srt->dice($srt->mv(0,-1)->nbadover->which);
926             }
927              
928 8         21 my $uniq = null;
929 8 50       48 if ($srtdice->nelem > 0) {
930 8         18273 $uniq = ($srtdice != $srtdice->rotate(-1))->mv(0,-1)->orover->which;
931             } else {
932 0         0 $uniq = $srtdice->orover->which;
933             }
934              
935 8         595 my $ans = null;
936 8 100       40 if ( $uniq->nelem > 0 ) {
937 1         4 $ans = $srtdice->dice($uniq);
938             } else {
939 7 50       49 $ans = ($srtdice->nelem > 0) ? $srtdice->slice("0,:") : $srtdice;
940             }
941 8         1217 return $ans->append($somebad)->append($nanvec->mv(0,-1))->mv(0,-1);
942             }
943              
944              
945              
946              
947              
948             =head2 hclip
949              
950             =for sig
951              
952             Signature: (a(); b(); [o] c())
953              
954             =for ref
955              
956             clip (threshold) C<$a> by C<$b> (C<$b> is upper bound)
957              
958             =for bad
959              
960             hclip processes bad values.
961             It will set the bad-value flag of all output piddles if the flag is set for any of the input piddles.
962              
963              
964             =cut
965              
966              
967              
968              
969             sub PDLA::hclip {
970 2     2 0 7 my ($x,$y) = @_;
971 2         5 my $c;
972 2 50       16 if ($x->is_inplace) {
    50          
973 0         0 $x->set_inplace(0); $c = $x;
  0         0  
974 0         0 } elsif ($#_ > 1) {$c=$_[2]} else {$c=PDLA->nullcreate($x)}
  2         8  
975 2         107 &PDLA::_hclip_int($x,$y,$c);
976 2         25 return $c;
977             }
978              
979              
980             *hclip = \&PDLA::hclip;
981              
982              
983              
984              
985              
986             =head2 lclip
987              
988             =for sig
989              
990             Signature: (a(); b(); [o] c())
991              
992             =for ref
993              
994             clip (threshold) C<$a> by C<$b> (C<$b> is lower bound)
995              
996             =for bad
997              
998             lclip processes bad values.
999             It will set the bad-value flag of all output piddles if the flag is set for any of the input piddles.
1000              
1001              
1002             =cut
1003              
1004              
1005              
1006              
1007             sub PDLA::lclip {
1008 2     2 0 349 my ($x,$y) = @_;
1009 2         4 my $c;
1010 2 50       15 if ($x->is_inplace) {
    50          
1011 0         0 $x->set_inplace(0); $c = $x;
  0         0  
1012 0         0 } elsif ($#_ > 1) {$c=$_[2]} else {$c=PDLA->nullcreate($x)}
  2         7  
1013 2         100 &PDLA::_lclip_int($x,$y,$c);
1014 2         22 return $c;
1015             }
1016              
1017              
1018             *lclip = \&PDLA::lclip;
1019              
1020              
1021              
1022              
1023             =head2 clip
1024              
1025             =for ref
1026              
1027             Clip (threshold) a piddle by (optional) upper or lower bounds.
1028              
1029             =for usage
1030              
1031             $y = $x->clip(0,3);
1032             $c = $x->clip(undef, $x);
1033              
1034             =cut
1035              
1036              
1037              
1038              
1039             =for bad
1040              
1041             clip handles bad values since it is just a
1042             wrapper around L and
1043             L.
1044              
1045             =cut
1046              
1047              
1048              
1049              
1050              
1051             =head2 clip
1052              
1053             =for sig
1054              
1055             Signature: (a(); l(); h(); [o] c())
1056              
1057              
1058             =for ref
1059              
1060             info not available
1061              
1062              
1063             =for bad
1064              
1065             clip processes bad values.
1066             It will set the bad-value flag of all output piddles if the flag is set for any of the input piddles.
1067              
1068              
1069             =cut
1070              
1071              
1072              
1073              
1074             *clip = \&PDLA::clip;
1075             sub PDLA::clip {
1076 2     2 0 671 my($x, $l, $h) = @_;
1077 2         4 my $d;
1078 2 50 33     10 unless(defined($l) || defined($h)) {
1079             # Deal with pathological case
1080 0 0       0 if($x->is_inplace) {
1081 0         0 $x->set_inplace(0);
1082 0         0 return $x;
1083             } else {
1084 0         0 return $x->copy;
1085             }
1086             }
1087              
1088 2 50       15 if($x->is_inplace) {
    50          
1089 0         0 $x->set_inplace(0); $d = $x
  0         0  
1090             } elsif ($#_ > 2) {
1091 0         0 $d=$_[3]
1092             } else {
1093 2         9 $d = PDLA->nullcreate($x);
1094             }
1095 2 50 33     17 if(defined($l) && defined($h)) {
    0          
    0          
1096 2         112 &PDLA::_clip_int($x,$l,$h,$d);
1097             } elsif( defined($l) ) {
1098 0         0 &PDLA::_lclip_int($x,$l,$d);
1099             } elsif( defined($h) ) {
1100 0         0 &PDLA::_hclip_int($x,$h,$d);
1101             } else {
1102 0         0 die "This can't happen (clip contingency) - file a bug";
1103             }
1104              
1105 2         27 return $d;
1106             }
1107              
1108              
1109             *clip = \&PDLA::clip;
1110              
1111              
1112              
1113              
1114              
1115             =head2 wtstat
1116              
1117             =for sig
1118              
1119             Signature: (a(n); wt(n); avg(); [o]b(); int deg)
1120              
1121              
1122              
1123             =for ref
1124              
1125             Weighted statistical moment of given degree
1126              
1127             This calculates a weighted statistic over the vector C.
1128             The formula is
1129              
1130             b() = (sum_i wt_i * (a_i ** degree - avg)) / (sum_i wt_i)
1131              
1132              
1133              
1134             =for bad
1135              
1136             =for bad
1137              
1138             Bad values are ignored in any calculation; C<$b> will only
1139             have its bad flag set if the output contains any bad data.
1140              
1141              
1142              
1143             =cut
1144              
1145              
1146              
1147              
1148              
1149              
1150             *wtstat = \&PDLA::wtstat;
1151              
1152              
1153              
1154              
1155              
1156             =head2 statsover
1157              
1158             =for sig
1159              
1160             Signature: (a(n); w(n); float+ [o]avg(); float+ [o]prms(); int+ [o]median(); int+ [o]min(); int+ [o]max(); float+ [o]adev(); float+ [o]rms())
1161              
1162              
1163              
1164             =for ref
1165              
1166             Calculate useful statistics over a dimension of a piddle
1167              
1168             =for usage
1169              
1170             ($mean,$prms,$median,$min,$max,$adev,$rms) = statsover($piddle, $weights);
1171              
1172             This utility function calculates various useful
1173             quantities of a piddle. These are:
1174              
1175             =over 3
1176              
1177             =item * the mean:
1178              
1179             MEAN = sum (x)/ N
1180              
1181             with C being the number of elements in x
1182              
1183             =item * the population RMS deviation from the mean:
1184              
1185             PRMS = sqrt( sum( (x-mean(x))^2 )/(N-1)
1186              
1187             The population deviation is the best-estimate of the deviation
1188             of the population from which a sample is drawn.
1189              
1190             =item * the median
1191              
1192             The median is the 50th percentile data value. Median is found by
1193             L, so WEIGHTING IS IGNORED FOR THE MEDIAN CALCULATION.
1194              
1195             =item * the minimum
1196              
1197             =item * the maximum
1198              
1199             =item * the average absolute deviation:
1200              
1201             AADEV = sum( abs(x-mean(x)) )/N
1202              
1203             =item * RMS deviation from the mean:
1204              
1205             RMS = sqrt(sum( (x-mean(x))^2 )/N)
1206              
1207             (also known as the root-mean-square deviation, or the square root of the
1208             variance)
1209              
1210             =back
1211              
1212             This operator is a projection operator so the calculation
1213             will take place over the final dimension. Thus if the input
1214             is N-dimensional each returned value will be N-1 dimensional,
1215             to calculate the statistics for the entire piddle either
1216             use C directly on the piddle or call C.
1217              
1218              
1219              
1220             =for bad
1221              
1222             =for bad
1223              
1224             Bad values are simply ignored in the calculation, effectively reducing
1225             the sample size. If all data are bad then the output data are marked bad.
1226              
1227              
1228              
1229             =cut
1230              
1231              
1232              
1233              
1234              
1235              
1236             sub PDLA::statsover {
1237 9 50   9 0 31 barf('Usage: ($mean,[$prms, $median, $min, $max, $adev, $rms]) = statsover($data,[$weights])') if $#_>1;
1238 9         24 my ($data, $weights) = @_;
1239 9 100       37 $weights = $data->ones() if !defined($weights);
1240              
1241 9         316 my $median = $data->medover();
1242 9         69 my $mean = PDLA->nullcreate($data);
1243 9         28 my $rms = PDLA->nullcreate($data);
1244 9         25 my $min = PDLA->nullcreate($data);
1245 9         24 my $max = PDLA->nullcreate($data);
1246 9         35 my $adev = PDLA->nullcreate($data);
1247 9         23 my $prms = PDLA->nullcreate($data);
1248 9         425 &PDLA::_statsover_int($data, $weights, $mean, $prms, $median, $min, $max, $adev, $rms);
1249              
1250 9 100       77 return $mean unless wantarray;
1251 5         50 return ($mean, $prms, $median, $min, $max, $adev, $rms);
1252             }
1253              
1254              
1255              
1256             *statsover = \&PDLA::statsover;
1257              
1258              
1259              
1260              
1261             =head2 stats
1262              
1263             =for ref
1264              
1265             Calculates useful statistics on a piddle
1266              
1267             =for usage
1268              
1269             ($mean,$prms,$median,$min,$max,$adev,$rms) = stats($piddle,[$weights]);
1270              
1271             This utility calculates all the most useful quantities in one call.
1272             It works the same way as L, except that the quantities are
1273             calculated considering the entire input PDLA as a single sample, rather
1274             than as a collection of rows. See L for definitions of the
1275             returned quantities.
1276              
1277             =cut
1278              
1279              
1280              
1281              
1282             =for bad
1283              
1284             Bad values are handled; if all input values are bad, then all of the output
1285             values are flagged bad.
1286              
1287             =cut
1288              
1289              
1290              
1291             *stats = \&PDLA::stats;
1292             sub PDLA::stats {
1293 7 50   7 0 161 barf('Usage: ($mean,[$rms]) = stats($data,[$weights])') if $#_>1;
1294 7         83 my ($data,$weights) = @_;
1295              
1296             # Ensure that $weights is properly threaded over; this could be
1297             # done rather more efficiently...
1298 7 100       24 if(defined $weights) {
1299 1 50       5 $weights = pdl($weights) unless UNIVERSAL::isa($weights,'PDLA');
1300 1 50 33     9 if( ($weights->ndims != $data->ndims) or
1301             (pdl($weights->dims) != pdl($data->dims))->or
1302             ) {
1303 0         0 $weights = $weights + zeroes($data)
1304             }
1305 1         7 $weights = $weights->flat;
1306             }
1307              
1308 7         32 return PDLA::statsover($data->flat,$weights);
1309             }
1310              
1311              
1312              
1313              
1314             =head2 histogram
1315              
1316             =for sig
1317              
1318             Signature: (in(n); int+[o] hist(m); double step; double min; int msize => m)
1319              
1320              
1321             =for ref
1322              
1323             Calculates a histogram for given stepsize and minimum.
1324              
1325             =for usage
1326              
1327             $h = histogram($data, $step, $min, $numbins);
1328             $hist = zeroes $numbins; # Put histogram in existing piddle.
1329             histogram($data, $hist, $step, $min, $numbins);
1330              
1331             The histogram will contain C<$numbins> bins starting from C<$min>, each
1332             C<$step> wide. The value in each bin is the number of
1333             values in C<$data> that lie within the bin limits.
1334              
1335              
1336             Data below the lower limit is put in the first bin, and data above the
1337             upper limit is put in the last bin.
1338              
1339             The output is reset in a different threadloop so that you
1340             can take a histogram of C<$a(10,12)> into C<$b(15)> and get the result
1341             you want.
1342              
1343             For a higher-level interface, see L.
1344              
1345             =for example
1346              
1347             pdla> p histogram(pdl(1,1,2),1,0,3)
1348             [0 2 1]
1349              
1350              
1351              
1352             =for bad
1353              
1354             histogram processes bad values.
1355             It will set the bad-value flag of all output piddles if the flag is set for any of the input piddles.
1356              
1357              
1358             =cut
1359              
1360              
1361              
1362              
1363              
1364              
1365             *histogram = \&PDLA::histogram;
1366              
1367              
1368              
1369              
1370              
1371             =head2 whistogram
1372              
1373             =for sig
1374              
1375             Signature: (in(n); float+ wt(n);float+[o] hist(m); double step; double min; int msize => m)
1376              
1377              
1378             =for ref
1379              
1380             Calculates a histogram from weighted data for given stepsize and minimum.
1381              
1382             =for usage
1383              
1384             $h = whistogram($data, $weights, $step, $min, $numbins);
1385             $hist = zeroes $numbins; # Put histogram in existing piddle.
1386             whistogram($data, $weights, $hist, $step, $min, $numbins);
1387              
1388             The histogram will contain C<$numbins> bins starting from C<$min>, each
1389             C<$step> wide. The value in each bin is the sum of the values in C<$weights>
1390             that correspond to values in C<$data> that lie within the bin limits.
1391              
1392             Data below the lower limit is put in the first bin, and data above the
1393             upper limit is put in the last bin.
1394              
1395             The output is reset in a different threadloop so that you
1396             can take a histogram of C<$a(10,12)> into C<$b(15)> and get the result
1397             you want.
1398              
1399             =for example
1400              
1401             pdla> p whistogram(pdl(1,1,2), pdl(0.1,0.1,0.5), 1, 0, 4)
1402             [0 0.2 0.5 0]
1403              
1404              
1405              
1406             =for bad
1407              
1408             whistogram processes bad values.
1409             It will set the bad-value flag of all output piddles if the flag is set for any of the input piddles.
1410              
1411              
1412             =cut
1413              
1414              
1415              
1416              
1417              
1418              
1419             *whistogram = \&PDLA::whistogram;
1420              
1421              
1422              
1423              
1424              
1425             =head2 histogram2d
1426              
1427             =for sig
1428              
1429             Signature: (ina(n); inb(n); int+[o] hist(ma,mb); double stepa; double mina; int masize => ma;
1430             double stepb; double minb; int mbsize => mb;)
1431              
1432              
1433             =for ref
1434              
1435             Calculates a 2d histogram.
1436              
1437             =for usage
1438              
1439             $h = histogram2d($datax, $datay, $stepx, $minx,
1440             $nbinx, $stepy, $miny, $nbiny);
1441             $hist = zeroes $nbinx, $nbiny; # Put histogram in existing piddle.
1442             histogram2d($datax, $datay, $hist, $stepx, $minx,
1443             $nbinx, $stepy, $miny, $nbiny);
1444              
1445             The histogram will contain C<$nbinx> x C<$nbiny> bins, with the lower
1446             limits of the first one at C<($minx, $miny)>, and with bin size
1447             C<($stepx, $stepy)>.
1448             The value in each bin is the number of
1449             values in C<$datax> and C<$datay> that lie within the bin limits.
1450              
1451             Data below the lower limit is put in the first bin, and data above the
1452             upper limit is put in the last bin.
1453              
1454             =for example
1455              
1456             pdla> p histogram2d(pdl(1,1,1,2,2),pdl(2,1,1,1,1),1,0,3,1,0,3)
1457             [
1458             [0 0 0]
1459             [0 2 2]
1460             [0 1 0]
1461             ]
1462              
1463              
1464              
1465             =for bad
1466              
1467             histogram2d processes bad values.
1468             It will set the bad-value flag of all output piddles if the flag is set for any of the input piddles.
1469              
1470              
1471             =cut
1472              
1473              
1474              
1475              
1476              
1477              
1478             *histogram2d = \&PDLA::histogram2d;
1479              
1480              
1481              
1482              
1483              
1484             =head2 whistogram2d
1485              
1486             =for sig
1487              
1488             Signature: (ina(n); inb(n); float+ wt(n);float+[o] hist(ma,mb); double stepa; double mina; int masize => ma;
1489             double stepb; double minb; int mbsize => mb;)
1490              
1491              
1492             =for ref
1493              
1494             Calculates a 2d histogram from weighted data.
1495              
1496             =for usage
1497              
1498             $h = whistogram2d($datax, $datay, $weights,
1499             $stepx, $minx, $nbinx, $stepy, $miny, $nbiny);
1500             $hist = zeroes $nbinx, $nbiny; # Put histogram in existing piddle.
1501             whistogram2d($datax, $datay, $weights, $hist,
1502             $stepx, $minx, $nbinx, $stepy, $miny, $nbiny);
1503              
1504             The histogram will contain C<$nbinx> x C<$nbiny> bins, with the lower
1505             limits of the first one at C<($minx, $miny)>, and with bin size
1506             C<($stepx, $stepy)>.
1507             The value in each bin is the sum of the values in
1508             C<$weights> that correspond to values in C<$datax> and C<$datay> that lie within the bin limits.
1509              
1510             Data below the lower limit is put in the first bin, and data above the
1511             upper limit is put in the last bin.
1512              
1513             =for example
1514              
1515             pdla> p whistogram2d(pdl(1,1,1,2,2),pdl(2,1,1,1,1),pdl(0.1,0.2,0.3,0.4,0.5),1,0,3,1,0,3)
1516             [
1517             [ 0 0 0]
1518             [ 0 0.5 0.9]
1519             [ 0 0.1 0]
1520             ]
1521              
1522              
1523              
1524              
1525             =for bad
1526              
1527             whistogram2d processes bad values.
1528             It will set the bad-value flag of all output piddles if the flag is set for any of the input piddles.
1529              
1530              
1531             =cut
1532              
1533              
1534              
1535              
1536              
1537              
1538             *whistogram2d = \&PDLA::whistogram2d;
1539              
1540              
1541              
1542              
1543              
1544             =head2 fibonacci
1545              
1546             =for sig
1547              
1548             Signature: ([o]x(n))
1549              
1550             =for ref
1551              
1552             Constructor - a vector with Fibonacci's sequence
1553              
1554             =for bad
1555              
1556             fibonacci does not process bad values.
1557             It will set the bad-value flag of all output piddles if the flag is set for any of the input piddles.
1558              
1559              
1560             =cut
1561              
1562              
1563              
1564              
1565 1 50 33 1 1 383 sub fibonacci { ref($_[0]) && ref($_[0]) ne 'PDLA::Type' ? $_[0]->fibonacci : PDLA->fibonacci(@_) }
1566             sub PDLA::fibonacci{
1567 1     1 0 3 my $class = shift;
1568 1 50       7 my $x = scalar(@_)? $class->new_from_specification(@_) : $class->new_or_inplace;
1569 1         4 &PDLA::_fibonacci_int($x->clump(-1));
1570 1         9 return $x;
1571             }
1572              
1573              
1574              
1575              
1576              
1577              
1578              
1579             =head2 append
1580              
1581             =for sig
1582              
1583             Signature: (a(n); b(m); [o] c(mn))
1584              
1585              
1586              
1587             =for ref
1588              
1589             append two piddles by concatenating along their first dimensions
1590              
1591             =for example
1592              
1593             $x = ones(2,4,7);
1594             $y = sequence 5;
1595             $c = $x->append($y); # size of $c is now (7,4,7) (a jumbo-piddle ;)
1596              
1597             C appends two piddles along their first dimensions. The rest of the
1598             dimensions must be compatible in the threading sense. The resulting
1599             size of the first dimension is the sum of the sizes of the first dimensions
1600             of the two argument piddles - i.e. C.
1601              
1602             Similar functions include L (below), which can append more
1603             than two piddles along an arbitrary dimension, and
1604             L, which can append more than two piddles that all
1605             have the same sized dimensions.
1606              
1607              
1608              
1609             =for bad
1610              
1611             append does not process bad values.
1612             It will set the bad-value flag of all output piddles if the flag is set for any of the input piddles.
1613              
1614              
1615             =cut
1616              
1617              
1618              
1619              
1620              
1621              
1622             *append = \&PDLA::append;
1623              
1624              
1625              
1626              
1627             =head2 glue
1628              
1629             =for usage
1630              
1631             $c = $x->glue(,$y,...)
1632              
1633             =for ref
1634              
1635             Glue two or more PDLAs together along an arbitrary dimension
1636             (N-D L).
1637              
1638             Sticks $x, $y, and all following arguments together along the
1639             specified dimension. All other dimensions must be compatible in the
1640             threading sense.
1641              
1642             Glue is permissive, in the sense that every PDLA is treated as having an
1643             infinite number of trivial dimensions of order 1 -- so C<< $x->glue(3,$y) >>
1644             works, even if $x and $y are only one dimensional.
1645              
1646             If one of the PDLAs has no elements, it is ignored. Likewise, if one
1647             of them is actually the undefined value, it is treated as if it had no
1648             elements.
1649              
1650             If the first parameter is a defined perl scalar rather than a pdl,
1651             then it is taken as a dimension along which to glue everything else,
1652             so you can say C<$cube = PDLA::glue(3,@image_list);> if you like.
1653              
1654             C is implemented in pdl, using a combination of L and
1655             L. It should probably be updated (one day) to a pure PP
1656             function.
1657              
1658             Similar functions include L (above), which appends
1659             only two piddles along their first dimension, and
1660             L, which can append more than two piddles that all
1661             have the same sized dimensions.
1662              
1663             =cut
1664              
1665             sub PDLA::glue{
1666 2     2 0 70 my($x) = shift;
1667 2         4 my($dim) = shift;
1668              
1669 2 50 33     12 if(defined $x && !(ref $x)) {
1670 0         0 my $y = $dim;
1671 0         0 $dim = $x;
1672 0         0 $x = $y;
1673             }
1674              
1675 2 50 33     16 if(!defined $x || $x->nelem==0) {
1676 0 0       0 return $x unless(@_);
1677 0 0       0 return shift() if(@_<=1);
1678 0         0 $x=shift;
1679 0         0 return PDLA::glue($x,$dim,@_);
1680             }
1681              
1682 2 50       9 if($dim - $x->dim(0) > 100) {
1683 0         0 print STDERR "warning:: PDLA::glue allocating >100 dimensions!\n";
1684             }
1685 2         12 while($dim >= $x->ndims) {
1686 0         0 $x = $x->dummy(-1,1);
1687             }
1688 2         14 $x = $x->xchg(0,$dim);
1689              
1690 2         6 while(scalar(@_)){
1691 4         15 my $y = shift;
1692 4 50 33     22 next unless(defined $y && $y->nelem);
1693              
1694 4         12 while($dim >= $y->ndims) {
1695 0         0 $y = $y->dummy(-1,1);
1696             }
1697 4         18 $y = $y->xchg(0,$dim);
1698 4         85 $x = $x->append($y);
1699             }
1700 2         21 $x->xchg(0,$dim);
1701             }
1702              
1703              
1704              
1705              
1706              
1707              
1708              
1709              
1710             =head2 axisvalues
1711              
1712             =for sig
1713              
1714             Signature: ([o,nc]a(n))
1715              
1716              
1717              
1718             =for ref
1719              
1720             Internal routine
1721              
1722             C is the internal primitive that implements
1723             L
1724             and alters its argument.
1725              
1726              
1727              
1728             =for bad
1729              
1730             axisvalues does not process bad values.
1731             It will set the bad-value flag of all output piddles if the flag is set for any of the input piddles.
1732              
1733              
1734             =cut
1735              
1736              
1737              
1738              
1739              
1740              
1741             *axisvalues = \&PDLA::axisvalues;
1742              
1743              
1744              
1745              
1746             =head2 random
1747              
1748             =for ref
1749              
1750             Constructor which returns piddle of random numbers
1751              
1752             =for usage
1753              
1754             $x = random([type], $nx, $ny, $nz,...);
1755             $x = random $y;
1756              
1757             etc (see L).
1758              
1759             This is the uniform distribution between 0 and 1 (assumedly
1760             excluding 1 itself). The arguments are the same as C
1761             (q.v.) - i.e. one can specify dimensions, types or give
1762             a template.
1763              
1764             You can use the perl function L to seed the random
1765             generator. For further details consult Perl's L
1766             documentation.
1767              
1768             =head2 randsym
1769              
1770             =for ref
1771              
1772             Constructor which returns piddle of random numbers
1773              
1774             =for usage
1775              
1776             $x = randsym([type], $nx, $ny, $nz,...);
1777             $x = randsym $y;
1778              
1779             etc (see L).
1780              
1781             This is the uniform distribution between 0 and 1 (excluding both 0 and
1782             1, cf L). The arguments are the same as C (q.v.) -
1783             i.e. one can specify dimensions, types or give a template.
1784              
1785             You can use the perl function L to seed the random
1786             generator. For further details consult Perl's L
1787             documentation.
1788              
1789             =cut
1790              
1791              
1792              
1793 9 100 66 9 1 2918 sub random { ref($_[0]) && ref($_[0]) ne 'PDLA::Type' ? $_[0]->random : PDLA->random(@_) }
1794             sub PDLA::random {
1795 9     9 0 20 my $class = shift;
1796 9 100       45 my $x = scalar(@_)? $class->new_from_specification(@_) : $class->new_or_inplace;
1797 9         105 &PDLA::_random_int($x);
1798 9         178 return $x;
1799             }
1800              
1801              
1802              
1803              
1804              
1805 2 50 33 2 1 14 sub randsym { ref($_[0]) && ref($_[0]) ne 'PDLA::Type' ? $_[0]->randsym : PDLA->randsym(@_) }
1806             sub PDLA::randsym {
1807 2     2 0 4 my $class = shift;
1808 2 50       11 my $x = scalar(@_)? $class->new_from_specification(@_) : $class->new_or_inplace;
1809 2         18 &PDLA::_randsym_int($x);
1810 2         84 return $x;
1811             }
1812              
1813              
1814              
1815              
1816              
1817              
1818             =head2 grandom
1819              
1820             =for ref
1821              
1822             Constructor which returns piddle of Gaussian random numbers
1823              
1824             =for usage
1825              
1826             $x = grandom([type], $nx, $ny, $nz,...);
1827             $x = grandom $y;
1828              
1829             etc (see L).
1830              
1831             This is generated using the math library routine C.
1832              
1833             Mean = 0, Stddev = 1
1834              
1835              
1836             You can use the perl function L to seed the random
1837             generator. For further details consult Perl's L
1838             documentation.
1839              
1840             =cut
1841              
1842 2 50 33 2 1 301 sub grandom { ref($_[0]) && ref($_[0]) ne 'PDLA::Type' ? $_[0]->grandom : PDLA->grandom(@_) }
1843             sub PDLA::grandom {
1844 2     2 0 5 my $class = shift;
1845 2 50       8 my $x = scalar(@_)? $class->new_from_specification(@_) : $class->new_or_inplace;
1846 78     78   40662 use PDLA::Math 'ndtri';
  78         283  
  78         642  
1847 2         6 $x .= ndtri(randsym($x));
1848 2         15 return $x;
1849             }
1850              
1851              
1852              
1853              
1854             =head2 vsearch
1855              
1856             =for sig
1857              
1858             Signature: ( vals(); xs(n); [o] indx(); [\%options] )
1859              
1860             =for ref
1861              
1862             Efficiently search for values in a sorted piddle, returning indices.
1863              
1864             =for usage
1865              
1866             $idx = vsearch( $vals, $x, [\%options] );
1867             vsearch( $vals, $x, $idx, [\%options ] );
1868              
1869             B performs a binary search in the ordered piddle C<$x>,
1870             for the values from C<$vals> piddle, returning indices into C<$x>.
1871             What is a "match", and the meaning of the returned indices, are determined
1872             by the options.
1873              
1874             The C option indicates which method of searching to use, and may
1875             be one of:
1876              
1877             =over
1878              
1879             =item C
1880              
1881             invoke B, returning indices appropriate for sampling
1882             within a distribution.
1883              
1884             =item C
1885              
1886             invoke B, returning the left-most possible
1887             insertion point which still leaves the piddle sorted.
1888              
1889             =item C
1890              
1891             invoke B, returning the right-most possible
1892             insertion point which still leaves the piddle sorted.
1893              
1894             =item C
1895              
1896             invoke B, returning the index of a matching element,
1897             else -(insertion point + 1)
1898              
1899             =item C
1900              
1901             invoke B, returning an index appropriate for binning
1902             on a grid where the left bin edges are I of the bin. See
1903             below for further explanation of the bin.
1904              
1905             =item C
1906              
1907             invoke B, returning an index appropriate for binning
1908             on a grid where the left bin edges are I of the bin. See
1909             below for further explanation of the bin.
1910              
1911             =back
1912              
1913             The default value of C is C.
1914              
1915             =cut
1916              
1917             sub vsearch {
1918 149 100   149 1 47581 my $opt = 'HASH' eq ref $_[-1]
1919             ? pop
1920             : { mode => 'sample' };
1921              
1922             croak( "unknown options to vsearch\n" )
1923 149 50 33     873 if ( ! defined $opt->{mode} && keys %$opt )
      33        
1924             || keys %$opt > 1;
1925              
1926 149         271 my $mode = $opt->{mode};
1927             goto
1928 149 50       9498 $mode eq 'sample' ? \&vsearch_sample
    100          
    100          
    100          
    100          
    100          
1929             : $mode eq 'insert_leftmost' ? \&vsearch_insert_leftmost
1930             : $mode eq 'insert_rightmost' ? \&vsearch_insert_rightmost
1931             : $mode eq 'match' ? \&vsearch_match
1932             : $mode eq 'bin_inclusive' ? \&vsearch_bin_inclusive
1933             : $mode eq 'bin_exclusive' ? \&vsearch_bin_exclusive
1934             : croak( "unknown vsearch mode: $mode\n" );
1935             }
1936              
1937             *PDLA::vsearch = \&vsearch;
1938              
1939              
1940              
1941              
1942              
1943             =head2 vsearch_sample
1944              
1945             =for sig
1946              
1947             Signature: (vals(); x(n); indx [o]idx())
1948              
1949              
1950             =for ref
1951              
1952             Search for values in a sorted array, return index appropriate for sampling from a distribution
1953              
1954             =for usage
1955              
1956             $idx = vsearch_sample($vals, $x);
1957              
1958             C<$x> must be sorted, but may be in decreasing or increasing
1959             order.
1960              
1961              
1962              
1963             B returns an index I for each value I of C<$vals> appropriate
1964             for sampling C<$vals>
1965              
1966              
1967              
1968            
1969              
1970             I has the following properties:
1971              
1972             =over
1973              
1974             =item *
1975              
1976             if C<$x> is sorted in increasing order
1977              
1978              
1979             V <= x[0] : I = 0
1980             x[0] < V <= x[-1] : I s.t. x[I-1] < V <= x[I]
1981             x[-1] < V : I = $x->nelem -1
1982              
1983              
1984              
1985             =item *
1986              
1987             if C<$x> is sorted in decreasing order
1988              
1989              
1990             V > x[0] : I = 0
1991             x[0] >= V > x[-1] : I s.t. x[I] >= V > x[I+1]
1992             x[-1] >= V : I = $x->nelem - 1
1993              
1994              
1995              
1996             =back
1997              
1998              
1999              
2000              
2001             If all elements of C<$x> are equal, I<< I = $x->nelem - 1 >>.
2002              
2003             If C<$x> contains duplicated elements, I is the index of the
2004             leftmost (by position in array) duplicate if I matches.
2005              
2006             =for example
2007              
2008             This function is useful e.g. when you have a list of probabilities
2009             for events and want to generate indices to events:
2010              
2011             $x = pdl(.01,.86,.93,1); # Barnsley IFS probabilities cumulatively
2012             $y = random 20;
2013             $c = vsearch_sample($y, $x); # Now, $c will have the appropriate distr.
2014              
2015             It is possible to use the L
2016             function to obtain cumulative probabilities from absolute probabilities.
2017              
2018              
2019              
2020              
2021              
2022              
2023              
2024             =for bad
2025              
2026             needs major (?) work to handles bad values
2027              
2028             =cut
2029              
2030              
2031              
2032              
2033              
2034              
2035             *vsearch_sample = \&PDLA::vsearch_sample;
2036              
2037              
2038              
2039              
2040              
2041             =head2 vsearch_insert_leftmost
2042              
2043             =for sig
2044              
2045             Signature: (vals(); x(n); indx [o]idx())
2046              
2047              
2048             =for ref
2049              
2050             Determine the insertion point for values in a sorted array, inserting before duplicates.
2051              
2052             =for usage
2053              
2054             $idx = vsearch_insert_leftmost($vals, $x);
2055              
2056             C<$x> must be sorted, but may be in decreasing or increasing
2057             order.
2058              
2059              
2060              
2061             B returns an index I for each value I of
2062             C<$vals> equal to the leftmost position (by index in array) within
2063             C<$x> that I may be inserted and still maintain the order in
2064             C<$x>.
2065              
2066             Insertion at index I involves shifting elements I and higher of
2067             C<$x> to the right by one and setting the now empty element at index
2068             I to I.
2069              
2070              
2071              
2072            
2073              
2074             I has the following properties:
2075              
2076             =over
2077              
2078             =item *
2079              
2080             if C<$x> is sorted in increasing order
2081              
2082              
2083             V <= x[0] : I = 0
2084             x[0] < V <= x[-1] : I s.t. x[I-1] < V <= x[I]
2085             x[-1] < V : I = $x->nelem
2086              
2087              
2088              
2089             =item *
2090              
2091             if C<$x> is sorted in decreasing order
2092              
2093              
2094             V > x[0] : I = -1
2095             x[0] >= V >= x[-1] : I s.t. x[I] >= V > x[I+1]
2096             x[-1] >= V : I = $x->nelem -1
2097              
2098              
2099              
2100             =back
2101              
2102              
2103              
2104              
2105             If all elements of C<$x> are equal,
2106              
2107             i = 0
2108              
2109             If C<$x> contains duplicated elements, I is the index of the
2110             leftmost (by index in array) duplicate if I matches.
2111              
2112              
2113              
2114              
2115              
2116              
2117              
2118             =for bad
2119              
2120             needs major (?) work to handles bad values
2121              
2122             =cut
2123              
2124              
2125              
2126              
2127              
2128              
2129             *vsearch_insert_leftmost = \&PDLA::vsearch_insert_leftmost;
2130              
2131              
2132              
2133              
2134              
2135             =head2 vsearch_insert_rightmost
2136              
2137             =for sig
2138              
2139             Signature: (vals(); x(n); indx [o]idx())
2140              
2141              
2142             =for ref
2143              
2144             Determine the insertion point for values in a sorted array, inserting after duplicates.
2145              
2146             =for usage
2147              
2148             $idx = vsearch_insert_rightmost($vals, $x);
2149              
2150             C<$x> must be sorted, but may be in decreasing or increasing
2151             order.
2152              
2153              
2154              
2155             B returns an index I for each value I of
2156             C<$vals> equal to the rightmost position (by index in array) within
2157             C<$x> that I may be inserted and still maintain the order in
2158             C<$x>.
2159              
2160             Insertion at index I involves shifting elements I and higher of
2161             C<$x> to the right by one and setting the now empty element at index
2162             I to I.
2163              
2164              
2165              
2166            
2167              
2168             I has the following properties:
2169              
2170             =over
2171              
2172             =item *
2173              
2174             if C<$x> is sorted in increasing order
2175              
2176              
2177             V < x[0] : I = 0
2178             x[0] <= V < x[-1] : I s.t. x[I-1] <= V < x[I]
2179             x[-1] <= V : I = $x->nelem
2180              
2181              
2182              
2183             =item *
2184              
2185             if C<$x> is sorted in decreasing order
2186              
2187              
2188             V >= x[0] : I = -1
2189             x[0] > V >= x[-1] : I s.t. x[I] >= V > x[I+1]
2190             x[-1] > V : I = $x->nelem -1
2191              
2192              
2193              
2194             =back
2195              
2196              
2197              
2198              
2199             If all elements of C<$x> are equal,
2200              
2201             i = $x->nelem - 1
2202              
2203             If C<$x> contains duplicated elements, I is the index of the
2204             leftmost (by index in array) duplicate if I matches.
2205              
2206              
2207              
2208              
2209              
2210              
2211              
2212             =for bad
2213              
2214             needs major (?) work to handles bad values
2215              
2216             =cut
2217              
2218              
2219              
2220              
2221              
2222              
2223             *vsearch_insert_rightmost = \&PDLA::vsearch_insert_rightmost;
2224              
2225              
2226              
2227              
2228              
2229             =head2 vsearch_match
2230              
2231             =for sig
2232              
2233             Signature: (vals(); x(n); indx [o]idx())
2234              
2235              
2236             =for ref
2237              
2238             Match values against a sorted array.
2239              
2240             =for usage
2241              
2242             $idx = vsearch_match($vals, $x);
2243              
2244             C<$x> must be sorted, but may be in decreasing or increasing
2245             order.
2246              
2247              
2248              
2249             B returns an index I for each value I of
2250             C<$vals>. If I matches an element in C<$x>, I is the
2251             index of that element, otherwise it is I<-( insertion_point + 1 )>,
2252             where I is an index in C<$x> where I may be
2253             inserted while maintaining the order in C<$x>. If C<$x> has
2254             duplicated values, I may refer to any of them.
2255              
2256              
2257              
2258            
2259              
2260              
2261              
2262              
2263              
2264             =for bad
2265              
2266             needs major (?) work to handles bad values
2267              
2268             =cut
2269              
2270              
2271              
2272              
2273              
2274              
2275             *vsearch_match = \&PDLA::vsearch_match;
2276              
2277              
2278              
2279              
2280              
2281             =head2 vsearch_bin_inclusive
2282              
2283             =for sig
2284              
2285             Signature: (vals(); x(n); indx [o]idx())
2286              
2287              
2288             =for ref
2289              
2290             Determine the index for values in a sorted array of bins, lower bound inclusive.
2291              
2292             =for usage
2293              
2294             $idx = vsearch_bin_inclusive($vals, $x);
2295              
2296             C<$x> must be sorted, but may be in decreasing or increasing
2297             order.
2298              
2299              
2300              
2301             C<$x> represents the edges of contiguous bins, with the first and
2302             last elements representing the outer edges of the outer bins, and the
2303             inner elements the shared bin edges.
2304              
2305             The lower bound of a bin is inclusive to the bin, its outer bound is exclusive to it.
2306             B returns an index I for each value I of C<$vals>
2307              
2308              
2309              
2310            
2311              
2312             I has the following properties:
2313              
2314             =over
2315              
2316             =item *
2317              
2318             if C<$x> is sorted in increasing order
2319              
2320              
2321             V < x[0] : I = -1
2322             x[0] <= V < x[-1] : I s.t. x[I] <= V < x[I+1]
2323             x[-1] <= V : I = $x->nelem - 1
2324              
2325              
2326              
2327             =item *
2328              
2329             if C<$x> is sorted in decreasing order
2330              
2331              
2332             V >= x[0] : I = 0
2333             x[0] > V >= x[-1] : I s.t. x[I+1] > V >= x[I]
2334             x[-1] > V : I = $x->nelem
2335              
2336              
2337              
2338             =back
2339              
2340              
2341              
2342              
2343             If all elements of C<$x> are equal,
2344              
2345             i = $x->nelem - 1
2346              
2347             If C<$x> contains duplicated elements, I is the index of the
2348             righmost (by index in array) duplicate if I matches.
2349              
2350              
2351              
2352              
2353              
2354              
2355              
2356             =for bad
2357              
2358             needs major (?) work to handles bad values
2359              
2360             =cut
2361              
2362              
2363              
2364              
2365              
2366              
2367             *vsearch_bin_inclusive = \&PDLA::vsearch_bin_inclusive;
2368              
2369              
2370              
2371              
2372              
2373             =head2 vsearch_bin_exclusive
2374              
2375             =for sig
2376              
2377             Signature: (vals(); x(n); indx [o]idx())
2378              
2379              
2380             =for ref
2381              
2382             Determine the index for values in a sorted array of bins, lower bound exclusive.
2383              
2384             =for usage
2385              
2386             $idx = vsearch_bin_exclusive($vals, $x);
2387              
2388             C<$x> must be sorted, but may be in decreasing or increasing
2389             order.
2390              
2391              
2392              
2393             C<$x> represents the edges of contiguous bins, with the first and
2394             last elements representing the outer edges of the outer bins, and the
2395             inner elements the shared bin edges.
2396              
2397             The lower bound of a bin is exclusive to the bin, its upper bound is inclusive to it.
2398             B returns an index I for each value I of C<$vals>.
2399              
2400              
2401              
2402            
2403              
2404             I has the following properties:
2405              
2406             =over
2407              
2408             =item *
2409              
2410             if C<$x> is sorted in increasing order
2411              
2412              
2413             V <= x[0] : I = -1
2414             x[0] < V <= x[-1] : I s.t. x[I] < V <= x[I+1]
2415             x[-1] < V : I = $x->nelem - 1
2416              
2417              
2418              
2419             =item *
2420              
2421             if C<$x> is sorted in decreasing order
2422              
2423              
2424             V > x[0] : I = 0
2425             x[0] >= V > x[-1] : I s.t. x[I-1] >= V > x[I]
2426             x[-1] >= V : I = $x->nelem
2427              
2428              
2429              
2430             =back
2431              
2432              
2433              
2434              
2435             If all elements of C<$x> are equal,
2436              
2437             i = $x->nelem - 1
2438              
2439             If C<$x> contains duplicated elements, I is the index of the
2440             righmost (by index in array) duplicate if I matches.
2441              
2442              
2443              
2444              
2445              
2446              
2447              
2448             =for bad
2449              
2450             needs major (?) work to handles bad values
2451              
2452             =cut
2453              
2454              
2455              
2456              
2457              
2458              
2459             *vsearch_bin_exclusive = \&PDLA::vsearch_bin_exclusive;
2460              
2461              
2462              
2463              
2464              
2465             =head2 interpolate
2466              
2467             =for sig
2468              
2469             Signature: (xi(); x(n); y(n); [o] yi(); int [o] err())
2470              
2471              
2472             =for ref
2473              
2474             routine for 1D linear interpolation
2475              
2476             =for usage
2477              
2478             ( $yi, $err ) = interpolate($xi, $x, $y)
2479              
2480             Given a set of points C<($x,$y)>, use linear interpolation
2481             to find the values C<$yi> at a set of points C<$xi>.
2482              
2483             C uses a binary search to find the suspects, er...,
2484             interpolation indices and therefore abscissas (ie C<$x>)
2485             have to be I ordered (increasing or decreasing).
2486             For interpolation at lots of
2487             closely spaced abscissas an approach that uses the last index found as
2488             a start for the next search can be faster (compare Numerical Recipes
2489             C routine). Feel free to implement that on top of the binary
2490             search if you like. For out of bounds values it just does a linear
2491             extrapolation and sets the corresponding element of C<$err> to 1,
2492             which is otherwise 0.
2493              
2494             See also L, which uses the same routine,
2495             differing only in the handling of extrapolation - an error message
2496             is printed rather than returning an error piddle.
2497              
2498              
2499              
2500             =for bad
2501              
2502             needs major (?) work to handles bad values
2503              
2504             =cut
2505              
2506              
2507              
2508              
2509              
2510              
2511             *interpolate = \&PDLA::interpolate;
2512              
2513              
2514              
2515              
2516             =head2 interpol
2517              
2518             =for sig
2519              
2520             Signature: (xi(); x(n); y(n); [o] yi())
2521              
2522             =for ref
2523              
2524             routine for 1D linear interpolation
2525              
2526             =for usage
2527              
2528             $yi = interpol($xi, $x, $y)
2529              
2530             C uses the same search method as L,
2531             hence C<$x> must be I ordered (either increasing or decreasing).
2532             The difference occurs in the handling of out-of-bounds values; here
2533             an error message is printed.
2534              
2535             =cut
2536              
2537             # kept in for backwards compatability
2538             sub interpol ($$$;$) {
2539 1     1 1 7 my $xi = shift;
2540 1         3 my $x = shift;
2541 1         2 my $y = shift;
2542              
2543 1         2 my $yi;
2544 1 50       4 if ( $#_ == 0 ) { $yi = $_[0]; }
  0         0  
2545 1         5 else { $yi = PDLA->null; }
2546              
2547 1         5 interpolate( $xi, $x, $y, $yi, my $err = PDLA->null );
2548 1 50       8 print "some values had to be extrapolated\n"
2549             if any $err;
2550              
2551 1 50       9 return $yi if $#_ == -1;
2552              
2553             } # sub: interpol()
2554             *PDLA::interpol = \&interpol;
2555              
2556              
2557              
2558              
2559             =head2 interpND
2560              
2561             =for ref
2562              
2563             Interpolate values from an N-D piddle, with switchable method
2564              
2565             =for example
2566              
2567             $source = 10*xvals(10,10) + yvals(10,10);
2568             $index = pdl([[2.2,3.5],[4.1,5.0]],[[6.0,7.4],[8,9]]);
2569             print $source->interpND( $index );
2570              
2571             InterpND acts like L,
2572             collapsing C<$index> by lookup
2573             into C<$source>; but it does interpolation rather than direct sampling.
2574             The interpolation method and boundary condition are switchable via
2575             an options hash.
2576              
2577             By default, linear or sample interpolation is used, with constant
2578             value outside the boundaries of the source pdl. No dataflow occurs,
2579             because in general the output is computed rather than indexed.
2580              
2581             All the interpolation methods treat the pixels as value-centered, so
2582             the C method will return C<< $a->(0) >> for coordinate values on
2583             the set [-0.5,0.5), and all methods will return C<< $a->(1) >> for
2584             a coordinate value of exactly 1.
2585              
2586              
2587             Recognized options:
2588              
2589             =over 3
2590              
2591             =item method
2592              
2593             Values can be:
2594              
2595             =over 3
2596              
2597             =item * 0, s, sample, Sample (default for integer source types)
2598              
2599             The nearest value is taken. Pixels are regarded as centered on their
2600             respective integer coordinates (no offset from the linear case).
2601              
2602             =item * 1, l, linear, Linear (default for floating point source types)
2603              
2604             The values are N-linearly interpolated from an N-dimensional cube of size 2.
2605              
2606             =item * 3, c, cube, cubic, Cubic
2607              
2608             The values are interpolated using a local cubic fit to the data. The
2609             fit is constrained to match the original data and its derivative at the
2610             data points. The second derivative of the fit is not continuous at the
2611             data points. Multidimensional datasets are interpolated by the
2612             successive-collapse method.
2613              
2614             (Note that the constraint on the first derivative causes a small amount
2615             of ringing around sudden features such as step functions).
2616              
2617             =item * f, fft, fourier, Fourier
2618              
2619             The source is Fourier transformed, and the interpolated values are
2620             explicitly calculated from the coefficients. The boundary condition
2621             option is ignored -- periodic boundaries are imposed.
2622              
2623             If you pass in the option "fft", and it is a list (ARRAY) ref, then it
2624             is a stash for the magnitude and phase of the source FFT. If the list
2625             has two elements then they are taken as already computed; otherwise
2626             they are calculated and put in the stash.
2627              
2628             =back
2629              
2630             =item b, bound, boundary, Boundary
2631              
2632             This option is passed unmodified into L,
2633             which is used as the indexing engine for the interpolation.
2634             Some current allowed values are 'extend', 'periodic', 'truncate', and 'mirror'
2635             (default is 'truncate').
2636              
2637             =item bad
2638              
2639             contains the fill value used for 'truncate' boundary. (default 0)
2640              
2641             =item fft
2642              
2643             An array ref whose associated list is used to stash the FFT of the source
2644             data, for the FFT method.
2645              
2646             =back
2647              
2648             =cut
2649              
2650             *interpND = *PDLA::interpND;
2651             sub PDLA::interpND {
2652 1     1 0 105 my $source = shift;
2653 1         2 my $index = shift;
2654 1         2 my $options = shift;
2655              
2656 1 50 33     6 barf 'Usage: interp_nd($source,$index,[{%options}])\n'
2657             if(defined $options and ref $options ne 'HASH');
2658              
2659 1 50       5 my($opt) = (defined $options) ? $options : {};
2660              
2661 1   33     14 my($method) = $opt->{m} || $opt->{meth} || $opt->{method} || $opt->{Method};
2662 1 50       5 if(!defined $method) {
2663 1 50       4 $method = ($source->type <= zeroes(long,1)->type) ?
2664             'sample' :
2665             'linear';
2666             }
2667              
2668 1   50     28 my($boundary) = $opt->{b} || $opt->{boundary} || $opt->{Boundary} || $opt->{bound} || $opt->{Bound} || 'extend';
2669 1   50     7 my($bad) = $opt->{bad} || $opt->{Bad} || 0.0;
2670              
2671 1 50 33     14 if($method =~ m/^s(am(p(le)?)?)?/i) {
    50 0        
    0          
    0          
2672 0         0 return $source->range(PDLA::Math::floor($index+0.5),0,$boundary);
2673             }
2674              
2675             elsif (($method eq 1) || $method =~ m/^l(in(ear)?)?/i) {
2676             ## key: (ith = index thread; cth = cube thread; sth = source thread)
2677 1         7 my $d = $index->dim(0);
2678 1         5 my $di = $index->ndims - 1;
2679              
2680             # Grab a 2-on-a-side n-cube around each desired pixel
2681 1         77 my $samp = $source->range($index->floor,2,$boundary); # (ith, cth, sth)
2682              
2683             # Reorder to put the cube dimensions in front and convert to a list
2684 1         31 $samp = $samp->reorder( $di .. $di+$d-1,
2685             0 .. $di-1,
2686             $di+$d .. $samp->ndims-1) # (cth, ith, sth)
2687             ->clump($d); # (clst, ith, sth)
2688              
2689             # Enumerate the corners of an n-cube and convert to a list
2690             # (the 'x' is the normal perl repeat operator)
2691 1         9 my $crnr = PDLA::Basic::ndcoords( (2) x $index->dim(0) ) # (index,cth)
2692             ->mv(0,-1)->clump($index->dim(0))->mv(-1,0); # (index, clst)
2693              
2694             # a & b are the weighting coefficients.
2695 1         6 my($x,$y);
2696 1         0 my($indexwhere);
2697 1         19 ($indexwhere = $index->where( 0 * $index )) .= -10; # Change NaN to invalid
2698             {
2699 1         6 my $bb = PDLA::Math::floor($index);
  1         14  
2700 1         24 $x = ($index - $bb) -> dummy(1,$crnr->dim(1)); # index, clst, ith
2701 1         41 $y = ($bb + 1 - $index) -> dummy(1,$crnr->dim(1)); # index, clst, ith
2702             }
2703              
2704             # Use 1/0 corners to select which multiplier happens, multiply
2705             # 'em all together to get sample weights, and sum to get the answer.
2706 1         109 my $out0 = ( ($x * ($crnr==1) + $y * ($crnr==0)) #index, clst, ith
2707             -> prodover #clst, ith
2708             );
2709              
2710 1         68 my $out = ($out0 * $samp)->sumover; # ith, sth
2711              
2712             # Work around BAD-not-being-contagious bug in PDLA <= 2.6 bad handling code --CED 3-April-2013
2713 1 50 33     13 if($PDLA::Bad::Status and $source->badflag) {
2714 0         0 my $baddies = $samp->isbad->orover;
2715 0         0 $out = $out->setbadif($baddies);
2716             }
2717              
2718 1         41 return $out;
2719              
2720             } elsif(($method eq 3) || $method =~ m/^c(u(b(e|ic)?)?)?/i) {
2721              
2722 0         0 my ($d,@di) = $index->dims;
2723 0         0 my $di = $index->ndims - 1;
2724              
2725             # Grab a 4-on-a-side n-cube around each desired pixel
2726 0         0 my $samp = $source->range($index->floor - 1,4,$boundary) #ith, cth, sth
2727             ->reorder( $di .. $di+$d-1, 0..$di-1, $di+$d .. $source->ndims-1 );
2728             # (cth, ith, sth)
2729              
2730             # Make a cube of the subpixel offsets, and expand its dims to
2731             # a 4-on-a-side N-1 cube, to match the slices of $samp (used below).
2732 0         0 my $y = $index - $index->floor;
2733 0         0 for my $i(1..$d-1) {
2734 0         0 $y = $y->dummy($i,4);
2735             }
2736              
2737             # Collapse by interpolation, one dimension at a time...
2738 0         0 for my $i(0..$d-1) {
2739 0         0 my $a0 = $samp->slice("(1)"); # Just-under-sample
2740 0         0 my $a1 = $samp->slice("(2)"); # Just-over-sample
2741 0         0 my $a1a0 = $a1 - $a0;
2742              
2743 0         0 my $gradient = 0.5 * ($samp->slice("2:3")-$samp->slice("0:1"));
2744 0         0 my $s0 = $gradient->slice("(0)"); # Just-under-gradient
2745 0         0 my $s1 = $gradient->slice("(1)"); # Just-over-gradient
2746              
2747 0         0 $bb = $y->slice("($i)");
2748              
2749             # Collapse the sample...
2750 0         0 $samp = ( $a0 +
2751             $bb * (
2752             $s0 +
2753             $bb * ( (3 * $a1a0 - 2*$s0 - $s1) +
2754             $bb * ( $s1 + $s0 - 2*$a1a0 )
2755             )
2756             )
2757             );
2758              
2759             # "Collapse" the subpixel offset...
2760 0         0 $y = $y->slice(":,($i)");
2761             }
2762              
2763 0         0 return $samp;
2764              
2765             } elsif($method =~ m/^f(ft|ourier)?/i) {
2766              
2767 0         0 eval "use PDLA::FFT;";
2768 0         0 my $fftref = $opt->{fft};
2769 0 0       0 $fftref = [] unless(ref $fftref eq 'ARRAY');
2770 0 0       0 if(@$fftref != 2) {
2771 0         0 my $x = $source->copy;
2772 0         0 my $y = zeroes($source);
2773 0         0 fftnd($x,$y);
2774 0         0 $fftref->[0] = sqrt($x*$x+$y*$y) / $x->nelem;
2775 0         0 $fftref->[1] = - atan2($y,$x);
2776             }
2777              
2778 0         0 my $i;
2779 0         0 my $c = PDLA::Basic::ndcoords($source); # (dim, source-dims)
2780 0         0 for $i(1..$index->ndims-1) {
2781 0         0 $c = $c->dummy($i,$index->dim($i))
2782             }
2783 0         0 my $id = $index->ndims-1;
2784 0         0 my $phase = (($c * $index * 3.14159 * 2 / pdl($source->dims))
2785             ->sumover) # (index-dims, source-dims)
2786             ->reorder($id..$id+$source->ndims-1,0..$id-1); # (src, index)
2787              
2788 0         0 my $phref = $fftref->[1]->copy; # (source-dims)
2789 0         0 my $mag = $fftref->[0]->copy; # (source-dims)
2790              
2791 0         0 for $i(1..$index->ndims-1) {
2792 0         0 $phref = $phref->dummy(-1,$index->dim($i));
2793 0         0 $mag = $mag->dummy(-1,$index->dim($i));
2794             }
2795 0         0 my $out = cos($phase + $phref ) * $mag;
2796 0         0 $out = $out->clump($source->ndims)->sumover;
2797              
2798 0         0 return $out;
2799             } else {
2800 0         0 barf("interpND: unknown method '$method'; valid ones are 'linear' and 'sample'.\n");
2801             }
2802             }
2803              
2804              
2805              
2806              
2807             =head2 one2nd
2808              
2809             =for ref
2810              
2811             Converts a one dimensional index piddle to a set of ND coordinates
2812              
2813             =for usage
2814              
2815             @coords=one2nd($x, $indices)
2816              
2817             returns an array of piddles containing the ND indexes corresponding to
2818             the one dimensional list indices. The indices are assumed to
2819             correspond to array C<$x> clumped using C. This routine is
2820             used in the old vector form of L, but is useful on
2821             its own occasionally.
2822              
2823             Returned piddles have the L datatype. C<$indices> can have
2824             values larger than C<< $x->nelem >> but negative values in C<$indices>
2825             will not give the answer you expect.
2826              
2827             =for example
2828              
2829             pdla> $x=pdl [[[1,2],[-1,1]], [[0,-3],[3,2]]]; $c=$x->clump(-1)
2830             pdla> $maxind=maximum_ind($c); p $maxind;
2831             6
2832             pdla> print one2nd($x, maximum_ind($c))
2833             0 1 1
2834             pdla> p $x->at(0,1,1)
2835             3
2836              
2837             =cut
2838              
2839             *one2nd = \&PDLA::one2nd;
2840             sub PDLA::one2nd {
2841 1 50   1 0 8 barf "Usage: one2nd \$array \$indices\n" if $#_ != 1;
2842 1         2 my ($x, $ind)=@_;
2843 1         4 my @dimension=$x->dims;
2844 1         4 $ind = indx($ind);
2845 1         3 my(@index);
2846 1         3 my $count=0;
2847 1         3 foreach (@dimension) {
2848 3         40 $index[$count++]=$ind % $_;
2849 3         20 $ind /= $_;
2850             }
2851 1         9 return @index;
2852             }
2853              
2854              
2855              
2856              
2857              
2858             =head2 which
2859              
2860             =for sig
2861              
2862             Signature: (mask(n); indx [o] inds(m))
2863              
2864              
2865             =for ref
2866              
2867             Returns indices of non-zero values from a 1-D PDLA
2868              
2869             =for usage
2870              
2871             $i = which($mask);
2872              
2873             returns a pdl with indices for all those elements that are nonzero in
2874             the mask. Note that the returned indices will be 1D. If you feed in a
2875             multidimensional mask, it will be flattened before the indices are
2876             calculated. See also L for multidimensional masks.
2877              
2878             If you want to index into the original mask or a similar piddle
2879             with output from C, remember to flatten it before calling index:
2880              
2881             $data = random 5, 5;
2882             $idx = which $data > 0.5; # $idx is now 1D
2883             $bigsum = $data->flat->index($idx)->sum; # flatten before indexing
2884              
2885             Compare also L for similar functionality.
2886              
2887             SEE ALSO:
2888              
2889             L returns separately the indices of both
2890             zero and nonzero values in the mask.
2891              
2892             L returns associated values from a data PDLA, rather than
2893             indices into the mask PDLA.
2894              
2895             L returns N-D indices into a multidimensional PDLA.
2896              
2897             =for example
2898              
2899             pdla> $x = sequence(10); p $x
2900             [0 1 2 3 4 5 6 7 8 9]
2901             pdla> $indx = which($x>6); p $indx
2902             [7 8 9]
2903              
2904              
2905              
2906             =for bad
2907              
2908             which processes bad values.
2909             It will set the bad-value flag of all output piddles if the flag is set for any of the input piddles.
2910              
2911              
2912             =cut
2913              
2914              
2915              
2916              
2917 167     167 1 741 sub which { my ($this,$out) = @_;
2918 167         526 $this = $this->flat;
2919 167 50       580 $out = $this->nullcreate unless defined $out;
2920 167         3005 PDLA::_which_int($this,$out);
2921 167         1752 return $out;
2922             }
2923             *PDLA::which = \&which;
2924              
2925              
2926             *which = \&PDLA::which;
2927              
2928              
2929              
2930              
2931              
2932             =head2 which_both
2933              
2934             =for sig
2935              
2936             Signature: (mask(n); indx [o] inds(m); indx [o]notinds(q))
2937              
2938              
2939             =for ref
2940              
2941             Returns indices of zero and nonzero values in a mask PDLA
2942              
2943             =for usage
2944              
2945             ($i, $c_i) = which_both($mask);
2946              
2947             This works just as L, but the complement of C<$i> will be in
2948             C<$c_i>.
2949              
2950             =for example
2951              
2952             pdla> $x = sequence(10); p $x
2953             [0 1 2 3 4 5 6 7 8 9]
2954             pdla> ($small, $big) = which_both ($x >= 5); p "$small\n $big"
2955             [5 6 7 8 9]
2956             [0 1 2 3 4]
2957              
2958              
2959              
2960             =for bad
2961              
2962             which_both processes bad values.
2963             It will set the bad-value flag of all output piddles if the flag is set for any of the input piddles.
2964              
2965              
2966             =cut
2967              
2968              
2969              
2970              
2971 1     1 1 7 sub which_both { my ($this,$outi,$outni) = @_;
2972 1         4 $this = $this->flat;
2973 1 50       6 $outi = $this->nullcreate unless defined $outi;
2974 1 50       6 $outni = $this->nullcreate unless defined $outni;
2975 1         45 PDLA::_which_both_int($this,$outi,$outni);
2976 1 50       8 return wantarray ? ($outi,$outni) : $outi;
2977             }
2978             *PDLA::which_both = \&which_both;
2979              
2980              
2981             *which_both = \&PDLA::which_both;
2982              
2983              
2984              
2985              
2986             =head2 where
2987              
2988             =for ref
2989              
2990             Use a mask to select values from one or more data PDLAs
2991              
2992             C accepts one or more data piddles and a mask piddle. It
2993             returns a list of output piddles, corresponding to the input data
2994             piddles. Each output piddle is a 1-dimensional list of values in its
2995             corresponding data piddle. The values are drawn from locations where
2996             the mask is nonzero.
2997              
2998             The output PDLAs are still connected to the original data PDLAs, for the
2999             purpose of dataflow.
3000              
3001             C combines the functionality of L and L
3002             into a single operation.
3003              
3004             BUGS:
3005              
3006             While C works OK for most N-dimensional cases, it does not
3007             thread properly over (for example) the (N+1)th dimension in data
3008             that is compared to an N-dimensional mask. Use C for that.
3009              
3010             =for usage
3011              
3012             $i = $x->where($x+5 > 0); # $i contains those elements of $x
3013             # where mask ($x+5 > 0) is 1
3014             $i .= -5; # Set those elements (of $x) to -5. Together, these
3015             # commands clamp $x to a maximum of -5.
3016              
3017             It is also possible to use the same mask for several piddles with
3018             the same call:
3019              
3020             ($i,$j,$k) = where($x,$y,$z, $x+5>0);
3021              
3022             Note: C<$i> is always 1-D, even if C<$x> is E1-D.
3023              
3024             WARNING: The first argument
3025             (the values) and the second argument (the mask) currently have to have
3026             the exact same dimensions (or horrible things happen). You *cannot*
3027             thread over a smaller mask, for example.
3028              
3029              
3030             =cut
3031              
3032             sub PDLA::where {
3033 105 50   105 0 1343 barf "Usage: where( \$pdl1, ..., \$pdlN, \$mask )\n" if $#_ == 0;
3034              
3035 105 100       257 if($#_ == 1) {
3036 104         194 my($data,$mask) = @_;
3037 104 100       405 $data = $_[0]->clump(-1) if $_[0]->getndims>1;
3038 104 100       309 $mask = $_[1]->clump(-1) if $_[0]->getndims>1;
3039 104         244 return $data->index($mask->which());
3040             } else {
3041 1 50       7 if($_[-1]->getndims > 1) {
3042 0         0 my $mask = $_[-1]->clump(-1)->which;
3043 0         0 return map {$_->clump(-1)->index($mask)} @_[0..$#_-1];
  0         0  
3044             } else {
3045 1         4 my $mask = $_[-1]->which;
3046 1         6 return map {$_->index($mask)} @_[0..$#_-1];
  2         38  
3047             }
3048             }
3049             }
3050             *where = \&PDLA::where;
3051              
3052              
3053              
3054              
3055             =head2 whereND
3056              
3057             =for ref
3058              
3059             C with support for ND masks and threading
3060              
3061             C accepts one or more data piddles and a
3062             mask piddle. It returns a list of output piddles,
3063             corresponding to the input data piddles. The values
3064             are drawn from locations where the mask is nonzero.
3065              
3066             C differs from C in that the mask
3067             dimensionality is preserved which allows for
3068             proper threading of the selection operation over
3069             higher dimensions.
3070              
3071             As with C the output PDLAs are still connected
3072             to the original data PDLAs, for the purpose of dataflow.
3073              
3074             =for usage
3075              
3076             $sdata = whereND $data, $mask
3077             ($s1, $s2, ..., $sn) = whereND $d1, $d2, ..., $dn, $mask
3078              
3079             where
3080              
3081             $data is M dimensional
3082             $mask is N < M dimensional
3083             dims($data) 1..N == dims($mask) 1..N
3084             with threading over N+1 to M dimensions
3085              
3086             =for example
3087              
3088             $data = sequence(4,3,2); # example data array
3089             $mask4 = (random(4)>0.5); # example 1-D mask array, has $n4 true values
3090             $mask43 = (random(4,3)>0.5); # example 2-D mask array, has $n43 true values
3091             $sdat4 = whereND $data, $mask4; # $sdat4 is a [$n4,3,2] pdl
3092             $sdat43 = whereND $data, $mask43; # $sdat43 is a [$n43,2] pdl
3093              
3094             Just as with C, you can use the returned value in an
3095             assignment. That means that both of these examples are valid:
3096              
3097             # Used to create a new slice stored in $sdat4:
3098             $sdat4 = $data->whereND($mask4);
3099             $sdat4 .= 0;
3100             # Used in lvalue context:
3101             $data->whereND($mask4) .= 0;
3102              
3103             =cut
3104              
3105             sub PDLA::whereND :lvalue {
3106 5 50   5 0 149 barf "Usage: whereND( \$pdl1, ..., \$pdlN, \$mask )\n" if $#_ == 0;
3107              
3108 5         10 my $mask = pop @_; # $mask has 0==false, 1==true
3109 5         6 my @to_return;
3110              
3111 5         13 my $n = PDLA::sum($mask);
3112              
3113 5         14 foreach my $arr (@_) {
3114              
3115 5         13 my $sub_i = $mask * ones($arr);
3116 5         22 my $where_sub_i = PDLA::where($arr, $sub_i);
3117              
3118             # count the number of dims in $mask and $arr
3119             # $mask = a b c d e f.....
3120 5         15 my @idims = dims($arr);
3121              
3122             # ...and pop off the number of dims in $mask
3123 5         12 foreach ( dims($mask) ) { shift(@idims) };
  8         14  
3124              
3125 5         9 my $ndim = 0;
3126 5         12 foreach my $id ($n, @idims[0..($#idims-1)]) {
3127 7 100       43 $where_sub_i = $where_sub_i->splitdim($ndim++,$id) if $n>0;
3128             }
3129              
3130 5         19 push @to_return, $where_sub_i;
3131             }
3132              
3133 5 50       22 return (@to_return == 1) ? $to_return[0] : @to_return;
3134             }
3135             *whereND = \&PDLA::whereND;
3136              
3137              
3138              
3139              
3140             =head2 whichND
3141              
3142             =for ref
3143              
3144             Return the coordinates of non-zero values in a mask.
3145              
3146             =for usage
3147              
3148             WhichND returns the N-dimensional coordinates of each nonzero value in
3149             a mask PDLA with any number of dimensions. The returned values arrive
3150             as an array-of-vectors suitable for use in
3151             L or L.
3152              
3153             $coords = whichND($mask);
3154              
3155             returns a PDLA containing the coordinates of the elements that are non-zero
3156             in C<$mask>, suitable for use in indexND. The 0th dimension contains the
3157             full coordinate listing of each point; the 1st dimension lists all the points.
3158             For example, if $mask has rank 4 and 100 matching elements, then $coords has
3159             dimension 4x100.
3160              
3161             If no such elements exist, then whichND returns a structured empty PDLA:
3162             an Nx0 PDLA that contains no values (but matches, threading-wise, with
3163             the vectors that would be produced if such elements existed).
3164              
3165             DEPRECATED BEHAVIOR IN LIST CONTEXT:
3166              
3167             whichND once delivered different values in list context than in scalar
3168             context, for historical reasons. In list context, it returned the
3169             coordinates transposed, as a collection of 1-PDLAs (one per dimension)
3170             in a list. This usage is deprecated in PDLA 2.4.10, and will cause a
3171             warning to be issued every time it is encountered. To avoid the
3172             warning, you can set the global variable "$PDLA::whichND" to 's' to
3173             get scalar behavior in all contexts, or to 'l' to get list behavior in
3174             list context.
3175              
3176             In later versions of PDLA, the deprecated behavior will disappear. Deprecated
3177             list context whichND expressions can be replaced with:
3178              
3179             @list = $x->whichND->mv(0,-1)->dog;
3180              
3181              
3182             SEE ALSO:
3183              
3184             L finds coordinates of nonzero values in a 1-D mask.
3185              
3186             L extracts values from a data PDLA that are associated
3187             with nonzero values in a mask PDLA.
3188              
3189             =for example
3190              
3191             pdla> $s=sequence(10,10,3,4)
3192             pdla> ($x, $y, $z, $w)=whichND($s == 203); p $x, $y, $z, $w
3193             [3] [0] [2] [0]
3194             pdla> print $s->at(list(cat($x,$y,$z,$w)))
3195             203
3196              
3197             =cut
3198              
3199             *whichND = \&PDLA::whichND;
3200             sub PDLA::whichND {
3201 11     11 0 269 my $mask = shift;
3202 11 50       43 $mask = PDLA::pdl('PDLA',$mask) unless(UNIVERSAL::isa($mask,'PDLA'));
3203              
3204             # List context: generate a perl list by dimension
3205 11 50       37 if(wantarray) {
3206 0 0       0 if(!defined($PDLA::whichND)) {
    0          
3207 0         0 printf STDERR "whichND: WARNING - list context deprecated. Set \$PDLA::whichND. Details in pod.";
3208             } elsif($PDLA::whichND =~ m/l/i) {
3209             # old list context enabled by setting $PDLA::whichND to 'l'
3210 0         0 my $ind=($mask->clump(-1))->which;
3211 0         0 return $mask->one2nd($ind);
3212             }
3213             # if $PDLA::whichND does not contain 'l' or 'L', fall through to scalar context
3214             }
3215              
3216             # Scalar context: generate an N-D index piddle
3217              
3218 11 100       57 unless($mask->nelem) {
3219 2         6 return PDLA::new_from_specification('PDLA',indx,$mask->ndims,0);
3220             }
3221              
3222 9 100       33 unless($mask->getndims) {
3223 2 100       7 return $mask ? pdl(indx,0) : PDLA::new_from_specification('PDLA',indx,0);
3224             }
3225              
3226 7         25 $ind = $mask->flat->which->dummy(0,$mask->getndims)->make_physical;
3227 7 100       134 if($ind->nelem==0) {
3228             # In the empty case, explicitly return the correct type of structured empty
3229 1         5 return PDLA::new_from_specification('PDLA',indx,$mask->ndims, 0);
3230             }
3231              
3232 6         36 my $mult = ones($mask->getndims)->long;
3233 6         49 my @mdims = $mask->dims;
3234 6         15 my $i;
3235              
3236 6         17 for $i(0..$#mdims-1) {
3237             # use $tmp for 5.005_03 compatibility
3238 10         500 (my $tmp = $mult->index($i+1)) .= $mult->index($i)*$mdims[$i];
3239             }
3240              
3241 6         26 for $i(0..$#mdims) {
3242 16         118 my($s) = $ind->index($i);
3243 16         163 $s /= $mult->index($i);
3244 16         105 $s %= $mdims[$i];
3245             }
3246              
3247 6         52 return $ind;
3248             }
3249              
3250              
3251              
3252              
3253             =head2 setops
3254              
3255             =for ref
3256              
3257             Implements simple set operations like union and intersection
3258              
3259             =for usage
3260              
3261             Usage: $set = setops($x, , $y);
3262              
3263             The operator can be C, C or C. This is then applied
3264             to C<$x> viewed as a set and C<$y> viewed as a set. Set theory says
3265             that a set may not have two or more identical elements, but setops
3266             takes care of this for you, so C<$x=pdl(1,1,2)> is OK. The functioning
3267             is as follows:
3268              
3269             =over
3270              
3271             =item C
3272              
3273             The resulting vector will contain the elements that are either in C<$x>
3274             I in C<$y> or both. This is the union in set operation terms
3275              
3276             =item C
3277              
3278             The resulting vector will contain the elements that are either in C<$x>
3279             or C<$y>, but not in both. This is
3280              
3281             Union($x, $y) - Intersection($x, $y)
3282              
3283             in set operation terms.
3284              
3285             =item C
3286              
3287             The resulting vector will contain the intersection of C<$x> and C<$y>, so
3288             the elements that are in both C<$x> and C<$y>. Note that for convenience
3289             this operation is also aliased to L.
3290              
3291             =back
3292              
3293             It should be emphasized that these routines are used when one or both of
3294             the sets C<$x>, C<$y> are hard to calculate or that you get from a separate
3295             subroutine.
3296              
3297             Finally IDL users might be familiar with Craig Markwardt's C
3298             routine which has inspired this routine although it was written independently
3299             However the present routine has a few less options (but see the examples)
3300              
3301             =for example
3302              
3303             You will very often use these functions on an index vector, so that is
3304             what we will show here. We will in fact something slightly silly. First
3305             we will find all squares that are also cubes below 10000.
3306              
3307             Create a sequence vector:
3308              
3309             pdla> $x = sequence(10000)
3310              
3311             Find all odd and even elements:
3312              
3313             pdla> ($even, $odd) = which_both( ($x % 2) == 0)
3314              
3315             Find all squares
3316              
3317             pdla> $squares= which(ceil(sqrt($x)) == floor(sqrt($x)))
3318              
3319             Find all cubes (being careful with roundoff error!)
3320              
3321             pdla> $cubes= which(ceil($x**(1.0/3.0)) == floor($x**(1.0/3.0)+1e-6))
3322              
3323             Then find all squares that are cubes:
3324              
3325             pdla> $both = setops($squares, 'AND', $cubes)
3326              
3327             And print these (assumes that C is loaded!)
3328              
3329             pdla> p $x($both)
3330             [0 1 64 729 4096]
3331              
3332             Then find all numbers that are either cubes or squares, but not both:
3333              
3334             pdla> $cube_xor_square = setops($squares, 'XOR', $cubes)
3335              
3336             pdla> p $cube_xor_square->nelem()
3337             112
3338              
3339             So there are a total of 112 of these!
3340              
3341             Finally find all odd squares:
3342              
3343             pdla> $odd_squares = setops($squares, 'AND', $odd)
3344              
3345              
3346             Another common occurrence is to want to get all objects that are
3347             in C<$x> and in the complement of C<$y>. But it is almost always best
3348             to create the complement explicitly since the universe that both are
3349             taken from is not known. Thus use L if possible
3350             to keep track of complements.
3351              
3352             If this is impossible the best approach is to make a temporary:
3353              
3354             This creates an index vector the size of the universe of the sets and
3355             set all elements in C<$y> to 0
3356              
3357             pdla> $tmp = ones($n_universe); $tmp($y) .= 0;
3358              
3359             This then finds the complement of C<$y>
3360              
3361             pdla> $C_b = which($tmp == 1);
3362              
3363             and this does the final selection:
3364              
3365             pdla> $set = setops($x, 'AND', $C_b)
3366              
3367             =cut
3368              
3369             *setops = \&PDLA::setops;
3370              
3371             sub PDLA::setops {
3372              
3373 5     5 0 744 my ($x, $op, $y)=@_;
3374              
3375             # Check that $x and $y are 1D.
3376 5 50 33     35 if ($x->ndims() > 1 || $y->ndims() > 1) {
3377 0         0 warn 'setops: $x and $y must be 1D - flattening them!'."\n";
3378 0         0 $x = $x->flat;
3379 0         0 $y = $y->flat;
3380             }
3381              
3382             #Make sure there are no duplicate elements.
3383 5         15 $x=$x->uniq;
3384 5         11 $y=$y->uniq;
3385              
3386 5         10 my $result;
3387              
3388 5 100       17 if ($op eq 'OR') {
    100          
    50          
3389             # Easy...
3390 1         10 $result = uniq(append($x, $y));
3391             } elsif ($op eq 'XOR') {
3392             # Make ordered list of set union.
3393 1         17 my $union = append($x, $y)->qsort;
3394             # Index lists.
3395 1         8 my $s1=zeroes(byte, $union->nelem());
3396 1         5 my $s2=zeroes(byte, $union->nelem());
3397              
3398             # Find indices which are duplicated - these are to be excluded
3399             #
3400             # We do this by comparing x with x shifted each way.
3401 1         21 my $i1 = which($union != rotate($union, 1));
3402 1         23 my $i2 = which($union != rotate($union, -1));
3403             #
3404             # We then mark/mask these in the s1 and s2 arrays to indicate which ones
3405             # are not equal to their neighbours.
3406             #
3407 1         8 my $ts;
3408 1 50       12 ($ts = $s1->index($i1)) .= 1 if $i1->nelem() > 0;
3409 1 50       12 ($ts = $s2->index($i2)) .= 1 if $i2->nelem() > 0;
3410              
3411 1         12 my $inds=which($s1 == $s2);
3412              
3413 1 50       8 if ($inds->nelem() > 0) {
3414 1         15 return $union->index($inds);
3415             } else {
3416 0         0 return $inds;
3417             }
3418              
3419             } elsif ($op eq 'AND') {
3420             # The intersection of the arrays.
3421              
3422             # Make ordered list of set union.
3423 3         44 my $union = append($x, $y)->qsort;
3424              
3425 3         59 return $union->where($union == rotate($union, -1));
3426             } else {
3427 0         0 print "The operation $op is not known!";
3428 0         0 return -1;
3429             }
3430              
3431             }
3432              
3433              
3434              
3435             =head2 intersect
3436              
3437             =for ref
3438              
3439             Calculate the intersection of two piddles
3440              
3441             =for usage
3442              
3443             Usage: $set = intersect($x, $y);
3444              
3445             This routine is merely a simple interface to L. See
3446             that for more information
3447              
3448             =for example
3449              
3450             Find all numbers less that 100 that are of the form 2*y and 3*x
3451              
3452             pdla> $x=sequence(100)
3453             pdla> $factor2 = which( ($x % 2) == 0)
3454             pdla> $factor3 = which( ($x % 3) == 0)
3455             pdla> $ii=intersect($factor2, $factor3)
3456             pdla> p $x($ii)
3457             [0 6 12 18 24 30 36 42 48 54 60 66 72 78 84 90 96]
3458              
3459             =cut
3460              
3461             *intersect = \&PDLA::intersect;
3462              
3463             sub PDLA::intersect {
3464              
3465 2     2 0 376 return setops($_[0], 'AND', $_[1]);
3466              
3467             }
3468              
3469              
3470              
3471             ;
3472              
3473              
3474             =head1 AUTHOR
3475              
3476             Copyright (C) Tuomas J. Lukka 1997 (lukka@husc.harvard.edu). Contributions
3477             by Christian Soeller (c.soeller@auckland.ac.nz), Karl Glazebrook
3478             (kgb@aaoepp.aao.gov.au), Craig DeForest (deforest@boulder.swri.edu)
3479             and Jarle Brinchmann (jarle@astro.up.pt)
3480             All rights reserved. There is no warranty. You are allowed
3481             to redistribute this software / documentation under certain
3482             conditions. For details, see the file COPYING in the PDLA
3483             distribution. If this file is separated from the PDLA distribution,
3484             the copyright notice should be included in the file.
3485              
3486             Updated for CPAN viewing compatibility by David Mertens.
3487              
3488             =cut
3489              
3490              
3491              
3492              
3493              
3494             # Exit with OK status
3495              
3496             1;
3497              
3498