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