~ubuntu-branches/ubuntu/trusty/pdl/trusty-proposed

« back to all changes in this revision

Viewing changes to .pc/fix_pod2man_errors.patch/Basic/Complex/complex.pd

  • Committer: Package Import Robot
  • Author(s): Henning Glawe
  • Date: 2013-11-11 13:34:09 UTC
  • mfrom: (2.1.14 sid)
  • Revision ID: package-import@ubuntu.com-20131111133409-kjib7wtpms3kwusg
Tags: 1:2.007-2
* successfully built with gcc 4.8 (closes: #701335, #713346)
* add build log evalution helpers to source package: extract
  test suite output from buildlog, cross-refernce test/subtest
  failures between architectures
* use shell to join stderr into stdout while running test suite
* fix Dumper.pm on kfreebsd: 'gnukfreebsd' was assumed as a bsd
  userland, which disabled/broke calls to 'uuencode' and 'uudecode'
* fix debian/filter-test.pl, which cut the test log too early
  due to a too-unspecific regex
* prefer F77Conf over ExtUtils::F77 in t/flexraw_fortran.t in order
  to prevent test failures on kfreebsd* and hurd*

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
$VERSION = 0.7;
 
2
 
 
3
# pp_setversion $VERSION;  # haven't worked out why it breaks my system (CS)
 
4
pp_beginwrap; # required for overload to work
 
5
 
 
6
# pp_def functions go into the PDL::Complex namespace
 
7
# to avoid clashing with PDL::FFTW funcs of the same name that go
 
8
# into the PDL namespace
 
9
# it should be of no effect to the user of the module but you
 
10
# never know....
 
11
pp_bless('PDL::Complex');
 
12
 
 
13
pp_addpm {At => Top}, <<'EOD';
 
14
   use PDL::Slices;
 
15
   use PDL::Types;
 
16
   use PDL::Bad;
 
17
 
 
18
   use vars qw($sep $sep2);
 
19
EOD
 
20
 
 
21
 
 
22
pp_addpm {At => Top}, <<'EOD';
 
23
=head1 NAME
 
24
 
 
25
PDL::Complex - handle complex numbers
 
26
 
 
27
=head1 SYNOPSIS
 
28
 
 
29
  use PDL;
 
30
  use PDL::Complex;
 
31
 
 
32
=head1 DESCRIPTION
 
33
 
 
34
This module features a growing number of functions manipulating complex
 
35
numbers. These are usually represented as a pair C<[ real imag ]> or
 
36
C<[ angle phase ]>. If not explicitly mentioned, the functions can work
 
37
inplace (not yet implemented!!!) and require rectangular form.
 
38
 
 
39
While there is a procedural interface available (C<< $a/$b*$c <=> Cmul
 
40
(Cdiv $a, $b), $c) >>), you can also opt to cast your pdl's into the
 
41
C<PDL::Complex> datatype, which works just like your normal piddles, but
 
42
with all the normal perl operators overloaded.
 
43
 
 
44
The latter means that C<sin($a) + $b/$c> will be evaluated using the
 
45
normal rules of complex numbers, while other pdl functions (like C<max>)
 
46
just treat the piddle as a real-valued piddle with a lowest dimension of
 
47
size 2, so C<max> will return the maximum of all real and imaginary parts,
 
48
not the "highest" (for some definition)
 
49
 
 
50
=head1 TIPS, TRICKS & CAVEATS
 
51
 
 
52
=over 4
 
53
 
 
54
=item *
 
55
 
 
56
C<i> is a constant exported by this module, which represents
 
57
C<-1**0.5>, i.e. the imaginary unit. it can be used to quickly and
 
58
conviniently write complex constants like this: C<4+3*i>.
 
59
 
 
60
=item *
 
61
 
 
62
Use C<r2C(real-values)> to convert from real to complex, as in C<$r
 
63
= Cpow $cplx, r2C 2>. The overloaded operators automatically do that for
 
64
you, all the other functions, do not. So C<Croots 1, 5> will return all
 
65
the fifths roots of 1+1*i (due to threading).
 
66
 
 
67
=item *
 
68
 
 
69
use C<cplx(real-valued-piddle)> to cast from normal piddles into the
 
70
complex datatype. Use C<real(complex-valued-piddle)> to cast back. This
 
71
requires a copy, though.
 
72
 
 
73
=item *
 
74
 
 
75
This module has received some testing by Vanuxem Gr�gory
 
76
(g.vanuxem at wanadoo dot fr). Please report any other errors you
 
77
come across!
 
78
 
 
79
=back
 
80
 
 
81
=head1 EXAMPLE WALK-THROUGH
 
82
 
 
83
The complex constant five is equal to C<pdl(1,0)>:
 
84
 
 
85
   pdl> p $x = r2C 5
 
86
   5 +0i
 
87
 
 
88
Now calculate the three cubic roots of of five:
 
89
 
 
90
   pdl> p $r = Croots $x, 3
 
91
   [1.70998 +0i  -0.854988 +1.48088i  -0.854988 -1.48088i]
 
92
 
 
93
Check that these really are the roots:
 
94
 
 
95
   pdl> p $r ** 3
 
96
   [5 +0i  5 -1.22465e-15i  5 -7.65714e-15i]
 
97
 
 
98
Duh! Could be better. Now try by multiplying C<$r> three times with itself:
 
99
 
 
100
   pdl> p $r*$r*$r
 
101
   [5 +0i  5 -4.72647e-15i  5 -7.53694e-15i]
 
102
 
 
103
Well... maybe C<Cpow> (which is used by the C<**> operator) isn't as
 
104
bad as I thought. Now multiply by C<i> and negate, which is just a very
 
105
expensive way of swapping real and imaginary parts.
 
106
 
 
107
   pdl> p -($r*i)
 
108
   [0 -1.70998i  1.48088 +0.854988i  -1.48088 +0.854988i]
 
109
 
 
110
Now plot the magnitude of (part of) the complex sine. First generate the
 
111
coefficients:
 
112
 
 
113
   pdl> $sin = i * zeroes(50)->xlinvals(2,4) + zeroes(50)->xlinvals(0,7)
 
114
 
 
115
Now plot the imaginary part, the real part and the magnitude of the sine
 
116
into the same diagram:
 
117
 
 
118
   pdl> use PDL::Graphics::Gnuplot
 
119
   pdl> gplot( with => 'lines',
 
120
              PDL::cat(im ( sin $sin ),
 
121
                       re ( sin $sin ),
 
122
                       abs( sin $sin ) ))
 
123
 
 
124
An ASCII version of this plot looks like this:
 
125
 
 
126
  30 ++-----+------+------+------+------+------+------+------+------+-----++
 
127
     +      +      +      +      +      +      +      +      +      +      +
 
128
     |                                                                   $$|
 
129
     |                                                                  $  |
 
130
  25 ++                                                               $$  ++
 
131
     |                                                              ***    |
 
132
     |                                                            **   *** |
 
133
     |                                                         $$*        *|
 
134
  20 ++                                                       $**         ++
 
135
     |                                                     $$$*           #|
 
136
     |                                                  $$$   *          # |
 
137
     |                                                $$     *           # |
 
138
  15 ++                                            $$$       *          # ++
 
139
     |                                          $$$        **           #  |
 
140
     |                                      $$$$          *            #   |
 
141
     |                                  $$$$              *            #   |
 
142
  10 ++                            $$$$$                 *            #   ++
 
143
     |                        $$$$$                     *             #    |
 
144
     |                 $$$$$$$                         *             #     |
 
145
   5 ++       $$$############                          *             #    ++
 
146
     |*****$$$###            ###                      *             #      |
 
147
     *    #*****                #                     *             #      |
 
148
     | ###      ***              ###                **              #      |
 
149
   0 ##            ***              #              *               #      ++
 
150
     |                *              #             *              #        |
 
151
     |                 ***            #          **               #        |
 
152
     |                    *            #        *                #         |
 
153
  -5 ++                    **           #      *                 #        ++
 
154
     |                       ***         ##  **                 #          |
 
155
     |                          *          #*                  #           |
 
156
     |                           ****    ***##                #            |
 
157
 -10 ++                              ****     #              #            ++
 
158
     |                                         #             #             |
 
159
     |                                          ##         ##              |
 
160
     +      +      +      +      +      +      +  ### + ###  +      +      +
 
161
 -15 ++-----+------+------+------+------+------+-----###-----+------+-----++
 
162
     0      5      10     15     20     25     30     35     40     45     50
 
163
 
 
164
=cut
 
165
 
 
166
my $i;
 
167
BEGIN { $i = bless pdl 0,1 }
 
168
sub i () { $i->copy };
 
169
EOD
 
170
 
 
171
for (qw(Ctan Catan re im i cplx real)) {
 
172
   pp_add_exported '', $_;
 
173
}
 
174
 
 
175
pp_addhdr <<'EOH';
 
176
 
 
177
#include <math.h>
 
178
 
 
179
#ifndef M_PI
 
180
# define M_PI   3.1415926535897932384626433832795029
 
181
#endif
 
182
#ifndef M_2PI
 
183
# define M_2PI  (2. * M_PI)
 
184
#endif
 
185
 
 
186
#if __GLIBC__ > 1 && (defined __USE_MISC || defined __USE_XOPEN || defined __USE_ISOC9X)
 
187
# define CABS(r,i) hypot (r, i)
 
188
#else
 
189
  static double
 
190
  CABS (double r, double i)
 
191
  {
 
192
    double t;
 
193
 
 
194
    if (r < 0) r = - r;
 
195
    if (i < 0) i = - i;
 
196
 
 
197
    if (i > r)
 
198
      {
 
199
        t = r; r = i; i = t;
 
200
      }
 
201
 
 
202
    if (r + i == r)
 
203
      return r;
 
204
 
 
205
    t = i / r;
 
206
    return r * sqrt (1 + t*t);
 
207
  }
 
208
#endif
 
209
 
 
210
#if __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1 && defined __USE_GNU
 
211
# define SINCOS(x,s,c) sincos ((x), &(s), &(c))
 
212
#else
 
213
# define SINCOS(x,s,c)                  \
 
214
        (s) = sin (x);                  \
 
215
        (c) = cos (x);
 
216
#endif
 
217
 
 
218
 
 
219
#define CSQRT(type,ar,ai,cr,ci)                 \
 
220
        type mag = CABS ((ar), (ai));           \
 
221
        type t;                                 \
 
222
                                                \
 
223
        if (mag == 0)                           \
 
224
          (cr) = (ci) = 0;                      \
 
225
        else if ((ar) > 0)                      \
 
226
          {                                     \
 
227
            t = sqrt (0.5 * (mag + (ar)));      \
 
228
            (cr) = t;                           \
 
229
            (ci) = 0.5 * (ai) / t;              \
 
230
          }                                     \
 
231
        else                                    \
 
232
          {                                     \
 
233
            t = sqrt (0.5 * (mag - (ar)));      \
 
234
                                                \
 
235
            if ((ai) < 0)                       \
 
236
              t = -t;                           \
 
237
                                                \
 
238
            (cr) = 0.5 * (ai) / t;              \
 
239
            (ci) = t;                           \
 
240
          }
 
241
 
 
242
 
 
243
#define CLOG(ar,ai,cr,ci)                       \
 
244
        (cr) = log (CABS ((ar), (ai)));         \
 
245
        (ci) = atan2 ((ai), (ar));
 
246
 
 
247
EOH
 
248
 
 
249
pp_addpm <<'EOP';
 
250
 
 
251
=head2 cplx real-valued-pdl
 
252
 
 
253
Cast a real-valued piddle to the complex datatype. The first dimension of
 
254
the piddle must be of size 2. After this the usual (complex) arithmetic
 
255
operators are applied to this pdl, rather than the normal elementwise pdl
 
256
operators.  Dataflow to the complex parent works. Use C<sever> on the result
 
257
if you don't want this.
 
258
 
 
259
 
 
260
=head2 complex real-valued-pdl
 
261
 
 
262
Cast a real-valued piddle to the complex datatype I<without> dataflow
 
263
and I<inplace>. Achieved by merely reblessing a piddle. The first dimension of
 
264
the piddle must be of size 2.
 
265
 
 
266
=head2 real cplx-valued-pdl
 
267
 
 
268
Cast a complex valued pdl back to the "normal" pdl datatype. Afterwards
 
269
the normal elementwise pdl operators are used in operations. Dataflow
 
270
to the real parent works. Use C<sever> on the result if you don't want this.
 
271
 
 
272
=cut
 
273
 
 
274
use Carp;
 
275
sub cplx($) {
 
276
   return $_[0] if UNIVERSAL::isa($_[0],'PDL::Complex'); # NOOP if just piddle
 
277
   croak "first dimsize must be 2" unless $_[0]->dims > 0 && $_[0]->dim(0) == 2;
 
278
   bless $_[0]->slice('');
 
279
}
 
280
 
 
281
sub complex($) {
 
282
   return $_[0] if UNIVERSAL::isa($_[0],'PDL::Complex'); # NOOP if just piddle
 
283
   croak "first dimsize must be 2" unless $_[0]->dims > 0 && $_[0]->dim(0) == 2;
 
284
   bless $_[0];
 
285
}
 
286
 
 
287
*PDL::cplx = \&cplx;
 
288
*PDL::complex = \&complex;
 
289
 
 
290
sub real($) {
 
291
   return $_[0] unless UNIVERSAL::isa($_[0],'PDL::Complex'); # NOOP unless complex
 
292
   bless $_[0]->slice(''), 'PDL';
 
293
}
 
294
 
 
295
EOP
 
296
 
 
297
pp_def 'r2C',
 
298
       Pars => 'r(); [o]c(m=2)',
 
299
       Doc => 'convert real to complex, assuming an imaginary part of zero',
 
300
       PMCode => << 'EOPM',
 
301
 
 
302
*PDL::r2C = \&PDL::Complex::r2C;
 
303
sub PDL::Complex::r2C($) {
 
304
  return $_[0] if UNIVERSAL::isa($_[0],'PDL::Complex');
 
305
  my $r = __PACKAGE__->initialize;
 
306
  &PDL::Complex::_r2C_int($_[0], $r);
 
307
  $r }
 
308
 
 
309
EOPM
 
310
       Code => q!
 
311
          $c(m=>0) = $r();
 
312
          $c(m=>1) = 0;
 
313
       !
 
314
;
 
315
 
 
316
pp_def 'i2C',
 
317
       Pars => 'r(); [o]c(m=2)',
 
318
       Doc => 'convert imaginary to complex, assuming a real part of zero',
 
319
       PMCode => '*PDL::i2C = \&PDL::Complex::i2C; sub PDL::Complex::i2C($) { my $r = __PACKAGE__->initialize; &PDL::Complex::_i2C_int($_[0], $r); $r }',
 
320
       Code => q!
 
321
          $c(m=>0) = 0;
 
322
          $c(m=>1) = $r();
 
323
       !
 
324
;
 
325
 
 
326
pp_def 'Cr2p',
 
327
       Pars => 'r(m=2); float+ [o]p(m=2)',
 
328
       Inplace => 1,
 
329
       Doc => 'convert complex numbers in rectangular form to polar (mod,arg) form. Works inplace',
 
330
       Code => q!
 
331
          $GENERIC() x = $r(m=>0);
 
332
          $GENERIC() y = $r(m=>1);
 
333
          $p(m=>0) = CABS (x, y);
 
334
          $p(m=>1) = atan2 (y, x);
 
335
       !
 
336
;
 
337
 
 
338
pp_def 'Cp2r',
 
339
       Pars => 'r(m=2); [o]p(m=2)',
 
340
       Inplace => 1,
 
341
       GenericTypes => [F,D],
 
342
       Doc => 'convert complex numbers in polar (mod,arg) form to rectangular form. Works inplace',
 
343
       Code => q!
 
344
          $GENERIC() m = $r(m=>0);
 
345
          $GENERIC() a = $r(m=>1);
 
346
          double s, c;
 
347
 
 
348
          SINCOS (a, s, c);
 
349
          $p(m=>0) = c * m;
 
350
          $p(m=>1) = s * m;
 
351
       !
 
352
;
 
353
 
 
354
pp_def 'Cadd', # this is here for a) completeness and b) not having to mess with PDL::Ops
 
355
        Pars => 'a(m=2); b(m=2); [o]c(m=2)',
 
356
        Doc => undef,
 
357
        Code => q^
 
358
           $GENERIC() ar = $a(m=>0), ai = $a(m=>1);
 
359
           $GENERIC() br = $b(m=>0), bi = $b(m=>1);
 
360
           $c(m=>0) = ar + br;
 
361
           $c(m=>1) = ai + bi;
 
362
        ^
 
363
;
 
364
 
 
365
pp_def 'Csub', # this is here for a) completeness and b) not having to mess with PDL::Ops
 
366
        Pars => 'a(m=2); b(m=2); [o]c(m=2)',
 
367
        Doc => undef,
 
368
        Code => q^
 
369
           $GENERIC() ar = $a(m=>0), ai = $a(m=>1);
 
370
           $GENERIC() br = $b(m=>0), bi = $b(m=>1);
 
371
           $c(m=>0) = ar - br;
 
372
           $c(m=>1) = ai - bi;
 
373
        ^
 
374
;
 
375
 
 
376
pp_def 'Cmul',
 
377
        Pars => 'a(m=2); b(m=2); [o]c(m=2)',
 
378
        Doc => 'complex multiplication',
 
379
        Code => q^
 
380
           $GENERIC() ar = $a(m=>0), ai = $a(m=>1);
 
381
           $GENERIC() br = $b(m=>0), bi = $b(m=>1);
 
382
           $c(m=>0) = ar*br - ai*bi;
 
383
           $c(m=>1) = ar*bi + ai*br;
 
384
        ^
 
385
;
 
386
 
 
387
pp_def 'Cprodover',
 
388
        Pars => 'a(m=2,n); [o]c(m=2)',
 
389
        Doc => 'Project via product to N-1 dimension',
 
390
        Code => q^
 
391
            PDL_Long iter;
 
392
            $GENERIC() br, bi, cr, ci,tmp;
 
393
            cr = $a(m=>0,n=>0);
 
394
            ci = $a(m=>1,n=>0);
 
395
           for  (iter=1; iter < $SIZE(n);iter++)
 
396
           {
 
397
                   br = $a(m=>0,n=>iter);
 
398
                   bi = $a(m=>1,n=>iter);
 
399
                   tmp =  cr*bi + ci*br;
 
400
                   cr = cr*br - ci*bi;
 
401
                   ci = tmp;
 
402
           }
 
403
            $c(m=>0) = cr;
 
404
            $c(m=>1) = ci;
 
405
        ^
 
406
;
 
407
 
 
408
pp_def 'Cscale',
 
409
        Pars => 'a(m=2); b(); [o]c(m=2)',
 
410
        Doc => 'mixed complex/real multiplication',
 
411
        Code => q^
 
412
           $GENERIC() ar = $a(m=>0), ai = $a(m=>1);
 
413
           $c(m=>0) = ar * $b();
 
414
           $c(m=>1) = ai * $b();
 
415
        ^
 
416
;
 
417
 
 
418
pp_def 'Cdiv',
 
419
        Pars => 'a(m=2); b(m=2); [o]c(m=2)',
 
420
        GenericTypes => [F,D],
 
421
        Doc => 'complex division',
 
422
        Code => q^
 
423
           $GENERIC() ar = $a(m=>0), ai = $a(m=>1);
 
424
           $GENERIC() br = $b(m=>0), bi = $b(m=>1);
 
425
 
 
426
           if (fabs (br) > fabs (bi))
 
427
             {
 
428
               $GENERIC() tt = bi / br;
 
429
               $GENERIC() dn = br + tt * bi;
 
430
               $c(m=>0) = (ar + tt * ai) / dn;
 
431
               $c(m=>1) = (ai - tt * ar) / dn;
 
432
             }
 
433
           else
 
434
             {
 
435
               $GENERIC() tt = br / bi;
 
436
               $GENERIC() dn = br * tt + bi;
 
437
               $c(m=>0) = (ar * tt + ai) / dn;
 
438
               $c(m=>1) = (ai * tt - ar) / dn;
 
439
             }
 
440
        ^
 
441
;
 
442
 
 
443
pp_def 'Ccmp',
 
444
        Pars => 'a(m=2); b(m=2); [o]c()',
 
445
        GenericTypes => [F,D],
 
446
        Doc => 'Complex comparison oeprator (spaceship). It orders by real first, then by imaginary. Hm, but it is mathematical nonsense! Complex numbers cannot be ordered.',
 
447
        Code => q^
 
448
           $GENERIC() a, b;
 
449
 
 
450
           a = $a(m=>0), b = $b(m=>0);
 
451
           if (a != b)
 
452
             $c() = (a > b) * 2 - 1;
 
453
           else
 
454
             {
 
455
               a = $a(m=>1), b = $b(m=>1);
 
456
               $c() = a == b ? 0
 
457
                             : (a > b) * 2 - 1;
 
458
             }
 
459
        ^
 
460
;
 
461
 
 
462
pp_def 'Cconj',
 
463
        Pars => 'a(m=2); [o]c(m=2)',
 
464
        Inplace => 1,
 
465
        Doc => 'complex conjugation. Works inplace',
 
466
        Code => q^
 
467
           $c(m=>0) =  $a(m=>0);
 
468
           $c(m=>1) = -$a(m=>1);
 
469
        ^
 
470
;
 
471
 
 
472
pp_def 'Cabs',
 
473
        Pars => 'a(m=2); [o]c()',
 
474
        GenericTypes => [F,D],
 
475
        Doc => 'complex C<abs()> (also known as I<modulus>)',
 
476
        PMCode => q^sub PDL::Complex::Cabs($) {
 
477
           my $pdl= shift;
 
478
           my $abs = PDL->null;
 
479
           &PDL::Complex::_Cabs_int($pdl, $abs);
 
480
           $abs;
 
481
        }^,
 
482
        Code => q^
 
483
           $GENERIC() ar = $a(m=>0), ai = $a(m=>1);
 
484
           $c() = CABS (ar, ai);
 
485
        ^
 
486
;
 
487
 
 
488
pp_def 'Cabs2',
 
489
        Pars => 'a(m=2); [o]c()',
 
490
        Doc => 'complex squared C<abs()> (also known I<squared modulus>)',
 
491
        PMCode => q^sub PDL::Complex::Cabs2($) {
 
492
           my $pdl= shift;
 
493
           my $abs2 = PDL->null;
 
494
           &PDL::Complex::_Cabs2_int($pdl, $abs2);
 
495
           $abs2;
 
496
        }^,
 
497
        Code => q^
 
498
           $GENERIC() ar = $a(m=>0), ai = $a(m=>1);
 
499
           $c() = ar*ar + ai*ai;
 
500
        ^
 
501
;
 
502
 
 
503
pp_def 'Carg',
 
504
        Pars => 'a(m=2); [o]c()',
 
505
        GenericTypes => [F,D],
 
506
        Doc => 'complex argument function ("angle")',
 
507
        PMCode => q^sub PDL::Complex::Carg($) {
 
508
           my $pdl= shift;
 
509
           my $arg = PDL->null;
 
510
           &PDL::Complex::_Carg_int($pdl, $arg);
 
511
           $arg;
 
512
        }^,
 
513
        Code => q^
 
514
           $c() = atan2 ($a(m=>1), $a(m=>0));
 
515
        ^
 
516
;
 
517
 
 
518
pp_def 'Csin',
 
519
        Pars => 'a(m=2); [o]c(m=2)',
 
520
        Inplace => 1,
 
521
        GenericTypes => [F,D],
 
522
        Doc => '  sin (a) = 1/(2*i) * (exp (a*i) - exp (-a*i)). Works inplace',
 
523
        Code => q^
 
524
           $GENERIC() ar = $a(m=>0), ai = $a(m=>1);
 
525
           double s, c;
 
526
 
 
527
           SINCOS (ar, s, c);
 
528
           $c(m=>0) = s * cosh (ai);
 
529
           $c(m=>1) = c * sinh (ai);
 
530
        ^
 
531
;
 
532
 
 
533
pp_def 'Ccos',
 
534
        Pars => 'a(m=2); [o]c(m=2)',
 
535
        Inplace => 1,
 
536
        GenericTypes => [F,D],
 
537
        Doc => '  cos (a) = 1/2 * (exp (a*i) + exp (-a*i)). Works inplace',
 
538
        Code => q^
 
539
           $GENERIC() ar = $a(m=>0), ai = $a(m=>1);
 
540
           double s, c;
 
541
 
 
542
           SINCOS (ar, s, c);
 
543
           $c(m=>0) =   c * cosh (ai);
 
544
           $c(m=>1) = - s * sinh (ai);
 
545
        ^
 
546
;
 
547
 
 
548
pp_addpm <<'EOD';
 
549
 
 
550
=head2 Ctan a [not inplace]
 
551
 
 
552
  tan (a) = -i * (exp (a*i) - exp (-a*i)) / (exp (a*i) + exp (-a*i))
 
553
 
 
554
=cut
 
555
 
 
556
sub Ctan($) { Csin($_[0]) / Ccos($_[0]) }
 
557
 
 
558
 
 
559
EOD
 
560
 
 
561
pp_def 'Cexp',
 
562
        Pars => 'a(m=2); [o]c(m=2)',
 
563
        Inplace => 1,
 
564
        GenericTypes => [F,D],
 
565
        Doc => 'exp (a) = exp (real (a)) * (cos (imag (a)) + i * sin (imag (a))). Works inplace',
 
566
        Code => q^
 
567
           $GENERIC() ar = $a(m=>0), ai = $a(m=>1);
 
568
           $GENERIC() ex = exp (ar);
 
569
           double s, c;
 
570
 
 
571
           SINCOS (ai, s, c);
 
572
           $c(m=>0) = ex * c;
 
573
           $c(m=>1) = ex * s;
 
574
        ^
 
575
;
 
576
 
 
577
pp_def 'Clog',
 
578
        Pars => 'a(m=2); [o]c(m=2)',
 
579
        Inplace => 1,
 
580
        GenericTypes => [F,D],
 
581
        Doc => 'log (a) = log (cabs (a)) + i * carg (a). Works inplace',
 
582
        Code => q^
 
583
           $GENERIC() ar = $a(m=>0), ai = $a(m=>1);
 
584
 
 
585
           CLOG (ar, ai, $c(m=>0), $c(m=>1));
 
586
        ^
 
587
;
 
588
 
 
589
pp_def 'Cpow',
 
590
        Pars => 'a(m=2); b(m=2); [o]c(m=2)',
 
591
        Inplace => ['a'],
 
592
        GenericTypes => [F,D],
 
593
        Doc => 'complex C<pow()> (C<**>-operator)',
 
594
        Code => q^
 
595
           $GENERIC() ar = $a(m=>0), ai = $a(m=>1);
 
596
           $GENERIC() br = $b(m=>0), bi = $b(m=>1);
 
597
 
 
598
           double logr, logi, x, y;
 
599
           double  s, c;
 
600
 
 
601
           if(ar == 0 && ai == 0){
 
602
             if(br == 0 && bi == 0) {
 
603
               $c(m=>0) = 1;
 
604
               $c(m=>1) = 0;
 
605
             }
 
606
             else {
 
607
               $c(m=>0) = 0;
 
608
               $c(m=>1) = 0;
 
609
             }
 
610
           }
 
611
           else {
 
612
             CLOG (ar, ai, logr, logi);
 
613
             x = exp (logr*br - logi*bi);
 
614
             y =      logr*bi + logi*br;
 
615
 
 
616
             SINCOS (y, s, c);
 
617
 
 
618
             $c(m=>0) = x * c;
 
619
             if(ai == 0 && bi == 0) $c(m=>1) = 0;
 
620
             else $c(m=>1) = x * s;
 
621
           }
 
622
        ^
 
623
;
 
624
 
 
625
pp_def 'Csqrt',
 
626
        Pars => 'a(m=2); [o]c(m=2)',
 
627
        Inplace => 1,
 
628
        GenericTypes => [F,D],
 
629
        Doc => 'Works inplace',
 
630
        Code => q^
 
631
           $GENERIC() ar = $a(m=>0), ai = $a(m=>1);
 
632
 
 
633
           CSQRT ($GENERIC(), ar, ai, $c(m=>0), $c(m=>1));
 
634
        ^
 
635
;
 
636
 
 
637
pp_def 'Casin',
 
638
        Pars => 'a(m=2); [o]c(m=2)',
 
639
        Inplace => 1,
 
640
        GenericTypes => [F,D],
 
641
        Doc => 'Works inplace',
 
642
        Code => q^
 
643
           $GENERIC() ar = $a(m=>0), ai = $a(m=>1);
 
644
 
 
645
           $GENERIC() t1 = sqrt ((ar+1)*(ar+1) + ai*ai);
 
646
           $GENERIC() t2 = sqrt ((ar-1)*(ar-1) + ai*ai);
 
647
           $GENERIC() alpha = (t1+t2)*0.5;
 
648
           $GENERIC() beta  = (t1-t2)*0.5;
 
649
 
 
650
           if      (alpha < 1) alpha = 1;
 
651
           if      (beta >  1) beta =  1;
 
652
           else if (beta < -1) beta = -1;
 
653
 
 
654
           $c(m=>0) =   atan2 (beta, sqrt (1-beta*beta));
 
655
           $c(m=>1) = - log (alpha + sqrt (alpha*alpha-1));
 
656
           if (ai > 0 || (ai == 0 && ar < -1))
 
657
              $c(m=>1) = - $c(m=>1);
 
658
        ^
 
659
;
 
660
 
 
661
pp_def 'Cacos',
 
662
        Pars => 'a(m=2); [o]c(m=2)',
 
663
        Inplace => 1,
 
664
        GenericTypes => [F,D],
 
665
        Doc => 'Works inplace',
 
666
        Code => q^
 
667
           $GENERIC() ar = $a(m=>0), ai = $a(m=>1);
 
668
 
 
669
           $GENERIC() t1 = sqrt ((ar+1)*(ar+1) + ai*ai);
 
670
           $GENERIC() t2 = sqrt ((ar-1)*(ar-1) + ai*ai);
 
671
           $GENERIC() alpha = (t1+t2)*0.5;
 
672
           $GENERIC() beta  = (t1-t2)*0.5;
 
673
 
 
674
           if      (alpha < 1) alpha = 1;
 
675
           if      (beta >  1) beta =  1;
 
676
           else if (beta < -1) beta = -1;
 
677
 
 
678
           $c(m=>0) = atan2 (sqrt (1-beta*beta), beta);
 
679
           $c(m=>1) = log (alpha + sqrt (alpha*alpha-1));
 
680
           if (ai > 0 || (ai == 0 && ar < -1))
 
681
              $c(m=>1) = - $c(m=>1);
 
682
        ^
 
683
;
 
684
 
 
685
pp_addpm <<'EOD';
 
686
 
 
687
=head2 Catan cplx [not inplace]
 
688
 
 
689
Return the complex C<atan()>.
 
690
 
 
691
=cut
 
692
 
 
693
sub Catan($) {
 
694
   my $z = shift;
 
695
   Cmul Clog(Cdiv (PDL::Complex::i+$z, PDL::Complex::i-$z)), pdl(0, 0.5);
 
696
}
 
697
 
 
698
EOD
 
699
 
 
700
pp_def 'Csinh',
 
701
        Pars => 'a(m=2); [o]c(m=2)',
 
702
        Inplace => 1,
 
703
        GenericTypes => [F,D],
 
704
        Doc => '  sinh (a) = (exp (a) - exp (-a)) / 2. Works inplace',
 
705
        Code => q^
 
706
           $GENERIC() ar = $a(m=>0), ai = $a(m=>1);
 
707
           double s, c;
 
708
 
 
709
           SINCOS (ai, s, c);
 
710
           $c(m=>0) = sinh (ar) * c;
 
711
           $c(m=>1) = cosh (ar) * s;
 
712
        ^
 
713
;
 
714
 
 
715
pp_def 'Ccosh',
 
716
        Pars => 'a(m=2); [o]c(m=2)',
 
717
        Inplace => 1,
 
718
        GenericTypes => [F,D],
 
719
        Doc => '  cosh (a) = (exp (a) + exp (-a)) / 2. Works inplace',
 
720
        Code => q^
 
721
           $GENERIC() ar = $a(m=>0), ai = $a(m=>1);
 
722
           double s, c;
 
723
 
 
724
           SINCOS (ai, s, c);
 
725
           $c(m=>0) = cosh (ar) * c;
 
726
           $c(m=>1) = sinh (ar) * s;
 
727
        ^
 
728
;
 
729
 
 
730
pp_def 'Ctanh',
 
731
        Pars => 'a(m=2); [o]c(m=2)',
 
732
        Inplace => 1,
 
733
        GenericTypes => [F,D],
 
734
        Doc => 'Works inplace',
 
735
        Code => q^
 
736
           $GENERIC() ar = $a(m=>0), ai = $a(m=>1);
 
737
           double den;
 
738
           double s, c;
 
739
 
 
740
           SINCOS (2*ai, s, c);
 
741
           den = cosh (2*ar) + c;
 
742
 
 
743
           $c(m=>0) = sinh (2*ar) / den;
 
744
           $c(m=>1) = s           / den;
 
745
        ^
 
746
;
 
747
 
 
748
pp_def 'Casinh',
 
749
        Pars => 'a(m=2); [o]c(m=2)',
 
750
        Inplace => 1,
 
751
        GenericTypes => [F,D],
 
752
        Doc => 'Works inplace',
 
753
        Code => q^
 
754
           $GENERIC() ar = $a(m=>0), ai = $a(m=>1);
 
755
           $GENERIC() yr = (ar-ai) * (ar+ai) + 1;
 
756
           $GENERIC() yi = 2*ar*ai;
 
757
 
 
758
           CSQRT ($GENERIC(), yr, yi, yr, yi)
 
759
 
 
760
           yr += ar;
 
761
           yi += ai;
 
762
 
 
763
           CLOG (yr, yi, $c(m=>0), $c(m=>1));
 
764
        ^
 
765
;
 
766
 
 
767
pp_def 'Cacosh',
 
768
        Pars => 'a(m=2); [o]c(m=2)',
 
769
        Inplace => 1,
 
770
        GenericTypes => [F,D],
 
771
        Doc => 'Works inplace',
 
772
        Code => q^
 
773
           $GENERIC() ar = $a(m=>0), ai = $a(m=>1);
 
774
 
 
775
           $GENERIC() yr = (ar-ai) * (ar+ai) - 1;
 
776
           $GENERIC() yi = 2*ar*ai;
 
777
 
 
778
           CSQRT ($GENERIC(), yr, yi, yr, yi)
 
779
 
 
780
           yr += ar;
 
781
           yi += ai;
 
782
 
 
783
           CLOG (yr, yi, $c(m=>0), $c(m=>1));
 
784
        ^
 
785
;
 
786
 
 
787
pp_def 'Catanh',
 
788
        Pars => 'a(m=2); [o]c(m=2)',
 
789
        Inplace => 1,
 
790
        GenericTypes => [F,D],
 
791
        Doc => 'Works inplace',
 
792
        Code => q^
 
793
           $GENERIC() ar = $a(m=>0), ai = $a(m=>1);
 
794
 
 
795
           double i2 = ai*ai;
 
796
           double num = i2 + (1+ar) * (1+ar);
 
797
           double den = i2 + (1-ar) * (1-ar);
 
798
 
 
799
           $c(m=>0) = 0.25 * (log(num) - log(den));
 
800
           $c(m=>1) = 0.5 * atan2 (2*ai, 1 - ar*ar - i2);
 
801
        ^
 
802
;
 
803
 
 
804
pp_def 'Cproj',
 
805
        Pars => 'a(m=2); [o]c(m=2)',
 
806
        Inplace => 1,
 
807
        GenericTypes => [F,D],
 
808
        Doc => 'compute the projection of a complex number to the riemann sphere. Works inplace',
 
809
        Code => q^
 
810
           $GENERIC() ar = $a(m=>0), ai = $a(m=>1);
 
811
 
 
812
           double den = ar*ar + ai*ai + 1;
 
813
 
 
814
           $c(m=>0) = 2*ar / den;
 
815
           $c(m=>1) = 2*ai / den;
 
816
        ^
 
817
;
 
818
 
 
819
pp_def 'Croots',
 
820
        Pars => 'a(m=2); [o]c(m=2,n)',
 
821
        OtherPars => 'int n => n',
 
822
        GenericTypes => [F,D],
 
823
        Doc => 'Compute the C<n> roots of C<a>. C<n> must be a positive integer. The result will always be a complex type!',
 
824
        PMCode => q^sub PDL::Complex::Croots($$) {
 
825
           my ($pdl, $n) = @_;
 
826
           my $r = PDL->null;
 
827
           &PDL::Complex::_Croots_int($pdl, $r, $n);
 
828
           bless $r;
 
829
        }^,
 
830
        Code => q^
 
831
           double s, c;
 
832
           double ar = $a(m=>0), ai = $a(m=>1),
 
833
                  n1 = 1 / (double)$COMP(n),
 
834
                  rr = pow (CABS (ar, ai), n1), /* do not optimize the sqrt out of this expr! */
 
835
                  at = atan2 (ai, ar) * n1,
 
836
                  ti = M_2PI * n1;
 
837
 
 
838
           loop(n) %{
 
839
               SINCOS (at, s, c);
 
840
 
 
841
               $c(m=>0) = rr * c;
 
842
               $c(m=>1) = rr * s;
 
843
 
 
844
               at += ti;
 
845
            %}
 
846
        ^
 
847
;
 
848
 
 
849
pp_addpm <<'EOD';
 
850
 
 
851
=head2 re cplx, im cplx
 
852
 
 
853
Return the real or imaginary part of the complex number(s) given. These
 
854
are slicing operators, so data flow works. The real and imaginary parts
 
855
are returned as piddles (ref eq PDL).
 
856
 
 
857
=cut
 
858
 
 
859
sub re($) { bless $_[0]->slice("(0)"), 'PDL'; }
 
860
sub im($) { bless $_[0]->slice("(1)"), 'PDL'; }
 
861
 
 
862
*PDL::Complex::re = \&re;
 
863
*PDL::Complex::im = \&im;
 
864
 
 
865
EOD
 
866
 
 
867
pp_def 'rCpolynomial',
 
868
       Pars => 'coeffs(n); x(c=2,m); [o]out(c=2,m)',
 
869
       Doc => 'evaluate the polynomial with (real) coefficients C<coeffs> at the (complex) position(s) C<x>. C<coeffs[0]> is the constant term.',
 
870
       GenericTypes => [F,D],
 
871
       Code => q!
 
872
          loop(m) %{
 
873
             double xr = 1;
 
874
             double xi = 0;
 
875
             double or = 0;
 
876
             double oi = 0;
 
877
             double Xr;
 
878
 
 
879
             loop(n) %{
 
880
                or += $coeffs() * xr;
 
881
                oi += $coeffs() * xi;
 
882
 
 
883
                Xr = xr;
 
884
                xr = Xr * $x(c=>0) - xi * $x(c=>1);
 
885
                xi = xi * $x(c=>0) + Xr * $x(c=>1);
 
886
             %}
 
887
 
 
888
             $out(c=>0) = or;
 
889
             $out(c=>1) = oi;
 
890
          %}
 
891
       !
 
892
;
 
893
 
 
894
pp_add_isa 'PDL';
 
895
 
 
896
pp_addpm {At => Bot}, <<'EOD';
 
897
 
 
898
# overload must be here, so that all the functions can be seen
 
899
 
 
900
# undocumented compatibility functions
 
901
sub Catan2($$) { Catan Cdiv $_[1], $_[0] }
 
902
sub atan2($$)  { Catan Cdiv $_[1], $_[0] }
 
903
 
 
904
sub _gen_biop {
 
905
   local $_ = shift;
 
906
   my $sub;
 
907
   if (/(\S+)\+(\w+)/) {
 
908
      $sub = eval 'sub { '.$2.' $_[0], ref $_[1] eq __PACKAGE__ ? $_[1] : r2C $_[1] }';
 
909
   } elsif (/(\S+)\-(\w+)/) {
 
910
      $sub = eval 'sub { my $b = ref $_[1] eq __PACKAGE__ ? $_[1] : r2C $_[1];
 
911
                       $_[2] ? '.$2.' $b, $_[0] : '.$2.' $_[0], $b }';
 
912
   } else {
 
913
      die;
 
914
   }
 
915
   if($1 eq "atan2" || $1 eq "<=>") { return ($1, $sub) }
 
916
   ($1, $sub, "$1=", $sub);
 
917
}
 
918
 
 
919
sub _gen_unop {
 
920
   my ($op, $func) = ($_[0] =~ /(.+)@(\w+)/);
 
921
   *$op = \&$func if $op =~ /\w+/; # create an alias
 
922
   ($op, eval 'sub { '.$func.' $_[0] }');
 
923
}
 
924
 
 
925
sub _gen_cpop {
 
926
   ($_[0], eval 'sub { my $b = ref $_[1] eq __PACKAGE__ ? $_[1] : r2C $_[1];
 
927
                 ($_[2] ? $b <=> $_[0] : $_[0] <=> $b) '.$_[0].' 0 }');
 
928
}
 
929
 
 
930
sub initialize {
 
931
   # Bless a null PDL into the supplied 1st arg package
 
932
   #   If 1st arg is a ref, get the package from it
 
933
   bless PDL->null, ref($_[0]) ? ref($_[0]) : $_[0];
 
934
}
 
935
 
 
936
use overload
 
937
   (map _gen_biop($_), qw(++Cadd --Csub *+Cmul /-Cdiv **-Cpow atan2-Catan2 <=>-Ccmp)),
 
938
   (map _gen_unop($_), qw(sin@Csin cos@Ccos exp@Cexp abs@Cabs log@Clog sqrt@Csqrt abs@Cabs)),
 
939
   (map _gen_cpop($_), qw(< <= == != >= >)),
 
940
   '++' => sub { $_[0] += 1 },
 
941
   '--' => sub { $_[0] -= 1 },
 
942
   '""' => \&PDL::Complex::string
 
943
;
 
944
 
 
945
# overwrite PDL's overloading to honour subclass methods in + - * /
 
946
{ package PDL;
 
947
        my $warningFlag;
 
948
        # This strange usage of BEGINs is to ensure the
 
949
        # warning messages get disabled and enabled in the
 
950
        # proper order. Without the BEGIN's the 'use overload'
 
951
        #  would be called first.
 
952
        BEGIN {$warningFlag = $^W; # Temporarily disable warnings caused by
 
953
               $^W = 0;            # redefining PDL's subs
 
954
              }
 
955
 
 
956
 
 
957
sub cp(;@) {
 
958
        my $foo;
 
959
        if (ref $_[1]
 
960
                && (ref $_[1] ne 'PDL')
 
961
                && defined ($foo = overload::Method($_[1],'+')))
 
962
                { &$foo($_[1], $_[0], !$_[2])}
 
963
        else { PDL::plus (@_)}
 
964
}
 
965
 
 
966
sub cm(;@) {
 
967
        my $foo;
 
968
        if (ref $_[1]
 
969
                && (ref $_[1] ne 'PDL')
 
970
                && defined ($foo = overload::Method($_[1],'*')))
 
971
                { &$foo($_[1], $_[0], !$_[2])}
 
972
        else { PDL::mult (@_)}
 
973
}
 
974
 
 
975
sub cmi(;@) {
 
976
        my $foo;
 
977
        if (ref $_[1]
 
978
                && (ref $_[1] ne 'PDL')
 
979
                && defined ($foo = overload::Method($_[1],'-')))
 
980
                { &$foo($_[1], $_[0], !$_[2])}
 
981
        else { PDL::minus (@_)}
 
982
}
 
983
 
 
984
sub cd(;@) {
 
985
        my $foo;
 
986
        if (ref $_[1]
 
987
                && (ref $_[1] ne 'PDL')
 
988
                && defined ($foo = overload::Method($_[1],'/')))
 
989
                { &$foo($_[1], $_[0], !$_[2])}
 
990
        else { PDL::divide (@_)}
 
991
}
 
992
 
 
993
 
 
994
  # Used in overriding standard PDL +, -, *, / ops in the complex subclass.
 
995
  use overload (
 
996
                 '+' => \&cp,
 
997
                 '*' => \&cm,
 
998
                 '-' => \&cmi,
 
999
                 '/' => \&cd,
 
1000
                );
 
1001
 
 
1002
 
 
1003
 
 
1004
        BEGIN{ $^W = $warningFlag;} # Put Back Warnings
 
1005
};
 
1006
 
 
1007
 
 
1008
{
 
1009
 
 
1010
   our $floatformat  = "%4.4g";    # Default print format for long numbers
 
1011
   our $doubleformat = "%6.6g";
 
1012
 
 
1013
   $PDL::Complex::_STRINGIZING = 0;
 
1014
 
 
1015
   sub PDL::Complex::string {
 
1016
      my($self,$format1,$format2)=@_;
 
1017
      my @dims = $self->dims;
 
1018
      return PDL::string($self) if ($dims[0] != 2);
 
1019
 
 
1020
      if($PDL::Complex::_STRINGIZING) {
 
1021
         return "ALREADY_STRINGIZING_NO_LOOPS";
 
1022
      }
 
1023
      local $PDL::Complex::_STRINGIZING = 1;
 
1024
      my $ndims = $self->getndims;
 
1025
      if($self->nelem > $PDL::toolongtoprint) {
 
1026
         return "TOO LONG TO PRINT";
 
1027
      }
 
1028
      if ($ndims==0){
 
1029
         PDL::Core::string($self,$format1);
 
1030
      }
 
1031
      return "Null" if $self->isnull;
 
1032
      return "Empty" if $self->isempty; # Empty piddle
 
1033
      local $sep  = $PDL::use_commas ? ", " : "  ";
 
1034
      local $sep2 = $PDL::use_commas ? ", " : "";
 
1035
      if ($ndims < 3) {
 
1036
         return str1D($self,$format1,$format2);
 
1037
      }
 
1038
      else{
 
1039
         return strND($self,$format1,$format2,0);
 
1040
      }
 
1041
   }
 
1042
 
 
1043
 
 
1044
    sub sum {
 
1045
       my($x) = @_;
 
1046
       my $tmp = $x->mv(0,1)->clump(0,2)->mv(1,0)->sumover;
 
1047
       return $tmp->squeeze;
 
1048
    }
 
1049
 
 
1050
   sub sumover{
 
1051
      my $m = shift;
 
1052
      PDL::Ufunc::sumover($m->xchg(0,1));
 
1053
   }
 
1054
 
 
1055
 
 
1056
   sub strND {
 
1057
      my($self,$format1,$format2,$level)=@_;
 
1058
      my @dims = $self->dims;
 
1059
 
 
1060
      if ($#dims==2) {
 
1061
         return str2D($self,$format1,$format2,$level);
 
1062
      }
 
1063
      else {
 
1064
         my $secbas = join '',map {":,"} @dims[0..$#dims-1];
 
1065
         my $ret="\n"." "x$level ."["; my $j;
 
1066
         for ($j=0; $j<$dims[$#dims]; $j++) {
 
1067
            my $sec = $secbas . "($j)";
 
1068
 
 
1069
            $ret .= strND($self->slice($sec),$format1,$format2, $level+1);
 
1070
            chop $ret; $ret .= $sep2;
 
1071
         }
 
1072
         chop $ret if $PDL::use_commas;
 
1073
         $ret .= "\n" ." "x$level ."]\n";
 
1074
         return $ret;
 
1075
      }
 
1076
   }
 
1077
 
 
1078
 
 
1079
   # String 1D array in nice format
 
1080
   #
 
1081
   sub str1D {
 
1082
      my($self,$format1,$format2)=@_;
 
1083
      barf "Not 1D" if $self->getndims() > 2;
 
1084
      my $x = PDL::Core::listref_c($self);
 
1085
      my ($ret,$dformat,$t, $i);
 
1086
 
 
1087
      my $dtype = $self->get_datatype();
 
1088
      $dformat = $PDL::Complex::floatformat  if $dtype == $PDL_F;
 
1089
      $dformat = $PDL::Complex::doubleformat if $dtype == $PDL_D;
 
1090
 
 
1091
      $ret = "[" if $self->getndims() > 1;
 
1092
      my $badflag = $self->badflag();
 
1093
      for($i=0; $i<=$#$x; $i++){
 
1094
         $t = $$x[$i];
 
1095
         if ( $badflag and $t eq "BAD" ) {
 
1096
            # do nothing
 
1097
         } elsif ($format1) {
 
1098
            $t =  sprintf $format1,$t;
 
1099
         } else{ # Default
 
1100
            if ($dformat && length($t)>7) { # Try smaller
 
1101
               $t = sprintf $dformat,$t;
 
1102
            }
 
1103
         }
 
1104
         $ret .= $i % 2 ?
 
1105
         $i<$#$x ? $t."i$sep" : $t."i"
 
1106
         : substr($$x[$i+1],0,1) eq "-" ?  "$t " : $t." +";
 
1107
      }
 
1108
      $ret.="]" if $self->getndims() > 1;
 
1109
      return $ret;
 
1110
   }
 
1111
 
 
1112
 
 
1113
   sub str2D {
 
1114
      my($self,$format1,$format2,$level)=@_;
 
1115
      my @dims = $self->dims();
 
1116
      barf "Not 2D" if scalar(@dims)!=3;
 
1117
      my $x = PDL::Core::listref_c($self);
 
1118
      my ($i, $f, $t, $len1, $len2, $ret);
 
1119
 
 
1120
      my $dtype = $self->get_datatype();
 
1121
      my $badflag = $self->badflag();
 
1122
 
 
1123
      my $findmax = 0;
 
1124
 
 
1125
      if (!defined $format1 || !defined $format2 ||
 
1126
         $format1 eq '' || $format2 eq '') {
 
1127
         $len1= $len2 = 0;
 
1128
 
 
1129
         if ( $badflag ) {
 
1130
            for ($i=0; $i<=$#$x; $i++) {
 
1131
               if ( $$x[$i] eq "BAD" ) {
 
1132
                  $f = 3;
 
1133
               }
 
1134
               else {
 
1135
                  $f = length($$x[$i]);
 
1136
               }
 
1137
               if ($i % 2) {
 
1138
                  $len2 = $f if $f > $len2;
 
1139
               }
 
1140
               else {
 
1141
                  $len1 = $f if $f > $len1;
 
1142
               }
 
1143
            }
 
1144
         } else {
 
1145
            for ($i=0; $i<=$#$x; $i++) {
 
1146
               $f = length($$x[$i]);
 
1147
               if ($i % 2){
 
1148
                  $len2 = $f if $f > $len2;
 
1149
               }
 
1150
               else{
 
1151
                  $len1 = $f if $f > $len1;
 
1152
               }
 
1153
            }
 
1154
         }
 
1155
 
 
1156
         $format1 = '%'.$len1.'s';
 
1157
         $format2 = '%'.$len2.'s';
 
1158
 
 
1159
         if ($len1 > 5){
 
1160
            if ($dtype == $PDL_F) {
 
1161
               $format1 = $PDL::Complex::floatformat;
 
1162
               $findmax = 1;
 
1163
            } elsif ($dtype == $PDL_D) {
 
1164
               $format1 = $PDL::Complex::doubleformat;
 
1165
               $findmax = 1;
 
1166
            } else {
 
1167
               $findmax = 0;
 
1168
            }
 
1169
         }
 
1170
         if($len2 > 5){
 
1171
            if ($dtype == $PDL_F) {
 
1172
               $format2 = $PDL::Complex::floatformat;
 
1173
               $findmax = 1;
 
1174
            } elsif ($dtype == $PDL_D) {
 
1175
               $format2 = $PDL::Complex::doubleformat;
 
1176
               $findmax = 1;
 
1177
            } else {
 
1178
               $findmax = 0 unless $findmax;
 
1179
            }
 
1180
         }
 
1181
      }
 
1182
 
 
1183
      if($findmax) {
 
1184
         $len1 = $len2=0;
 
1185
 
 
1186
         if ( $badflag ) {
 
1187
            for($i=0; $i<=$#$x; $i++){
 
1188
               $findmax = $i % 2;
 
1189
               if ( $$x[$i] eq 'BAD' ){
 
1190
                  $f = 3;
 
1191
               }
 
1192
               else{
 
1193
                  $f = $findmax ? length(sprintf $format2,$$x[$i]) :
 
1194
                  length(sprintf $format1,$$x[$i]);
 
1195
               }
 
1196
               if ($findmax){
 
1197
                  $len2 = $f if $f > $len2;
 
1198
               }
 
1199
               else{
 
1200
                  $len1 = $f if $f > $len1;
 
1201
               }
 
1202
            }
 
1203
         } else {
 
1204
            for ($i=0; $i<=$#$x; $i++) {
 
1205
               if ($i % 2){
 
1206
                  $f = length(sprintf $format2,$$x[$i]);
 
1207
                  $len2 = $f if $f > $len2;
 
1208
               }
 
1209
               else{
 
1210
                  $f = length(sprintf $format1,$$x[$i]);
 
1211
                  $len1 = $f if $f > $len1;
 
1212
               }
 
1213
            }
 
1214
         }
 
1215
 
 
1216
 
 
1217
      } # if: $findmax
 
1218
 
 
1219
      $ret = "\n" . ' 'x$level . "[\n";
 
1220
      {
 
1221
         my $level = $level+1;
 
1222
         $ret .= ' 'x$level .'[';
 
1223
         $len2 += 2;
 
1224
 
 
1225
         for ($i=0; $i<=$#$x; $i++) {
 
1226
            $findmax = $i % 2;
 
1227
            if ($findmax){
 
1228
               if ( $badflag and  $$x[$i] eq 'BAD' ){
 
1229
                  #||
 
1230
                  #($findmax && $$x[$i - 1 ] eq 'BAD') ||
 
1231
                  #(!$findmax && $$x[$i +1 ] eq 'BAD')){
 
1232
                  $f = "BAD";
 
1233
               }
 
1234
               else{
 
1235
                  $f = sprintf $format2, $$x[$i];
 
1236
                  if (substr($$x[$i],0,1) eq '-'){
 
1237
                     $f.='i';
 
1238
                  }
 
1239
                  else{
 
1240
                     $f =~ s/(\s*)(.*)/+$2i/;
 
1241
                  }
 
1242
               }
 
1243
               $t = $len2-length($f);
 
1244
            }
 
1245
            else{
 
1246
               if ( $badflag and  $$x[$i] eq 'BAD' ){
 
1247
                  $f = "BAD";
 
1248
               }
 
1249
               else{
 
1250
                  $f = sprintf $format1, $$x[$i];
 
1251
                  $t =  $len1-length($f);
 
1252
               }
 
1253
            }
 
1254
 
 
1255
            $f = ' 'x$t.$f if $t>0;
 
1256
 
 
1257
            $ret .= $f;
 
1258
            if (($i+1)%($dims[1]*2)) {
 
1259
               $ret.=$sep if $findmax;
 
1260
            }
 
1261
            else{ # End of output line
 
1262
               $ret.=']';
 
1263
               if ($i==$#$x) { # very last number
 
1264
                  $ret.="\n";
 
1265
               }
 
1266
               else{
 
1267
                  $ret.= $sep2."\n" . ' 'x$level .'[';
 
1268
               }
 
1269
            }
 
1270
         }
 
1271
      }
 
1272
      $ret .= ' 'x$level."]\n";
 
1273
      return $ret;
 
1274
   }
 
1275
 
 
1276
}
 
1277
 
 
1278
=head1 AUTHOR
 
1279
 
 
1280
Copyright (C) 2000 Marc Lehmann <pcg@goof.com>.
 
1281
All rights reserved. There is no warranty. You are allowed
 
1282
to redistribute this software / documentation as described
 
1283
in the file COPYING in the PDL distribution.
 
1284
 
 
1285
=head1 SEE ALSO
 
1286
 
 
1287
perl(1), L<PDL>.
 
1288
 
 
1289
=cut
 
1290
 
 
1291
 
 
1292
EOD
 
1293
 
 
1294
pp_done;
 
1295