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