perl 5.003_06: lib/Math/Complex.pm
[p5sagit/p5-mst-13.2.git] / lib / Math / Complex.pm
CommitLineData
66730be0 1# $RCSFile$
2#
3# Complex numbers and associated mathematical functions
4# -- Raphael Manfredi, Sept 1996
a0d0e21e 5
6require Exporter;
66730be0 7package Math::Complex; @ISA = qw(Exporter);
a0d0e21e 8
66730be0 9@EXPORT = qw(
10 pi i Re Im arg
11 log10 logn cbrt root
12 tan cotan asin acos atan acotan
13 sinh cosh tanh cotanh asinh acosh atanh acotanh
14 cplx cplxe
15);
a0d0e21e 16
a5f75d66 17use overload
66730be0 18 '+' => \&plus,
19 '-' => \&minus,
20 '*' => \&multiply,
21 '/' => \&divide,
22 '**' => \&power,
23 '<=>' => \&spaceship,
24 'neg' => \&negate,
25 '~' => \&conjugate,
26 'abs' => \&abs,
27 'sqrt' => \&sqrt,
28 'exp' => \&exp,
29 'log' => \&log,
30 'sin' => \&sin,
31 'cos' => \&cos,
32 'atan2' => \&atan2,
33 qw("" stringify);
34
35#
36# Package globals
37#
38
39$package = 'Math::Complex'; # Package name
40$display = 'cartesian'; # Default display format
41
42#
43# Object attributes (internal):
44# cartesian [real, imaginary] -- cartesian form
45# polar [rho, theta] -- polar form
46# c_dirty cartesian form not up-to-date
47# p_dirty polar form not up-to-date
48# display display format (package's global when not set)
49#
50
51#
52# ->make
53#
54# Create a new complex number (cartesian form)
55#
56sub make {
57 my $self = bless {}, shift;
58 my ($re, $im) = @_;
59 $self->{cartesian} = [$re, $im];
60 $self->{c_dirty} = 0;
61 $self->{p_dirty} = 1;
62 return $self;
63}
64
65#
66# ->emake
67#
68# Create a new complex number (exponential form)
69#
70sub emake {
71 my $self = bless {}, shift;
72 my ($rho, $theta) = @_;
73 $theta += pi() if $rho < 0;
74 $self->{polar} = [abs($rho), $theta];
75 $self->{p_dirty} = 0;
76 $self->{c_dirty} = 1;
77 return $self;
78}
79
80sub new { &make } # For backward compatibility only.
81
82#
83# cplx
84#
85# Creates a complex number from a (re, im) tuple.
86# This avoids the burden of writing Math::Complex->make(re, im).
87#
88sub cplx {
89 my ($re, $im) = @_;
90 return $package->make($re, $im);
91}
92
93#
94# cplxe
95#
96# Creates a complex number from a (rho, theta) tuple.
97# This avoids the burden of writing Math::Complex->emake(rho, theta).
98#
99sub cplxe {
100 my ($rho, $theta) = @_;
101 return $package->emake($rho, $theta);
102}
103
104#
105# pi
106#
107# The number defined as 2 * pi = 360 degrees
108#
109sub pi () {
110 $pi = 4 * atan2(1, 1) unless $pi;
111 return $pi;
112}
113
114#
115# i
116#
117# The number defined as i*i = -1;
118#
119sub i () {
120 $i = bless {} unless $i; # There can be only one i
121 $i->{cartesian} = [0, 1];
122 $i->{polar} = [1, pi/2];
123 $i->{c_dirty} = 0;
124 $i->{p_dirty} = 0;
125 return $i;
126}
127
128#
129# Attribute access/set routines
130#
131
132sub cartesian {$_[0]->{c_dirty} ? $_[0]->update_cartesian : $_[0]->{cartesian}}
133sub polar {$_[0]->{p_dirty} ? $_[0]->update_polar : $_[0]->{polar}}
134
135sub set_cartesian { $_[0]->{p_dirty}++; $_[0]->{cartesian} = $_[1] }
136sub set_polar { $_[0]->{c_dirty}++; $_[0]->{polar} = $_[1] }
137
138#
139# ->update_cartesian
140#
141# Recompute and return the cartesian form, given accurate polar form.
142#
143sub update_cartesian {
144 my $self = shift;
145 my ($r, $t) = @{$self->{polar}};
146 $self->{c_dirty} = 0;
147 return $self->{cartesian} = [$r * cos $t, $r * sin $t];
148}
149
150#
151#
152# ->update_polar
153#
154# Recompute and return the polar form, given accurate cartesian form.
155#
156sub update_polar {
157 my $self = shift;
158 my ($x, $y) = @{$self->{cartesian}};
159 $self->{p_dirty} = 0;
160 return $self->{polar} = [0, 0] if $x == 0 && $y == 0;
161 return $self->{polar} = [sqrt($x*$x + $y*$y), atan2($y, $x)];
162}
163
164#
165# (plus)
166#
167# Computes z1+z2.
168#
169sub plus {
170 my ($z1, $z2, $regular) = @_;
171 my ($re1, $im1) = @{$z1->cartesian};
172 my ($re2, $im2) = ref $z2 ? @{$z2->cartesian} : ($z2);
173 unless (defined $regular) {
174 $z1->set_cartesian([$re1 + $re2, $im1 + $im2]);
175 return $z1;
176 }
177 return (ref $z1)->make($re1 + $re2, $im1 + $im2);
178}
179
180#
181# (minus)
182#
183# Computes z1-z2.
184#
185sub minus {
186 my ($z1, $z2, $inverted) = @_;
187 my ($re1, $im1) = @{$z1->cartesian};
188 my ($re2, $im2) = ref $z2 ? @{$z2->cartesian} : ($z2);
189 unless (defined $inverted) {
190 $z1->set_cartesian([$re1 - $re2, $im1 - $im2]);
191 return $z1;
192 }
193 return $inverted ?
194 (ref $z1)->make($re2 - $re1, $im2 - $im1) :
195 (ref $z1)->make($re1 - $re2, $im1 - $im2);
196}
197
198#
199# (multiply)
200#
201# Computes z1*z2.
202#
203sub multiply {
204 my ($z1, $z2, $regular) = @_;
205 my ($r1, $t1) = @{$z1->polar};
206 my ($r2, $t2) = ref $z2 ? @{$z2->polar} : (abs($z2), $z2 >= 0 ? 0 : pi);
207 unless (defined $regular) {
208 $z1->set_polar([$r1 * $r2, $t1 + $t2]);
209 return $z1;
210 }
211 return (ref $z1)->emake($r1 * $r2, $t1 + $t2);
212}
213
214#
215# (divide)
216#
217# Computes z1/z2.
218#
219sub divide {
220 my ($z1, $z2, $inverted) = @_;
221 my ($r1, $t1) = @{$z1->polar};
222 my ($r2, $t2) = ref $z2 ? @{$z2->polar} : (abs($z2), $z2 >= 0 ? 0 : pi);
223 unless (defined $inverted) {
224 $z1->set_polar([$r1 / $r2, $t1 - $t2]);
225 return $z1;
226 }
227 return $inverted ?
228 (ref $z1)->emake($r2 / $r1, $t2 - $t1) :
229 (ref $z1)->emake($r1 / $r2, $t1 - $t2);
230}
231
232#
233# (power)
234#
235# Computes z1**z2 = exp(z2 * log z1)).
236#
237sub power {
238 my ($z1, $z2, $inverted) = @_;
239 return exp($z1 * log $z2) if defined $inverted && $inverted;
240 return exp($z2 * log $z1);
241}
242
243#
244# (spaceship)
245#
246# Computes z1 <=> z2.
247# Sorts on the real part first, then on the imaginary part. Thus 2-4i > 3+8i.
248#
249sub spaceship {
250 my ($z1, $z2, $inverted) = @_;
251 my ($re1, $im1) = @{$z1->cartesian};
252 my ($re2, $im2) = ref $z2 ? @{$z2->cartesian} : ($z2);
253 my $sgn = $inverted ? -1 : 1;
254 return $sgn * ($re1 <=> $re2) if $re1 != $re2;
255 return $sgn * ($im1 <=> $im2);
256}
257
258#
259# (negate)
260#
261# Computes -z.
262#
263sub negate {
264 my ($z) = @_;
265 if ($z->{c_dirty}) {
266 my ($r, $t) = @{$z->polar};
267 return (ref $z)->emake($r, pi + $t);
268 }
269 my ($re, $im) = @{$z->cartesian};
270 return (ref $z)->make(-$re, -$im);
271}
272
273#
274# (conjugate)
275#
276# Compute complex's conjugate.
277#
278sub conjugate {
279 my ($z) = @_;
280 if ($z->{c_dirty}) {
281 my ($r, $t) = @{$z->polar};
282 return (ref $z)->emake($r, -$t);
283 }
284 my ($re, $im) = @{$z->cartesian};
285 return (ref $z)->make($re, -$im);
286}
287
288#
289# (abs)
290#
291# Compute complex's norm (rho).
292#
293sub abs {
294 my ($z) = @_;
295 my ($r, $t) = @{$z->polar};
296 return abs($r);
297}
298
299#
300# arg
301#
302# Compute complex's argument (theta).
303#
304sub arg {
305 my ($z) = @_;
306 return 0 unless ref $z;
307 my ($r, $t) = @{$z->polar};
308 return $t;
309}
310
311#
312# (sqrt)
313#
314# Compute sqrt(z) (positive only).
315#
316sub sqrt {
317 my ($z) = @_;
318 my ($r, $t) = @{$z->polar};
319 return (ref $z)->emake(sqrt($r), $t/2);
320}
321
322#
323# cbrt
324#
325# Compute cbrt(z) (cubic root, primary only).
326#
327sub cbrt {
328 my ($z) = @_;
329 return $z ** (1/3) unless ref $z;
330 my ($r, $t) = @{$z->polar};
331 return (ref $z)->emake($r**(1/3), $t/3);
332}
333
334#
335# root
336#
337# Computes all nth root for z, returning an array whose size is n.
338# `n' must be a positive integer.
339#
340# The roots are given by (for k = 0..n-1):
341#
342# z^(1/n) = r^(1/n) (cos ((t+2 k pi)/n) + i sin ((t+2 k pi)/n))
343#
344sub root {
345 my ($z, $n) = @_;
346 $n = int($n + 0.5);
347 return undef unless $n > 0;
348 my ($r, $t) = ref $z ? @{$z->polar} : (abs($z), $z >= 0 ? 0 : pi);
349 my @root;
350 my $k;
351 my $theta_inc = 2 * pi / $n;
352 my $rho = $r ** (1/$n);
353 my $theta;
354 my $complex = ref($z) || $package;
355 for ($k = 0, $theta = $t / $n; $k < $n; $k++, $theta += $theta_inc) {
356 push(@root, $complex->emake($rho, $theta));
a0d0e21e 357 }
66730be0 358 return @root;
a0d0e21e 359}
360
66730be0 361#
362# Re
363#
364# Return Re(z).
365#
a0d0e21e 366sub Re {
66730be0 367 my ($z) = @_;
368 return $z unless ref $z;
369 my ($re, $im) = @{$z->cartesian};
370 return $re;
a0d0e21e 371}
372
66730be0 373#
374# Im
375#
376# Return Im(z).
377#
a0d0e21e 378sub Im {
66730be0 379 my ($z) = @_;
380 return 0 unless ref $z;
381 my ($re, $im) = @{$z->cartesian};
382 return $im;
a0d0e21e 383}
384
66730be0 385#
386# (exp)
387#
388# Computes exp(z).
389#
390sub exp {
391 my ($z) = @_;
392 my ($x, $y) = @{$z->cartesian};
393 return (ref $z)->emake(exp($x), $y);
394}
395
396#
397# (log)
398#
399# Compute log(z).
400#
401sub log {
402 my ($z) = @_;
403 my ($r, $t) = @{$z->polar};
404 return (ref $z)->make(log($r), $t);
405}
406
407#
408# log10
409#
410# Compute log10(z).
411#
412sub log10 {
413 my ($z) = @_;
414 $log10 = log(10) unless defined $log10;
415 return log($z) / $log10 unless ref $z;
416 my ($r, $t) = @{$z->polar};
417 return (ref $z)->make(log($r) / $log10, $t / $log10);
418}
419
420#
421# logn
422#
423# Compute logn(z,n) = log(z) / log(n)
424#
425sub logn {
426 my ($z, $n) = @_;
427 my $logn = $logn{$n};
428 $logn = $logn{$n} = log($n) unless defined $logn; # Cache log(n)
429 return log($z) / log($n);
430}
431
432#
433# (cos)
434#
435# Compute cos(z) = (exp(iz) + exp(-iz))/2.
436#
437sub cos {
438 my ($z) = @_;
439 my ($x, $y) = @{$z->cartesian};
440 my $ey = exp($y);
441 my $ey_1 = 1 / $ey;
442 return (ref $z)->make(cos($x) * ($ey + $ey_1)/2, sin($x) * ($ey_1 - $ey)/2);
443}
444
445#
446# (sin)
447#
448# Compute sin(z) = (exp(iz) - exp(-iz))/2.
449#
450sub sin {
451 my ($z) = @_;
452 my ($x, $y) = @{$z->cartesian};
453 my $ey = exp($y);
454 my $ey_1 = 1 / $ey;
455 return (ref $z)->make(sin($x) * ($ey + $ey_1)/2, cos($x) * ($ey - $ey_1)/2);
456}
457
458#
459# tan
460#
461# Compute tan(z) = sin(z) / cos(z).
462#
463sub tan {
464 my ($z) = @_;
465 return sin($z) / cos($z);
466}
467
468#
469# cotan
470#
471# Computes cotan(z) = 1 / tan(z).
472#
473sub cotan {
474 my ($z) = @_;
475 return cos($z) / sin($z);
476}
477
478#
479# acos
480#
481# Computes the arc cosine acos(z) = -i log(z + sqrt(z*z-1)).
482#
483sub acos {
484 my ($z) = @_;
485 my $cz = $z*$z - 1;
486 $cz = cplx($cz, 0) if !ref $cz && $cz < 0; # Force complex if <0
487 return ~i * log($z + sqrt $cz); # ~i is -i
488}
489
490#
491# asin
492#
493# Computes the arc sine asin(z) = -i log(iz + sqrt(1-z*z)).
494#
495sub asin {
496 my ($z) = @_;
497 my $cz = 1 - $z*$z;
498 $cz = cplx($cz, 0) if !ref $cz && $cz < 0; # Force complex if <0
499 return ~i * log(i * $z + sqrt $cz); # ~i is -i
500}
501
502#
503# atan
504#
505# Computes the arc tagent atan(z) = i/2 log((i+z) / (i-z)).
506#
507sub atan {
508 my ($z) = @_;
509 return i/2 * log((i + $z) / (i - $z));
a0d0e21e 510}
511
66730be0 512#
513# acotan
514#
515# Computes the arc cotangent acotan(z) = -i/2 log((i+z) / (z-i))
516#
517sub acotan {
518 my ($z) = @_;
519 return i/-2 * log((i + $z) / ($z - i));
520}
521
522#
523# cosh
524#
525# Computes the hyperbolic cosine cosh(z) = (exp(z) + exp(-z))/2.
526#
527sub cosh {
528 my ($z) = @_;
529 my ($x, $y) = ref $z ? @{$z->cartesian} : ($z);
530 my $ex = exp($x);
531 my $ex_1 = 1 / $ex;
532 return ($ex + $ex_1)/2 unless ref $z;
533 return (ref $z)->make(cos($y) * ($ex + $ex_1)/2, sin($y) * ($ex - $ex_1)/2);
534}
535
536#
537# sinh
538#
539# Computes the hyperbolic sine sinh(z) = (exp(z) - exp(-z))/2.
540#
541sub sinh {
542 my ($z) = @_;
543 my ($x, $y) = ref $z ? @{$z->cartesian} : ($z);
544 my $ex = exp($x);
545 my $ex_1 = 1 / $ex;
546 return ($ex - $ex_1)/2 unless ref $z;
547 return (ref $z)->make(cos($y) * ($ex - $ex_1)/2, sin($y) * ($ex + $ex_1)/2);
548}
549
550#
551# tanh
552#
553# Computes the hyperbolic tangent tanh(z) = sinh(z) / cosh(z).
554#
555sub tanh {
556 my ($z) = @_;
557 return sinh($z) / cosh($z);
558}
559
560#
561# cotanh
562#
563# Comptutes the hyperbolic cotangent cotanh(z) = cosh(z) / sinh(z).
564#
565sub cotanh {
566 my ($z) = @_;
567 return cosh($z) / sinh($z);
568}
569
570#
571# acosh
572#
573# Computes the arc hyperbolic cosine acosh(z) = log(z + sqrt(z*z-1)).
574#
575sub acosh {
576 my ($z) = @_;
577 my $cz = $z*$z - 1;
578 $cz = cplx($cz, 0) if !ref $cz && $cz < 0; # Force complex if <0
579 return log($z + sqrt $cz);
580}
581
582#
583# asinh
584#
585# Computes the arc hyperbolic sine asinh(z) = log(z + sqrt(z*z-1))
586#
587sub asinh {
588 my ($z) = @_;
589 my $cz = $z*$z + 1; # Already complex if <0
590 return log($z + sqrt $cz);
591}
592
593#
594# atanh
595#
596# Computes the arc hyperbolic tangent atanh(z) = 1/2 log((1+z) / (1-z)).
597#
598sub atanh {
599 my ($z) = @_;
600 my $cz = (1 + $z) / (1 - $z);
601 $cz = cplx($cz, 0) if !ref $cz && $cz < 0; # Force complex if <0
602 return log($cz) / 2;
603}
604
605#
606# acotanh
607#
608# Computes the arc hyperbolic cotangent acotanh(z) = 1/2 log((1+z) / (z-1)).
609#
610sub acotanh {
611 my ($z) = @_;
612 my $cz = (1 + $z) / ($z - 1);
613 $cz = cplx($cz, 0) if !ref $cz && $cz < 0; # Force complex if <0
614 return log($cz) / 2;
615}
616
617#
618# (atan2)
619#
620# Compute atan(z1/z2).
621#
622sub atan2 {
623 my ($z1, $z2, $inverted) = @_;
624 my ($re1, $im1) = @{$z1->cartesian};
625 my ($re2, $im2) = ref $z2 ? @{$z2->cartesian} : ($z2);
626 my $tan;
627 if (defined $inverted && $inverted) { # atan(z2/z1)
628 return pi * ($re2 > 0 ? 1 : -1) if $re1 == 0 && $im1 == 0;
629 $tan = $z2 / $z1;
630 } else {
631 return pi * ($re1 > 0 ? 1 : -1) if $re2 == 0 && $im2 == 0;
632 $tan = $z1 / $z2;
633 }
634 return atan($tan);
635}
636
637#
638# display_format
639# ->display_format
640#
641# Set (fetch if no argument) display format for all complex numbers that
642# don't happen to have overrriden it via ->display_format
643#
644# When called as a method, this actually sets the display format for
645# the current object.
646#
647# Valid object formats are 'c' and 'p' for cartesian and polar. The first
648# letter is used actually, so the type can be fully spelled out for clarity.
649#
650sub display_format {
651 my $self = shift;
652 my $format = undef;
653
654 if (ref $self) { # Called as a method
655 $format = shift;
656 } else { # Regular procedure call
657 $format = $self;
658 undef $self;
659 }
660
661 if (defined $self) {
662 return defined $self->{display} ? $self->{display} : $display
663 unless defined $format;
664 return $self->{display} = $format;
665 }
666
667 return $display unless defined $format;
668 return $display = $format;
669}
670
671#
672# (stringify)
673#
674# Show nicely formatted complex number under its cartesian or polar form,
675# depending on the current display format:
676#
677# . If a specific display format has been recorded for this object, use it.
678# . Otherwise, use the generic current default for all complex numbers,
679# which is a package global variable.
680#
a0d0e21e 681sub stringify {
66730be0 682 my ($z) = shift;
683 my $format;
684
685 $format = $display;
686 $format = $z->{display} if defined $z->{display};
687
688 return $z->stringify_polar if $format =~ /^p/i;
689 return $z->stringify_cartesian;
690}
691
692#
693# ->stringify_cartesian
694#
695# Stringify as a cartesian representation 'a+bi'.
696#
697sub stringify_cartesian {
698 my $z = shift;
699 my ($x, $y) = @{$z->cartesian};
700 my ($re, $im);
701
702 $re = "$x" if abs($x) >= 1e-14;
703 if ($y == 1) { $im = 'i' }
704 elsif ($y == -1) { $im = '-i' }
705 elsif (abs($y) >= 1e-14) { $im = "${y}i" }
706
707 my $str;
708 $str = $re if defined $re;
709 $str .= "+$im" if defined $im;
710 $str =~ s/\+-/-/;
711 $str =~ s/^\+//;
712 $str = '0' unless $str;
713
714 return $str;
715}
716
717#
718# ->stringify_polar
719#
720# Stringify as a polar representation '[r,t]'.
721#
722sub stringify_polar {
723 my $z = shift;
724 my ($r, $t) = @{$z->polar};
725 my $theta;
726
727 return '[0,0]' if $r <= 1e-14;
a0d0e21e 728
66730be0 729 my $tpi = 2 * pi;
730 my $nt = $t / $tpi;
731 $nt = ($nt - int($nt)) * $tpi;
732 $nt += $tpi if $nt < 0; # Range [0, 2pi]
a0d0e21e 733
66730be0 734 if (abs($nt) <= 1e-14) { $theta = 0 }
735 elsif (abs(pi-$nt) <= 1e-14) { $theta = 'pi' }
736
737 return "\[$r,$theta\]" if defined $theta;
738
739 #
740 # Okay, number is not a real. Try to identify pi/n and friends...
741 #
742
743 $nt -= $tpi if $nt > pi;
744 my ($n, $k, $kpi);
745
746 for ($k = 1, $kpi = pi; $k < 10; $k++, $kpi += pi) {
747 $n = int($kpi / $nt + ($nt > 0 ? 1 : -1) * 0.5);
748 if (abs($kpi/$n - $nt) <= 1e-14) {
749 $theta = ($nt < 0 ? '-':'').($k == 1 ? 'pi':"${k}pi").'/'.abs($n);
750 last;
751 }
752 }
753
754 $theta = $nt unless defined $theta;
755
756 return "\[$r,$theta\]";
a0d0e21e 757}
a5f75d66 758
7591;
760__END__
761
762=head1 NAME
763
66730be0 764Math::Complex - complex numbers and associated mathematical functions
a5f75d66 765
766=head1 SYNOPSIS
767
66730be0 768 use Math::Complex;
769 $z = Math::Complex->make(5, 6);
770 $t = 4 - 3*i + $z;
771 $j = cplxe(1, 2*pi/3);
a5f75d66 772
773=head1 DESCRIPTION
774
66730be0 775This package lets you create and manipulate complex numbers. By default,
776I<Perl> limits itself to real numbers, but an extra C<use> statement brings
777full complex support, along with a full set of mathematical functions
778typically associated with and/or extended to complex numbers.
779
780If you wonder what complex numbers are, they were invented to be able to solve
781the following equation:
782
783 x*x = -1
784
785and by definition, the solution is noted I<i> (engineers use I<j> instead since
786I<i> usually denotes an intensity, but the name does not matter). The number
787I<i> is a pure I<imaginary> number.
788
789The arithmetics with pure imaginary numbers works just like you would expect
790it with real numbers... you just have to remember that
791
792 i*i = -1
793
794so you have:
795
796 5i + 7i = i * (5 + 7) = 12i
797 4i - 3i = i * (4 - 3) = i
798 4i * 2i = -8
799 6i / 2i = 3
800 1 / i = -i
801
802Complex numbers are numbers that have both a real part and an imaginary
803part, and are usually noted:
804
805 a + bi
806
807where C<a> is the I<real> part and C<b> is the I<imaginary> part. The
808arithmetic with complex numbers is straightforward. You have to
809keep track of the real and the imaginary parts, but otherwise the
810rules used for real numbers just apply:
811
812 (4 + 3i) + (5 - 2i) = (4 + 5) + i(3 - 2) = 9 + i
813 (2 + i) * (4 - i) = 2*4 + 4i -2i -i*i = 8 + 2i + 1 = 9 + 2i
814
815A graphical representation of complex numbers is possible in a plane
816(also called the I<complex plane>, but it's really a 2D plane).
817The number
818
819 z = a + bi
820
821is the point whose coordinates are (a, b). Actually, it would
822be the vector originating from (0, 0) to (a, b). It follows that the addition
823of two complex numbers is a vectorial addition.
824
825Since there is a bijection between a point in the 2D plane and a complex
826number (i.e. the mapping is unique and reciprocal), a complex number
827can also be uniquely identified with polar coordinates:
828
829 [rho, theta]
830
831where C<rho> is the distance to the origin, and C<theta> the angle between
832the vector and the I<x> axis. There is a notation for this using the
833exponential form, which is:
834
835 rho * exp(i * theta)
836
837where I<i> is the famous imaginary number introduced above. Conversion
838between this form and the cartesian form C<a + bi> is immediate:
839
840 a = rho * cos(theta)
841 b = rho * sin(theta)
842
843which is also expressed by this formula:
844
845 z = rho * exp(i * theta) = rho * (cos theta + i * sin theta)
846
847In other words, it's the projection of the vector onto the I<x> and I<y>
848axes. Mathematicians call I<rho> the I<norm> or I<modulus> and I<theta>
849the I<argument> of the complex number. The I<norm> of C<z> will be
850noted C<abs(z)>.
851
852The polar notation (also known as the trigonometric
853representation) is much more handy for performing multiplications and
854divisions of complex numbers, whilst the cartesian notation is better
855suited for additions and substractions. Real numbers are on the I<x>
856axis, and therefore I<theta> is zero.
857
858All the common operations that can be performed on a real number have
859been defined to work on complex numbers as well, and are merely
860I<extensions> of the operations defined on real numbers. This means
861they keep their natural meaning when there is no imaginary part, provided
862the number is within their definition set.
863
864For instance, the C<sqrt> routine which computes the square root of
865its argument is only defined for positive real numbers and yields a
866positive real number (it is an application from B<R+> to B<R+>).
867If we allow it to return a complex number, then it can be extended to
868negative real numbers to become an application from B<R> to B<C> (the
869set of complex numbers):
870
871 sqrt(x) = x >= 0 ? sqrt(x) : sqrt(-x)*i
872
873It can also be extended to be an application from B<C> to B<C>,
874whilst its restriction to B<R> behaves as defined above by using
875the following definition:
876
877 sqrt(z = [r,t]) = sqrt(r) * exp(i * t/2)
878
879Indeed, a negative real number can be noted C<[x,pi]>
880(the modulus I<x> is always positive, so C<[x,pi]> is really C<-x>, a
881negative number)
882and the above definition states that
883
884 sqrt([x,pi]) = sqrt(x) * exp(i*pi/2) = [sqrt(x),pi/2] = sqrt(x)*i
885
886which is exactly what we had defined for negative real numbers above.
a5f75d66 887
66730be0 888All the common mathematical functions defined on real numbers that
889are extended to complex numbers share that same property of working
890I<as usual> when the imaginary part is zero (otherwise, it would not
891be called an extension, would it?).
a5f75d66 892
66730be0 893A I<new> operation possible on a complex number that is
894the identity for real numbers is called the I<conjugate>, and is noted
895with an horizontal bar above the number, or C<~z> here.
a5f75d66 896
66730be0 897 z = a + bi
898 ~z = a - bi
a5f75d66 899
66730be0 900Simple... Now look:
a5f75d66 901
66730be0 902 z * ~z = (a + bi) * (a - bi) = a*a + b*b
a5f75d66 903
66730be0 904We saw that the norm of C<z> was noted C<abs(z)> and was defined as the
905distance to the origin, also known as:
a5f75d66 906
66730be0 907 rho = abs(z) = sqrt(a*a + b*b)
a5f75d66 908
66730be0 909so
910
911 z * ~z = abs(z) ** 2
912
913If z is a pure real number (i.e. C<b == 0>), then the above yields:
914
915 a * a = abs(a) ** 2
916
917which is true (C<abs> has the regular meaning for real number, i.e. stands
918for the absolute value). This example explains why the norm of C<z> is
919noted C<abs(z)>: it extends the C<abs> function to complex numbers, yet
920is the regular C<abs> we know when the complex number actually has no
921imaginary part... This justifies I<a posteriori> our use of the C<abs>
922notation for the norm.
923
924=head1 OPERATIONS
925
926Given the following notations:
927
928 z1 = a + bi = r1 * exp(i * t1)
929 z2 = c + di = r2 * exp(i * t2)
930 z = <any complex or real number>
931
932the following (overloaded) operations are supported on complex numbers:
933
934 z1 + z2 = (a + c) + i(b + d)
935 z1 - z2 = (a - c) + i(b - d)
936 z1 * z2 = (r1 * r2) * exp(i * (t1 + t2))
937 z1 / z2 = (r1 / r2) * exp(i * (t1 - t2))
938 z1 ** z2 = exp(z2 * log z1)
939 ~z1 = a - bi
940 abs(z1) = r1 = sqrt(a*a + b*b)
941 sqrt(z1) = sqrt(r1) * exp(i * t1/2)
942 exp(z1) = exp(a) * exp(i * b)
943 log(z1) = log(r1) + i*t1
944 sin(z1) = 1/2i (exp(i * z1) - exp(-i * z1))
945 cos(z1) = 1/2 (exp(i * z1) + exp(-i * z1))
946 abs(z1) = r1
947 atan2(z1, z2) = atan(z1/z2)
948
949The following extra operations are supported on both real and complex
950numbers:
951
952 Re(z) = a
953 Im(z) = b
954 arg(z) = t
955
956 cbrt(z) = z ** (1/3)
957 log10(z) = log(z) / log(10)
958 logn(z, n) = log(z) / log(n)
959
960 tan(z) = sin(z) / cos(z)
961 cotan(z) = 1 / tan(z)
962
963 asin(z) = -i * log(i*z + sqrt(1-z*z))
964 acos(z) = -i * log(z + sqrt(z*z-1))
965 atan(z) = i/2 * log((i+z) / (i-z))
966 acotan(z) = -i/2 * log((i+z) / (z-i))
967
968 sinh(z) = 1/2 (exp(z) - exp(-z))
969 cosh(z) = 1/2 (exp(z) + exp(-z))
970 tanh(z) = sinh(z) / cosh(z)
971 cotanh(z) = 1 / tanh(z)
972
973 asinh(z) = log(z + sqrt(z*z+1))
974 acosh(z) = log(z + sqrt(z*z-1))
975 atanh(z) = 1/2 * log((1+z) / (1-z))
976 acotanh(z) = 1/2 * log((1+z) / (z-1))
977
978The I<root> function is available to compute all the I<n>th
979roots of some complex, where I<n> is a strictly positive integer.
980There are exactly I<n> such roots, returned as a list. Getting the
981number mathematicians call C<j> such that:
982
983 1 + j + j*j = 0;
984
985is a simple matter of writing:
986
987 $j = ((root(1, 3))[1];
988
989The I<k>th root for C<z = [r,t]> is given by:
990
991 (root(z, n))[k] = r**(1/n) * exp(i * (t + 2*k*pi)/n)
992
993The I<spaceshift> operation is also defined. In order to ensure its
994restriction to real numbers is conform to what you would expect, the
995comparison is run on the real part of the complex number first,
996and imaginary parts are compared only when the real parts match.
997
998=head1 CREATION
999
1000To create a complex number, use either:
1001
1002 $z = Math::Complex->make(3, 4);
1003 $z = cplx(3, 4);
1004
1005if you know the cartesian form of the number, or
1006
1007 $z = 3 + 4*i;
1008
1009if you like. To create a number using the trigonometric form, use either:
1010
1011 $z = Math::Complex->emake(5, pi/3);
1012 $x = cplxe(5, pi/3);
1013
1014instead. The first argument is the modulus, the second is the angle (in radians).
1015(Mnmemonic: C<e> is used as a notation for complex numbers in the trigonometric
1016form).
1017
1018It is possible to write:
1019
1020 $x = cplxe(-3, pi/4);
1021
1022but that will be silently converted into C<[3,-3pi/4]>, since the modulus
1023must be positive (it represents the distance to the origin in the complex
1024plane).
1025
1026=head1 STRINGIFICATION
1027
1028When printed, a complex number is usually shown under its cartesian
1029form I<a+bi>, but there are legitimate cases where the polar format
1030I<[r,t]> is more appropriate.
1031
1032By calling the routine C<Math::Complex::display_format> and supplying either
1033C<"polar"> or C<"cartesian">, you override the default display format,
1034which is C<"cartesian">. Not supplying any argument returns the current
1035setting.
1036
1037This default can be overridden on a per-number basis by calling the
1038C<display_format> method instead. As before, not supplying any argument
1039returns the current display format for this number. Otherwise whatever you
1040specify will be the new display format for I<this> particular number.
1041
1042For instance:
1043
1044 use Math::Complex;
1045
1046 Math::Complex::display_format('polar');
1047 $j = ((root(1, 3))[1];
1048 print "j = $j\n"; # Prints "j = [1,2pi/3]
1049 $j->display_format('cartesian');
1050 print "j = $j\n"; # Prints "j = -0.5+0.866025403784439i"
1051
1052The polar format attempts to emphasize arguments like I<k*pi/n>
1053(where I<n> is a positive integer and I<k> an integer within [-9,+9]).
1054
1055=head1 USAGE
1056
1057Thanks to overloading, the handling of arithmetics with complex numbers
1058is simple and almost transparent.
1059
1060Here are some examples:
1061
1062 use Math::Complex;
1063
1064 $j = cplxe(1, 2*pi/3); # $j ** 3 == 1
1065 print "j = $j, j**3 = ", $j ** 3, "\n";
1066 print "1 + j + j**2 = ", 1 + $j + $j**2, "\n";
1067
1068 $z = -16 + 0*i; # Force it to be a complex
1069 print "sqrt($z) = ", sqrt($z), "\n";
1070
1071 $k = exp(i * 2*pi/3);
1072 print "$j - $k = ", $j - $k, "\n";
a5f75d66 1073
1074=head1 BUGS
1075
66730be0 1076Saying C<use Math::Complex;> exports many mathematical routines in the caller
1077environment. This is construed as a feature by the Author, actually... ;-)
1078
1079The code is not optimized for speed, although we try to use the cartesian
1080form for addition-like operators and the trigonometric form for all
1081multiplication-like operators.
1082
1083The arg() routine does not ensure the angle is within the range [-pi,+pi]
1084(a side effect caused by multiplication and division using the trigonometric
1085representation).
a5f75d66 1086
66730be0 1087All routines expect to be given real or complex numbers. Don't attempt to
1088use BigFloat, since Perl has currently no rule to disambiguate a '+'
1089operation (for instance) between two overloaded entities.
a5f75d66 1090
66730be0 1091=head1 AUTHOR
a5f75d66 1092
66730be0 1093Raphael Manfredi <F<Raphael_Manfredi@grenoble.hp.com>>