The Im() function wasn't returning zero for non-Math::Complex
[p5sagit/p5-mst-13.2.git] / lib / Math / Complex.pm
CommitLineData
66730be0 1#
2# Complex numbers and associated mathematical functions
b42d0ec9 3# -- Raphael Manfredi Since Sep 1996
4# -- Jarkko Hietaniemi Since Mar 1997
5# -- Daniel S. Lewart Since Sep 1997
fb73857a 6#
a0d0e21e 7
5aabfad6 8package Math::Complex;
a0d0e21e 9
9fbe1b12 10our($VERSION, @ISA, @EXPORT, %EXPORT_TAGS, $Inf);
11
476757f7 12$VERSION = 1.31;
13
9fbe1b12 14BEGIN {
ffb4440d 15 unless ($^O eq 'unicosmk') {
16 my $e = $!;
17 # We do want an arithmetic overflow.
18 eval '$Inf = CORE::exp(CORE::exp(30))';
19 $! = $e; # Clear ERANGE.
20 undef $Inf unless $Inf =~ /^inf(?:inity)?$/i; # Inf INF inf Infinity
21 }
5240e574 22 $Inf = "Inf" if !defined $Inf || !($Inf > 0); # Desperation.
9fbe1b12 23}
fb73857a 24
9fbe1b12 25use strict;
fb73857a 26
9fbe1b12 27my $i;
28my %LOGN;
0c721ce2 29
9fbe1b12 30require Exporter;
0c721ce2 31
5aabfad6 32@ISA = qw(Exporter);
33
5aabfad6 34my @trig = qw(
35 pi
fb73857a 36 tan
5aabfad6 37 csc cosec sec cot cotan
38 asin acos atan
39 acsc acosec asec acot acotan
40 sinh cosh tanh
41 csch cosech sech coth cotanh
42 asinh acosh atanh
43 acsch acosech asech acoth acotanh
44 );
45
46@EXPORT = (qw(
b42d0ec9 47 i Re Im rho theta arg
fb73857a 48 sqrt log ln
5aabfad6 49 log10 logn cbrt root
50 cplx cplxe
51 ),
52 @trig);
53
54%EXPORT_TAGS = (
55 'trig' => [@trig],
66730be0 56);
a0d0e21e 57
a5f75d66 58use overload
0c721ce2 59 '+' => \&plus,
60 '-' => \&minus,
61 '*' => \&multiply,
62 '/' => \&divide,
66730be0 63 '**' => \&power,
1fa12f56 64 '==' => \&numeq,
66730be0 65 '<=>' => \&spaceship,
66 'neg' => \&negate,
0c721ce2 67 '~' => \&conjugate,
66730be0 68 'abs' => \&abs,
69 'sqrt' => \&sqrt,
70 'exp' => \&exp,
71 'log' => \&log,
72 'sin' => \&sin,
73 'cos' => \&cos,
0c721ce2 74 'tan' => \&tan,
66730be0 75 'atan2' => \&atan2,
76 qw("" stringify);
77
78#
b42d0ec9 79# Package "privates"
66730be0 80#
81
16357284 82my %DISPLAY_FORMAT = ('style' => 'cartesian',
83 'polar_pretty_print' => 1);
84my $eps = 1e-14; # Epsilon
66730be0 85
86#
87# Object attributes (internal):
88# cartesian [real, imaginary] -- cartesian form
89# polar [rho, theta] -- polar form
90# c_dirty cartesian form not up-to-date
91# p_dirty polar form not up-to-date
92# display display format (package's global when not set)
93#
94
b42d0ec9 95# Die on bad *make() arguments.
96
97sub _cannot_make {
98 die "@{[(caller(1))[3]]}: Cannot take $_[0] of $_[1].\n";
99}
100
66730be0 101#
102# ->make
103#
104# Create a new complex number (cartesian form)
105#
106sub make {
107 my $self = bless {}, shift;
108 my ($re, $im) = @_;
b42d0ec9 109 my $rre = ref $re;
110 if ( $rre ) {
111 if ( $rre eq ref $self ) {
112 $re = Re($re);
113 } else {
114 _cannot_make("real part", $rre);
115 }
116 }
117 my $rim = ref $im;
118 if ( $rim ) {
119 if ( $rim eq ref $self ) {
120 $im = Im($im);
121 } else {
122 _cannot_make("imaginary part", $rim);
123 }
124 }
125 $self->{'cartesian'} = [ $re, $im ];
66730be0 126 $self->{c_dirty} = 0;
127 $self->{p_dirty} = 1;
b42d0ec9 128 $self->display_format('cartesian');
66730be0 129 return $self;
130}
131
132#
133# ->emake
134#
135# Create a new complex number (exponential form)
136#
137sub emake {
138 my $self = bless {}, shift;
139 my ($rho, $theta) = @_;
b42d0ec9 140 my $rrh = ref $rho;
141 if ( $rrh ) {
142 if ( $rrh eq ref $self ) {
143 $rho = rho($rho);
144 } else {
145 _cannot_make("rho", $rrh);
146 }
147 }
148 my $rth = ref $theta;
149 if ( $rth ) {
150 if ( $rth eq ref $self ) {
151 $theta = theta($theta);
152 } else {
153 _cannot_make("theta", $rth);
154 }
155 }
fb73857a 156 if ($rho < 0) {
157 $rho = -$rho;
158 $theta = ($theta <= 0) ? $theta + pi() : $theta - pi();
159 }
160 $self->{'polar'} = [$rho, $theta];
66730be0 161 $self->{p_dirty} = 0;
162 $self->{c_dirty} = 1;
b42d0ec9 163 $self->display_format('polar');
66730be0 164 return $self;
165}
166
167sub new { &make } # For backward compatibility only.
168
169#
170# cplx
171#
172# Creates a complex number from a (re, im) tuple.
173# This avoids the burden of writing Math::Complex->make(re, im).
174#
175sub cplx {
176 my ($re, $im) = @_;
16357284 177 return __PACKAGE__->make($re, defined $im ? $im : 0);
66730be0 178}
179
180#
181# cplxe
182#
183# Creates a complex number from a (rho, theta) tuple.
184# This avoids the burden of writing Math::Complex->emake(rho, theta).
185#
186sub cplxe {
187 my ($rho, $theta) = @_;
16357284 188 return __PACKAGE__->emake($rho, defined $theta ? $theta : 0);
66730be0 189}
190
191#
192# pi
193#
fb73857a 194# The number defined as pi = 180 degrees
66730be0 195#
6570f784 196sub pi () { 4 * CORE::atan2(1, 1) }
5cd24f17 197
198#
fb73857a 199# pit2
5cd24f17 200#
fb73857a 201# The full circle
202#
6570f784 203sub pit2 () { 2 * pi }
fb73857a 204
5cd24f17 205#
fb73857a 206# pip2
207#
208# The quarter circle
209#
6570f784 210sub pip2 () { pi / 2 }
5cd24f17 211
fb73857a 212#
d09ae4e6 213# deg1
214#
215# One degree in radians, used in stringify_polar.
216#
217
6570f784 218sub deg1 () { pi / 180 }
d09ae4e6 219
220#
fb73857a 221# uplog10
222#
223# Used in log10().
224#
6570f784 225sub uplog10 () { 1 / CORE::log(10) }
66730be0 226
227#
228# i
229#
230# The number defined as i*i = -1;
231#
232sub i () {
5cd24f17 233 return $i if ($i);
234 $i = bless {};
40da2db3 235 $i->{'cartesian'} = [0, 1];
fb73857a 236 $i->{'polar'} = [1, pip2];
66730be0 237 $i->{c_dirty} = 0;
238 $i->{p_dirty} = 0;
239 return $i;
240}
241
242#
1fa12f56 243# ip2
244#
245# Half of i.
246#
247sub ip2 () { i / 2 }
248
249#
66730be0 250# Attribute access/set routines
251#
252
0c721ce2 253sub cartesian {$_[0]->{c_dirty} ?
254 $_[0]->update_cartesian : $_[0]->{'cartesian'}}
255sub polar {$_[0]->{p_dirty} ?
256 $_[0]->update_polar : $_[0]->{'polar'}}
66730be0 257
40da2db3 258sub set_cartesian { $_[0]->{p_dirty}++; $_[0]->{'cartesian'} = $_[1] }
259sub set_polar { $_[0]->{c_dirty}++; $_[0]->{'polar'} = $_[1] }
66730be0 260
261#
262# ->update_cartesian
263#
264# Recompute and return the cartesian form, given accurate polar form.
265#
266sub update_cartesian {
267 my $self = shift;
40da2db3 268 my ($r, $t) = @{$self->{'polar'}};
66730be0 269 $self->{c_dirty} = 0;
a8693bd3 270 return $self->{'cartesian'} = [$r * CORE::cos($t), $r * CORE::sin($t)];
66730be0 271}
272
273#
274#
275# ->update_polar
276#
277# Recompute and return the polar form, given accurate cartesian form.
278#
279sub update_polar {
280 my $self = shift;
40da2db3 281 my ($x, $y) = @{$self->{'cartesian'}};
66730be0 282 $self->{p_dirty} = 0;
40da2db3 283 return $self->{'polar'} = [0, 0] if $x == 0 && $y == 0;
1fa12f56 284 return $self->{'polar'} = [CORE::sqrt($x*$x + $y*$y),
285 CORE::atan2($y, $x)];
66730be0 286}
287
288#
289# (plus)
290#
291# Computes z1+z2.
292#
293sub plus {
294 my ($z1, $z2, $regular) = @_;
295 my ($re1, $im1) = @{$z1->cartesian};
0e505df1 296 $z2 = cplx($z2) unless ref $z2;
5cd24f17 297 my ($re2, $im2) = ref $z2 ? @{$z2->cartesian} : ($z2, 0);
66730be0 298 unless (defined $regular) {
299 $z1->set_cartesian([$re1 + $re2, $im1 + $im2]);
300 return $z1;
301 }
302 return (ref $z1)->make($re1 + $re2, $im1 + $im2);
303}
304
305#
306# (minus)
307#
308# Computes z1-z2.
309#
310sub minus {
311 my ($z1, $z2, $inverted) = @_;
312 my ($re1, $im1) = @{$z1->cartesian};
0e505df1 313 $z2 = cplx($z2) unless ref $z2;
314 my ($re2, $im2) = @{$z2->cartesian};
66730be0 315 unless (defined $inverted) {
316 $z1->set_cartesian([$re1 - $re2, $im1 - $im2]);
317 return $z1;
318 }
319 return $inverted ?
320 (ref $z1)->make($re2 - $re1, $im2 - $im1) :
321 (ref $z1)->make($re1 - $re2, $im1 - $im2);
0e505df1 322
66730be0 323}
324
325#
326# (multiply)
327#
328# Computes z1*z2.
329#
330sub multiply {
fb73857a 331 my ($z1, $z2, $regular) = @_;
332 if ($z1->{p_dirty} == 0 and ref $z2 and $z2->{p_dirty} == 0) {
333 # if both polar better use polar to avoid rounding errors
334 my ($r1, $t1) = @{$z1->polar};
335 my ($r2, $t2) = @{$z2->polar};
336 my $t = $t1 + $t2;
337 if ($t > pi()) { $t -= pit2 }
338 elsif ($t <= -pi()) { $t += pit2 }
339 unless (defined $regular) {
340 $z1->set_polar([$r1 * $r2, $t]);
66730be0 341 return $z1;
fb73857a 342 }
343 return (ref $z1)->emake($r1 * $r2, $t);
344 } else {
345 my ($x1, $y1) = @{$z1->cartesian};
346 if (ref $z2) {
347 my ($x2, $y2) = @{$z2->cartesian};
348 return (ref $z1)->make($x1*$x2-$y1*$y2, $x1*$y2+$y1*$x2);
349 } else {
350 return (ref $z1)->make($x1*$z2, $y1*$z2);
351 }
66730be0 352 }
66730be0 353}
354
355#
0e505df1 356# _divbyzero
0c721ce2 357#
358# Die on division by zero.
359#
0e505df1 360sub _divbyzero {
5cd24f17 361 my $mess = "$_[0]: Division by zero.\n";
362
363 if (defined $_[1]) {
364 $mess .= "(Because in the definition of $_[0], the divisor ";
1fa12f56 365 $mess .= "$_[1] " unless ("$_[1]" eq '0');
5cd24f17 366 $mess .= "is 0)\n";
367 }
368
0c721ce2 369 my @up = caller(1);
fb73857a 370
5cd24f17 371 $mess .= "Died at $up[1] line $up[2].\n";
372
373 die $mess;
0c721ce2 374}
375
376#
66730be0 377# (divide)
378#
379# Computes z1/z2.
380#
381sub divide {
382 my ($z1, $z2, $inverted) = @_;
fb73857a 383 if ($z1->{p_dirty} == 0 and ref $z2 and $z2->{p_dirty} == 0) {
384 # if both polar better use polar to avoid rounding errors
385 my ($r1, $t1) = @{$z1->polar};
386 my ($r2, $t2) = @{$z2->polar};
387 my $t;
388 if ($inverted) {
0e505df1 389 _divbyzero "$z2/0" if ($r1 == 0);
fb73857a 390 $t = $t2 - $t1;
391 if ($t > pi()) { $t -= pit2 }
392 elsif ($t <= -pi()) { $t += pit2 }
393 return (ref $z1)->emake($r2 / $r1, $t);
394 } else {
0e505df1 395 _divbyzero "$z1/0" if ($r2 == 0);
fb73857a 396 $t = $t1 - $t2;
397 if ($t > pi()) { $t -= pit2 }
398 elsif ($t <= -pi()) { $t += pit2 }
399 return (ref $z1)->emake($r1 / $r2, $t);
400 }
401 } else {
402 my ($d, $x2, $y2);
403 if ($inverted) {
404 ($x2, $y2) = @{$z1->cartesian};
405 $d = $x2*$x2 + $y2*$y2;
406 _divbyzero "$z2/0" if $d == 0;
407 return (ref $z1)->make(($x2*$z2)/$d, -($y2*$z2)/$d);
408 } else {
409 my ($x1, $y1) = @{$z1->cartesian};
410 if (ref $z2) {
411 ($x2, $y2) = @{$z2->cartesian};
412 $d = $x2*$x2 + $y2*$y2;
413 _divbyzero "$z1/0" if $d == 0;
414 my $u = ($x1*$x2 + $y1*$y2)/$d;
415 my $v = ($y1*$x2 - $x1*$y2)/$d;
416 return (ref $z1)->make($u, $v);
417 } else {
418 _divbyzero "$z1/0" if $z2 == 0;
419 return (ref $z1)->make($x1/$z2, $y1/$z2);
420 }
421 }
0c721ce2 422 }
66730be0 423}
424
425#
426# (power)
427#
428# Computes z1**z2 = exp(z2 * log z1)).
429#
430sub power {
431 my ($z1, $z2, $inverted) = @_;
ace5de91 432 if ($inverted) {
2820d885 433 return 1 if $z1 == 0 || $z2 == 1;
434 return 0 if $z2 == 0 && Re($z1) > 0;
ace5de91 435 } else {
2820d885 436 return 1 if $z2 == 0 || $z1 == 1;
437 return 0 if $z1 == 0 && Re($z2) > 0;
ace5de91 438 }
1fa12f56 439 my $w = $inverted ? &exp($z1 * &log($z2))
440 : &exp($z2 * &log($z1));
d09ae4e6 441 # If both arguments cartesian, return cartesian, else polar.
442 return $z1->{c_dirty} == 0 &&
443 (not ref $z2 or $z2->{c_dirty} == 0) ?
444 cplx(@{$w->cartesian}) : $w;
66730be0 445}
446
447#
448# (spaceship)
449#
450# Computes z1 <=> z2.
2820d885 451# Sorts on the real part first, then on the imaginary part. Thus 2-4i < 3+8i.
66730be0 452#
453sub spaceship {
454 my ($z1, $z2, $inverted) = @_;
5cd24f17 455 my ($re1, $im1) = ref $z1 ? @{$z1->cartesian} : ($z1, 0);
456 my ($re2, $im2) = ref $z2 ? @{$z2->cartesian} : ($z2, 0);
66730be0 457 my $sgn = $inverted ? -1 : 1;
458 return $sgn * ($re1 <=> $re2) if $re1 != $re2;
459 return $sgn * ($im1 <=> $im2);
460}
461
462#
1fa12f56 463# (numeq)
464#
465# Computes z1 == z2.
466#
467# (Required in addition to spaceship() because of NaNs.)
468sub numeq {
469 my ($z1, $z2, $inverted) = @_;
470 my ($re1, $im1) = ref $z1 ? @{$z1->cartesian} : ($z1, 0);
471 my ($re2, $im2) = ref $z2 ? @{$z2->cartesian} : ($z2, 0);
472 return $re1 == $re2 && $im1 == $im2 ? 1 : 0;
473}
474
475#
66730be0 476# (negate)
477#
478# Computes -z.
479#
480sub negate {
481 my ($z) = @_;
482 if ($z->{c_dirty}) {
483 my ($r, $t) = @{$z->polar};
fb73857a 484 $t = ($t <= 0) ? $t + pi : $t - pi;
485 return (ref $z)->emake($r, $t);
66730be0 486 }
487 my ($re, $im) = @{$z->cartesian};
488 return (ref $z)->make(-$re, -$im);
489}
490
491#
492# (conjugate)
493#
494# Compute complex's conjugate.
495#
496sub conjugate {
497 my ($z) = @_;
498 if ($z->{c_dirty}) {
499 my ($r, $t) = @{$z->polar};
500 return (ref $z)->emake($r, -$t);
501 }
502 my ($re, $im) = @{$z->cartesian};
503 return (ref $z)->make($re, -$im);
504}
505
506#
507# (abs)
508#
b42d0ec9 509# Compute or set complex's norm (rho).
66730be0 510#
511sub abs {
b42d0ec9 512 my ($z, $rho) = @_;
1fa12f56 513 unless (ref $z) {
514 if (@_ == 2) {
515 $_[0] = $_[1];
516 } else {
517 return CORE::abs($z);
518 }
519 }
b42d0ec9 520 if (defined $rho) {
521 $z->{'polar'} = [ $rho, ${$z->polar}[1] ];
522 $z->{p_dirty} = 0;
523 $z->{c_dirty} = 1;
524 return $rho;
525 } else {
526 return ${$z->polar}[0];
527 }
528}
529
530sub _theta {
531 my $theta = $_[0];
532
533 if ($$theta > pi()) { $$theta -= pit2 }
534 elsif ($$theta <= -pi()) { $$theta += pit2 }
66730be0 535}
536
537#
538# arg
539#
b42d0ec9 540# Compute or set complex's argument (theta).
66730be0 541#
542sub arg {
b42d0ec9 543 my ($z, $theta) = @_;
544 return $z unless ref $z;
545 if (defined $theta) {
546 _theta(\$theta);
547 $z->{'polar'} = [ ${$z->polar}[0], $theta ];
548 $z->{p_dirty} = 0;
549 $z->{c_dirty} = 1;
550 } else {
551 $theta = ${$z->polar}[1];
552 _theta(\$theta);
553 }
554 return $theta;
66730be0 555}
556
557#
558# (sqrt)
559#
0c721ce2 560# Compute sqrt(z).
66730be0 561#
b42d0ec9 562# It is quite tempting to use wantarray here so that in list context
563# sqrt() would return the two solutions. This, however, would
564# break things like
565#
566# print "sqrt(z) = ", sqrt($z), "\n";
567#
568# The two values would be printed side by side without no intervening
569# whitespace, quite confusing.
570# Therefore if you want the two solutions use the root().
571#
66730be0 572sub sqrt {
573 my ($z) = @_;
b42d0ec9 574 my ($re, $im) = ref $z ? @{$z->cartesian} : ($z, 0);
1fa12f56 575 return $re < 0 ? cplx(0, CORE::sqrt(-$re)) : CORE::sqrt($re)
576 if $im == 0;
66730be0 577 my ($r, $t) = @{$z->polar};
a8693bd3 578 return (ref $z)->emake(CORE::sqrt($r), $t/2);
66730be0 579}
580
581#
582# cbrt
583#
0c721ce2 584# Compute cbrt(z) (cubic root).
66730be0 585#
b42d0ec9 586# Why are we not returning three values? The same answer as for sqrt().
587#
66730be0 588sub cbrt {
589 my ($z) = @_;
1fa12f56 590 return $z < 0 ?
591 -CORE::exp(CORE::log(-$z)/3) :
592 ($z > 0 ? CORE::exp(CORE::log($z)/3): 0)
fb73857a 593 unless ref $z;
66730be0 594 my ($r, $t) = @{$z->polar};
1fa12f56 595 return 0 if $r == 0;
a8693bd3 596 return (ref $z)->emake(CORE::exp(CORE::log($r)/3), $t/3);
66730be0 597}
598
599#
0e505df1 600# _rootbad
601#
602# Die on bad root.
603#
604sub _rootbad {
1fa12f56 605 my $mess = "Root $_[0] illegal, root rank must be positive integer.\n";
0e505df1 606
607 my @up = caller(1);
fb73857a 608
0e505df1 609 $mess .= "Died at $up[1] line $up[2].\n";
610
611 die $mess;
612}
613
614#
66730be0 615# root
616#
617# Computes all nth root for z, returning an array whose size is n.
618# `n' must be a positive integer.
619#
620# The roots are given by (for k = 0..n-1):
621#
622# z^(1/n) = r^(1/n) (cos ((t+2 k pi)/n) + i sin ((t+2 k pi)/n))
623#
624sub root {
625 my ($z, $n) = @_;
0e505df1 626 _rootbad($n) if ($n < 1 or int($n) != $n);
1fa12f56 627 my ($r, $t) = ref $z ?
628 @{$z->polar} : (CORE::abs($z), $z >= 0 ? 0 : pi);
66730be0 629 my @root;
630 my $k;
fb73857a 631 my $theta_inc = pit2 / $n;
66730be0 632 my $rho = $r ** (1/$n);
633 my $theta;
d09ae4e6 634 my $cartesian = ref $z && $z->{c_dirty} == 0;
66730be0 635 for ($k = 0, $theta = $t / $n; $k < $n; $k++, $theta += $theta_inc) {
d09ae4e6 636 my $w = cplxe($rho, $theta);
637 # Yes, $cartesian is loop invariant.
638 push @root, $cartesian ? cplx(@{$w->cartesian}) : $w;
a0d0e21e 639 }
66730be0 640 return @root;
a0d0e21e 641}
642
66730be0 643#
644# Re
645#
b42d0ec9 646# Return or set Re(z).
66730be0 647#
a0d0e21e 648sub Re {
b42d0ec9 649 my ($z, $Re) = @_;
66730be0 650 return $z unless ref $z;
b42d0ec9 651 if (defined $Re) {
652 $z->{'cartesian'} = [ $Re, ${$z->cartesian}[1] ];
653 $z->{c_dirty} = 0;
654 $z->{p_dirty} = 1;
655 } else {
656 return ${$z->cartesian}[0];
657 }
a0d0e21e 658}
659
66730be0 660#
661# Im
662#
b42d0ec9 663# Return or set Im(z).
66730be0 664#
a0d0e21e 665sub Im {
b42d0ec9 666 my ($z, $Im) = @_;
178326e7 667 return 0 unless ref $z;
b42d0ec9 668 if (defined $Im) {
669 $z->{'cartesian'} = [ ${$z->cartesian}[0], $Im ];
670 $z->{c_dirty} = 0;
671 $z->{p_dirty} = 1;
672 } else {
673 return ${$z->cartesian}[1];
674 }
675}
676
677#
678# rho
679#
680# Return or set rho(w).
681#
682sub rho {
683 Math::Complex::abs(@_);
684}
685
686#
687# theta
688#
689# Return or set theta(w).
690#
691sub theta {
692 Math::Complex::arg(@_);
a0d0e21e 693}
694
66730be0 695#
696# (exp)
697#
698# Computes exp(z).
699#
700sub exp {
701 my ($z) = @_;
702 my ($x, $y) = @{$z->cartesian};
a8693bd3 703 return (ref $z)->emake(CORE::exp($x), $y);
66730be0 704}
705
706#
8c03c583 707# _logofzero
708#
fb73857a 709# Die on logarithm of zero.
8c03c583 710#
711sub _logofzero {
712 my $mess = "$_[0]: Logarithm of zero.\n";
713
714 if (defined $_[1]) {
715 $mess .= "(Because in the definition of $_[0], the argument ";
716 $mess .= "$_[1] " unless ($_[1] eq '0');
717 $mess .= "is 0)\n";
718 }
719
720 my @up = caller(1);
fb73857a 721
8c03c583 722 $mess .= "Died at $up[1] line $up[2].\n";
723
724 die $mess;
725}
726
727#
66730be0 728# (log)
729#
730# Compute log(z).
731#
732sub log {
733 my ($z) = @_;
fb73857a 734 unless (ref $z) {
735 _logofzero("log") if $z == 0;
a8693bd3 736 return $z > 0 ? CORE::log($z) : cplx(CORE::log(-$z), pi);
fb73857a 737 }
5cd24f17 738 my ($r, $t) = @{$z->polar};
fb73857a 739 _logofzero("log") if $r == 0;
740 if ($t > pi()) { $t -= pit2 }
741 elsif ($t <= -pi()) { $t += pit2 }
a8693bd3 742 return (ref $z)->make(CORE::log($r), $t);
66730be0 743}
744
745#
0c721ce2 746# ln
747#
748# Alias for log().
749#
750sub ln { Math::Complex::log(@_) }
751
752#
66730be0 753# log10
754#
755# Compute log10(z).
756#
5cd24f17 757
66730be0 758sub log10 {
fb73857a 759 return Math::Complex::log($_[0]) * uplog10;
66730be0 760}
761
762#
763# logn
764#
765# Compute logn(z,n) = log(z) / log(n)
766#
767sub logn {
768 my ($z, $n) = @_;
0c721ce2 769 $z = cplx($z, 0) unless ref $z;
9fbe1b12 770 my $logn = $LOGN{$n};
771 $logn = $LOGN{$n} = CORE::log($n) unless defined $logn; # Cache log(n)
1fa12f56 772 return &log($z) / $logn;
66730be0 773}
774
775#
776# (cos)
777#
778# Compute cos(z) = (exp(iz) + exp(-iz))/2.
779#
780sub cos {
781 my ($z) = @_;
1fa12f56 782 return CORE::cos($z) unless ref $z;
66730be0 783 my ($x, $y) = @{$z->cartesian};
a8693bd3 784 my $ey = CORE::exp($y);
1fa12f56 785 my $sx = CORE::sin($x);
786 my $cx = CORE::cos($x);
787 my $ey_1 = $ey ? 1 / $ey : $Inf;
788 return (ref $z)->make($cx * ($ey + $ey_1)/2,
789 $sx * ($ey_1 - $ey)/2);
66730be0 790}
791
792#
793# (sin)
794#
795# Compute sin(z) = (exp(iz) - exp(-iz))/2.
796#
797sub sin {
798 my ($z) = @_;
1fa12f56 799 return CORE::sin($z) unless ref $z;
66730be0 800 my ($x, $y) = @{$z->cartesian};
a8693bd3 801 my $ey = CORE::exp($y);
1fa12f56 802 my $sx = CORE::sin($x);
803 my $cx = CORE::cos($x);
804 my $ey_1 = $ey ? 1 / $ey : $Inf;
805 return (ref $z)->make($sx * ($ey + $ey_1)/2,
806 $cx * ($ey - $ey_1)/2);
66730be0 807}
808
809#
810# tan
811#
812# Compute tan(z) = sin(z) / cos(z).
813#
814sub tan {
815 my ($z) = @_;
1fa12f56 816 my $cz = &cos($z);
817 _divbyzero "tan($z)", "cos($z)" if $cz == 0;
818 return &sin($z) / $cz;
66730be0 819}
820
821#
0c721ce2 822# sec
823#
824# Computes the secant sec(z) = 1 / cos(z).
825#
826sub sec {
827 my ($z) = @_;
1fa12f56 828 my $cz = &cos($z);
0e505df1 829 _divbyzero "sec($z)", "cos($z)" if ($cz == 0);
0c721ce2 830 return 1 / $cz;
831}
832
833#
834# csc
835#
836# Computes the cosecant csc(z) = 1 / sin(z).
837#
838sub csc {
839 my ($z) = @_;
1fa12f56 840 my $sz = &sin($z);
0e505df1 841 _divbyzero "csc($z)", "sin($z)" if ($sz == 0);
0c721ce2 842 return 1 / $sz;
843}
844
66730be0 845#
0c721ce2 846# cosec
66730be0 847#
0c721ce2 848# Alias for csc().
849#
850sub cosec { Math::Complex::csc(@_) }
851
852#
853# cot
854#
fb73857a 855# Computes cot(z) = cos(z) / sin(z).
0c721ce2 856#
857sub cot {
66730be0 858 my ($z) = @_;
1fa12f56 859 my $sz = &sin($z);
0e505df1 860 _divbyzero "cot($z)", "sin($z)" if ($sz == 0);
1fa12f56 861 return &cos($z) / $sz;
66730be0 862}
863
864#
0c721ce2 865# cotan
866#
867# Alias for cot().
868#
869sub cotan { Math::Complex::cot(@_) }
870
871#
66730be0 872# acos
873#
874# Computes the arc cosine acos(z) = -i log(z + sqrt(z*z-1)).
875#
876sub acos {
fb73857a 877 my $z = $_[0];
1fa12f56 878 return CORE::atan2(CORE::sqrt(1-$z*$z), $z)
879 if (! ref $z) && CORE::abs($z) <= 1;
40b904b7 880 $z = cplx($z, 0) unless ref $z;
881 my ($x, $y) = @{$z->cartesian};
1fa12f56 882 return 0 if $x == 1 && $y == 0;
a8693bd3 883 my $t1 = CORE::sqrt(($x+1)*($x+1) + $y*$y);
884 my $t2 = CORE::sqrt(($x-1)*($x-1) + $y*$y);
fb73857a 885 my $alpha = ($t1 + $t2)/2;
886 my $beta = ($t1 - $t2)/2;
887 $alpha = 1 if $alpha < 1;
888 if ($beta > 1) { $beta = 1 }
889 elsif ($beta < -1) { $beta = -1 }
a8693bd3 890 my $u = CORE::atan2(CORE::sqrt(1-$beta*$beta), $beta);
891 my $v = CORE::log($alpha + CORE::sqrt($alpha*$alpha-1));
fb73857a 892 $v = -$v if $y > 0 || ($y == 0 && $x < -1);
40b904b7 893 return (ref $z)->make($u, $v);
66730be0 894}
895
896#
897# asin
898#
899# Computes the arc sine asin(z) = -i log(iz + sqrt(1-z*z)).
900#
901sub asin {
fb73857a 902 my $z = $_[0];
1fa12f56 903 return CORE::atan2($z, CORE::sqrt(1-$z*$z))
904 if (! ref $z) && CORE::abs($z) <= 1;
40b904b7 905 $z = cplx($z, 0) unless ref $z;
906 my ($x, $y) = @{$z->cartesian};
1fa12f56 907 return 0 if $x == 0 && $y == 0;
a8693bd3 908 my $t1 = CORE::sqrt(($x+1)*($x+1) + $y*$y);
909 my $t2 = CORE::sqrt(($x-1)*($x-1) + $y*$y);
fb73857a 910 my $alpha = ($t1 + $t2)/2;
911 my $beta = ($t1 - $t2)/2;
912 $alpha = 1 if $alpha < 1;
913 if ($beta > 1) { $beta = 1 }
914 elsif ($beta < -1) { $beta = -1 }
a8693bd3 915 my $u = CORE::atan2($beta, CORE::sqrt(1-$beta*$beta));
916 my $v = -CORE::log($alpha + CORE::sqrt($alpha*$alpha-1));
fb73857a 917 $v = -$v if $y > 0 || ($y == 0 && $x < -1);
40b904b7 918 return (ref $z)->make($u, $v);
66730be0 919}
920
921#
922# atan
923#
0c721ce2 924# Computes the arc tangent atan(z) = i/2 log((i+z) / (i-z)).
66730be0 925#
926sub atan {
927 my ($z) = @_;
a8693bd3 928 return CORE::atan2($z, 1) unless ref $z;
1fa12f56 929 my ($x, $y) = ref $z ? @{$z->cartesian} : ($z, 0);
930 return 0 if $x == 0 && $y == 0;
8c03c583 931 _divbyzero "atan(i)" if ( $z == i);
1fa12f56 932 _logofzero "atan(-i)" if (-$z == i); # -i is a bad file test...
933 my $log = &log((i + $z) / (i - $z));
934 return ip2 * $log;
a0d0e21e 935}
936
66730be0 937#
0c721ce2 938# asec
939#
940# Computes the arc secant asec(z) = acos(1 / z).
941#
942sub asec {
943 my ($z) = @_;
0e505df1 944 _divbyzero "asec($z)", $z if ($z == 0);
fb73857a 945 return acos(1 / $z);
0c721ce2 946}
947
948#
5cd24f17 949# acsc
0c721ce2 950#
8c03c583 951# Computes the arc cosecant acsc(z) = asin(1 / z).
0c721ce2 952#
5cd24f17 953sub acsc {
0c721ce2 954 my ($z) = @_;
0e505df1 955 _divbyzero "acsc($z)", $z if ($z == 0);
fb73857a 956 return asin(1 / $z);
0c721ce2 957}
958
959#
5cd24f17 960# acosec
66730be0 961#
5cd24f17 962# Alias for acsc().
0c721ce2 963#
5cd24f17 964sub acosec { Math::Complex::acsc(@_) }
0c721ce2 965
66730be0 966#
0c721ce2 967# acot
968#
8c03c583 969# Computes the arc cotangent acot(z) = atan(1 / z)
0c721ce2 970#
971sub acot {
66730be0 972 my ($z) = @_;
1fa12f56 973 _divbyzero "acot(0)" if $z == 0;
974 return ($z >= 0) ? CORE::atan2(1, $z) : CORE::atan2(-1, -$z)
975 unless ref $z;
976 _divbyzero "acot(i)" if ($z - i == 0);
977 _logofzero "acot(-i)" if ($z + i == 0);
8c03c583 978 return atan(1 / $z);
66730be0 979}
980
981#
0c721ce2 982# acotan
983#
984# Alias for acot().
985#
986sub acotan { Math::Complex::acot(@_) }
987
988#
66730be0 989# cosh
990#
991# Computes the hyperbolic cosine cosh(z) = (exp(z) + exp(-z))/2.
992#
993sub cosh {
994 my ($z) = @_;
fb73857a 995 my $ex;
0e505df1 996 unless (ref $z) {
a8693bd3 997 $ex = CORE::exp($z);
1fa12f56 998 return $ex ? ($ex + 1/$ex)/2 : $Inf;
0e505df1 999 }
1000 my ($x, $y) = @{$z->cartesian};
a8693bd3 1001 $ex = CORE::exp($x);
1fa12f56 1002 my $ex_1 = $ex ? 1 / $ex : $Inf;
a8693bd3 1003 return (ref $z)->make(CORE::cos($y) * ($ex + $ex_1)/2,
1004 CORE::sin($y) * ($ex - $ex_1)/2);
66730be0 1005}
1006
1007#
1008# sinh
1009#
1010# Computes the hyperbolic sine sinh(z) = (exp(z) - exp(-z))/2.
1011#
1012sub sinh {
1013 my ($z) = @_;
fb73857a 1014 my $ex;
0e505df1 1015 unless (ref $z) {
1fa12f56 1016 return 0 if $z == 0;
a8693bd3 1017 $ex = CORE::exp($z);
1fa12f56 1018 return $ex ? ($ex - 1/$ex)/2 : "-$Inf";
0e505df1 1019 }
1020 my ($x, $y) = @{$z->cartesian};
1fa12f56 1021 my $cy = CORE::cos($y);
1022 my $sy = CORE::sin($y);
a8693bd3 1023 $ex = CORE::exp($x);
1fa12f56 1024 my $ex_1 = $ex ? 1 / $ex : $Inf;
5240e574 1025 return (ref $z)->make(CORE::cos($y) * ($ex - $ex_1)/2,
1026 CORE::sin($y) * ($ex + $ex_1)/2);
66730be0 1027}
1028
1029#
1030# tanh
1031#
1032# Computes the hyperbolic tangent tanh(z) = sinh(z) / cosh(z).
1033#
1034sub tanh {
1035 my ($z) = @_;
0c721ce2 1036 my $cz = cosh($z);
0e505df1 1037 _divbyzero "tanh($z)", "cosh($z)" if ($cz == 0);
0c721ce2 1038 return sinh($z) / $cz;
66730be0 1039}
1040
1041#
0c721ce2 1042# sech
1043#
1044# Computes the hyperbolic secant sech(z) = 1 / cosh(z).
1045#
1046sub sech {
1047 my ($z) = @_;
1048 my $cz = cosh($z);
0e505df1 1049 _divbyzero "sech($z)", "cosh($z)" if ($cz == 0);
0c721ce2 1050 return 1 / $cz;
1051}
1052
1053#
1054# csch
1055#
1056# Computes the hyperbolic cosecant csch(z) = 1 / sinh(z).
66730be0 1057#
0c721ce2 1058sub csch {
1059 my ($z) = @_;
1060 my $sz = sinh($z);
0e505df1 1061 _divbyzero "csch($z)", "sinh($z)" if ($sz == 0);
0c721ce2 1062 return 1 / $sz;
1063}
1064
1065#
1066# cosech
1067#
1068# Alias for csch().
1069#
1070sub cosech { Math::Complex::csch(@_) }
1071
66730be0 1072#
0c721ce2 1073# coth
1074#
1075# Computes the hyperbolic cotangent coth(z) = cosh(z) / sinh(z).
1076#
1077sub coth {
66730be0 1078 my ($z) = @_;
0c721ce2 1079 my $sz = sinh($z);
1fa12f56 1080 _divbyzero "coth($z)", "sinh($z)" if $sz == 0;
0c721ce2 1081 return cosh($z) / $sz;
66730be0 1082}
1083
1084#
0c721ce2 1085# cotanh
1086#
1087# Alias for coth().
1088#
1089sub cotanh { Math::Complex::coth(@_) }
1090
1091#
66730be0 1092# acosh
1093#
fb73857a 1094# Computes the arc hyperbolic cosine acosh(z) = log(z + sqrt(z*z-1)).
66730be0 1095#
1096sub acosh {
1097 my ($z) = @_;
fb73857a 1098 unless (ref $z) {
fb73857a 1099 $z = cplx($z, 0);
1100 }
8c03c583 1101 my ($re, $im) = @{$z->cartesian};
fb73857a 1102 if ($im == 0) {
1fa12f56 1103 return CORE::log($re + CORE::sqrt($re*$re - 1))
1104 if $re >= 1;
1105 return cplx(0, CORE::atan2(CORE::sqrt(1 - $re*$re), $re))
1106 if CORE::abs($re) < 1;
fb73857a 1107 }
9bc5fa8d 1108 my $t = &sqrt($z * $z - 1) + $z;
40b904b7 1109 # Try Taylor if looking bad (this usually means that
1110 # $z was large negative, therefore the sqrt is really
1111 # close to abs(z), summing that with z...)
9bc5fa8d 1112 $t = 1/(2 * $z) - 1/(8 * $z**3) + 1/(16 * $z**5) - 5/(128 * $z**7)
1113 if $t == 0;
1114 my $u = &log($t);
40b904b7 1115 $u->Im(-$u->Im) if $re < 0 && $im == 0;
9bc5fa8d 1116 return $re < 0 ? -$u : $u;
66730be0 1117}
1118
1119#
1120# asinh
1121#
1fa12f56 1122# Computes the arc hyperbolic sine asinh(z) = log(z + sqrt(z*z+1))
66730be0 1123#
1124sub asinh {
1125 my ($z) = @_;
1fa12f56 1126 unless (ref $z) {
1127 my $t = $z + CORE::sqrt($z*$z + 1);
1128 return CORE::log($t) if $t;
1129 }
9bc5fa8d 1130 my $t = &sqrt($z * $z + 1) + $z;
40b904b7 1131 # Try Taylor if looking bad (this usually means that
1132 # $z was large negative, therefore the sqrt is really
1133 # close to abs(z), summing that with z...)
9bc5fa8d 1134 $t = 1/(2 * $z) - 1/(8 * $z**3) + 1/(16 * $z**5) - 5/(128 * $z**7)
1135 if $t == 0;
1fa12f56 1136 return &log($t);
66730be0 1137}
1138
1139#
1140# atanh
1141#
1142# Computes the arc hyperbolic tangent atanh(z) = 1/2 log((1+z) / (1-z)).
1143#
1144sub atanh {
1145 my ($z) = @_;
fb73857a 1146 unless (ref $z) {
a8693bd3 1147 return CORE::log((1 + $z)/(1 - $z))/2 if CORE::abs($z) < 1;
fb73857a 1148 $z = cplx($z, 0);
1149 }
1fa12f56 1150 _divbyzero 'atanh(1)', "1 - $z" if (1 - $z == 0);
1151 _logofzero 'atanh(-1)' if (1 + $z == 0);
1152 return 0.5 * &log((1 + $z) / (1 - $z));
66730be0 1153}
1154
1155#
0c721ce2 1156# asech
1157#
1158# Computes the hyperbolic arc secant asech(z) = acosh(1 / z).
1159#
1160sub asech {
1161 my ($z) = @_;
1fa12f56 1162 _divbyzero 'asech(0)', "$z" if ($z == 0);
0c721ce2 1163 return acosh(1 / $z);
1164}
1165
1166#
1167# acsch
66730be0 1168#
0c721ce2 1169# Computes the hyperbolic arc cosecant acsch(z) = asinh(1 / z).
66730be0 1170#
0c721ce2 1171sub acsch {
66730be0 1172 my ($z) = @_;
0e505df1 1173 _divbyzero 'acsch(0)', $z if ($z == 0);
0c721ce2 1174 return asinh(1 / $z);
1175}
1176
1177#
1178# acosech
1179#
1180# Alias for acosh().
1181#
1182sub acosech { Math::Complex::acsch(@_) }
1183
1184#
1185# acoth
1186#
1187# Computes the arc hyperbolic cotangent acoth(z) = 1/2 log((1+z) / (z-1)).
1188#
1189sub acoth {
1190 my ($z) = @_;
1fa12f56 1191 _divbyzero 'acoth(0)' if ($z == 0);
fb73857a 1192 unless (ref $z) {
a8693bd3 1193 return CORE::log(($z + 1)/($z - 1))/2 if CORE::abs($z) > 1;
fb73857a 1194 $z = cplx($z, 0);
1195 }
1fa12f56 1196 _divbyzero 'acoth(1)', "$z - 1" if ($z - 1 == 0);
1197 _logofzero 'acoth(-1)', "1 + $z" if (1 + $z == 0);
1198 return &log((1 + $z) / ($z - 1)) / 2;
66730be0 1199}
1200
1201#
0c721ce2 1202# acotanh
1203#
1204# Alias for acot().
1205#
1206sub acotanh { Math::Complex::acoth(@_) }
1207
1208#
66730be0 1209# (atan2)
1210#
1211# Compute atan(z1/z2).
1212#
1213sub atan2 {
1214 my ($z1, $z2, $inverted) = @_;
fb73857a 1215 my ($re1, $im1, $re2, $im2);
1216 if ($inverted) {
1217 ($re1, $im1) = ref $z2 ? @{$z2->cartesian} : ($z2, 0);
1218 ($re2, $im2) = @{$z1->cartesian};
66730be0 1219 } else {
fb73857a 1220 ($re1, $im1) = @{$z1->cartesian};
1221 ($re2, $im2) = ref $z2 ? @{$z2->cartesian} : ($z2, 0);
1222 }
1223 if ($im2 == 0) {
1fa12f56 1224 return CORE::atan2($re1, $re2) if $im1 == 0;
1225 return ($im1<=>0) * pip2 if $re2 == 0;
66730be0 1226 }
fb73857a 1227 my $w = atan($z1/$z2);
1228 my ($u, $v) = ref $w ? @{$w->cartesian} : ($w, 0);
1229 $u += pi if $re2 < 0;
1230 $u -= pit2 if $u > pi;
1231 return cplx($u, $v);
66730be0 1232}
1233
1234#
1235# display_format
1236# ->display_format
1237#
16357284 1238# Set (get if no argument) the display format for all complex numbers that
fb73857a 1239# don't happen to have overridden it via ->display_format
66730be0 1240#
16357284 1241# When called as an object method, this actually sets the display format for
66730be0 1242# the current object.
1243#
1244# Valid object formats are 'c' and 'p' for cartesian and polar. The first
1245# letter is used actually, so the type can be fully spelled out for clarity.
1246#
1247sub display_format {
16357284 1248 my $self = shift;
1249 my %display_format = %DISPLAY_FORMAT;
66730be0 1250
16357284 1251 if (ref $self) { # Called as an object method
1252 if (exists $self->{display_format}) {
1253 my %obj = %{$self->{display_format}};
1254 @display_format{keys %obj} = values %obj;
1255 }
476757f7 1256 }
1257 if (@_ == 1) {
1258 $display_format{style} = shift;
1259 } else {
1260 my %new = @_;
1261 @display_format{keys %new} = values %new;
66730be0 1262 }
1263
476757f7 1264 if (ref $self) { # Called as an object method
16357284 1265 $self->{display_format} = { %display_format };
1266 return
1267 wantarray ?
1268 %{$self->{display_format}} :
1269 $self->{display_format}->{style};
66730be0 1270 }
1271
476757f7 1272 # Called as a class method
16357284 1273 %DISPLAY_FORMAT = %display_format;
1274 return
1275 wantarray ?
1276 %DISPLAY_FORMAT :
1277 $DISPLAY_FORMAT{style};
66730be0 1278}
1279
1280#
1281# (stringify)
1282#
1283# Show nicely formatted complex number under its cartesian or polar form,
1284# depending on the current display format:
1285#
1286# . If a specific display format has been recorded for this object, use it.
1287# . Otherwise, use the generic current default for all complex numbers,
1288# which is a package global variable.
1289#
a0d0e21e 1290sub stringify {
66730be0 1291 my ($z) = shift;
66730be0 1292
16357284 1293 my $style = $z->display_format;
1294
1295 $style = $DISPLAY_FORMAT{style} unless defined $style;
66730be0 1296
16357284 1297 return $z->stringify_polar if $style =~ /^p/i;
66730be0 1298 return $z->stringify_cartesian;
1299}
1300
1301#
1302# ->stringify_cartesian
1303#
1304# Stringify as a cartesian representation 'a+bi'.
1305#
1306sub stringify_cartesian {
1307 my $z = shift;
1308 my ($x, $y) = @{$z->cartesian};
1309 my ($re, $im);
1310
16357284 1311 my %format = $z->display_format;
1312 my $format = $format{format};
1313
1fa12f56 1314 if ($x) {
1315 if ($x =~ /^NaN[QS]?$/i) {
1316 $re = $x;
1317 } else {
1318 if ($x =~ /^-?$Inf$/oi) {
1319 $re = $x;
1320 } else {
1321 $re = defined $format ? sprintf($format, $x) : $x;
1322 }
1323 }
1324 } else {
1325 undef $re;
1326 }
1327
1328 if ($y) {
40b904b7 1329 if ($y =~ /^(NaN[QS]?)$/i) {
1fa12f56 1330 $im = $y;
1331 } else {
1332 if ($y =~ /^-?$Inf$/oi) {
1333 $im = $y;
1334 } else {
40b904b7 1335 $im =
1336 defined $format ?
1337 sprintf($format, $y) :
1338 ($y == 1 ? "" : ($y == -1 ? "-" : $y));
1fa12f56 1339 }
1340 }
1341 $im .= "i";
1342 } else {
1343 undef $im;
16357284 1344 }
66730be0 1345
1fa12f56 1346 my $str = $re;
1347
16357284 1348 if (defined $im) {
1349 if ($y < 0) {
1350 $str .= $im;
1fa12f56 1351 } elsif ($y > 0 || $im =~ /^NaN[QS]?i$/i) {
16357284 1352 $str .= "+" if defined $re;
1353 $str .= $im;
1354 }
1fa12f56 1355 } elsif (!defined $re) {
1356 $str = "0";
16357284 1357 }
66730be0 1358
1359 return $str;
1360}
1361
d09ae4e6 1362
66730be0 1363#
1364# ->stringify_polar
1365#
1366# Stringify as a polar representation '[r,t]'.
1367#
1368sub stringify_polar {
1369 my $z = shift;
1370 my ($r, $t) = @{$z->polar};
1371 my $theta;
1372
16357284 1373 my %format = $z->display_format;
1fa12f56 1374 my $format = $format{format};
16357284 1375
1fa12f56 1376 if ($t =~ /^NaN[QS]?$/i || $t =~ /^-?$Inf$/oi) {
1377 $theta = $t;
1378 } elsif ($t == pi) {
1379 $theta = "pi";
1380 } elsif ($r == 0 || $t == 0) {
1381 $theta = defined $format ? sprintf($format, $t) : $t;
55497cff 1382 }
66730be0 1383
1fa12f56 1384 return "[$r,$theta]" if defined $theta;
1385
66730be0 1386 #
1fa12f56 1387 # Try to identify pi/n and friends.
66730be0 1388 #
1389
1fa12f56 1390 $t -= int(CORE::abs($t) / pit2) * pit2;
1391
e97e26fa 1392 if ($format{polar_pretty_print} && $t) {
1fa12f56 1393 my ($a, $b);
9bc5fa8d 1394 for $a (2..9) {
1fa12f56 1395 $b = $t * $a / pi;
e97e26fa 1396 if ($b =~ /^-?\d+$/) {
1fa12f56 1397 $b = $b < 0 ? "-" : "" if CORE::abs($b) == 1;
1398 $theta = "${b}pi/$a";
d09ae4e6 1399 last;
66730be0 1400 }
d09ae4e6 1401 }
66730be0 1402 }
1403
16357284 1404 if (defined $format) {
1405 $r = sprintf($format, $r);
1fa12f56 1406 $theta = sprintf($format, $theta) unless defined $theta;
1407 } else {
1408 $theta = $t unless defined $theta;
16357284 1409 }
1410
1fa12f56 1411 return "[$r,$theta]";
a0d0e21e 1412}
a5f75d66 1413
14141;
1415__END__
1416
1cf6bcb8 1417=pod
1418
a5f75d66 1419=head1 NAME
1420
66730be0 1421Math::Complex - complex numbers and associated mathematical functions
a5f75d66 1422
1423=head1 SYNOPSIS
1424
66730be0 1425 use Math::Complex;
fb73857a 1426
66730be0 1427 $z = Math::Complex->make(5, 6);
1428 $t = 4 - 3*i + $z;
1429 $j = cplxe(1, 2*pi/3);
a5f75d66 1430
1431=head1 DESCRIPTION
1432
66730be0 1433This package lets you create and manipulate complex numbers. By default,
1434I<Perl> limits itself to real numbers, but an extra C<use> statement brings
1435full complex support, along with a full set of mathematical functions
1436typically associated with and/or extended to complex numbers.
1437
1438If you wonder what complex numbers are, they were invented to be able to solve
1439the following equation:
1440
1441 x*x = -1
1442
1443and by definition, the solution is noted I<i> (engineers use I<j> instead since
1444I<i> usually denotes an intensity, but the name does not matter). The number
1445I<i> is a pure I<imaginary> number.
1446
1447The arithmetics with pure imaginary numbers works just like you would expect
1448it with real numbers... you just have to remember that
1449
1450 i*i = -1
1451
1452so you have:
1453
1454 5i + 7i = i * (5 + 7) = 12i
1455 4i - 3i = i * (4 - 3) = i
1456 4i * 2i = -8
1457 6i / 2i = 3
1458 1 / i = -i
1459
1460Complex numbers are numbers that have both a real part and an imaginary
1461part, and are usually noted:
1462
1463 a + bi
1464
1465where C<a> is the I<real> part and C<b> is the I<imaginary> part. The
1466arithmetic with complex numbers is straightforward. You have to
1467keep track of the real and the imaginary parts, but otherwise the
1468rules used for real numbers just apply:
1469
1470 (4 + 3i) + (5 - 2i) = (4 + 5) + i(3 - 2) = 9 + i
1471 (2 + i) * (4 - i) = 2*4 + 4i -2i -i*i = 8 + 2i + 1 = 9 + 2i
1472
1473A graphical representation of complex numbers is possible in a plane
1474(also called the I<complex plane>, but it's really a 2D plane).
1475The number
1476
1477 z = a + bi
1478
1479is the point whose coordinates are (a, b). Actually, it would
1480be the vector originating from (0, 0) to (a, b). It follows that the addition
1481of two complex numbers is a vectorial addition.
1482
1483Since there is a bijection between a point in the 2D plane and a complex
1484number (i.e. the mapping is unique and reciprocal), a complex number
1485can also be uniquely identified with polar coordinates:
1486
1487 [rho, theta]
1488
1489where C<rho> is the distance to the origin, and C<theta> the angle between
1490the vector and the I<x> axis. There is a notation for this using the
1491exponential form, which is:
1492
1493 rho * exp(i * theta)
1494
1495where I<i> is the famous imaginary number introduced above. Conversion
1496between this form and the cartesian form C<a + bi> is immediate:
1497
1498 a = rho * cos(theta)
1499 b = rho * sin(theta)
1500
1501which is also expressed by this formula:
1502
fb73857a 1503 z = rho * exp(i * theta) = rho * (cos theta + i * sin theta)
66730be0 1504
1505In other words, it's the projection of the vector onto the I<x> and I<y>
1506axes. Mathematicians call I<rho> the I<norm> or I<modulus> and I<theta>
1507the I<argument> of the complex number. The I<norm> of C<z> will be
1508noted C<abs(z)>.
1509
1510The polar notation (also known as the trigonometric
1511representation) is much more handy for performing multiplications and
1512divisions of complex numbers, whilst the cartesian notation is better
fb73857a 1513suited for additions and subtractions. Real numbers are on the I<x>
1514axis, and therefore I<theta> is zero or I<pi>.
66730be0 1515
1516All the common operations that can be performed on a real number have
1517been defined to work on complex numbers as well, and are merely
1518I<extensions> of the operations defined on real numbers. This means
1519they keep their natural meaning when there is no imaginary part, provided
1520the number is within their definition set.
1521
1522For instance, the C<sqrt> routine which computes the square root of
fb73857a 1523its argument is only defined for non-negative real numbers and yields a
1524non-negative real number (it is an application from B<R+> to B<R+>).
66730be0 1525If we allow it to return a complex number, then it can be extended to
1526negative real numbers to become an application from B<R> to B<C> (the
1527set of complex numbers):
1528
1529 sqrt(x) = x >= 0 ? sqrt(x) : sqrt(-x)*i
1530
1531It can also be extended to be an application from B<C> to B<C>,
1532whilst its restriction to B<R> behaves as defined above by using
1533the following definition:
1534
1535 sqrt(z = [r,t]) = sqrt(r) * exp(i * t/2)
1536
fb73857a 1537Indeed, a negative real number can be noted C<[x,pi]> (the modulus
1538I<x> is always non-negative, so C<[x,pi]> is really C<-x>, a negative
1539number) and the above definition states that
66730be0 1540
1541 sqrt([x,pi]) = sqrt(x) * exp(i*pi/2) = [sqrt(x),pi/2] = sqrt(x)*i
1542
1543which is exactly what we had defined for negative real numbers above.
b42d0ec9 1544The C<sqrt> returns only one of the solutions: if you want the both,
1545use the C<root> function.
a5f75d66 1546
66730be0 1547All the common mathematical functions defined on real numbers that
1548are extended to complex numbers share that same property of working
1549I<as usual> when the imaginary part is zero (otherwise, it would not
1550be called an extension, would it?).
a5f75d66 1551
66730be0 1552A I<new> operation possible on a complex number that is
1553the identity for real numbers is called the I<conjugate>, and is noted
1554with an horizontal bar above the number, or C<~z> here.
a5f75d66 1555
66730be0 1556 z = a + bi
1557 ~z = a - bi
a5f75d66 1558
66730be0 1559Simple... Now look:
a5f75d66 1560
66730be0 1561 z * ~z = (a + bi) * (a - bi) = a*a + b*b
a5f75d66 1562
66730be0 1563We saw that the norm of C<z> was noted C<abs(z)> and was defined as the
1564distance to the origin, also known as:
a5f75d66 1565
66730be0 1566 rho = abs(z) = sqrt(a*a + b*b)
a5f75d66 1567
66730be0 1568so
1569
1570 z * ~z = abs(z) ** 2
1571
1572If z is a pure real number (i.e. C<b == 0>), then the above yields:
1573
1574 a * a = abs(a) ** 2
1575
1576which is true (C<abs> has the regular meaning for real number, i.e. stands
1577for the absolute value). This example explains why the norm of C<z> is
1578noted C<abs(z)>: it extends the C<abs> function to complex numbers, yet
1579is the regular C<abs> we know when the complex number actually has no
1580imaginary part... This justifies I<a posteriori> our use of the C<abs>
1581notation for the norm.
1582
1583=head1 OPERATIONS
1584
1585Given the following notations:
1586
1587 z1 = a + bi = r1 * exp(i * t1)
1588 z2 = c + di = r2 * exp(i * t2)
1589 z = <any complex or real number>
1590
1591the following (overloaded) operations are supported on complex numbers:
1592
1593 z1 + z2 = (a + c) + i(b + d)
1594 z1 - z2 = (a - c) + i(b - d)
1595 z1 * z2 = (r1 * r2) * exp(i * (t1 + t2))
1596 z1 / z2 = (r1 / r2) * exp(i * (t1 - t2))
1597 z1 ** z2 = exp(z2 * log z1)
b42d0ec9 1598 ~z = a - bi
1599 abs(z) = r1 = sqrt(a*a + b*b)
1600 sqrt(z) = sqrt(r1) * exp(i * t/2)
1601 exp(z) = exp(a) * exp(i * b)
1602 log(z) = log(r1) + i*t
1603 sin(z) = 1/2i (exp(i * z1) - exp(-i * z))
1604 cos(z) = 1/2 (exp(i * z1) + exp(-i * z))
66730be0 1605 atan2(z1, z2) = atan(z1/z2)
1606
1607The following extra operations are supported on both real and complex
1608numbers:
1609
1610 Re(z) = a
1611 Im(z) = b
1612 arg(z) = t
b42d0ec9 1613 abs(z) = r
66730be0 1614
1615 cbrt(z) = z ** (1/3)
1616 log10(z) = log(z) / log(10)
1617 logn(z, n) = log(z) / log(n)
1618
1619 tan(z) = sin(z) / cos(z)
0c721ce2 1620
5aabfad6 1621 csc(z) = 1 / sin(z)
1622 sec(z) = 1 / cos(z)
0c721ce2 1623 cot(z) = 1 / tan(z)
66730be0 1624
1625 asin(z) = -i * log(i*z + sqrt(1-z*z))
fb73857a 1626 acos(z) = -i * log(z + i*sqrt(1-z*z))
66730be0 1627 atan(z) = i/2 * log((i+z) / (i-z))
0c721ce2 1628
5aabfad6 1629 acsc(z) = asin(1 / z)
1630 asec(z) = acos(1 / z)
8c03c583 1631 acot(z) = atan(1 / z) = -i/2 * log((i+z) / (z-i))
66730be0 1632
1633 sinh(z) = 1/2 (exp(z) - exp(-z))
1634 cosh(z) = 1/2 (exp(z) + exp(-z))
0c721ce2 1635 tanh(z) = sinh(z) / cosh(z) = (exp(z) - exp(-z)) / (exp(z) + exp(-z))
1636
5aabfad6 1637 csch(z) = 1 / sinh(z)
1638 sech(z) = 1 / cosh(z)
0c721ce2 1639 coth(z) = 1 / tanh(z)
fb73857a 1640
66730be0 1641 asinh(z) = log(z + sqrt(z*z+1))
1642 acosh(z) = log(z + sqrt(z*z-1))
1643 atanh(z) = 1/2 * log((1+z) / (1-z))
66730be0 1644
5aabfad6 1645 acsch(z) = asinh(1 / z)
1646 asech(z) = acosh(1 / z)
0c721ce2 1647 acoth(z) = atanh(1 / z) = 1/2 * log((1+z) / (z-1))
1648
b42d0ec9 1649I<arg>, I<abs>, I<log>, I<csc>, I<cot>, I<acsc>, I<acot>, I<csch>,
1650I<coth>, I<acosech>, I<acotanh>, have aliases I<rho>, I<theta>, I<ln>,
1651I<cosec>, I<cotan>, I<acosec>, I<acotan>, I<cosech>, I<cotanh>,
1652I<acosech>, I<acotanh>, respectively. C<Re>, C<Im>, C<arg>, C<abs>,
1653C<rho>, and C<theta> can be used also also mutators. The C<cbrt>
1654returns only one of the solutions: if you want all three, use the
1655C<root> function.
0c721ce2 1656
1657The I<root> function is available to compute all the I<n>
66730be0 1658roots of some complex, where I<n> is a strictly positive integer.
1659There are exactly I<n> such roots, returned as a list. Getting the
1660number mathematicians call C<j> such that:
1661
1662 1 + j + j*j = 0;
1663
1664is a simple matter of writing:
1665
1666 $j = ((root(1, 3))[1];
1667
1668The I<k>th root for C<z = [r,t]> is given by:
1669
1670 (root(z, n))[k] = r**(1/n) * exp(i * (t + 2*k*pi)/n)
1671
f4837644 1672The I<spaceship> comparison operator, E<lt>=E<gt>, is also defined. In
1673order to ensure its restriction to real numbers is conform to what you
1674would expect, the comparison is run on the real part of the complex
1675number first, and imaginary parts are compared only when the real
1676parts match.
66730be0 1677
1678=head1 CREATION
1679
1680To create a complex number, use either:
1681
1682 $z = Math::Complex->make(3, 4);
1683 $z = cplx(3, 4);
1684
1685if you know the cartesian form of the number, or
1686
1687 $z = 3 + 4*i;
1688
fb73857a 1689if you like. To create a number using the polar form, use either:
66730be0 1690
1691 $z = Math::Complex->emake(5, pi/3);
1692 $x = cplxe(5, pi/3);
1693
0c721ce2 1694instead. The first argument is the modulus, the second is the angle
fb73857a 1695(in radians, the full circle is 2*pi). (Mnemonic: C<e> is used as a
1696notation for complex numbers in the polar form).
66730be0 1697
1698It is possible to write:
1699
1700 $x = cplxe(-3, pi/4);
1701
16357284 1702but that will be silently converted into C<[3,-3pi/4]>, since the
1703modulus must be non-negative (it represents the distance to the origin
1704in the complex plane).
66730be0 1705
b42d0ec9 1706It is also possible to have a complex number as either argument of
1707either the C<make> or C<emake>: the appropriate component of
1708the argument will be used.
1709
1710 $z1 = cplx(-2, 1);
1711 $z2 = cplx($z1, 4);
1712
66730be0 1713=head1 STRINGIFICATION
1714
1715When printed, a complex number is usually shown under its cartesian
16357284 1716style I<a+bi>, but there are legitimate cases where the polar style
66730be0 1717I<[r,t]> is more appropriate.
1718
16357284 1719By calling the class method C<Math::Complex::display_format> and
1720supplying either C<"polar"> or C<"cartesian"> as an argument, you
5287f86b 1721override the default display style, which is C<"cartesian">. Not
16357284 1722supplying any argument returns the current settings.
66730be0 1723
1724This default can be overridden on a per-number basis by calling the
1725C<display_format> method instead. As before, not supplying any argument
5287f86b 1726returns the current display style for this number. Otherwise whatever you
1727specify will be the new display style for I<this> particular number.
66730be0 1728
1729For instance:
1730
1731 use Math::Complex;
1732
1733 Math::Complex::display_format('polar');
16357284 1734 $j = (root(1, 3))[1];
1735 print "j = $j\n"; # Prints "j = [1,2pi/3]"
66730be0 1736 $j->display_format('cartesian');
1737 print "j = $j\n"; # Prints "j = -0.5+0.866025403784439i"
1738
5287f86b 1739The polar style attempts to emphasize arguments like I<k*pi/n>
9bc5fa8d 1740(where I<n> is a positive integer and I<k> an integer within [-9, +9]),
5287f86b 1741this is called I<polar pretty-printing>.
66730be0 1742
16357284 1743=head2 CHANGED IN PERL 5.6
1744
1745The C<display_format> class method and the corresponding
1746C<display_format> object method can now be called using
1747a parameter hash instead of just a one parameter.
1748
1749The old display format style, which can have values C<"cartesian"> or
40b904b7 1750C<"polar">, can be changed using the C<"style"> parameter.
1751
1752 $j->display_format(style => "polar");
1753
1754The one parameter calling convention also still works.
1755
1756 $j->display_format("polar");
16357284 1757
1758There are two new display parameters.
1759
40b904b7 1760The first one is C<"format">, which is a sprintf()-style format string
1761to be used for both numeric parts of the complex number(s). The is
1762somewhat system-dependent but most often it corresponds to C<"%.15g">.
1763You can revert to the default by setting the C<format> to C<undef>.
16357284 1764
1765 # the $j from the above example
1766
1767 $j->display_format('format' => '%.5f');
1768 print "j = $j\n"; # Prints "j = -0.50000+0.86603i"
40b904b7 1769 $j->display_format('format' => undef);
16357284 1770 print "j = $j\n"; # Prints "j = -0.5+0.86603i"
1771
1772Notice that this affects also the return values of the
1773C<display_format> methods: in list context the whole parameter hash
40b904b7 1774will be returned, as opposed to only the style parameter value.
1775This is a potential incompatibility with earlier versions if you
1776have been calling the C<display_format> method in list context.
16357284 1777
5287f86b 1778The second new display parameter is C<"polar_pretty_print">, which can
1779be set to true or false, the default being true. See the previous
1780section for what this means.
16357284 1781
66730be0 1782=head1 USAGE
1783
1784Thanks to overloading, the handling of arithmetics with complex numbers
1785is simple and almost transparent.
1786
1787Here are some examples:
1788
1789 use Math::Complex;
1790
1791 $j = cplxe(1, 2*pi/3); # $j ** 3 == 1
1792 print "j = $j, j**3 = ", $j ** 3, "\n";
1793 print "1 + j + j**2 = ", 1 + $j + $j**2, "\n";
1794
1795 $z = -16 + 0*i; # Force it to be a complex
1796 print "sqrt($z) = ", sqrt($z), "\n";
1797
1798 $k = exp(i * 2*pi/3);
1799 print "$j - $k = ", $j - $k, "\n";
a5f75d66 1800
b42d0ec9 1801 $z->Re(3); # Re, Im, arg, abs,
1802 $j->arg(2); # (the last two aka rho, theta)
1803 # can be used also as mutators.
1804
1805=head1 ERRORS DUE TO DIVISION BY ZERO OR LOGARITHM OF ZERO
5aabfad6 1806
1807The division (/) and the following functions
1808
b42d0ec9 1809 log ln log10 logn
2820d885 1810 tan sec csc cot
b42d0ec9 1811 atan asec acsc acot
1812 tanh sech csch coth
1813 atanh asech acsch acoth
5aabfad6 1814
1815cannot be computed for all arguments because that would mean dividing
8c03c583 1816by zero or taking logarithm of zero. These situations cause fatal
1817runtime errors looking like this
5aabfad6 1818
1819 cot(0): Division by zero.
5cd24f17 1820 (Because in the definition of cot(0), the divisor sin(0) is 0)
5aabfad6 1821 Died at ...
1822
8c03c583 1823or
1824
1825 atanh(-1): Logarithm of zero.
1826 Died at...
1827
1828For the C<csc>, C<cot>, C<asec>, C<acsc>, C<acot>, C<csch>, C<coth>,
b42d0ec9 1829C<asech>, C<acsch>, the argument cannot be C<0> (zero). For the the
1830logarithmic functions and the C<atanh>, C<acoth>, the argument cannot
1831be C<1> (one). For the C<atanh>, C<acoth>, the argument cannot be
1832C<-1> (minus one). For the C<atan>, C<acot>, the argument cannot be
1833C<i> (the imaginary unit). For the C<atan>, C<acoth>, the argument
1834cannot be C<-i> (the negative imaginary unit). For the C<tan>,
1835C<sec>, C<tanh>, the argument cannot be I<pi/2 + k * pi>, where I<k>
1836is any integer.
1837
1838Note that because we are operating on approximations of real numbers,
1839these errors can happen when merely `too close' to the singularities
40b904b7 1840listed above.
b42d0ec9 1841
1842=head1 ERRORS DUE TO INDIGESTIBLE ARGUMENTS
1843
1844The C<make> and C<emake> accept both real and complex arguments.
1845When they cannot recognize the arguments they will die with error
1846messages like the following
1847
1848 Math::Complex::make: Cannot take real part of ...
1849 Math::Complex::make: Cannot take real part of ...
1850 Math::Complex::emake: Cannot take rho of ...
1851 Math::Complex::emake: Cannot take theta of ...
5cd24f17 1852
a5f75d66 1853=head1 BUGS
1854
5cd24f17 1855Saying C<use Math::Complex;> exports many mathematical routines in the
fb73857a 1856caller environment and even overrides some (C<sqrt>, C<log>).
1857This is construed as a feature by the Authors, actually... ;-)
a5f75d66 1858
66730be0 1859All routines expect to be given real or complex numbers. Don't attempt to
1860use BigFloat, since Perl has currently no rule to disambiguate a '+'
1861operation (for instance) between two overloaded entities.
a5f75d66 1862
d09ae4e6 1863In Cray UNICOS there is some strange numerical instability that results
1864in root(), cos(), sin(), cosh(), sinh(), losing accuracy fast. Beware.
1865The bug may be in UNICOS math libs, in UNICOS C compiler, in Math::Complex.
1866Whatever it is, it does not manifest itself anywhere else where Perl runs.
1867
0c721ce2 1868=head1 AUTHORS
a5f75d66 1869
6e238990 1870Raphael Manfredi <F<Raphael_Manfredi@pobox.com>> and
ace5de91 1871Jarkko Hietaniemi <F<jhi@iki.fi>>.
5cd24f17 1872
fb73857a 1873Extensive patches by Daniel S. Lewart <F<d-lewart@uiuc.edu>>.
1874
5cd24f17 1875=cut
1876
b42d0ec9 18771;
1878
5cd24f17 1879# eof