File Coverage

blib/lib/Math/GComplex.pm
Criterion Covered Total %
statement 435 521 83.4
branch 155 270 57.4
condition 29 96 30.2
subroutine 86 110 78.1
pod 73 73 100.0
total 778 1070 72.7


line stmt bran cond sub pod time code
1             package Math::GComplex;
2              
3 3     3   204399 use 5.010;
  3         33  
4 3     3   17 use strict;
  3         6  
  3         65  
5 3     3   13 use warnings;
  3         5  
  3         2059  
6              
7             our $VERSION = '0.11';
8              
9             use overload
10             '""' => \&stringify,
11             '0+' => \&numify,
12             bool => \&boolify,
13              
14             '+' => \&add,
15             '*' => \&mul,
16              
17             '==' => \&eq,
18             '!=' => \&ne,
19              
20             '~' => \&conj,
21             '&' => \&and,
22             '|' => \&or,
23             '^' => \&xor,
24              
25             '>>' => \&rsft,
26             '<<' => \&lsft,
27              
28 0 0   0   0 '>' => sub { $_[2] ? (goto <) : (goto >) },
29 0 0   0   0 '>=' => sub { $_[2] ? (goto &le) : (goto &ge) },
30 16 50   16   57 '<' => sub { $_[2] ? (goto >) : (goto <) },
31 2 50   2   10 '<=' => sub { $_[2] ? (goto &ge) : (goto &le) },
32              
33 0 0 0 0   0 '<=>' => sub { $_[2] ? -(&cmp($_[0], $_[1]) // return undef) : &cmp($_[0], $_[1]) },
34              
35 240 100   240   693 '/' => sub { @_ = ($_[1], $_[0]) if $_[2]; goto &div },
  240         600  
36 225 100   225   530 '-' => sub { @_ = ($_[1], $_[0]) if $_[2]; goto &sub },
  225         514  
37              
38 105 100   105   3800 '**' => sub { @_ = $_[2] ? @_[1, 0] : @_[0, 1]; goto &pow },
  105         265  
39 0 0   0   0 '%' => sub { @_ = $_[2] ? @_[1, 0] : @_[0, 1]; goto &mod },
  0         0  
40              
41 4 50   4   23 atan2 => sub { @_ = $_[2] ? @_[1, 0] : @_[0, 1]; goto &atan2 },
  4         16  
42              
43 22     22   4789 eq => sub { "$_[0]" eq "$_[1]" },
44 0     0   0 ne => sub { "$_[0]" ne "$_[1]" },
45              
46 0 0   0   0 cmp => sub { $_[2] ? ("$_[1]" cmp $_[0]->stringify) : ($_[0]->stringify cmp "$_[1]") },
47              
48 3         97 neg => \&neg,
49             sin => \&sin,
50             cos => \&cos,
51             exp => \&exp,
52             log => \&log,
53             int => \&int,
54             abs => \&abs,
55 3     3   3631 sqrt => \&sqrt;
  3         2973  
56              
57             {
58              
59             my %const = ( # prototypes are assigned in import()
60             i => \&i,
61             );
62              
63             my %trig = (
64 10     10   997 sin => sub (_) { goto &sin }, # built-in function
65             sinh => \&sinh,
66             asin => \&asin,
67             asinh => \&asinh,
68              
69 10     10   941 cos => sub (_) { goto &cos }, # built-in function
70             cosh => \&cosh,
71             acos => \&acos,
72             acosh => \&acosh,
73              
74             tan => \&tan,
75             tanh => \&tanh,
76             atan => \&atan,
77             atanh => \&atanh,
78              
79             cot => \&cot,
80             coth => \&coth,
81             acot => \&acot,
82             acoth => \&acoth,
83              
84             sec => \&sec,
85             sech => \&sech,
86             asec => \&asec,
87             asech => \&asech,
88              
89             csc => \&csc,
90             csch => \&csch,
91             acsc => \&acsc,
92             acsch => \&acsch,
93              
94 5     5   304 atan2 => sub ($$) { goto &atan2 }, # built-in function
95              
96             deg2rad => \°2rad,
97             rad2deg => \&rad2deg,
98             );
99              
100             my %special = (
101 24     24   60 exp => sub (_) { goto &exp }, # built-in function
102 30     30   68 log => sub (_) { goto &log }, # built-in function
103 15     15   36 sqrt => sub (_) { goto &sqrt }, # built-in function
104             cbrt => \&cbrt,
105             logn => \&logn,
106             root => \&root,
107             pow => \&pow,
108             pown => \&pown,
109             );
110              
111             my %misc = (
112              
113             acmp => \&acmp,
114             cplx => \&cplx,
115              
116             abs => sub (_) { goto &abs }, # built-in function
117              
118             inv => \&inv,
119             sgn => \&sgn,
120             conj => \&conj,
121             norm => \&norm,
122              
123             real => \&real,
124             imag => \&imag,
125              
126             floor => \&floor,
127             ceil => \&ceil,
128              
129             reals => \&reals,
130             );
131              
132             sub import {
133 3     3   33 shift;
134              
135 3         12 my $caller = caller(0);
136              
137 3         19 while (@_) {
138 41         67 my $name = shift(@_);
139              
140 41 100 100     181 if ($name eq ':overload') {
    100 66        
    100          
    100          
    50          
    50          
    0          
141             overload::constant
142 88     88   229 integer => sub { __PACKAGE__->new($_[0], 0) },
143 1     3   8 float => sub { __PACKAGE__->new($_[0], 0) };
  3         8  
144              
145             # Export the 'i' constant
146 1         43 foreach my $pair (['i', i()]) {
147 1         4 my $sub = $caller . '::' . $pair->[0];
148 3     3   2938 no strict 'refs';
  3         7  
  3         132  
149 3     3   18 no warnings 'redefine';
  3         4  
  3         265  
150 1         3 my $value = $pair->[1];
151 1     0   18 *$sub = sub () { $value };
  0         0  
152             }
153             }
154             elsif (exists $const{$name}) {
155 3     3   20 no strict 'refs';
  3         6  
  3         92  
156 3     3   15 no warnings 'redefine';
  3         14  
  3         322  
157 1         4 my $caller_sub = $caller . '::' . $name;
158 1         3 my $sub = $const{$name};
159 1         3 my $value = $sub->();
160 0     0   0 *$caller_sub = sub() { $value }
161 1         17 }
162             elsif ( exists($trig{$name})
163             or exists($special{$name})
164             or exists($misc{$name})) {
165 3     3   32 no strict 'refs';
  3         17  
  3         94  
166 3     3   39 no warnings 'redefine';
  3         7  
  3         20002  
167 37         68 my $caller_sub = $caller . '::' . $name;
168 37   66     211 *$caller_sub = $trig{$name} // $misc{$name} // $special{$name};
      33        
169             }
170             elsif ($name eq ':trig') {
171 1         17 push @_, keys(%trig);
172             }
173             elsif ($name eq ':misc') {
174 0         0 push @_, keys(%misc);
175             }
176             elsif ($name eq ':special') {
177 1         8 push @_, keys(%special);
178             }
179             elsif ($name eq ':all') {
180 0         0 push @_, keys(%const), keys(%trig), keys(%special), keys(%misc);
181             }
182             else {
183 0         0 die "unknown import: <<$name>>";
184             }
185             }
186 3         1086 return;
187             }
188              
189             sub unimport {
190 0     0   0 overload::remove_constant(float => '',
191             integer => '',);
192             }
193             }
194              
195             #
196             ## Be somewhat compatible with Math::Complex
197             #
198              
199             sub _cartesian {
200 0     0   0 my ($self) = @_;
201 0   0     0 $self->{cartesian} //= [$self->{a}, $self->{b}];
202             }
203              
204             sub _polar {
205 0     0   0 my ($self) = @_;
206 0   0     0 $self->{polar} //= [CORE::sqrt($self->{a} * $self->{a} + $self->{b} * $self->{b}), CORE::atan2($self->{b}, $self->{a})];
207             }
208              
209             #
210             ## Create a new Math::GComplex object
211             #
212              
213             sub new {
214 2907     2907 1 6159 my ($class, $x, $y) = @_;
215              
216 2907   50     17577 bless {
      100        
217             a => $x // 0,
218             b => $y // 0,
219             }, $class;
220             }
221              
222             *make = \&new;
223              
224             #
225             ## cplx(a, b) = a + b*i
226             #
227              
228             sub cplx {
229 0     0 1 0 my ($x, $y) = @_;
230              
231 0   0     0 bless {
      0        
232             a => $x // 0,
233             b => $y // 0,
234             },
235             __PACKAGE__;
236             }
237              
238             sub emake {
239 0     0 1 0 my ($class, $r, $theta) = @_;
240              
241 0   0     0 bless {
      0        
      0        
      0        
242             a => ($r // 0) * CORE::cos($theta // 0),
243             b => ($r // 0) * CORE::sin($theta // 0),
244             }, $class;
245             }
246              
247             #
248             ## cplxe(r, theta) = r*cos(theta) + r*sin(theta)*i
249             #
250              
251             sub cplxe {
252 0     0 1 0 my ($r, $theta) = @_;
253              
254 0   0     0 bless {
      0        
      0        
      0        
255             a => ($r // 0) * CORE::cos($theta // 0),
256             b => ($r // 0) * CORE::sin($theta // 0),
257             },
258             __PACKAGE__;
259             }
260              
261             #
262             ## i = sqrt(-1)
263             #
264              
265             sub i {
266 2     2 1 10 __PACKAGE__->new(0, 1);
267             }
268              
269             #
270             ## (a + b*i) + (x + y*i) = (a + x) + (b + y)*i
271             #
272              
273             sub add {
274 116     116 1 5563 my ($x, $y) = @_;
275              
276 116 50       246 $x = __PACKAGE__->new($x) if ref($x) ne __PACKAGE__;
277 116 100       242 $y = __PACKAGE__->new($y) if ref($y) ne __PACKAGE__;
278              
279 116         306 __PACKAGE__->new($x->{a} + $y->{a}, $x->{b} + $y->{b});
280             }
281              
282             #
283             ## (a + b*i) - (x + y*i) = (a - x) + (b - y)*i
284             #
285              
286             sub sub {
287 225     225 1 402 my ($x, $y) = @_;
288              
289 225 100       501 $x = __PACKAGE__->new($x) if ref($x) ne __PACKAGE__;
290 225 100       458 $y = __PACKAGE__->new($y) if ref($y) ne __PACKAGE__;
291              
292 225         628 __PACKAGE__->new($x->{a} - $y->{a}, $x->{b} - $y->{b});
293             }
294              
295             #
296             ## (a + b*i) * (x + y*i) = i*(a*y + b*x) + a*x - b*y
297             #
298              
299             sub mul {
300 271     271 1 4067 my ($x, $y) = @_;
301              
302 271 50       555 $x = __PACKAGE__->new($x) if ref($x) ne __PACKAGE__;
303 271 100       506 $y = __PACKAGE__->new($y) if ref($y) ne __PACKAGE__;
304              
305 271         875 __PACKAGE__->new($x->{a} * $y->{a} - $x->{b} * $y->{b}, $x->{a} * $y->{b} + $x->{b} * $y->{a});
306             }
307              
308             #
309             ## (a + b*i) / (x + y*i) = (a*x + b*y)/(x*x + y*y) + (b*x - a*y)/(x*x + y*y) * i
310             #
311              
312             sub div {
313 357     357 1 627 my ($x, $y) = @_;
314              
315 357 100       715 $x = __PACKAGE__->new($x) if ref($x) ne __PACKAGE__;
316 357 100       672 $y = __PACKAGE__->new($y) if ref($y) ne __PACKAGE__;
317              
318 357         735 my $d = $y->{a} * $y->{a} + $y->{b} * $y->{b};
319              
320 357 50       692 if ($d == 0) {
321 0         0 return $x->log->sub($y->log)->exp;
322             }
323              
324 357         1123 __PACKAGE__->new(($x->{a} * $y->{a} + $x->{b} * $y->{b}) / $d, ($x->{b} * $y->{a} - $x->{a} * $y->{b}) / $d);
325             }
326              
327             #
328             ## mod(x, y) = x - y*floor(x/y)
329             #
330              
331             sub mod {
332 0     0 1 0 my ($x, $y) = @_;
333              
334 0 0       0 $x = __PACKAGE__->new($x) if ref($x) ne __PACKAGE__;
335 0 0       0 $y = __PACKAGE__->new($y) if ref($y) ne __PACKAGE__;
336              
337 0         0 $x->sub($x->div($y)->floor->mul($y));
338             }
339              
340             #
341             ## inv(x) = 1/x
342             #
343              
344             sub inv ($) {
345 37     37 1 75 my ($x) = @_;
346              
347 37 50       86 $x = __PACKAGE__->new($x) if ref($x) ne __PACKAGE__;
348              
349 37         56 state $one = __PACKAGE__->new(1, 0);
350              
351 37         81 $one->div($x);
352             }
353              
354             #
355             ## abs(a + b*i) = sqrt(a^2 + b^2)
356             #
357              
358             sub abs {
359 184     184 1 361 my ($x) = @_;
360              
361 184 50       388 $x = __PACKAGE__->new($x) if ref($x) ne __PACKAGE__;
362              
363 184         634 CORE::sqrt($x->{a} * $x->{a} + $x->{b} * $x->{b});
364             }
365              
366             #
367             ## sgn(a + b*i) = (a + b*i) / abs(a + b*i)
368             #
369              
370             sub sgn ($) {
371 0     0 1 0 my ($x) = @_;
372              
373 0 0       0 $x = __PACKAGE__->new($x) if ref($x) ne __PACKAGE__;
374              
375 0 0 0     0 if ($x->{a} == 0 and $x->{b} == 0) {
376 0         0 return __PACKAGE__->new(0, 0);
377             }
378              
379 0         0 $x->div($x->abs);
380             }
381              
382             #
383             ## neg(a + b*i) = -a - b*i
384             #
385              
386             sub neg {
387 35     35 1 84 my ($x) = @_;
388              
389 35 50       90 $x = __PACKAGE__->new($x) if ref($x) ne __PACKAGE__;
390              
391 35         92 __PACKAGE__->new(-$x->{a}, -$x->{b});
392             }
393              
394             #
395             ## conj(a + b*i) = a - b*i
396             #
397              
398             sub conj ($) {
399 0     0 1 0 my ($x) = @_;
400              
401 0 0       0 $x = __PACKAGE__->new($x) if ref($x) ne __PACKAGE__;
402              
403 0         0 __PACKAGE__->new($x->{a}, -$x->{b});
404             }
405              
406             #
407             ## norm(a + b*i) = a**2 + b**2
408             #
409              
410             sub norm ($) {
411 0     0 1 0 my ($x) = @_;
412              
413 0 0       0 $x = __PACKAGE__->new($x) if ref($x) ne __PACKAGE__;
414              
415 0         0 $x->{a} * $x->{a} + $x->{b} * $x->{b};
416             }
417              
418             #
419             ## (a+b*i) AND (x+y*i) = (a AND x) + (b AND y)*i
420             #
421              
422             sub and {
423 1     1 1 4 my ($x, $y) = @_;
424              
425 1 50       5 $x = __PACKAGE__->new($x) if ref($x) ne __PACKAGE__;
426 1 50       4 $y = __PACKAGE__->new($y) if ref($y) ne __PACKAGE__;
427              
428 1         7 __PACKAGE__->new($x->{a} & $y->{a}, $x->{b} & $y->{b});
429             }
430              
431             #
432             ## (a+b*i) OR (x+y*i) = (a OR x) + (b OR y)*i
433             #
434              
435             sub or {
436 1     1 1 3 my ($x, $y) = @_;
437              
438 1 50       6 $x = __PACKAGE__->new($x) if ref($x) ne __PACKAGE__;
439 1 50       6 $y = __PACKAGE__->new($y) if ref($y) ne __PACKAGE__;
440              
441 1         5 __PACKAGE__->new($x->{a} | $y->{a}, $x->{b} | $y->{b});
442             }
443              
444             #
445             ## (a+b*i) XOR (x+y*i) = (a XOR x) + (b XOR y)*i
446             #
447              
448             sub xor {
449 1     1 1 5 my ($x, $y) = @_;
450              
451 1 50       6 $x = __PACKAGE__->new($x) if ref($x) ne __PACKAGE__;
452 1 50       4 $y = __PACKAGE__->new($y) if ref($y) ne __PACKAGE__;
453              
454 1         5 __PACKAGE__->new($x->{a} ^ $y->{a}, $x->{b} ^ $y->{b});
455             }
456              
457             #
458             ## (a+b*i) << n = (a << n) + (b << n)*i
459             ## (a+b*i) << (x+y*i) = int((a+b*i) * 2^(x+y*i))
460             #
461              
462             sub lsft {
463 1     1 1 4 my ($x, $y) = @_;
464              
465 1 50       6 $x = __PACKAGE__->new($x) if ref($x) ne __PACKAGE__;
466 1 50       5 $y = __PACKAGE__->new($y) if ref($y) ne __PACKAGE__;
467              
468 1 50       4 if ($y->{b} == 0) {
469 1         6 return __PACKAGE__->new($x->{a} << $y->{a}, $x->{b} << $y->{a});
470             }
471              
472 0         0 state $two = __PACKAGE__->new(2, 0);
473 0         0 $x->mul($two->pow($y))->int;
474             }
475              
476             #
477             ## (a+b*i) >> n = (a >> n) + (b >> n)*i
478             ## (a+b*i) >> (x+y*i) = int((a+b*i) / 2^(x+y*i))
479             #
480              
481             sub rsft {
482 1     1 1 305 my ($x, $y) = @_;
483              
484 1 50       6 $x = __PACKAGE__->new($x) if ref($x) ne __PACKAGE__;
485 1 50       5 $y = __PACKAGE__->new($y) if ref($y) ne __PACKAGE__;
486              
487 1 50       4 if ($y->{b} == 0) {
488 1         7 return __PACKAGE__->new($x->{a} >> $y->{a}, $x->{b} >> $y->{a});
489             }
490              
491 0         0 state $two = __PACKAGE__->new(2, 0);
492 0         0 $x->div($two->pow($y))->int;
493             }
494              
495             #
496             ## log(a + b*i) = log(a^2 + b^2)/2 + atan2(b, a)*i -- where a,b are real
497             #
498              
499             sub log {
500 409     409 1 645 my ($x) = @_;
501              
502 409 50       769 $x = __PACKAGE__->new($x) if ref($x) ne __PACKAGE__;
503              
504 409         792 my $t = $x->{a} * $x->{a} + $x->{b} * $x->{b};
505              
506 409 50 66     1273 if (!ref($t) and $t == 0) {
507 0         0 return __PACKAGE__->new(0 + '-Inf', 0);
508             }
509              
510 409         1378 __PACKAGE__->new(CORE::log($t) / 2, CORE::atan2($x->{b}, $x->{a}));
511             }
512              
513             #
514             ## logn(x, n) = log(x) / log(n)
515             #
516              
517             sub logn ($$) {
518 3     3 1 11 my ($x, $n) = @_;
519              
520 3 50       11 $x = __PACKAGE__->new($x) if ref($x) ne __PACKAGE__;
521 3 50       12 $n = __PACKAGE__->new($n) if ref($n) ne __PACKAGE__;
522              
523 3         10 $x->log->div($n->log);
524             }
525              
526             #
527             ## exp(a + b*i) = exp(a)*cos(b) + exp(a)*sin(b)*i
528             #
529              
530             sub exp {
531 486     486 1 763 my ($x) = @_;
532              
533 486 50       971 $x = __PACKAGE__->new($x) if ref($x) ne __PACKAGE__;
534              
535 486         963 my $exp = CORE::exp($x->{a});
536              
537 486         1460 __PACKAGE__->new($exp * CORE::cos($x->{b}), $exp * CORE::sin($x->{b}));
538             }
539              
540             #
541             ## x^y = exp(log(x) * y)
542             #
543              
544             sub pow {
545 108     108 1 221 my ($x, $y) = @_;
546              
547 108 100       236 $x = __PACKAGE__->new($x) if ref($x) ne __PACKAGE__;
548 108 100       230 $y = __PACKAGE__->new($y) if ref($y) ne __PACKAGE__;
549              
550 108 50 66     285 if ($x->{a} == 0 and $x->{b} == 0) {
551              
552 0 0       0 if ($y->{a} < 0) {
553 0         0 return $x->inv;
554             }
555              
556 0 0 0     0 if ($y->{a} == 0 and $y->{b} == 0) {
557 0         0 return __PACKAGE__->new($x->{a} + 1, $x->{b});
558             }
559              
560 0         0 return $x;
561             }
562              
563 108         192 $x->log->mul($y)->exp;
564             }
565              
566             sub pown ($$) {
567 17     17 1 550 my ($x, $y) = @_;
568              
569 17 50       44 $x = __PACKAGE__->new($x) if ref($x) ne __PACKAGE__;
570              
571 17         42 $y = CORE::int($y);
572 17         38 my $neg = $y < 0;
573 17         38 $y = CORE::int(CORE::abs($y));
574              
575 17 100 100     74 if ($x->{a} == 0 and $x->{b} == 0) {
576              
577 2 50       6 if ($neg) {
578 0         0 return $x->inv;
579             }
580              
581 2 100       6 if ($y == 0) {
582 1         6 return __PACKAGE__->new($x->{a} + 1, $x->{b});
583             }
584              
585 1         5 return $x;
586             }
587              
588 15         28 my ($rx, $ry) = (1, 0);
589 15         21 my ($ax, $bx) = (@{$x}{qw(a b)});
  15         34  
590              
591 15         22 while (1) {
592 42 100       94 ($rx, $ry) = ($rx * $ax - $ry * $bx, $rx * $bx + $ry * $ax) if ($y & 1);
593 42 100       81 ($y >>= 1) or last;
594 27         46 ($ax, $bx) = ($ax * $ax - $bx * $bx, $ax * $bx + $bx * $ax);
595             }
596              
597 15         31 my $res = __PACKAGE__->new($rx, $ry);
598 15 100       64 $neg ? $res->inv : $res;
599             }
600              
601             #
602             ## root(x, y) = exp(log(x) / y)
603             #
604              
605             sub root ($$) {
606 3     3 1 10 my ($x, $y) = @_;
607              
608 3 50       10 $x = __PACKAGE__->new($x) if ref($x) ne __PACKAGE__;
609 3 50       12 $y = __PACKAGE__->new($y) if ref($y) ne __PACKAGE__;
610              
611 3         20 $x->pow($y->inv);
612             }
613              
614             #
615             ## sqrt(a + b*i) = exp(log(a + b*i) / 2)
616             #
617              
618             sub sqrt {
619 133     133 1 248 my ($x) = @_;
620              
621 133 50       266 $x = __PACKAGE__->new($x) if ref($x) ne __PACKAGE__;
622              
623 133         263 my $r = $x->log;
624              
625 133         254 $r->{a} /= 2;
626 133         184 $r->{b} /= 2;
627              
628 133         239 $r->exp;
629             }
630              
631             #
632             ## cbrt(a + b*i) = exp(log(a + b*i) / 3)
633             #
634              
635             sub cbrt ($) {
636 6     6 1 1928 my ($x) = @_;
637              
638 6 50       20 $x = __PACKAGE__->new($x) if ref($x) ne __PACKAGE__;
639              
640 6 50 33     24 if ($x->{a} == 0 and $x->{b} == 0) {
641 0         0 return __PACKAGE__->new(0, 0);
642             }
643              
644 6         17 my $r = $x->log;
645              
646 6         16 $r->{a} /= 3;
647 6         10 $r->{b} /= 3;
648              
649 6         16 $r->exp;
650             }
651              
652             #
653             ## int(a + b*i) = int(a) + int(b)*i
654             #
655              
656             sub int {
657 16     16 1 27 my ($x) = @_;
658              
659 16 50       39 $x = __PACKAGE__->new($x) if ref($x) ne __PACKAGE__;
660              
661 16         29 my $t1 = CORE::int($x->{a});
662 16         25 my $t2 = CORE::int($x->{b});
663              
664 16         33 __PACKAGE__->new($t1, $t2);
665             }
666              
667             #
668             ## floor(a + b*i) = floor(a) + floor(b)*i
669             #
670              
671             sub floor ($) {
672 0     0 1 0 my ($x) = @_;
673              
674 0 0       0 $x = __PACKAGE__->new($x) if ref($x) ne __PACKAGE__;
675              
676 0         0 my $t1 = CORE::int($x->{a});
677 0 0 0     0 $t1 -= 1 if ($x->{a} != $t1 and $x->{a} < 0);
678              
679 0         0 my $t2 = CORE::int($x->{b});
680 0 0 0     0 $t2 -= 1 if ($x->{b} != $t2 and $x->{b} < 0);
681              
682 0         0 __PACKAGE__->new($t1, $t2);
683             }
684              
685             #
686             ## ceil(a + b*i) = -floor(-(a + b*i))
687             #
688              
689             sub ceil ($) {
690 0     0 1 0 my ($x) = @_;
691              
692 0 0       0 $x = __PACKAGE__->new($x) if ref($x) ne __PACKAGE__;
693              
694 0         0 my $t = $x->neg->floor;
695              
696 0         0 $t->{a} = -$t->{a};
697 0         0 $t->{b} = -$t->{b};
698              
699 0         0 $t;
700             }
701              
702             ########################################################################
703             # SIN / SINH / ASIN / ASINH
704             ########################################################################
705              
706             #
707             ## sin(a + b*i) = i*(exp(b - i*a) - exp(-b + i*a))/2
708             #
709              
710             sub sin {
711 11     11 1 28 my ($x) = @_;
712              
713 11 100       57 $x = __PACKAGE__->new($x) if ref($x) ne __PACKAGE__;
714              
715 11         86 my $t1 = __PACKAGE__->new(+$x->{b}, -$x->{a})->exp;
716 11         86 my $t2 = __PACKAGE__->new(-$x->{b}, +$x->{a})->exp;
717              
718 11         31 $t1->{a} -= $t2->{a};
719 11         26 $t1->{b} -= $t2->{b};
720              
721 11         25 $t1->{a} /= 2;
722 11         48 $t1->{b} /= 2;
723              
724 11         45 @{$t1}{qw(a b)} = (-$t1->{b}, $t1->{a});
  11         28  
725              
726 11         75 $t1;
727             }
728              
729             #
730             ## sinh(a + b*i) = (exp(2 * (a + b*i)) - 1) / (2*exp(a + b*i))
731             #
732              
733             sub sinh ($) {
734 13     13 1 536 my ($x) = @_;
735              
736 13 100       45 $x = __PACKAGE__->new($x) if ref($x) ne __PACKAGE__;
737              
738 13         46 my $t1 = __PACKAGE__->new($x->{a} * 2, $x->{b} * 2)->exp;
739              
740 13         36 $t1->{a} -= 1;
741              
742 13         25 my $t2 = $x->exp;
743              
744 13         29 $t2->{a} *= 2;
745 13         22 $t2->{b} *= 2;
746              
747 13         29 $t1->div($t2);
748             }
749              
750             #
751             ## asin(a + b*i) = -i*log(sqrt(1 - (a + b*i)^2) + i*a - b)
752             #
753              
754             sub asin ($) {
755 12     12 1 305 my ($x) = @_;
756              
757 12 100       39 $x = __PACKAGE__->new($x) if ref($x) ne __PACKAGE__;
758              
759 12         64 my $r = __PACKAGE__->new(1 - ($x->{a} * $x->{a} - $x->{b} * $x->{b}), -($x->{a} * $x->{b} + $x->{b} * $x->{a}))->sqrt;
760              
761 12         29 $r->{a} -= $x->{b};
762 12         21 $r->{b} += $x->{a};
763              
764 12         23 $r = $r->log;
765 12         45 @{$r}{qw(a b)} = ($r->{b}, -$r->{a});
  12         24  
766 12         46 $r;
767             }
768              
769             #
770             ## asinh(a + b*i) = log(sqrt((a + b*i)^2 + 1) + (a + b*i))
771             #
772              
773             sub asinh ($) {
774 12     12 1 337 my ($x) = @_;
775              
776 12 100       40 $x = __PACKAGE__->new($x) if ref($x) ne __PACKAGE__;
777              
778 12         56 my $r = __PACKAGE__->new($x->{a} * $x->{a} - $x->{b} * $x->{b} + 1, $x->{a} * $x->{b} + $x->{b} * $x->{a})->sqrt;
779              
780 12         30 $r->{a} += $x->{a};
781 12         18 $r->{b} += $x->{b};
782              
783 12         24 $r->log;
784             }
785              
786             ########################################################################
787             # COS / COSH / ACOS / ACOSH
788             ########################################################################
789              
790             #
791             ## cos(a + b*i) = (exp(-b + i*a) + exp(b - i*a))/2
792             #
793              
794             sub cos {
795 20     20 1 51 my ($x) = @_;
796              
797 20 100       59 $x = __PACKAGE__->new($x) if ref($x) ne __PACKAGE__;
798              
799 20         84 my $t1 = __PACKAGE__->new(-$x->{b}, +$x->{a})->exp;
800 20         68 my $t2 = __PACKAGE__->new(+$x->{b}, -$x->{a})->exp;
801              
802 20         53 $t1->{a} += $t2->{a};
803 20         33 $t1->{b} += $t2->{b};
804              
805 20         34 $t1->{a} /= 2;
806 20         38 $t1->{b} /= 2;
807              
808 20         60 $t1;
809             }
810              
811             #
812             ## cosh(a + b*i) = (exp(2 * (a + b*i)) + 1) / (2*exp(a + b*i))
813             #
814              
815             sub cosh ($) {
816 21     21 1 810 my ($x) = @_;
817              
818 21 100       60 $x = __PACKAGE__->new($x) if ref($x) ne __PACKAGE__;
819              
820 21         64 my $t1 = __PACKAGE__->new($x->{a} * 2, $x->{b} * 2)->exp;
821              
822 21         49 $t1->{a} += 1;
823              
824 21         48 my $t2 = $x->exp;
825              
826 21         43 $t2->{a} *= 2;
827 21         33 $t2->{b} *= 2;
828              
829 21         40 $t1->div($t2);
830             }
831              
832             #
833             ## acos(a + b*i) = -2*i*log(i*sqrt((1 - (a + b*i))/2) + sqrt((1 + (a + b*i))/2))
834             #
835              
836             sub acos ($) {
837 20     20 1 4086 my ($x) = @_;
838              
839 20 50       60 $x = __PACKAGE__->new($x) if ref($x) ne __PACKAGE__;
840              
841 20         76 my $t1 = __PACKAGE__->new((1 - $x->{a}) / 2, $x->{b} / -2)->sqrt;
842 20         80 my $t2 = __PACKAGE__->new((1 + $x->{a}) / 2, $x->{b} / +2)->sqrt;
843              
844 20         53 @{$t1}{qw(a b)} = (-$t1->{b}, $t1->{a});
  20         46  
845              
846 20         42 $t1->{a} += $t2->{a};
847 20         33 $t1->{b} += $t2->{b};
848              
849 20         38 my $r = $t1->log;
850              
851 20         42 $r->{a} *= -2;
852 20         29 $r->{b} *= -2;
853              
854 20         41 @{$r}{qw(a b)} = (-$r->{b}, $r->{a});
  20         37  
855              
856 20         77 $r;
857             }
858              
859             #
860             ## acosh(a + b*i) = log((a + b*i) + sqrt((a + b*i) - 1) * sqrt((a + b*i) + 1))
861             #
862              
863             sub acosh ($) {
864 10     10 1 21 my ($x) = @_;
865              
866 10 50       49 $x = __PACKAGE__->new($x) if ref($x) ne __PACKAGE__;
867              
868 10         36 my $t1 = __PACKAGE__->new($x->{a} - 1, $x->{b})->sqrt;
869 10         33 my $t2 = __PACKAGE__->new($x->{a} + 1, $x->{b})->sqrt;
870              
871 10         32 my $t3 = $t1->mul($t2);
872              
873 10         22 $t3->{a} += $x->{a};
874 10         16 $t3->{b} += $x->{b};
875              
876 10         16 $t3->log;
877             }
878              
879             ########################################################################
880             # TAN / TANH / ATAN / ATANH
881             ########################################################################
882              
883             #
884             ## tan(a + b*i) = (2*i)/(exp(2*i*(a + b*i)) + 1) - i
885             #
886              
887             sub tan ($) {
888 10     10 1 1157 my ($x) = @_;
889              
890 10 100       38 $x = __PACKAGE__->new($x) if ref($x) ne __PACKAGE__;
891              
892 10         45 my $r = __PACKAGE__->new(-2 * $x->{b}, 2 * $x->{a})->exp;
893              
894 10         28 $r->{a} += 1;
895              
896 10         30 my $den = $r->{a} * $r->{a} + $r->{b} * $r->{b};
897              
898 10         17 $r->{a} *= 2;
899 10         15 $r->{b} *= 2;
900              
901 10 50 33     51 if (!ref($den) and $den == 0) {
902 0         0 $r = $r->div($den);
903             }
904             else {
905 10         19 $r->{a} /= $den;
906 10         19 $r->{b} /= $den;
907             }
908              
909 10         18 $r->{a} -= 1;
910              
911 10         22 @{$r}{qw(a b)} = ($r->{b}, $r->{a});
  10         22  
912              
913 10         52 $r;
914             }
915              
916             #
917             ## tanh(a + b*i) = (exp(2 * (a + b*i)) - 1) / (exp(2 * (a + b*i)) + 1)
918             #
919              
920             sub tanh ($) {
921 13     13 1 854 my ($x) = @_;
922              
923 13 100       44 $x = __PACKAGE__->new($x) if ref($x) ne __PACKAGE__;
924              
925 13         47 my $t1 = __PACKAGE__->new($x->{a} * 2, $x->{b} * 2)->exp;
926              
927 13         45 my $t2 = __PACKAGE__->new($t1->{a} - 1, $t1->{b});
928 13         35 my $t3 = __PACKAGE__->new($t1->{a} + 1, $t1->{b});
929              
930 13         31 $t2->div($t3);
931             }
932              
933             #
934             ## atan(a + b*i) = i * (log(1 - i*(a + b*i)) - log(1 + i*(a + b*i))) / 2
935             #
936              
937             sub atan ($) {
938 16     16 1 305 my ($x) = @_;
939              
940 16 100       42 $x = __PACKAGE__->new($x) if ref($x) ne __PACKAGE__;
941              
942 16         52 my $t1 = __PACKAGE__->new(+$x->{b} + 1, -$x->{a})->log;
943 16         106 my $t2 = __PACKAGE__->new(-$x->{b} + 1, +$x->{a})->log;
944              
945 16         42 $t1->{a} -= $t2->{a};
946 16         25 $t1->{b} -= $t2->{b};
947              
948 16         28 $t1->{a} /= 2;
949 16         23 $t1->{b} /= 2;
950              
951 16         38 @{$t1}{qw(a b)} = (-$t1->{b}, $t1->{a});
  16         32  
952              
953 16         61 $t1;
954             }
955              
956             #
957             ## atan2(a, b) = -i * log((b + a*i) / sqrt(a^2 + b^2))
958             #
959              
960             sub atan2 {
961 9     9 1 23 my ($x, $y) = @_;
962              
963 9 100       36 $x = __PACKAGE__->new($x) if ref($x) ne __PACKAGE__;
964 9 100       30 $y = __PACKAGE__->new($y) if ref($y) ne __PACKAGE__;
965              
966 9         30 my $t = __PACKAGE__->new($y->{a} - $x->{b}, $x->{a} + $y->{b});
967              
968 9         47 $t = $t->div($x->mul($x)->add($y->mul($y))->sqrt)->log;
969              
970 9         41 @{$t}{qw(a b)} = ($t->{b}, -$t->{a});
  9         21  
971              
972 9         150 $t;
973             }
974              
975             #
976             ## atanh(a + b*i) = (log(1 + (a + b*i)) - log(1 - (a + b*i))) / 2
977             #
978              
979             sub atanh ($) {
980 14     14 1 328 my ($x) = @_;
981              
982 14 100       38 $x = __PACKAGE__->new($x) if ref($x) ne __PACKAGE__;
983              
984 14         42 my $t1 = __PACKAGE__->new(1 + $x->{a}, +$x->{b})->log;
985 14         53 my $t2 = __PACKAGE__->new(1 - $x->{a}, -$x->{b})->log;
986              
987 14         36 $t1->{a} -= $t2->{a};
988 14         28 $t1->{b} -= $t2->{b};
989              
990 14         19 $t1->{a} /= 2;
991 14         25 $t1->{b} /= 2;
992              
993 14         47 $t1;
994             }
995              
996             ########################################################################
997             # COT / COTH / ACOT / ACOTH
998             ########################################################################
999              
1000             #
1001             ## cot(a + b*i) = (2*i)/(exp(2*i*(a + b*i)) - 1) + i
1002             #
1003              
1004             sub cot ($) {
1005 6     6 1 558 my ($x) = @_;
1006              
1007 6 100       26 $x = __PACKAGE__->new($x) if ref($x) ne __PACKAGE__;
1008              
1009 6         27 my $r = __PACKAGE__->new(-2 * $x->{b}, 2 * $x->{a})->exp;
1010              
1011 6         60 $r->{a} -= 1;
1012              
1013 6         22 my $den = $r->{a} * $r->{a} + $r->{b} * $r->{b};
1014              
1015 6         13 $r->{a} *= 2;
1016 6         10 $r->{b} *= 2;
1017              
1018 6 50 33     32 if (!ref($den) and $den == 0) {
1019 0         0 $r = $r->div($den);
1020             }
1021             else {
1022 6         12 $r->{a} /= $den;
1023 6         11 $r->{b} /= $den;
1024             }
1025              
1026 6         12 $r->{a} += 1;
1027              
1028 6         16 @{$r}{qw(a b)} = ($r->{b}, $r->{a});
  6         13  
1029              
1030 6         23 $r;
1031             }
1032              
1033             #
1034             ## coth(a + b*i) = (exp(2 * (a + b*i)) + 1) / (exp(2 * (a + b*i)) - 1)
1035             #
1036              
1037             sub coth ($) {
1038 7     7 1 835 my ($x) = @_;
1039              
1040 7 100       40 $x = __PACKAGE__->new($x) if ref($x) ne __PACKAGE__;
1041              
1042 7         33 my $t1 = __PACKAGE__->new($x->{a} * 2, $x->{b} * 2)->exp;
1043              
1044 7         31 my $t2 = __PACKAGE__->new($t1->{a} + 1, $t1->{b});
1045 7         26 my $t3 = __PACKAGE__->new($t1->{a} - 1, $t1->{b});
1046              
1047 7         20 $t2->div($t3);
1048             }
1049              
1050             #
1051             ## acot(a + b*i) = atan(1/(a + b*i))
1052             #
1053              
1054             sub acot ($) {
1055 8     8 1 278 my ($x) = @_;
1056              
1057 8 100       31 $x = __PACKAGE__->new($x) if ref($x) ne __PACKAGE__;
1058              
1059 8         19 $x->inv->atan;
1060             }
1061              
1062             #
1063             ## acoth(a + b*i) = atanh(1 / (a + b*i))
1064             #
1065              
1066             sub acoth ($) {
1067 7     7 1 312 my ($x) = @_;
1068              
1069 7 100       27 $x = __PACKAGE__->new($x) if ref($x) ne __PACKAGE__;
1070              
1071 7         18 $x->inv->atanh;
1072             }
1073              
1074             ########################################################################
1075             # SEC / SECH / ASEC / ASECH
1076             ########################################################################
1077              
1078             #
1079             ## sec(a + b*i) = 2/(exp(-i*(a + b*i)) + exp(i*(a + b*i)))
1080             #
1081              
1082             sub sec ($) {
1083 5     5 1 548 my ($x) = @_;
1084              
1085 5 100       26 $x = __PACKAGE__->new($x) if ref($x) ne __PACKAGE__;
1086              
1087 5         27 my $t1 = __PACKAGE__->new(+$x->{b}, -$x->{a})->exp;
1088 5         23 my $t2 = __PACKAGE__->new(-$x->{b}, +$x->{a})->exp;
1089              
1090 5         16 $t1->{a} += $t2->{a};
1091 5         11 $t1->{b} += $t2->{b};
1092              
1093 5         20 my $den = $t1->{a} * $t1->{a} + $t1->{b} * $t1->{b};
1094              
1095 5         10 $t1->{a} *= +2;
1096 5         12 $t1->{b} *= -2;
1097              
1098 5 50 33     31 if (!ref($den) and $den == 0) {
1099 0         0 $t1 = $t1->div($den);
1100             }
1101             else {
1102 5         10 $t1->{a} /= $den;
1103 5         12 $t1->{b} /= $den;
1104             }
1105              
1106 5         21 $t1;
1107             }
1108              
1109             #
1110             ## sech(a + b*i) = (2 * exp(a + b*i)) / (exp(2 * (a + b*i)) + 1)
1111             #
1112              
1113             sub sech ($) {
1114 7     7 1 1168 my ($x) = @_;
1115              
1116 7 100       33 $x = __PACKAGE__->new($x) if ref($x) ne __PACKAGE__;
1117              
1118 7         24 my $t1 = $x->exp;
1119 7         25 my $t2 = __PACKAGE__->new($x->{a} * 2, $x->{b} * 2)->exp;
1120              
1121 7         21 $t1->{a} *= 2;
1122 7         14 $t1->{b} *= 2;
1123              
1124 7         13 $t2->{a} += 1;
1125              
1126 7         15 $t1->div($t2);
1127             }
1128              
1129             #
1130             ## asec(a + b*i) = acos(1/(a + b*i))
1131             #
1132              
1133             sub asec ($) {
1134 4     4 1 13 my ($x) = @_;
1135              
1136 4 50       14 $x = __PACKAGE__->new($x) if ref($x) ne __PACKAGE__;
1137              
1138 4         14 $x->inv->acos;
1139             }
1140              
1141             #
1142             ## asech(a + b*i) = acosh(1/(a + b*i))
1143             #
1144              
1145             sub asech ($) {
1146 4     4 1 290 my ($x) = @_;
1147              
1148 4 100       20 $x = __PACKAGE__->new($x) if ref($x) ne __PACKAGE__;
1149              
1150 4         13 $x->inv->acosh;
1151             }
1152              
1153             ########################################################################
1154             # CSC / CSCH / ACSC / ACSCH
1155             ########################################################################
1156              
1157             #
1158             ## csc(a + b*i) = -(2*i)/(exp(-i * (a + b*i)) - exp(i * (a + b*i)))
1159             #
1160              
1161             sub csc ($) {
1162 5     5 1 551 my ($x) = @_;
1163              
1164 5 100       29 $x = __PACKAGE__->new($x) if ref($x) ne __PACKAGE__;
1165              
1166 5         23 my $t1 = __PACKAGE__->new(+$x->{b}, -$x->{a})->exp;
1167 5         24 my $t2 = __PACKAGE__->new(-$x->{b}, +$x->{a})->exp;
1168              
1169 5         17 $t1->{a} -= $t2->{a};
1170 5         11 $t1->{b} -= $t2->{b};
1171              
1172 5         16 my $den = $t1->{a} * $t1->{a} + $t1->{b} * $t1->{b};
1173              
1174 5         11 $t1->{a} *= -2;
1175 5         9 $t1->{b} *= -2;
1176              
1177 5 50 33     31 if (!ref($den) and $den == 0) {
1178 0         0 $t1 = $t1->div($den);
1179             }
1180             else {
1181 5         11 $t1->{a} /= $den;
1182 5         10 $t1->{b} /= $den;
1183             }
1184              
1185 5         15 @{$t1}{qw(a b)} = ($t1->{b}, $t1->{a});
  5         14  
1186              
1187 5         22 $t1;
1188             }
1189              
1190             #
1191             ## csch(a + b*i) = (2*exp(a + b*i)) / (exp(2 * (a + b*i)) - 1)
1192             #
1193              
1194             sub csch ($) {
1195 7     7 1 816 my ($x) = @_;
1196              
1197 7 100       32 $x = __PACKAGE__->new($x) if ref($x) ne __PACKAGE__;
1198              
1199 7         20 my $t1 = $x->exp;
1200 7         28 my $t2 = __PACKAGE__->new($x->{a} * 2, $x->{b} * 2)->exp;
1201              
1202 7         21 $t1->{a} *= 2;
1203 7         13 $t1->{b} *= 2;
1204              
1205 7         15 $t2->{a} -= 1;
1206              
1207 7         16 $t1->div($t2);
1208             }
1209              
1210             #
1211             ## acsc(a + b*i) = asin(1/(a + b*i))
1212             #
1213              
1214             sub acsc ($) {
1215 4     4 1 9 my ($x) = @_;
1216              
1217 4 50       14 $x = __PACKAGE__->new($x) if ref($x) ne __PACKAGE__;
1218              
1219 4         16 $x->inv->asin;
1220             }
1221              
1222             #
1223             ## acsch(a + b*i) = asinh(1/(a + b*i))
1224             #
1225              
1226             sub acsch ($) {
1227 5     5 1 579 my ($x) = @_;
1228              
1229 5 100       23 $x = __PACKAGE__->new($x) if ref($x) ne __PACKAGE__;
1230              
1231 5         16 $x->inv->asinh;
1232             }
1233              
1234             #
1235             ## deg2rad(x) = x / 180 * atan2(0, -abs(x))
1236             #
1237              
1238             sub deg2rad ($) {
1239 7     7 1 845 my ($x) = @_;
1240              
1241 7 100       25 $x = __PACKAGE__->new($x) if ref($x) ne __PACKAGE__;
1242              
1243 7         24 my $t = __PACKAGE__->new($x->{a} / 180, $x->{b} / 180);
1244 7         26 my $pi = CORE::atan2(0, -($x->{a} * $x->{a} + $x->{b} * $x->{b}));
1245              
1246 7 50       16 if (!ref($pi)) {
1247 7         12 $t->{a} *= $pi;
1248 7         10 $t->{b} *= $pi;
1249 7         31 return $t;
1250             }
1251              
1252 0         0 $t->mul($pi);
1253             }
1254              
1255             #
1256             ## rad2deg(x) = x * 180 / atan2(0, -abs(x))
1257             #
1258              
1259             sub rad2deg ($) {
1260 7     7 1 295 my ($x) = @_;
1261              
1262 7 100       21 $x = __PACKAGE__->new($x) if ref($x) ne __PACKAGE__;
1263              
1264 7         32 my $r = __PACKAGE__->new($x->{a} * 180, $x->{b} * 180);
1265 7         20 my $t = $x->{a} * $x->{a} + $x->{b} * $x->{b};
1266              
1267 7 100       16 if ($t == 0) {
1268 3         14 return $r;
1269             }
1270              
1271 4         9 my $pi = CORE::atan2(0, -$t);
1272              
1273 4 50 33     20 if (!ref($pi) and $pi != 0) {
1274 4         6 $r->{a} /= $pi;
1275 4         8 $r->{b} /= $pi;
1276 4         16 return $r;
1277             }
1278              
1279 0         0 $r->div($pi);
1280             }
1281              
1282             ########################### MISC FUNCTIONS ###########################
1283              
1284             #
1285             ## real(a + b*i) = a
1286             #
1287              
1288             sub real ($) {
1289 14     14 1 48 my ($x) = @_;
1290              
1291 14 50       33 $x = __PACKAGE__->new($x) if ref($x) ne __PACKAGE__;
1292              
1293 14         65 $x->{a};
1294             }
1295              
1296             #
1297             ## imag(a + b*i) = b
1298             #
1299              
1300             sub imag ($) {
1301 14     14 1 30 my ($x) = @_;
1302              
1303 14 50       70 $x = __PACKAGE__->new($x) if ref($x) ne __PACKAGE__;
1304              
1305 14         54 $x->{b};
1306             }
1307              
1308             #
1309             ## reals(a + b*i) = (a, b)
1310             #
1311              
1312             sub reals ($) {
1313 1     1 1 613 my ($x) = @_;
1314              
1315 1 50       6 $x = __PACKAGE__->new($x) if ref($x) ne __PACKAGE__;
1316              
1317 1         5 ($x->{a}, $x->{b});
1318             }
1319              
1320             #
1321             ## Equality
1322             #
1323              
1324             sub eq {
1325 5     5 1 667 my ($x, $y) = @_;
1326              
1327 5 50       18 $x = __PACKAGE__->new($x) if ref($x) ne __PACKAGE__;
1328 5 50       20 $y = __PACKAGE__->new($y) if ref($y) ne __PACKAGE__;
1329              
1330             $x->{a} == $y->{a}
1331 5 100       70 and $x->{b} == $y->{b};
1332             }
1333              
1334             #
1335             ## Inequality
1336             #
1337              
1338             sub ne {
1339 0     0 1 0 my ($x, $y) = @_;
1340              
1341 0 0       0 $x = __PACKAGE__->new($x) if ref($x) ne __PACKAGE__;
1342 0 0       0 $y = __PACKAGE__->new($y) if ref($y) ne __PACKAGE__;
1343              
1344             $x->{a} != $y->{a}
1345 0 0       0 or $x->{b} != $y->{b};
1346             }
1347              
1348             #
1349             ## Comparisons
1350             #
1351              
1352             sub cmp {
1353 18     18 1 34 my ($x, $y) = @_;
1354              
1355 18 50       39 $x = __PACKAGE__->new($x) if ref($x) ne __PACKAGE__;
1356 18 50       38 $y = __PACKAGE__->new($y) if ref($y) ne __PACKAGE__;
1357              
1358             (($x->{a} <=> $y->{a}) // return undef)
1359 18 100 50     119 or (($x->{b} <=> $y->{b}) // return undef);
      50        
1360             }
1361              
1362             sub acmp ($$) {
1363 0     0 1 0 my ($x, $y) = @_;
1364              
1365 0 0       0 $x = __PACKAGE__->new($x) if ref($x) ne __PACKAGE__;
1366 0 0       0 $y = __PACKAGE__->new($y) if ref($y) ne __PACKAGE__;
1367              
1368 0         0 $x->abs <=> $y->abs;
1369             }
1370              
1371             sub lt {
1372 16     16 1 32 my ($x, $y) = @_;
1373              
1374 16 50       34 $x = __PACKAGE__->new($x) if ref($x) ne __PACKAGE__;
1375 16 50       40 $y = __PACKAGE__->new($y) if ref($y) ne __PACKAGE__;
1376              
1377 16   50     52 ($x->cmp($y) // return undef) < 0;
1378             }
1379              
1380             sub le {
1381 0     0 1 0 my ($x, $y) = @_;
1382              
1383 0 0       0 $x = __PACKAGE__->new($x) if ref($x) ne __PACKAGE__;
1384 0 0       0 $y = __PACKAGE__->new($y) if ref($y) ne __PACKAGE__;
1385              
1386 0   0     0 ($x->cmp($y) // return undef) <= 0;
1387             }
1388              
1389             sub gt {
1390 0     0 1 0 my ($x, $y) = @_;
1391              
1392 0 0       0 $x = __PACKAGE__->new($x) if ref($x) ne __PACKAGE__;
1393 0 0       0 $y = __PACKAGE__->new($y) if ref($y) ne __PACKAGE__;
1394              
1395 0   0     0 ($x->cmp($y) // return undef) > 0;
1396             }
1397              
1398             sub ge {
1399 2     2 1 5 my ($x, $y) = @_;
1400              
1401 2 50       7 $x = __PACKAGE__->new($x) if ref($x) ne __PACKAGE__;
1402 2 50       8 $y = __PACKAGE__->new($y) if ref($y) ne __PACKAGE__;
1403              
1404 2   50     8 ($x->cmp($y) // return undef) >= 0;
1405             }
1406              
1407             sub stringify {
1408 54     54 1 114 my ($x) = @_;
1409              
1410 54 50       165 $x = __PACKAGE__->new($x) if ref($x) ne __PACKAGE__;
1411              
1412 54         573 "($x->{a} $x->{b})";
1413             }
1414              
1415             sub boolify {
1416 194     194 1 848 my ($x) = @_;
1417              
1418 194 50       386 $x = __PACKAGE__->new($x) if ref($x) ne __PACKAGE__;
1419              
1420 194   33     863 !!$x->{a} or !!$x->{b};
1421             }
1422              
1423             sub numify {
1424 13     13 1 2644 my ($x) = @_;
1425              
1426 13 50       34 $x = __PACKAGE__->new($x) if ref($x) ne __PACKAGE__;
1427              
1428 13         41 $x->{a};
1429             }
1430              
1431             1; # End of Math::GComplex