File Coverage

blib/lib/Math/Complex.pm
Criterion Covered Total %
statement 632 673 93.9
branch 373 480 77.7
condition 78 110 70.9
subroutine 90 91 98.9
pod 1 55 1.8
total 1174 1409 83.3


line stmt bran cond sub pod time code
1             #
2             # Complex numbers and associated mathematical functions
3             # -- Raphael Manfredi Since Sep 1996
4             # -- Jarkko Hietaniemi Since Mar 1997
5             # -- Daniel S. Lewart Since Sep 1997
6             #
7              
8             package Math::Complex;
9              
10 3     3   30559 { use 5.006; }
  3         10  
  3         115  
11 3     3   15 use strict;
  3         5  
  3         122  
12              
13             our $VERSION = 1.59;
14              
15 3     3   15 use Config;
  3         6  
  3         1002  
16              
17             our($Inf, $ExpInf);
18             BEGIN {
19 3     3   21 my %DBL_MAX =
20             (
21             4 => '1.70141183460469229e+38',
22             8 => '1.7976931348623157e+308',
23             # AFAICT the 10, 12, and 16-byte long doubles
24             # all have the same maximum.
25             10 => '1.1897314953572317650857593266280070162E+4932',
26             12 => '1.1897314953572317650857593266280070162E+4932',
27             16 => '1.1897314953572317650857593266280070162E+4932',
28             );
29 3   0     2863 my $nvsize = $Config{nvsize} ||
30             ($Config{uselongdouble} && $Config{longdblsize}) ||
31             $Config{doublesize};
32 3 50       10173 die "Math::Complex: Could not figure out nvsize\n"
33             unless defined $nvsize;
34 3 50       19 die "Math::Complex: Cannot not figure out max nv (nvsize = $nvsize)\n"
35             unless defined $DBL_MAX{$nvsize};
36 3         159 my $DBL_MAX = eval $DBL_MAX{$nvsize};
37 3 50       14 die "Math::Complex: Could not figure out max nv (nvsize = $nvsize)\n"
38             unless defined $DBL_MAX;
39 3         6 my $BIGGER_THAN_THIS = 1e30; # Must find something bigger than this.
40 3 50       16 if ($^O eq 'unicosmk') {
41 0         0 $Inf = $DBL_MAX;
42             } else {
43 3         529 local $SIG{FPE} = { };
44 3         58 local $!;
45             # We do want an arithmetic overflow, Inf INF inf Infinity.
46 3         18 for my $t (
47             'exp(99999)', # Enough even with 128-bit long doubles.
48             'inf',
49             'Inf',
50             'INF',
51             'infinity',
52             'Infinity',
53             'INFINITY',
54             '1e99999',
55             ) {
56 3         13 local $^W = 0;
57 3         191 my $i = eval "$t+1.0";
58 3 50 33     33 if (defined $i && $i > $BIGGER_THAN_THIS) {
59 3         6 $Inf = $i;
60 3         12 last;
61             }
62             }
63 3 50       23 $Inf = $DBL_MAX unless defined $Inf; # Oh well, close enough.
64 3 50       11 die "Math::Complex: Could not get Infinity"
65             unless $Inf > $BIGGER_THAN_THIS;
66 3         109 $ExpInf = exp(99999);
67             }
68             # print "# On this machine, Inf = '$Inf'\n";
69             }
70              
71 3     3   21 use Scalar::Util qw(set_prototype);
  3         5  
  3         502  
72              
73 3     3   18 use warnings;
  3         5  
  3         89  
74 3     3   12 no warnings 'syntax'; # To avoid the (_) warnings.
  3         5  
  3         419  
75              
76             BEGIN {
77             # For certain functions that we override, in 5.10 or better
78             # we can set a smarter prototype that will handle the lexical $_
79             # (also a 5.10+ feature).
80 3 50   3   20 if ($] >= 5.010000) {
81 3         20 set_prototype \&abs, '_';
82 3         14 set_prototype \&cos, '_';
83 3         11 set_prototype \&exp, '_';
84 3         10 set_prototype \&log, '_';
85 3         10 set_prototype \&sin, '_';
86 3         1529 set_prototype \&sqrt, '_';
87             }
88             }
89              
90             my $i;
91             my %LOGN;
92              
93             # Regular expression for floating point numbers.
94             # These days we could use Scalar::Util::lln(), I guess.
95             my $gre = qr'\s*([\+\-]?(?:(?:(?:\d+(?:_\d+)*(?:\.\d*(?:_\d+)*)?|\.\d+(?:_\d+)*)(?:[eE][\+\-]?\d+(?:_\d+)*)?))|inf)'i;
96              
97             require Exporter;
98              
99             our @ISA = qw(Exporter);
100              
101             my @trig = qw(
102             pi
103             tan
104             csc cosec sec cot cotan
105             asin acos atan
106             acsc acosec asec acot acotan
107             sinh cosh tanh
108             csch cosech sech coth cotanh
109             asinh acosh atanh
110             acsch acosech asech acoth acotanh
111             );
112              
113             our @EXPORT = (qw(
114             i Re Im rho theta arg
115             sqrt log ln
116             log10 logn cbrt root
117             cplx cplxe
118             atan2
119             ),
120             @trig);
121              
122             my @pi = qw(pi pi2 pi4 pip2 pip4 Inf);
123              
124             our @EXPORT_OK = @pi;
125              
126             our %EXPORT_TAGS = (
127             'trig' => [@trig],
128             'pi' => [@pi],
129             );
130              
131             use overload
132 3         74 '=' => \&_copy,
133             '+=' => \&_plus,
134             '+' => \&_plus,
135             '-=' => \&_minus,
136             '-' => \&_minus,
137             '*=' => \&_multiply,
138             '*' => \&_multiply,
139             '/=' => \&_divide,
140             '/' => \&_divide,
141             '**=' => \&_power,
142             '**' => \&_power,
143             '==' => \&_numeq,
144             '<=>' => \&_spaceship,
145             'neg' => \&_negate,
146             '~' => \&_conjugate,
147             'abs' => \&abs,
148             'sqrt' => \&sqrt,
149             'exp' => \&exp,
150             'log' => \&log,
151             'sin' => \&sin,
152             'cos' => \&cos,
153             'atan2' => \&atan2,
154 3     3   6109 '""' => \&_stringify;
  3         3262  
155              
156             #
157             # Package "privates"
158             #
159              
160             my %DISPLAY_FORMAT = ('style' => 'cartesian',
161             'polar_pretty_print' => 1);
162             my $eps = 1e-14; # Epsilon
163              
164             #
165             # Object attributes (internal):
166             # cartesian [real, imaginary] -- cartesian form
167             # polar [rho, theta] -- polar form
168             # c_dirty cartesian form not up-to-date
169             # p_dirty polar form not up-to-date
170             # display display format (package's global when not set)
171             #
172              
173             # Die on bad *make() arguments.
174              
175             sub _cannot_make {
176 0     0   0 die "@{[(caller(1))[3]]}: Cannot take $_[0] of '$_[1]'.\n";
  0         0  
177             }
178              
179             sub _make {
180 748     748   981 my $arg = shift;
181 748         837 my ($p, $q);
182              
183 748 100       4431 if ($arg =~ /^$gre$/) {
    100          
    50          
184 570         1237 ($p, $q) = ($1, 0);
185             } elsif ($arg =~ /^(?:$gre)?$gre\s*i\s*$/) {
186 177   100     865 ($p, $q) = ($1 || 0, $2);
187             } elsif ($arg =~ /^\s*\(\s*$gre\s*(?:,\s*$gre\s*)?\)\s*$/) {
188 1   50     5 ($p, $q) = ($1, $2 || 0);
189             }
190              
191 748 50       1721 if (defined $p) {
192 748         1480 $p =~ s/^\+//;
193 748         900 $p =~ s/^(-?)inf$/"${1}9**9**9"/e;
  0         0  
194 748         1317 $q =~ s/^\+//;
195 748         907 $q =~ s/^(-?)inf$/"${1}9**9**9"/e;
  0         0  
196             }
197              
198 748         2639 return ($p, $q);
199             }
200              
201             sub _emake {
202 13     13   23 my $arg = shift;
203 13         13 my ($p, $q);
204              
205 13 100       342 if ($arg =~ /^\s*\[\s*$gre\s*(?:,\s*$gre\s*)?\]\s*$/) {
    100          
    50          
    50          
206 6   100     53 ($p, $q) = ($1, $2 || 0);
207             } elsif ($arg =~ m!^\s*\[\s*$gre\s*(?:,\s*([-+]?\d*\s*)?pi(?:/\s*(\d+))?\s*)?\]\s*$!) {
208 6 100 100     75 ($p, $q) = ($1, ($2 eq '-' ? -1 : ($2 || 1)) * pi() / ($3 || 1));
      50        
209             } elsif ($arg =~ /^\s*\[\s*$gre\s*\]\s*$/) {
210 0         0 ($p, $q) = ($1, 0);
211             } elsif ($arg =~ /^\s*$gre\s*$/) {
212 1         27 ($p, $q) = ($1, 0);
213             }
214              
215 13 50       36 if (defined $p) {
216 13         19 $p =~ s/^\+//;
217 13         34 $q =~ s/^\+//;
218 13         14 $p =~ s/^(-?)inf$/"${1}9**9**9"/e;
  0         0  
219 13         28 $q =~ s/^(-?)inf$/"${1}9**9**9"/e;
  0         0  
220             }
221              
222 13         52 return ($p, $q);
223             }
224              
225             sub _copy {
226 1     1   7 my $self = shift;
227 1         4 my $clone = {%$self};
228 1 50       4 if ($self->{'cartesian'}) {
229 1         8 $clone->{'cartesian'} = [@{$self->{'cartesian'}}];
  1         5  
230             }
231 1 50       4 if ($self->{'polar'}) {
232 0         0 $clone->{'polar'} = [@{$self->{'polar'}}];
  0         0  
233             }
234 1         2 bless $clone,__PACKAGE__;
235 1         5 return $clone;
236             }
237              
238             #
239             # ->make
240             #
241             # Create a new complex number (cartesian form)
242             #
243             sub make {
244 6500     6500 0 16308 my $self = bless {}, shift;
245 6500         8027 my ($re, $im);
246 6500 100       21235 if (@_ == 0) {
    100          
    50          
247 2         4 ($re, $im) = (0, 0);
248             } elsif (@_ == 1) {
249 757 100       1981 return (ref $self)->emake($_[0])
250             if ($_[0] =~ /^\s*\[/);
251 748         2083 ($re, $im) = _make($_[0]);
252             } elsif (@_ == 2) {
253 5741         9830 ($re, $im) = @_;
254             }
255 6491 50       14051 if (defined $re) {
256 6491 50       57606 _cannot_make("real part", $re) unless $re =~ /^$gre$/;
257             }
258 6491   100     24874 $im ||= 0;
259 6491 50       43502 _cannot_make("imaginary part", $im) unless $im =~ /^$gre$/;
260 6491         19967 $self->_set_cartesian([$re, $im ]);
261 6491         13504 $self->display_format('cartesian');
262              
263 6491         51224 return $self;
264             }
265              
266             #
267             # ->emake
268             #
269             # Create a new complex number (exponential form)
270             #
271             sub emake {
272 551     551 0 2097 my $self = bless {}, shift;
273 551         633 my ($rho, $theta);
274 551 100       1880 if (@_ == 0) {
    100          
    50          
275 2         5 ($rho, $theta) = (0, 0);
276             } elsif (@_ == 1) {
277 13 50 33     57 return (ref $self)->make($_[0])
278             if ($_[0] =~ /^\s*\(/ || $_[0] =~ /i\s*$/);
279 13         45 ($rho, $theta) = _emake($_[0]);
280             } elsif (@_ == 2) {
281 536         1003 ($rho, $theta) = @_;
282             }
283 551 50 33     2217 if (defined $rho && defined $theta) {
284 551 100       1239 if ($rho < 0) {
285 2         7 $rho = -$rho;
286 2 50       13 $theta = ($theta <= 0) ? $theta + pi() : $theta - pi();
287             }
288             }
289 551 50       889 if (defined $rho) {
290 551 50       5477 _cannot_make("rho", $rho) unless $rho =~ /^$gre$/;
291             }
292 551   100     1137 $theta ||= 0;
293 551 50       4178 _cannot_make("theta", $theta) unless $theta =~ /^$gre$/;
294 551         1673 $self->_set_polar([$rho, $theta]);
295 551         1123 $self->display_format('polar');
296              
297 551         2860 return $self;
298             }
299              
300 1     1 0 205728 sub new { &make } # For backward compatibility only.
301              
302             #
303             # cplx
304             #
305             # Creates a complex number from a (re, im) tuple.
306             # This avoids the burden of writing Math::Complex->make(re, im).
307             #
308             sub cplx {
309 1594     1594 0 59082 return __PACKAGE__->make(@_);
310             }
311              
312             #
313             # cplxe
314             #
315             # Creates a complex number from a (rho, theta) tuple.
316             # This avoids the burden of writing Math::Complex->emake(rho, theta).
317             #
318             sub cplxe {
319 249     249 0 2791 return __PACKAGE__->emake(@_);
320             }
321              
322             #
323             # pi
324             #
325             # The number defined as pi = 180 degrees
326             #
327             sub pi () { 4 * CORE::atan2(1, 1) }
328              
329             #
330             # pi2
331             #
332             # The full circle
333             #
334             sub pi2 () { 2 * pi }
335              
336             #
337             # pi4
338             #
339             # The full circle twice.
340             #
341             sub pi4 () { 4 * pi }
342              
343             #
344             # pip2
345             #
346             # The quarter circle
347             #
348             sub pip2 () { pi / 2 }
349              
350             #
351             # pip4
352             #
353             # The eighth circle.
354             #
355             sub pip4 () { pi / 4 }
356              
357             #
358             # _uplog10
359             #
360             # Used in log10().
361             #
362             sub _uplog10 () { 1 / CORE::log(10) }
363              
364             #
365             # i
366             #
367             # The number defined as i*i = -1;
368             #
369             sub i () {
370 552 100   552 0 3068 return $i if ($i);
371 1         6 $i = bless {};
372 1         6 $i->{'cartesian'} = [0, 1];
373 1         5 $i->{'polar'} = [1, pip2];
374 1         3 $i->{c_dirty} = 0;
375 1         5 $i->{p_dirty} = 0;
376 1         7 return $i;
377             }
378              
379             #
380             # _ip2
381             #
382             # Half of i.
383             #
384 70     70   110 sub _ip2 () { i / 2 }
385              
386             #
387             # Attribute access/set routines
388             #
389              
390 14755 100   14755   55215 sub _cartesian {$_[0]->{c_dirty} ?
391             $_[0]->_update_cartesian : $_[0]->{'cartesian'}}
392 1813 100   1813   6671 sub _polar {$_[0]->{p_dirty} ?
393             $_[0]->_update_polar : $_[0]->{'polar'}}
394              
395 6505     6505   14203 sub _set_cartesian { $_[0]->{p_dirty}++; $_[0]->{c_dirty} = 0;
  6505         10344  
396 6505         12495 $_[0]->{'cartesian'} = $_[1] }
397 551     551   1167 sub _set_polar { $_[0]->{c_dirty}++; $_[0]->{p_dirty} = 0;
  551         920  
398 551         970 $_[0]->{'polar'} = $_[1] }
399              
400             #
401             # ->_update_cartesian
402             #
403             # Recompute and return the cartesian form, given accurate polar form.
404             #
405             sub _update_cartesian {
406 501     501   590 my $self = shift;
407 501         532 my ($r, $t) = @{$self->{'polar'}};
  501         997  
408 501         688 $self->{c_dirty} = 0;
409 501         2967 return $self->{'cartesian'} = [$r * CORE::cos($t), $r * CORE::sin($t)];
410             }
411              
412             #
413             #
414             # ->_update_polar
415             #
416             # Recompute and return the polar form, given accurate cartesian form.
417             #
418             sub _update_polar {
419 1144     1144   1392 my $self = shift;
420 1144         1142 my ($x, $y) = @{$self->{'cartesian'}};
  1144         2417  
421 1144         1807 $self->{p_dirty} = 0;
422 1144 100 100     8651 return $self->{'polar'} = [0, 0] if $x == 0 && $y == 0;
423 831         16985 return $self->{'polar'} = [CORE::sqrt($x*$x + $y*$y),
424             CORE::atan2($y, $x)];
425             }
426              
427             #
428             # (_plus)
429             #
430             # Computes z1+z2.
431             #
432             sub _plus {
433 484     484   849 my ($z1, $z2, $regular) = @_;
434 484         499 my ($re1, $im1) = @{$z1->_cartesian};
  484         1042  
435 484 100       1198 $z2 = cplx($z2) unless ref $z2;
436 484 50       2740 my ($re2, $im2) = ref $z2 ? @{$z2->_cartesian} : ($z2, 0);
  484         913  
437 484 100       1788 unless (defined $regular) {
438 7         27 $z1->_set_cartesian([$re1 + $re2, $im1 + $im2]);
439 7         108 return $z1;
440             }
441 477         1838 return (ref $z1)->make($re1 + $re2, $im1 + $im2);
442             }
443              
444             #
445             # (_minus)
446             #
447             # Computes z1-z2.
448             #
449             sub _minus {
450 1063     1063   5912 my ($z1, $z2, $inverted) = @_;
451 1063         1274 my ($re1, $im1) = @{$z1->_cartesian};
  1063         2025  
452 1063 100       2593 $z2 = cplx($z2) unless ref $z2;
453 1063         1422 my ($re2, $im2) = @{$z2->_cartesian};
  1063         2110  
454 1063 100       2279 unless (defined $inverted) {
455 7         20 $z1->_set_cartesian([$re1 - $re2, $im1 - $im2]);
456 7         82 return $z1;
457             }
458 1056 100       5356 return $inverted ?
459             (ref $z1)->make($re2 - $re1, $im2 - $im1) :
460             (ref $z1)->make($re1 - $re2, $im1 - $im2);
461              
462             }
463              
464             #
465             # (_multiply)
466             #
467             # Computes z1*z2.
468             #
469             sub _multiply {
470 531     531   1040 my ($z1, $z2, $regular) = @_;
471 531 100 100     2495 if ($z1->{p_dirty} == 0 and ref $z2 and $z2->{p_dirty} == 0) {
      100        
472             # if both polar better use polar to avoid rounding errors
473 32         41 my ($r1, $t1) = @{$z1->_polar};
  32         76  
474 32         47 my ($r2, $t2) = @{$z2->_polar};
  32         66  
475 32         60 my $t = $t1 + $t2;
476 32 100       96 if ($t > pi()) { $t -= pi2 }
  8 50       14  
477 0         0 elsif ($t <= -pi()) { $t += pi2 }
478 32 50       66 unless (defined $regular) {
479 0         0 $z1->_set_polar([$r1 * $r2, $t]);
480 0         0 return $z1;
481             }
482 32         118 return (ref $z1)->emake($r1 * $r2, $t);
483             } else {
484 499         527 my ($x1, $y1) = @{$z1->_cartesian};
  499         1100  
485 499 100       1124 if (ref $z2) {
486 302         280 my ($x2, $y2) = @{$z2->_cartesian};
  302         497  
487 302         1523 return (ref $z1)->make($x1*$x2-$y1*$y2, $x1*$y2+$y1*$x2);
488             } else {
489 197         708 return (ref $z1)->make($x1*$z2, $y1*$z2);
490             }
491             }
492             }
493              
494             #
495             # _divbyzero
496             #
497             # Die on division by zero.
498             #
499             sub _divbyzero {
500 16     16   32 my $mess = "$_[0]: Division by zero.\n";
501              
502 16 100       31 if (defined $_[1]) {
503 10         15 $mess .= "(Because in the definition of $_[0], the divisor ";
504 10 100       22 $mess .= "$_[1] " unless ("$_[1]" eq '0');
505 10         11 $mess .= "is 0)\n";
506             }
507              
508 16         85 my @up = caller(1);
509              
510 16         40 $mess .= "Died at $up[1] line $up[2].\n";
511              
512 16         311 die $mess;
513             }
514              
515             #
516             # (_divide)
517             #
518             # Computes z1/z2.
519             #
520             sub _divide {
521 983     983   2005 my ($z1, $z2, $inverted) = @_;
522 983 100 100     3915 if ($z1->{p_dirty} == 0 and ref $z2 and $z2->{p_dirty} == 0) {
      66        
523             # if both polar better use polar to avoid rounding errors
524 2         3 my ($r1, $t1) = @{$z1->_polar};
  2         5  
525 2         3 my ($r2, $t2) = @{$z2->_polar};
  2         6  
526 2         3 my $t;
527 2 50       6 if ($inverted) {
528 0 0       0 _divbyzero "$z2/0" if ($r1 == 0);
529 0         0 $t = $t2 - $t1;
530 0 0       0 if ($t > pi()) { $t -= pi2 }
  0 0       0  
531 0         0 elsif ($t <= -pi()) { $t += pi2 }
532 0         0 return (ref $z1)->emake($r2 / $r1, $t);
533             } else {
534 2 50       6 _divbyzero "$z1/0" if ($r2 == 0);
535 2         4 $t = $t1 - $t2;
536 2 50       9 if ($t > pi()) { $t -= pi2 }
  0 50       0  
537 0         0 elsif ($t <= -pi()) { $t += pi2 }
538 2         6 return (ref $z1)->emake($r1 / $r2, $t);
539             }
540             } else {
541 981         999 my ($d, $x2, $y2);
542 981 100       1606 if ($inverted) {
543 463         516 ($x2, $y2) = @{$z1->_cartesian};
  463         890  
544 463         912 $d = $x2*$x2 + $y2*$y2;
545 463 50       945 _divbyzero "$z2/0" if $d == 0;
546 463         1755 return (ref $z1)->make(($x2*$z2)/$d, -($y2*$z2)/$d);
547             } else {
548 518         508 my ($x1, $y1) = @{$z1->_cartesian};
  518         941  
549 518 100       1180 if (ref $z2) {
550 333         332 ($x2, $y2) = @{$z2->_cartesian};
  333         543  
551 333         624 $d = $x2*$x2 + $y2*$y2;
552 333 50       649 _divbyzero "$z1/0" if $d == 0;
553 333         513 my $u = ($x1*$x2 + $y1*$y2)/$d;
554 333         608 my $v = ($y1*$x2 - $x1*$y2)/$d;
555 333         911 return (ref $z1)->make($u, $v);
556             } else {
557 185 100       350 _divbyzero "$z1/0" if $z2 == 0;
558 184         587 return (ref $z1)->make($x1/$z2, $y1/$z2);
559             }
560             }
561             }
562             }
563              
564             #
565             # (_power)
566             #
567             # Computes z1**z2 = exp(z2 * log z1)).
568             #
569             sub _power {
570 97     97   2029 my ($z1, $z2, $inverted) = @_;
571 97 50       173 if ($inverted) {
572 0 0 0     0 return 1 if $z1 == 0 || $z2 == 1;
573 0 0 0     0 return 0 if $z2 == 0 && Re($z1) > 0;
574             } else {
575 97 100 100     306 return 1 if $z2 == 0 || $z1 == 1;
576 87 100 66     159 return 0 if $z1 == 0 && Re($z2) > 0;
577             }
578 83 50       227 my $w = $inverted ? &exp($z1 * &log($z2))
579             : &exp($z2 * &log($z1));
580             # If both arguments cartesian, return cartesian, else polar.
581 83         160 return $z1->{c_dirty} == 0 &&
582             (not ref $z2 or $z2->{c_dirty} == 0) ?
583 83 50 33     758 cplx(@{$w->_cartesian}) : $w;
584             }
585              
586             #
587             # (_spaceship)
588             #
589             # Computes z1 <=> z2.
590             # Sorts on the real part first, then on the imaginary part. Thus 2-4i < 3+8i.
591             #
592             sub _spaceship {
593 4     4   33 my ($z1, $z2, $inverted) = @_;
594 4 50       12 my ($re1, $im1) = ref $z1 ? @{$z1->_cartesian} : ($z1, 0);
  4         12  
595 4 50       12 my ($re2, $im2) = ref $z2 ? @{$z2->_cartesian} : ($z2, 0);
  4         8  
596 4 50       11 my $sgn = $inverted ? -1 : 1;
597 4 100       44 return $sgn * ($re1 <=> $re2) if $re1 != $re2;
598 2         36 return $sgn * ($im1 <=> $im2);
599             }
600              
601             #
602             # (_numeq)
603             #
604             # Computes z1 == z2.
605             #
606             # (Required in addition to _spaceship() because of NaNs.)
607             sub _numeq {
608 1599     1599   3181 my ($z1, $z2, $inverted) = @_;
609 1599 50       3282 my ($re1, $im1) = ref $z1 ? @{$z1->_cartesian} : ($z1, 0);
  1599         2924  
610 1599 100       3824 my ($re2, $im2) = ref $z2 ? @{$z2->_cartesian} : ($z2, 0);
  467         721  
611 1599 100 100     7964 return $re1 == $re2 && $im1 == $im2 ? 1 : 0;
612             }
613              
614             #
615             # (_negate)
616             #
617             # Computes -z.
618             #
619             sub _negate {
620 183     183   594 my ($z) = @_;
621 183 100       435 if ($z->{c_dirty}) {
622 1         2 my ($r, $t) = @{$z->_polar};
  1         3  
623 1 50       7 $t = ($t <= 0) ? $t + pi : $t - pi;
624 1         4 return (ref $z)->emake($r, $t);
625             }
626 182         210 my ($re, $im) = @{$z->_cartesian};
  182         386  
627 182         589 return (ref $z)->make(-$re, -$im);
628             }
629              
630             #
631             # (_conjugate)
632             #
633             # Compute complex's _conjugate.
634             #
635             sub _conjugate {
636 18     18   11503 my ($z) = @_;
637 18 100       78 if ($z->{c_dirty}) {
638 3         6 my ($r, $t) = @{$z->_polar};
  3         8  
639 3         15 return (ref $z)->emake($r, -$t);
640             }
641 15         26 my ($re, $im) = @{$z->_cartesian};
  15         57  
642 15         78 return (ref $z)->make($re, -$im);
643             }
644              
645             #
646             # (abs)
647             #
648             # Compute or set complex's norm (rho).
649             #
650             sub abs {
651 811 100   811 0 3201 my ($z, $rho) = @_ ? @_ : $_;
652 811 100       2221 unless (ref $z) {
653 1 50       4 if (@_ == 2) {
654 0         0 $_[0] = $_[1];
655             } else {
656 1         11 return CORE::abs($z);
657             }
658             }
659 810 100       1485 if (defined $rho) {
660 1         2 $z->{'polar'} = [ $rho, ${$z->_polar}[1] ];
  1         3  
661 1         3 $z->{p_dirty} = 0;
662 1         2 $z->{c_dirty} = 1;
663 1         11 return $rho;
664             } else {
665 809         736 return ${$z->_polar}[0];
  809         1437  
666             }
667             }
668              
669             sub _theta {
670 40     40   41 my $theta = $_[0];
671              
672 40 50       149 if ($$theta > pi()) { $$theta -= pi2 }
  0 50       0  
673 0         0 elsif ($$theta <= -pi()) { $$theta += pi2 }
674             }
675              
676             #
677             # arg
678             #
679             # Compute or set complex's argument (theta).
680             #
681             sub arg {
682 40     40 0 79 my ($z, $theta) = @_;
683 40 50       90 return $z unless ref $z;
684 40 100       61 if (defined $theta) {
685 1         4 _theta(\$theta);
686 1         1 $z->{'polar'} = [ ${$z->_polar}[0], $theta ];
  1         3  
687 1         3 $z->{p_dirty} = 0;
688 1         2 $z->{c_dirty} = 1;
689             } else {
690 39         41 $theta = ${$z->_polar}[1];
  39         63  
691 39         81 _theta(\$theta);
692             }
693 40         186 return $theta;
694             }
695              
696             #
697             # (sqrt)
698             #
699             # Compute sqrt(z).
700             #
701             # It is quite tempting to use wantarray here so that in list context
702             # sqrt() would return the two solutions. This, however, would
703             # break things like
704             #
705             # print "sqrt(z) = ", sqrt($z), "\n";
706             #
707             # The two values would be printed side by side without no intervening
708             # whitespace, quite confusing.
709             # Therefore if you want the two solutions use the root().
710             #
711             sub sqrt {
712 168 100   168 0 1436 my ($z) = @_ ? $_[0] : $_;
713 168 100       311 my ($re, $im) = ref $z ? @{$z->_cartesian} : ($z, 0);
  145         258  
714 168 100       721 return $re < 0 ? cplx(0, CORE::sqrt(-$re)) : CORE::sqrt($re)
    100          
715             if $im == 0;
716 80         93 my ($r, $t) = @{$z->_polar};
  80         168  
717 80         302 return (ref $z)->emake(CORE::sqrt($r), $t/2);
718             }
719              
720             #
721             # cbrt
722             #
723             # Compute cbrt(z) (cubic root).
724             #
725             # Why are we not returning three values? The same answer as for sqrt().
726             #
727             sub cbrt {
728 22     22 0 2373 my ($z) = @_;
729 22 50       112 return $z < 0 ?
    50          
    100          
730             -CORE::exp(CORE::log(-$z)/3) :
731             ($z > 0 ? CORE::exp(CORE::log($z)/3): 0)
732             unless ref $z;
733 11         29 my ($r, $t) = @{$z->_polar};
  11         26  
734 11 50       34 return 0 if $r == 0;
735 11         66 return (ref $z)->emake(CORE::exp(CORE::log($r)/3), $t/3);
736             }
737              
738             #
739             # _rootbad
740             #
741             # Die on bad root.
742             #
743             sub _rootbad {
744 4     4   22 my $mess = "Root '$_[0]' illegal, root rank must be positive integer.\n";
745              
746 4         18 my @up = caller(1);
747              
748 4         13 $mess .= "Died at $up[1] line $up[2].\n";
749              
750 4         69 die $mess;
751             }
752              
753             #
754             # root
755             #
756             # Computes all nth root for z, returning an array whose size is n.
757             # `n' must be a positive integer.
758             #
759             # The roots are given by (for k = 0..n-1):
760             #
761             # z^(1/n) = r^(1/n) (cos ((t+2 k pi)/n) + i sin ((t+2 k pi)/n))
762             #
763             sub root {
764 60     60 0 11270 my ($z, $n, $k) = @_;
765 60 100 66     320 _rootbad($n) if ($n < 1 or int($n) != $n);
766 55         109 my ($r, $t) = ref $z ?
767 56 50       136 @{$z->_polar} : (CORE::abs($z), $z >= 0 ? 0 : pi);
    100          
768 56         113 my $theta_inc = pi2 / $n;
769 56         212 my $rho = $r ** (1/$n);
770 56   100     252 my $cartesian = ref $z && $z->{c_dirty} == 0;
771 56 100       150 if (@_ == 2) {
    50          
772 34         38 my @root;
773 34         108 for (my $i = 0, my $theta = $t / $n;
774             $i < $n;
775             $i++, $theta += $theta_inc) {
776 190         325 my $w = cplxe($rho, $theta);
777             # Yes, $cartesian is loop invariant.
778 190 100       363 push @root, $cartesian ? cplx(@{$w->_cartesian}) : $w;
  179         318  
779             }
780 34         221 return @root;
781             } elsif (@_ == 3) {
782 22         56 my $w = cplxe($rho, $t / $n + $k * $theta_inc);
783 22 50       40 return $cartesian ? cplx(@{$w->_cartesian}) : $w;
  22         31  
784             }
785             }
786              
787             #
788             # Re
789             #
790             # Return or set Re(z).
791             #
792             sub Re {
793 32     32 0 173 my ($z, $Re) = @_;
794 32 50       71 return $z unless ref $z;
795 32 100       59 if (defined $Re) {
796 1         2 $z->{'cartesian'} = [ $Re, ${$z->_cartesian}[1] ];
  1         4  
797 1         3 $z->{c_dirty} = 0;
798 1         11 $z->{p_dirty} = 1;
799             } else {
800 31         32 return ${$z->_cartesian}[0];
  31         62  
801             }
802             }
803              
804             #
805             # Im
806             #
807             # Return or set Im(z).
808             #
809             sub Im {
810 38     38 0 320 my ($z, $Im) = @_;
811 38 50       135 return 0 unless ref $z;
812 38 100       70 if (defined $Im) {
813 6         9 $z->{'cartesian'} = [ ${$z->_cartesian}[0], $Im ];
  6         11  
814 6         12 $z->{c_dirty} = 0;
815 6         22 $z->{p_dirty} = 1;
816             } else {
817 32         65 return ${$z->_cartesian}[1];
  32         70  
818             }
819             }
820              
821             #
822             # rho
823             #
824             # Return or set rho(w).
825             #
826             sub rho {
827 2     2 0 14 Math::Complex::abs(@_);
828             }
829              
830             #
831             # theta
832             #
833             # Return or set theta(w).
834             #
835             sub theta {
836 2     2 0 306 Math::Complex::arg(@_);
837             }
838              
839             #
840             # (exp)
841             #
842             # Computes exp(z).
843             #
844             sub exp {
845 161 100   161 0 4823 my ($z) = @_ ? @_ : $_;
846 161 100       328 return CORE::exp($z) unless ref $z;
847 160         172 my ($x, $y) = @{$z->_cartesian};
  160         305  
848 160         587 return (ref $z)->emake(CORE::exp($x), $y);
849             }
850              
851             #
852             # _logofzero
853             #
854             # Die on logarithm of zero.
855             #
856             sub _logofzero {
857 5     5   11 my $mess = "$_[0]: Logarithm of zero.\n";
858              
859 5 100       10 if (defined $_[1]) {
860 1         3 $mess .= "(Because in the definition of $_[0], the argument ";
861 1 50       5 $mess .= "$_[1] " unless ($_[1] eq '0');
862 1         2 $mess .= "is 0)\n";
863             }
864              
865 5         28 my @up = caller(1);
866              
867 5         16 $mess .= "Died at $up[1] line $up[2].\n";
868              
869 5         106 die $mess;
870             }
871              
872             #
873             # (log)
874             #
875             # Compute log(z).
876             #
877             sub log {
878 517 100   517 0 6405 my ($z) = @_ ? @_ : $_;
879 517 100       1098 unless (ref $z) {
880 45 50       92 _logofzero("log") if $z == 0;
881 45 50       162 return $z > 0 ? CORE::log($z) : cplx(CORE::log(-$z), pi);
882             }
883 472         496 my ($r, $t) = @{$z->_polar};
  472         847  
884 472 100       1193 _logofzero("log") if $r == 0;
885 471 50       1400 if ($t > pi()) { $t -= pi2 }
  0 50       0  
886 0         0 elsif ($t <= -pi()) { $t += pi2 }
887 471         1955 return (ref $z)->make(CORE::log($r), $t);
888             }
889              
890             #
891             # ln
892             #
893             # Alias for log().
894             #
895 11     11 0 1687 sub ln { Math::Complex::log(@_) }
896              
897             #
898             # log10
899             #
900             # Compute log10(z).
901             #
902              
903             sub log10 {
904 11     11 0 1799 return Math::Complex::log($_[0]) * _uplog10;
905             }
906              
907             #
908             # logn
909             #
910             # Compute logn(z,n) = log(z) / log(n)
911             #
912             sub logn {
913 22     22 0 3291 my ($z, $n) = @_;
914 22 50       58 $z = cplx($z, 0) unless ref $z;
915 22         28 my $logn = $LOGN{$n};
916 22 100       48 $logn = $LOGN{$n} = CORE::log($n) unless defined $logn; # Cache log(n)
917 22         35 return &log($z) / $logn;
918             }
919              
920             #
921             # (cos)
922             #
923             # Compute cos(z) = (exp(iz) + exp(-iz))/2.
924             #
925             sub cos {
926 193 100   193 0 5734 my ($z) = @_ ? @_ : $_;
927 193 100       464 return CORE::cos($z) unless ref $z;
928 188         181 my ($x, $y) = @{$z->_cartesian};
  188         332  
929 188         383 my $ey = CORE::exp($y);
930 188         296 my $sx = CORE::sin($x);
931 188         718 my $cx = CORE::cos($x);
932 188 50       368 my $ey_1 = $ey ? 1 / $ey : Inf();
933 188         697 return (ref $z)->make($cx * ($ey + $ey_1)/2,
934             $sx * ($ey_1 - $ey)/2);
935             }
936              
937             #
938             # (sin)
939             #
940             # Compute sin(z) = (exp(iz) - exp(-iz))/2.
941             #
942             sub sin {
943 216 100   216 0 2068 my ($z) = @_ ? @_ : $_;
944 216 100       580 return CORE::sin($z) unless ref $z;
945 209         226 my ($x, $y) = @{$z->_cartesian};
  209         423  
946 209         615 my $ey = CORE::exp($y);
947 209         485 my $sx = CORE::sin($x);
948 209         683 my $cx = CORE::cos($x);
949 209 50       418 my $ey_1 = $ey ? 1 / $ey : Inf();
950 209         832 return (ref $z)->make($sx * ($ey + $ey_1)/2,
951             $cx * ($ey - $ey_1)/2);
952             }
953              
954             #
955             # tan
956             #
957             # Compute tan(z) = sin(z) / cos(z).
958             #
959             sub tan {
960 41     41 0 3424 my ($z) = @_;
961 41         93 my $cz = &cos($z);
962 41 50       109 _divbyzero "tan($z)", "cos($z)" if $cz == 0;
963 41         86 return &sin($z) / $cz;
964             }
965              
966             #
967             # sec
968             #
969             # Computes the secant sec(z) = 1 / cos(z).
970             #
971             sub sec {
972 34     34 0 2316 my ($z) = @_;
973 34         65 my $cz = &cos($z);
974 34 50       86 _divbyzero "sec($z)", "cos($z)" if ($cz == 0);
975 34         72 return 1 / $cz;
976             }
977              
978             #
979             # csc
980             #
981             # Computes the cosecant csc(z) = 1 / sin(z).
982             #
983             sub csc {
984 56     56 0 4932 my ($z) = @_;
985 56         146 my $sz = &sin($z);
986 56 100       148 _divbyzero "csc($z)", "sin($z)" if ($sz == 0);
987 55         113 return 1 / $sz;
988             }
989              
990             #
991             # cosec
992             #
993             # Alias for csc().
994             #
995 11     11 0 70 sub cosec { Math::Complex::csc(@_) }
996              
997             #
998             # cot
999             #
1000             # Computes cot(z) = cos(z) / sin(z).
1001             #
1002             sub cot {
1003 56     56 0 4399 my ($z) = @_;
1004 56         100 my $sz = &sin($z);
1005 56 100       137 _divbyzero "cot($z)", "sin($z)" if ($sz == 0);
1006 55         108 return &cos($z) / $sz;
1007             }
1008              
1009             #
1010             # cotan
1011             #
1012             # Alias for cot().
1013             #
1014 11     11 0 78 sub cotan { Math::Complex::cot(@_) }
1015              
1016             #
1017             # acos
1018             #
1019             # Computes the arc cosine acos(z) = -i log(z + sqrt(z*z-1)).
1020             #
1021             sub acos {
1022 99     99 0 2685 my $z = $_[0];
1023 99 100 66     500 return CORE::atan2(CORE::sqrt(1-$z*$z), $z)
1024             if (! ref $z) && CORE::abs($z) <= 1;
1025 71 50       174 $z = cplx($z, 0) unless ref $z;
1026 71         73 my ($x, $y) = @{$z->_cartesian};
  71         268  
1027 71 100 66     263 return 0 if $x == 1 && $y == 0;
1028 69         171 my $t1 = CORE::sqrt(($x+1)*($x+1) + $y*$y);
1029 69         146 my $t2 = CORE::sqrt(($x-1)*($x-1) + $y*$y);
1030 69         88 my $alpha = ($t1 + $t2)/2;
1031 69         86 my $beta = ($t1 - $t2)/2;
1032 69 50       125 $alpha = 1 if $alpha < 1;
1033 69 50       184 if ($beta > 1) { $beta = 1 }
  0 50       0  
1034 0         0 elsif ($beta < -1) { $beta = -1 }
1035 69         163 my $u = CORE::atan2(CORE::sqrt(1-$beta*$beta), $beta);
1036 69         181 my $v = CORE::log($alpha + CORE::sqrt($alpha*$alpha-1));
1037 69 100 100     293 $v = -$v if $y > 0 || ($y == 0 && $x < -1);
      66        
1038 69         181 return (ref $z)->make($u, $v);
1039             }
1040              
1041             #
1042             # asin
1043             #
1044             # Computes the arc sine asin(z) = -i log(iz + sqrt(1-z*z)).
1045             #
1046             sub asin {
1047 106     106 0 3159 my $z = $_[0];
1048 106 100 100     431 return CORE::atan2($z, CORE::sqrt(1-$z*$z))
1049             if (! ref $z) && CORE::abs($z) <= 1;
1050 94 100       208 $z = cplx($z, 0) unless ref $z;
1051 94         91 my ($x, $y) = @{$z->_cartesian};
  94         213  
1052 94 100 100     307 return 0 if $x == 0 && $y == 0;
1053 93         210 my $t1 = CORE::sqrt(($x+1)*($x+1) + $y*$y);
1054 93         147 my $t2 = CORE::sqrt(($x-1)*($x-1) + $y*$y);
1055 93         141 my $alpha = ($t1 + $t2)/2;
1056 93         130 my $beta = ($t1 - $t2)/2;
1057 93 50       195 $alpha = 1 if $alpha < 1;
1058 93 50       227 if ($beta > 1) { $beta = 1 }
  0 50       0  
1059 0         0 elsif ($beta < -1) { $beta = -1 }
1060 93         340 my $u = CORE::atan2($beta, CORE::sqrt(1-$beta*$beta));
1061 93         210 my $v = -CORE::log($alpha + CORE::sqrt($alpha*$alpha-1));
1062 93 100 100     824 $v = -$v if $y > 0 || ($y == 0 && $x < -1);
      66        
1063 93         258 return (ref $z)->make($u, $v);
1064             }
1065              
1066             #
1067             # atan
1068             #
1069             # Computes the arc tangent atan(z) = i/2 log((i+z) / (i-z)).
1070             #
1071             sub atan {
1072 75     75 0 2580 my ($z) = @_;
1073 75 100       348 return CORE::atan2($z, 1) unless ref $z;
1074 74 50       145 my ($x, $y) = ref $z ? @{$z->_cartesian} : ($z, 0);
  74         136  
1075 74 100 100     268 return 0 if $x == 0 && $y == 0;
1076 73 100       530 _divbyzero "atan(i)" if ( $z == i);
1077 71 100       180 _logofzero "atan(-i)" if (-$z == i); # -i is a bad file test...
1078 70         289 my $log = &log((i + $z) / (i - $z));
1079 70         535 return _ip2 * $log;
1080             }
1081              
1082             #
1083             # asec
1084             #
1085             # Computes the arc secant asec(z) = acos(1 / z).
1086             #
1087             sub asec {
1088 34     34 0 4189 my ($z) = @_;
1089 34 100       86 _divbyzero "asec($z)", $z if ($z == 0);
1090 33         72 return acos(1 / $z);
1091             }
1092              
1093             #
1094             # acsc
1095             #
1096             # Computes the arc cosecant acsc(z) = asin(1 / z).
1097             #
1098             sub acsc {
1099 56     56 0 7311 my ($z) = @_;
1100 56 100       168 _divbyzero "acsc($z)", $z if ($z == 0);
1101 55         141 return asin(1 / $z);
1102             }
1103              
1104             #
1105             # acosec
1106             #
1107             # Alias for acsc().
1108             #
1109 11     11 0 98 sub acosec { Math::Complex::acsc(@_) }
1110              
1111             #
1112             # acot
1113             #
1114             # Computes the arc cotangent acot(z) = atan(1 / z)
1115             #
1116             sub acot {
1117 47     47 0 4410 my ($z) = @_;
1118 47 100       106 _divbyzero "acot(0)" if $z == 0;
1119 46 50       121 return ($z >= 0) ? CORE::atan2(1, $z) : CORE::atan2(-1, -$z)
    100          
1120             unless ref $z;
1121 45 100       76 _divbyzero "acot(i)" if ($z - i == 0);
1122 44 100       175 _logofzero "acot(-i)" if ($z + i == 0);
1123 43         176 return atan(1 / $z);
1124             }
1125              
1126             #
1127             # acotan
1128             #
1129             # Alias for acot().
1130             #
1131 11     11 0 97 sub acotan { Math::Complex::acot(@_) }
1132              
1133             #
1134             # cosh
1135             #
1136             # Computes the hyperbolic cosine cosh(z) = (exp(z) + exp(-z))/2.
1137             #
1138             sub cosh {
1139 197     197 0 3914 my ($z) = @_;
1140 197         215 my $ex;
1141 197 100       435 unless (ref $z) {
1142 23         62 $ex = CORE::exp($z);
1143 23 100       111 return $ex ? ($ex == $ExpInf ? Inf() : ($ex + 1/$ex)/2) : Inf();
    100          
1144             }
1145 174         184 my ($x, $y) = @{$z->_cartesian};
  174         315  
1146 174         376 $ex = CORE::exp($x);
1147 174 50       431 my $ex_1 = $ex ? 1 / $ex : Inf();
1148 174         843 return (ref $z)->make(CORE::cos($y) * ($ex + $ex_1)/2,
1149             CORE::sin($y) * ($ex - $ex_1)/2);
1150             }
1151              
1152             #
1153             # sinh
1154             #
1155             # Computes the hyperbolic sine sinh(z) = (exp(z) - exp(-z))/2.
1156             #
1157             sub sinh {
1158 219     219 0 3135 my ($z) = @_;
1159 219         335 my $ex;
1160 219 100       519 unless (ref $z) {
1161 23 100       57 return 0 if $z == 0;
1162 21         43 $ex = CORE::exp($z);
1163 21 100       88 return $ex ? ($ex == $ExpInf ? Inf() : ($ex - 1/$ex)/2) : -Inf();
    100          
1164             }
1165 196         198 my ($x, $y) = @{$z->_cartesian};
  196         349  
1166 196         380 my $cy = CORE::cos($y);
1167 196         291 my $sy = CORE::sin($y);
1168 196         272 $ex = CORE::exp($x);
1169 196 50       395 my $ex_1 = $ex ? 1 / $ex : Inf();
1170 196         881 return (ref $z)->make(CORE::cos($y) * ($ex - $ex_1)/2,
1171             CORE::sin($y) * ($ex + $ex_1)/2);
1172             }
1173              
1174             #
1175             # tanh
1176             #
1177             # Computes the hyperbolic tangent tanh(z) = sinh(z) / cosh(z).
1178             #
1179             sub tanh {
1180 42     42 0 2642 my ($z) = @_;
1181 42         75 my $cz = cosh($z);
1182 42 50       112 _divbyzero "tanh($z)", "cosh($z)" if ($cz == 0);
1183 42         76 my $sz = sinh($z);
1184 42 100       98 return 1 if $cz == $sz;
1185 40 100       90 return -1 if $cz == -$sz;
1186 38         160 return $sz / $cz;
1187             }
1188              
1189             #
1190             # sech
1191             #
1192             # Computes the hyperbolic secant sech(z) = 1 / cosh(z).
1193             #
1194             sub sech {
1195 36     36 0 1476 my ($z) = @_;
1196 36         71 my $cz = cosh($z);
1197 36 50       93 _divbyzero "sech($z)", "cosh($z)" if ($cz == 0);
1198 36         91 return 1 / $cz;
1199             }
1200              
1201             #
1202             # csch
1203             #
1204             # Computes the hyperbolic cosecant csch(z) = 1 / sinh(z).
1205             #
1206             sub csch {
1207 56     56 0 2225 my ($z) = @_;
1208 56         113 my $sz = sinh($z);
1209 56 100       155 _divbyzero "csch($z)", "sinh($z)" if ($sz == 0);
1210 55         129 return 1 / $sz;
1211             }
1212              
1213             #
1214             # cosech
1215             #
1216             # Alias for csch().
1217             #
1218 10     10 0 61 sub cosech { Math::Complex::csch(@_) }
1219              
1220             #
1221             # coth
1222             #
1223             # Computes the hyperbolic cotangent coth(z) = cosh(z) / sinh(z).
1224             #
1225             sub coth {
1226 56     56 0 2218 my ($z) = @_;
1227 56         456 my $sz = sinh($z);
1228 56 100       217 _divbyzero "coth($z)", "sinh($z)" if $sz == 0;
1229 55         112 my $cz = cosh($z);
1230 55 100       137 return 1 if $cz == $sz;
1231 53 100       290 return -1 if $cz == -$sz;
1232 51         249 return $cz / $sz;
1233             }
1234              
1235             #
1236             # cotanh
1237             #
1238             # Alias for coth().
1239             #
1240 10     10 0 62 sub cotanh { Math::Complex::coth(@_) }
1241              
1242             #
1243             # acosh
1244             #
1245             # Computes the area/inverse hyperbolic cosine acosh(z) = log(z + sqrt(z*z-1)).
1246             #
1247             sub acosh {
1248 61     61 0 2095 my ($z) = @_;
1249 61 100       151 unless (ref $z) {
1250 2         8 $z = cplx($z, 0);
1251             }
1252 61         70 my ($re, $im) = @{$z->_cartesian};
  61         113  
1253 61 100       154 if ($im == 0) {
1254 32 100       262 return CORE::log($re + CORE::sqrt($re*$re - 1))
1255             if $re >= 1;
1256 18 100       82 return cplx(0, CORE::atan2(CORE::sqrt(1 - $re*$re), $re))
1257             if CORE::abs($re) < 1;
1258             }
1259 34         82 my $t = &sqrt($z * $z - 1) + $z;
1260             # Try Taylor if looking bad (this usually means that
1261             # $z was large negative, therefore the sqrt is really
1262             # close to abs(z), summing that with z...)
1263 34 50       248 $t = 1/(2 * $z) - 1/(8 * $z**3) + 1/(16 * $z**5) - 5/(128 * $z**7)
1264             if $t == 0;
1265 34         77 my $u = &log($t);
1266 34 100 100     165 $u->Im(-$u->Im) if $re < 0 && $im == 0;
1267 34 100       264 return $re < 0 ? -$u : $u;
1268             }
1269              
1270             #
1271             # asinh
1272             #
1273             # Computes the area/inverse hyperbolic sine asinh(z) = log(z + sqrt(z*z+1))
1274             #
1275             sub asinh {
1276 74     74 0 945 my ($z) = @_;
1277 74 100       167 unless (ref $z) {
1278 3         8 my $t = $z + CORE::sqrt($z*$z + 1);
1279 3 50       17 return CORE::log($t) if $t;
1280             }
1281 71         172 my $t = &sqrt($z * $z + 1) + $z;
1282             # Try Taylor if looking bad (this usually means that
1283             # $z was large negative, therefore the sqrt is really
1284             # close to abs(z), summing that with z...)
1285 71 50       475 $t = 1/(2 * $z) - 1/(8 * $z**3) + 1/(16 * $z**5) - 5/(128 * $z**7)
1286             if $t == 0;
1287 71         140 return &log($t);
1288             }
1289              
1290             #
1291             # atanh
1292             #
1293             # Computes the area/inverse hyperbolic tangent atanh(z) = 1/2 log((1+z) / (1-z)).
1294             #
1295             sub atanh {
1296 34     34 0 2465 my ($z) = @_;
1297 34 100       88 unless (ref $z) {
1298 3 100       16 return CORE::log((1 + $z)/(1 - $z))/2 if CORE::abs($z) < 1;
1299 2         6 $z = cplx($z, 0);
1300             }
1301 33 100       79 _divbyzero 'atanh(1)', "1 - $z" if (1 - $z == 0);
1302 32 100       119 _logofzero 'atanh(-1)' if (1 + $z == 0);
1303 31         115 return 0.5 * &log((1 + $z) / (1 - $z));
1304             }
1305              
1306             #
1307             # asech
1308             #
1309             # Computes the area/inverse hyperbolic secant asech(z) = acosh(1 / z).
1310             #
1311             sub asech {
1312 28     28 0 2437 my ($z) = @_;
1313 28 100       73 _divbyzero 'asech(0)', "$z" if ($z == 0);
1314 27         59 return acosh(1 / $z);
1315             }
1316              
1317             #
1318             # acsch
1319             #
1320             # Computes the area/inverse hyperbolic cosecant acsch(z) = asinh(1 / z).
1321             #
1322             sub acsch {
1323 41     41 0 3677 my ($z) = @_;
1324 41 100       93 _divbyzero 'acsch(0)', $z if ($z == 0);
1325 40         88 return asinh(1 / $z);
1326             }
1327              
1328             #
1329             # acosech
1330             #
1331             # Alias for acosh().
1332             #
1333 6     6 0 47 sub acosech { Math::Complex::acsch(@_) }
1334              
1335             #
1336             # acoth
1337             #
1338             # Computes the area/inverse hyperbolic cotangent acoth(z) = 1/2 log((1+z) / (z-1)).
1339             #
1340             sub acoth {
1341 40     40 0 3872 my ($z) = @_;
1342 40 100       105 _divbyzero 'acoth(0)' if ($z == 0);
1343 39 100       137 unless (ref $z) {
1344 3 100       14 return CORE::log(($z + 1)/($z - 1))/2 if CORE::abs($z) > 1;
1345 2         3 $z = cplx($z, 0);
1346             }
1347 38 100       166 _divbyzero 'acoth(1)', "$z - 1" if ($z - 1 == 0);
1348 37 100       157 _logofzero 'acoth(-1)', "1 + $z" if (1 + $z == 0);
1349 36         146 return &log((1 + $z) / ($z - 1)) / 2;
1350             }
1351              
1352             #
1353             # acotanh
1354             #
1355             # Alias for acot().
1356             #
1357 6     6 0 71 sub acotanh { Math::Complex::acoth(@_) }
1358              
1359             #
1360             # (atan2)
1361             #
1362             # Compute atan(z1/z2), minding the right quadrant.
1363             #
1364             sub atan2 {
1365 40     40 0 1124 my ($z1, $z2, $inverted) = @_;
1366 40         49 my ($re1, $im1, $re2, $im2);
1367 40 50       76 if ($inverted) {
1368 0 0       0 ($re1, $im1) = ref $z2 ? @{$z2->_cartesian} : ($z2, 0);
  0         0  
1369 0 0       0 ($re2, $im2) = ref $z1 ? @{$z1->_cartesian} : ($z1, 0);
  0         0  
1370             } else {
1371 40 100       92 ($re1, $im1) = ref $z1 ? @{$z1->_cartesian} : ($z1, 0);
  3         7  
1372 40 100       92 ($re2, $im2) = ref $z2 ? @{$z2->_cartesian} : ($z2, 0);
  3         5  
1373             }
1374 40 100 100     171 if ($im1 || $im2) {
1375             # In MATLAB the imaginary parts are ignored.
1376             # warn "atan2: Imaginary parts ignored";
1377             # http://documents.wolfram.com/mathematica/functions/ArcTan
1378             # NOTE: Mathematica ArcTan[x,y] while atan2(y,x)
1379 4         9 my $s = $z1 * $z1 + $z2 * $z2;
1380 4 50       22 _divbyzero("atan2") if $s == 0;
1381 4         8 my $i = &i;
1382 4         12 my $r = $z2 + $z1 * $i;
1383 4         17 return -$i * &log($r / &sqrt( $s ));
1384             }
1385 36         285 return CORE::atan2($re1, $re2);
1386             }
1387              
1388             #
1389             # display_format
1390             # ->display_format
1391             #
1392             # Set (get if no argument) the display format for all complex numbers that
1393             # don't happen to have overridden it via ->display_format
1394             #
1395             # When called as an object method, this actually sets the display format for
1396             # the current object.
1397             #
1398             # Valid object formats are 'c' and 'p' for cartesian and polar. The first
1399             # letter is used actually, so the type can be fully spelled out for clarity.
1400             #
1401             sub display_format {
1402 18463     18463 0 24650 my $self = shift;
1403 18463         49688 my %display_format = %DISPLAY_FORMAT;
1404              
1405 18463 100       42714 if (ref $self) { # Called as an object method
1406 18462 100       44390 if (exists $self->{display_format}) {
1407 11419         10818 my %obj = %{$self->{display_format}};
  11419         34621  
1408 11419         39081 @display_format{keys %obj} = values %obj;
1409             }
1410             }
1411 18463 100       35826 if (@_ == 1) {
1412 7043         11424 $display_format{style} = shift;
1413             } else {
1414 11420         14681 my %new = @_;
1415 11420         18454 @display_format{keys %new} = values %new;
1416             }
1417              
1418 18463 100       35469 if (ref $self) { # Called as an object method
1419 18462         56127 $self->{display_format} = { %display_format };
1420             return
1421             wantarray ?
1422 18462 100       66928 %{$self->{display_format}} :
  5713         24447  
1423             $self->{display_format}->{style};
1424             }
1425              
1426             # Called as a class method
1427 1         3 %DISPLAY_FORMAT = %display_format;
1428             return
1429             wantarray ?
1430 1 50       16 %DISPLAY_FORMAT :
1431             $DISPLAY_FORMAT{style};
1432             }
1433              
1434             #
1435             # (_stringify)
1436             #
1437             # Show nicely formatted complex number under its cartesian or polar form,
1438             # depending on the current display format:
1439             #
1440             # . If a specific display format has been recorded for this object, use it.
1441             # . Otherwise, use the generic current default for all complex numbers,
1442             # which is a package global variable.
1443             #
1444             sub _stringify {
1445 5699     5699   23266 my ($z) = shift;
1446              
1447 5699         11215 my $style = $z->display_format;
1448              
1449 5699 50       11647 $style = $DISPLAY_FORMAT{style} unless defined $style;
1450              
1451 5699 100       17268 return $z->_stringify_polar if $style =~ /^p/i;
1452 5431         10571 return $z->_stringify_cartesian;
1453             }
1454              
1455             #
1456             # ->_stringify_cartesian
1457             #
1458             # Stringify as a cartesian representation 'a+bi'.
1459             #
1460             sub _stringify_cartesian {
1461 5438     5438   6191 my $z = shift;
1462 5438         6158 my ($x, $y) = @{$z->_cartesian};
  5438         8830  
1463 5438         6347 my ($re, $im);
1464              
1465 5438         9533 my %format = $z->display_format;
1466 5438         8751 my $format = $format{format};
1467              
1468 5438 100       9673 if ($x) {
1469 3966 50       14749 if ($x =~ /^NaN[QS]?$/i) {
1470 0         0 $re = $x;
1471             } else {
1472 3966 50       12162 if ($x =~ /^-?\Q$Inf\E$/oi) {
1473 0         0 $re = $x;
1474             } else {
1475 3966 100       8020 $re = defined $format ? sprintf($format, $x) : $x;
1476             }
1477             }
1478             } else {
1479 1472         1928 undef $re;
1480             }
1481              
1482 5438 100       7735 if ($y) {
1483 3565 50       9692 if ($y =~ /^(NaN[QS]?)$/i) {
1484 0         0 $im = $y;
1485             } else {
1486 3565 50       9137 if ($y =~ /^-?\Q$Inf\E$/oi) {
1487 0         0 $im = $y;
1488             } else {
1489 3565 100       9791 $im =
    100          
    100          
1490             defined $format ?
1491             sprintf($format, $y) :
1492             ($y == 1 ? "" : ($y == -1 ? "-" : $y));
1493             }
1494             }
1495 3565         7161 $im .= "i";
1496             } else {
1497 1873         2347 undef $im;
1498             }
1499              
1500 5438         5784 my $str = $re;
1501              
1502 5438 100       9215 if (defined $im) {
    100          
1503 3565 100 33     9950 if ($y < 0) {
    50          
1504 1049         3891 $str .= $im;
1505             } elsif ($y > 0 || $im =~ /^NaN[QS]?i$/i) {
1506 2516 100       9627 $str .= "+" if defined $re;
1507 2516         3593 $str .= $im;
1508             }
1509             } elsif (!defined $re) {
1510 94         114 $str = "0";
1511             }
1512              
1513 5438         135914 return $str;
1514             }
1515              
1516              
1517             #
1518             # ->_stringify_polar
1519             #
1520             # Stringify as a polar representation '[r,t]'.
1521             #
1522             sub _stringify_polar {
1523 273     273   390 my $z = shift;
1524 273         304 my ($r, $t) = @{$z->_polar};
  273         435  
1525 273         303 my $theta;
1526              
1527 273         491 my %format = $z->display_format;
1528 273         453 my $format = $format{format};
1529              
1530 273 50 33     3071 if ($t =~ /^NaN[QS]?$/i || $t =~ /^-?\Q$Inf\E$/oi) {
    100 66        
    100          
1531 0         0 $theta = $t;
1532             } elsif ($t == pi) {
1533 5         11 $theta = "pi";
1534             } elsif ($r == 0 || $t == 0) {
1535 12 50       24 $theta = defined $format ? sprintf($format, $t) : $t;
1536             }
1537              
1538 273 100       948 return "[$r,$theta]" if defined $theta;
1539              
1540             #
1541             # Try to identify pi/n and friends.
1542             #
1543              
1544 256         554 $t -= int(CORE::abs($t) / pi2) * pi2;
1545              
1546 256 100 66     1703 if ($format{polar_pretty_print} && $t) {
1547 252         252 my ($a, $b);
1548 252         401 for $a (2..9) {
1549 1616         1829 $b = $t * $a / pi;
1550 1616 100       6587 if ($b =~ /^-?\d+$/) {
1551 60 100       154 $b = $b < 0 ? "-" : "" if CORE::abs($b) == 1;
    100          
1552 60         105 $theta = "${b}pi/$a";
1553 60         90 last;
1554             }
1555             }
1556             }
1557              
1558 256 100       531 if (defined $format) {
1559 2         7 $r = sprintf($format, $r);
1560 2 50       7 $theta = sprintf($format, $t) unless defined $theta;
1561             } else {
1562 254 100       609 $theta = $t unless defined $theta;
1563             }
1564              
1565 256         7940 return "[$r,$theta]";
1566             }
1567              
1568             sub Inf {
1569 46     46 1 735 return $Inf;
1570             }
1571              
1572             1;
1573             __END__