SYN SYN
[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
ee8c7f54 10our($VERSION, @ISA, @EXPORT, %EXPORT_TAGS, $Inf);
11
22d4bb9c 12$VERSION = 1.31;
13
ee8c7f54 14BEGIN {
22d4bb9c 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 }
ee8c7f54 22 $Inf = "Inf" if !defined $Inf || !($Inf > 0); # Desperation.
23}
fb73857a 24
ee8c7f54 25use strict;
fb73857a 26
ee8c7f54 27my $i;
28my %LOGN;
0c721ce2 29
ee8c7f54 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,
ee8c7f54 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#
ee8c7f54 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;
ee8c7f54 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 ";
ee8c7f54 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 }
ee8c7f54 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#
ee8c7f54 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) = @_;
ee8c7f54 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);
ee8c7f54 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) = @_;
ee8c7f54 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};
ee8c7f54 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 {
ee8c7f54 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);
ee8c7f54 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) = @_;
667 return $z unless ref $z;
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;
ee8c7f54 770 my $logn = $LOGN{$n};
771 $logn = $LOGN{$n} = CORE::log($n) unless defined $logn; # Cache log(n)
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) = @_;
ee8c7f54 782 return CORE::cos($z) unless ref $z;
66730be0 783 my ($x, $y) = @{$z->cartesian};
a8693bd3 784 my $ey = CORE::exp($y);
ee8c7f54 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) = @_;
ee8c7f54 799 return CORE::sin($z) unless ref $z;
66730be0 800 my ($x, $y) = @{$z->cartesian};
a8693bd3 801 my $ey = CORE::exp($y);
ee8c7f54 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) = @_;
ee8c7f54 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) = @_;
ee8c7f54 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) = @_;
ee8c7f54 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) = @_;
ee8c7f54 859 my $sz = &sin($z);
0e505df1 860 _divbyzero "cot($z)", "sin($z)" if ($sz == 0);
ee8c7f54 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];
ee8c7f54 878 return CORE::atan2(CORE::sqrt(1-$z*$z), $z)
879 if (! ref $z) && CORE::abs($z) <= 1;
880 $z = cplx($z, 0) unless ref $z;
881 my ($x, $y) = @{$z->cartesian};
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);
ee8c7f54 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];
ee8c7f54 903 return CORE::atan2($z, CORE::sqrt(1-$z*$z))
904 if (! ref $z) && CORE::abs($z) <= 1;
905 $z = cplx($z, 0) unless ref $z;
906 my ($x, $y) = @{$z->cartesian};
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);
ee8c7f54 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;
ee8c7f54 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);
ee8c7f54 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) = @_;
ee8c7f54 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);
ee8c7f54 998 return $ex ? ($ex + 1/$ex)/2 : $Inf;
0e505df1 999 }
1000 my ($x, $y) = @{$z->cartesian};
a8693bd3 1001 $ex = CORE::exp($x);
ee8c7f54 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) {
ee8c7f54 1016 return 0 if $z == 0;
a8693bd3 1017 $ex = CORE::exp($z);
ee8c7f54 1018 return $ex ? ($ex - 1/$ex)/2 : "-$Inf";
0e505df1 1019 }
1020 my ($x, $y) = @{$z->cartesian};
ee8c7f54 1021 my $cy = CORE::cos($y);
1022 my $sy = CORE::sin($y);
a8693bd3 1023 $ex = CORE::exp($x);
ee8c7f54 1024 my $ex_1 = $ex ? 1 / $ex : $Inf;
a8693bd3 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);
ee8c7f54 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) {
ee8c7f54 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 }
ee8c7f54 1108 my $t = &sqrt($z * $z - 1) + $z;
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...)
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);
1115 $u->Im(-$u->Im) if $re < 0 && $im == 0;
1116 return $re < 0 ? -$u : $u;
66730be0 1117}
1118
1119#
1120# asinh
1121#
ee8c7f54 1122# Computes the arc hyperbolic sine asinh(z) = log(z + sqrt(z*z+1))
66730be0 1123#
1124sub asinh {
1125 my ($z) = @_;
ee8c7f54 1126 unless (ref $z) {
1127 my $t = $z + CORE::sqrt($z*$z + 1);
1128 return CORE::log($t) if $t;
1129 }
1130 my $t = &sqrt($z * $z + 1) + $z;
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...)
1134 $t = 1/(2 * $z) - 1/(8 * $z**3) + 1/(16 * $z**5) - 5/(128 * $z**7)
1135 if $t == 0;
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 }
ee8c7f54 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) = @_;
ee8c7f54 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) = @_;
ee8c7f54 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 }
ee8c7f54 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) {
ee8c7f54 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 }
22d4bb9c 1256 }
1257 if (@_ == 1) {
1258 $display_format{style} = shift;
1259 } else {
1260 my %new = @_;
1261 @display_format{keys %new} = values %new;
66730be0 1262 }
1263
22d4bb9c 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
22d4bb9c 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
ee8c7f54 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) {
1329 if ($y =~ /^(NaN[QS]?)$/i) {
1330 $im = $y;
1331 } else {
1332 if ($y =~ /^-?$Inf$/oi) {
1333 $im = $y;
1334 } else {
1335 $im =
1336 defined $format ?
1337 sprintf($format, $y) :
1338 ($y == 1 ? "" : ($y == -1 ? "-" : $y));
1339 }
1340 }
1341 $im .= "i";
1342 } else {
1343 undef $im;
16357284 1344 }
66730be0 1345
ee8c7f54 1346 my $str = $re;
1347
16357284 1348 if (defined $im) {
1349 if ($y < 0) {
1350 $str .= $im;
ee8c7f54 1351 } elsif ($y > 0 || $im =~ /^NaN[QS]?i$/i) {
16357284 1352 $str .= "+" if defined $re;
1353 $str .= $im;
1354 }
ee8c7f54 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;
ee8c7f54 1374 my $format = $format{format};
16357284 1375
ee8c7f54 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
ee8c7f54 1384 return "[$r,$theta]" if defined $theta;
1385
66730be0 1386 #
ee8c7f54 1387 # Try to identify pi/n and friends.
66730be0 1388 #
1389
ee8c7f54 1390 $t -= int(CORE::abs($t) / pit2) * pit2;
1391
22d4bb9c 1392 if ($format{polar_pretty_print} && $t) {
ee8c7f54 1393 my ($a, $b);
1394 for $a (2..9) {
1395 $b = $t * $a / pi;
22d4bb9c 1396 if ($b =~ /^-?\d+$/) {
ee8c7f54 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);
ee8c7f54 1406 $theta = sprintf($format, $theta) unless defined $theta;
1407 } else {
1408 $theta = $t unless defined $theta;
16357284 1409 }
1410
ee8c7f54 1411 return "[$r,$theta]";
a0d0e21e 1412}
a5f75d66 1413
14141;
1415__END__
1416
1417=head1 NAME
1418
66730be0 1419Math::Complex - complex numbers and associated mathematical functions
a5f75d66 1420
1421=head1 SYNOPSIS
1422
66730be0 1423 use Math::Complex;
fb73857a 1424
66730be0 1425 $z = Math::Complex->make(5, 6);
1426 $t = 4 - 3*i + $z;
1427 $j = cplxe(1, 2*pi/3);
a5f75d66 1428
1429=head1 DESCRIPTION
1430
66730be0 1431This package lets you create and manipulate complex numbers. By default,
1432I<Perl> limits itself to real numbers, but an extra C<use> statement brings
1433full complex support, along with a full set of mathematical functions
1434typically associated with and/or extended to complex numbers.
1435
1436If you wonder what complex numbers are, they were invented to be able to solve
1437the following equation:
1438
1439 x*x = -1
1440
1441and by definition, the solution is noted I<i> (engineers use I<j> instead since
1442I<i> usually denotes an intensity, but the name does not matter). The number
1443I<i> is a pure I<imaginary> number.
1444
1445The arithmetics with pure imaginary numbers works just like you would expect
1446it with real numbers... you just have to remember that
1447
1448 i*i = -1
1449
1450so you have:
1451
1452 5i + 7i = i * (5 + 7) = 12i
1453 4i - 3i = i * (4 - 3) = i
1454 4i * 2i = -8
1455 6i / 2i = 3
1456 1 / i = -i
1457
1458Complex numbers are numbers that have both a real part and an imaginary
1459part, and are usually noted:
1460
1461 a + bi
1462
1463where C<a> is the I<real> part and C<b> is the I<imaginary> part. The
1464arithmetic with complex numbers is straightforward. You have to
1465keep track of the real and the imaginary parts, but otherwise the
1466rules used for real numbers just apply:
1467
1468 (4 + 3i) + (5 - 2i) = (4 + 5) + i(3 - 2) = 9 + i
1469 (2 + i) * (4 - i) = 2*4 + 4i -2i -i*i = 8 + 2i + 1 = 9 + 2i
1470
1471A graphical representation of complex numbers is possible in a plane
1472(also called the I<complex plane>, but it's really a 2D plane).
1473The number
1474
1475 z = a + bi
1476
1477is the point whose coordinates are (a, b). Actually, it would
1478be the vector originating from (0, 0) to (a, b). It follows that the addition
1479of two complex numbers is a vectorial addition.
1480
1481Since there is a bijection between a point in the 2D plane and a complex
1482number (i.e. the mapping is unique and reciprocal), a complex number
1483can also be uniquely identified with polar coordinates:
1484
1485 [rho, theta]
1486
1487where C<rho> is the distance to the origin, and C<theta> the angle between
1488the vector and the I<x> axis. There is a notation for this using the
1489exponential form, which is:
1490
1491 rho * exp(i * theta)
1492
1493where I<i> is the famous imaginary number introduced above. Conversion
1494between this form and the cartesian form C<a + bi> is immediate:
1495
1496 a = rho * cos(theta)
1497 b = rho * sin(theta)
1498
1499which is also expressed by this formula:
1500
fb73857a 1501 z = rho * exp(i * theta) = rho * (cos theta + i * sin theta)
66730be0 1502
1503In other words, it's the projection of the vector onto the I<x> and I<y>
1504axes. Mathematicians call I<rho> the I<norm> or I<modulus> and I<theta>
1505the I<argument> of the complex number. The I<norm> of C<z> will be
1506noted C<abs(z)>.
1507
1508The polar notation (also known as the trigonometric
1509representation) is much more handy for performing multiplications and
1510divisions of complex numbers, whilst the cartesian notation is better
fb73857a 1511suited for additions and subtractions. Real numbers are on the I<x>
1512axis, and therefore I<theta> is zero or I<pi>.
66730be0 1513
1514All the common operations that can be performed on a real number have
1515been defined to work on complex numbers as well, and are merely
1516I<extensions> of the operations defined on real numbers. This means
1517they keep their natural meaning when there is no imaginary part, provided
1518the number is within their definition set.
1519
1520For instance, the C<sqrt> routine which computes the square root of
fb73857a 1521its argument is only defined for non-negative real numbers and yields a
1522non-negative real number (it is an application from B<R+> to B<R+>).
66730be0 1523If we allow it to return a complex number, then it can be extended to
1524negative real numbers to become an application from B<R> to B<C> (the
1525set of complex numbers):
1526
1527 sqrt(x) = x >= 0 ? sqrt(x) : sqrt(-x)*i
1528
1529It can also be extended to be an application from B<C> to B<C>,
1530whilst its restriction to B<R> behaves as defined above by using
1531the following definition:
1532
1533 sqrt(z = [r,t]) = sqrt(r) * exp(i * t/2)
1534
fb73857a 1535Indeed, a negative real number can be noted C<[x,pi]> (the modulus
1536I<x> is always non-negative, so C<[x,pi]> is really C<-x>, a negative
1537number) and the above definition states that
66730be0 1538
1539 sqrt([x,pi]) = sqrt(x) * exp(i*pi/2) = [sqrt(x),pi/2] = sqrt(x)*i
1540
1541which is exactly what we had defined for negative real numbers above.
b42d0ec9 1542The C<sqrt> returns only one of the solutions: if you want the both,
1543use the C<root> function.
a5f75d66 1544
66730be0 1545All the common mathematical functions defined on real numbers that
1546are extended to complex numbers share that same property of working
1547I<as usual> when the imaginary part is zero (otherwise, it would not
1548be called an extension, would it?).
a5f75d66 1549
66730be0 1550A I<new> operation possible on a complex number that is
1551the identity for real numbers is called the I<conjugate>, and is noted
1552with an horizontal bar above the number, or C<~z> here.
a5f75d66 1553
66730be0 1554 z = a + bi
1555 ~z = a - bi
a5f75d66 1556
66730be0 1557Simple... Now look:
a5f75d66 1558
66730be0 1559 z * ~z = (a + bi) * (a - bi) = a*a + b*b
a5f75d66 1560
66730be0 1561We saw that the norm of C<z> was noted C<abs(z)> and was defined as the
1562distance to the origin, also known as:
a5f75d66 1563
66730be0 1564 rho = abs(z) = sqrt(a*a + b*b)
a5f75d66 1565
66730be0 1566so
1567
1568 z * ~z = abs(z) ** 2
1569
1570If z is a pure real number (i.e. C<b == 0>), then the above yields:
1571
1572 a * a = abs(a) ** 2
1573
1574which is true (C<abs> has the regular meaning for real number, i.e. stands
1575for the absolute value). This example explains why the norm of C<z> is
1576noted C<abs(z)>: it extends the C<abs> function to complex numbers, yet
1577is the regular C<abs> we know when the complex number actually has no
1578imaginary part... This justifies I<a posteriori> our use of the C<abs>
1579notation for the norm.
1580
1581=head1 OPERATIONS
1582
1583Given the following notations:
1584
1585 z1 = a + bi = r1 * exp(i * t1)
1586 z2 = c + di = r2 * exp(i * t2)
1587 z = <any complex or real number>
1588
1589the following (overloaded) operations are supported on complex numbers:
1590
1591 z1 + z2 = (a + c) + i(b + d)
1592 z1 - z2 = (a - c) + i(b - d)
1593 z1 * z2 = (r1 * r2) * exp(i * (t1 + t2))
1594 z1 / z2 = (r1 / r2) * exp(i * (t1 - t2))
1595 z1 ** z2 = exp(z2 * log z1)
b42d0ec9 1596 ~z = a - bi
1597 abs(z) = r1 = sqrt(a*a + b*b)
1598 sqrt(z) = sqrt(r1) * exp(i * t/2)
1599 exp(z) = exp(a) * exp(i * b)
1600 log(z) = log(r1) + i*t
1601 sin(z) = 1/2i (exp(i * z1) - exp(-i * z))
1602 cos(z) = 1/2 (exp(i * z1) + exp(-i * z))
66730be0 1603 atan2(z1, z2) = atan(z1/z2)
1604
1605The following extra operations are supported on both real and complex
1606numbers:
1607
1608 Re(z) = a
1609 Im(z) = b
1610 arg(z) = t
b42d0ec9 1611 abs(z) = r
66730be0 1612
1613 cbrt(z) = z ** (1/3)
1614 log10(z) = log(z) / log(10)
1615 logn(z, n) = log(z) / log(n)
1616
1617 tan(z) = sin(z) / cos(z)
0c721ce2 1618
5aabfad6 1619 csc(z) = 1 / sin(z)
1620 sec(z) = 1 / cos(z)
0c721ce2 1621 cot(z) = 1 / tan(z)
66730be0 1622
1623 asin(z) = -i * log(i*z + sqrt(1-z*z))
fb73857a 1624 acos(z) = -i * log(z + i*sqrt(1-z*z))
66730be0 1625 atan(z) = i/2 * log((i+z) / (i-z))
0c721ce2 1626
5aabfad6 1627 acsc(z) = asin(1 / z)
1628 asec(z) = acos(1 / z)
8c03c583 1629 acot(z) = atan(1 / z) = -i/2 * log((i+z) / (z-i))
66730be0 1630
1631 sinh(z) = 1/2 (exp(z) - exp(-z))
1632 cosh(z) = 1/2 (exp(z) + exp(-z))
0c721ce2 1633 tanh(z) = sinh(z) / cosh(z) = (exp(z) - exp(-z)) / (exp(z) + exp(-z))
1634
5aabfad6 1635 csch(z) = 1 / sinh(z)
1636 sech(z) = 1 / cosh(z)
0c721ce2 1637 coth(z) = 1 / tanh(z)
fb73857a 1638
66730be0 1639 asinh(z) = log(z + sqrt(z*z+1))
1640 acosh(z) = log(z + sqrt(z*z-1))
1641 atanh(z) = 1/2 * log((1+z) / (1-z))
66730be0 1642
5aabfad6 1643 acsch(z) = asinh(1 / z)
1644 asech(z) = acosh(1 / z)
0c721ce2 1645 acoth(z) = atanh(1 / z) = 1/2 * log((1+z) / (z-1))
1646
b42d0ec9 1647I<arg>, I<abs>, I<log>, I<csc>, I<cot>, I<acsc>, I<acot>, I<csch>,
1648I<coth>, I<acosech>, I<acotanh>, have aliases I<rho>, I<theta>, I<ln>,
1649I<cosec>, I<cotan>, I<acosec>, I<acotan>, I<cosech>, I<cotanh>,
1650I<acosech>, I<acotanh>, respectively. C<Re>, C<Im>, C<arg>, C<abs>,
1651C<rho>, and C<theta> can be used also also mutators. The C<cbrt>
1652returns only one of the solutions: if you want all three, use the
1653C<root> function.
0c721ce2 1654
1655The I<root> function is available to compute all the I<n>
66730be0 1656roots of some complex, where I<n> is a strictly positive integer.
1657There are exactly I<n> such roots, returned as a list. Getting the
1658number mathematicians call C<j> such that:
1659
1660 1 + j + j*j = 0;
1661
1662is a simple matter of writing:
1663
1664 $j = ((root(1, 3))[1];
1665
1666The I<k>th root for C<z = [r,t]> is given by:
1667
1668 (root(z, n))[k] = r**(1/n) * exp(i * (t + 2*k*pi)/n)
1669
f4837644 1670The I<spaceship> comparison operator, E<lt>=E<gt>, is also defined. In
1671order to ensure its restriction to real numbers is conform to what you
1672would expect, the comparison is run on the real part of the complex
1673number first, and imaginary parts are compared only when the real
1674parts match.
66730be0 1675
1676=head1 CREATION
1677
1678To create a complex number, use either:
1679
1680 $z = Math::Complex->make(3, 4);
1681 $z = cplx(3, 4);
1682
1683if you know the cartesian form of the number, or
1684
1685 $z = 3 + 4*i;
1686
fb73857a 1687if you like. To create a number using the polar form, use either:
66730be0 1688
1689 $z = Math::Complex->emake(5, pi/3);
1690 $x = cplxe(5, pi/3);
1691
0c721ce2 1692instead. The first argument is the modulus, the second is the angle
fb73857a 1693(in radians, the full circle is 2*pi). (Mnemonic: C<e> is used as a
1694notation for complex numbers in the polar form).
66730be0 1695
1696It is possible to write:
1697
1698 $x = cplxe(-3, pi/4);
1699
16357284 1700but that will be silently converted into C<[3,-3pi/4]>, since the
1701modulus must be non-negative (it represents the distance to the origin
1702in the complex plane).
66730be0 1703
b42d0ec9 1704It is also possible to have a complex number as either argument of
1705either the C<make> or C<emake>: the appropriate component of
1706the argument will be used.
1707
1708 $z1 = cplx(-2, 1);
1709 $z2 = cplx($z1, 4);
1710
66730be0 1711=head1 STRINGIFICATION
1712
1713When printed, a complex number is usually shown under its cartesian
16357284 1714style I<a+bi>, but there are legitimate cases where the polar style
66730be0 1715I<[r,t]> is more appropriate.
1716
16357284 1717By calling the class method C<Math::Complex::display_format> and
1718supplying either C<"polar"> or C<"cartesian"> as an argument, you
5287f86b 1719override the default display style, which is C<"cartesian">. Not
16357284 1720supplying any argument returns the current settings.
66730be0 1721
1722This default can be overridden on a per-number basis by calling the
1723C<display_format> method instead. As before, not supplying any argument
5287f86b 1724returns the current display style for this number. Otherwise whatever you
1725specify will be the new display style for I<this> particular number.
66730be0 1726
1727For instance:
1728
1729 use Math::Complex;
1730
1731 Math::Complex::display_format('polar');
16357284 1732 $j = (root(1, 3))[1];
1733 print "j = $j\n"; # Prints "j = [1,2pi/3]"
66730be0 1734 $j->display_format('cartesian');
1735 print "j = $j\n"; # Prints "j = -0.5+0.866025403784439i"
1736
5287f86b 1737The polar style attempts to emphasize arguments like I<k*pi/n>
ee8c7f54 1738(where I<n> is a positive integer and I<k> an integer within [-9, +9]),
5287f86b 1739this is called I<polar pretty-printing>.
66730be0 1740
16357284 1741=head2 CHANGED IN PERL 5.6
1742
1743The C<display_format> class method and the corresponding
1744C<display_format> object method can now be called using
1745a parameter hash instead of just a one parameter.
1746
1747The old display format style, which can have values C<"cartesian"> or
ee8c7f54 1748C<"polar">, can be changed using the C<"style"> parameter.
1749
1750 $j->display_format(style => "polar");
1751
1752The one parameter calling convention also still works.
1753
1754 $j->display_format("polar");
16357284 1755
1756There are two new display parameters.
1757
ee8c7f54 1758The first one is C<"format">, which is a sprintf()-style format string
1759to be used for both numeric parts of the complex number(s). The is
1760somewhat system-dependent but most often it corresponds to C<"%.15g">.
1761You can revert to the default by setting the C<format> to C<undef>.
16357284 1762
1763 # the $j from the above example
1764
1765 $j->display_format('format' => '%.5f');
1766 print "j = $j\n"; # Prints "j = -0.50000+0.86603i"
ee8c7f54 1767 $j->display_format('format' => undef);
16357284 1768 print "j = $j\n"; # Prints "j = -0.5+0.86603i"
1769
1770Notice that this affects also the return values of the
1771C<display_format> methods: in list context the whole parameter hash
ee8c7f54 1772will be returned, as opposed to only the style parameter value.
1773This is a potential incompatibility with earlier versions if you
1774have been calling the C<display_format> method in list context.
16357284 1775
5287f86b 1776The second new display parameter is C<"polar_pretty_print">, which can
1777be set to true or false, the default being true. See the previous
1778section for what this means.
16357284 1779
66730be0 1780=head1 USAGE
1781
1782Thanks to overloading, the handling of arithmetics with complex numbers
1783is simple and almost transparent.
1784
1785Here are some examples:
1786
1787 use Math::Complex;
1788
1789 $j = cplxe(1, 2*pi/3); # $j ** 3 == 1
1790 print "j = $j, j**3 = ", $j ** 3, "\n";
1791 print "1 + j + j**2 = ", 1 + $j + $j**2, "\n";
1792
1793 $z = -16 + 0*i; # Force it to be a complex
1794 print "sqrt($z) = ", sqrt($z), "\n";
1795
1796 $k = exp(i * 2*pi/3);
1797 print "$j - $k = ", $j - $k, "\n";
a5f75d66 1798
b42d0ec9 1799 $z->Re(3); # Re, Im, arg, abs,
1800 $j->arg(2); # (the last two aka rho, theta)
1801 # can be used also as mutators.
1802
1803=head1 ERRORS DUE TO DIVISION BY ZERO OR LOGARITHM OF ZERO
5aabfad6 1804
1805The division (/) and the following functions
1806
b42d0ec9 1807 log ln log10 logn
2820d885 1808 tan sec csc cot
b42d0ec9 1809 atan asec acsc acot
1810 tanh sech csch coth
1811 atanh asech acsch acoth
5aabfad6 1812
1813cannot be computed for all arguments because that would mean dividing
8c03c583 1814by zero or taking logarithm of zero. These situations cause fatal
1815runtime errors looking like this
5aabfad6 1816
1817 cot(0): Division by zero.
5cd24f17 1818 (Because in the definition of cot(0), the divisor sin(0) is 0)
5aabfad6 1819 Died at ...
1820
8c03c583 1821or
1822
1823 atanh(-1): Logarithm of zero.
1824 Died at...
1825
1826For the C<csc>, C<cot>, C<asec>, C<acsc>, C<acot>, C<csch>, C<coth>,
b42d0ec9 1827C<asech>, C<acsch>, the argument cannot be C<0> (zero). For the the
1828logarithmic functions and the C<atanh>, C<acoth>, the argument cannot
1829be C<1> (one). For the C<atanh>, C<acoth>, the argument cannot be
1830C<-1> (minus one). For the C<atan>, C<acot>, the argument cannot be
1831C<i> (the imaginary unit). For the C<atan>, C<acoth>, the argument
1832cannot be C<-i> (the negative imaginary unit). For the C<tan>,
1833C<sec>, C<tanh>, the argument cannot be I<pi/2 + k * pi>, where I<k>
1834is any integer.
1835
1836Note that because we are operating on approximations of real numbers,
1837these errors can happen when merely `too close' to the singularities
ee8c7f54 1838listed above.
b42d0ec9 1839
1840=head1 ERRORS DUE TO INDIGESTIBLE ARGUMENTS
1841
1842The C<make> and C<emake> accept both real and complex arguments.
1843When they cannot recognize the arguments they will die with error
1844messages like the following
1845
1846 Math::Complex::make: Cannot take real part of ...
1847 Math::Complex::make: Cannot take real part of ...
1848 Math::Complex::emake: Cannot take rho of ...
1849 Math::Complex::emake: Cannot take theta of ...
5cd24f17 1850
a5f75d66 1851=head1 BUGS
1852
5cd24f17 1853Saying C<use Math::Complex;> exports many mathematical routines in the
fb73857a 1854caller environment and even overrides some (C<sqrt>, C<log>).
1855This is construed as a feature by the Authors, actually... ;-)
a5f75d66 1856
66730be0 1857All routines expect to be given real or complex numbers. Don't attempt to
1858use BigFloat, since Perl has currently no rule to disambiguate a '+'
1859operation (for instance) between two overloaded entities.
a5f75d66 1860
d09ae4e6 1861In Cray UNICOS there is some strange numerical instability that results
1862in root(), cos(), sin(), cosh(), sinh(), losing accuracy fast. Beware.
1863The bug may be in UNICOS math libs, in UNICOS C compiler, in Math::Complex.
1864Whatever it is, it does not manifest itself anywhere else where Perl runs.
1865
0c721ce2 1866=head1 AUTHORS
a5f75d66 1867
6e238990 1868Raphael Manfredi <F<Raphael_Manfredi@pobox.com>> and
ace5de91 1869Jarkko Hietaniemi <F<jhi@iki.fi>>.
5cd24f17 1870
fb73857a 1871Extensive patches by Daniel S. Lewart <F<d-lewart@uiuc.edu>>.
1872
5cd24f17 1873=cut
1874
b42d0ec9 18751;
1876
5cd24f17 1877# eof