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