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