PDLA-Core

 view release on metacpan or  search on metacpan

GENERATED/PDLA/Complex.pm  view on Meta::CPAN

   0 ##            ***              #              *               #      ++
     |                *              #             *              #        |
     |                 ***            #          **               #        |
     |                    *            #        *                #         |
  -5 ++                    **           #      *                 #        ++
     |                       ***         ##  **                 #          |
     |                          *          #*                  #           |
     |                           ****    ***##                #            |
 -10 ++                              ****     #              #            ++
     |                                         #             #             |
     |                                          ##         ##              |
     +      +      +      +      +      +      +  ### + ###  +      +      +
 -15 ++-----+------+------+------+------+------+-----###-----+------+-----++
     0      5      10     15     20     25     30     35     40     45     50


=head1 OPERATORS

The following operators are overloaded:

=over 4

=item +, += (addition)

=item -, -= (subtraction)

=item *, *= (multiplication; L<Cmul|/Cmul>)

=item /, /= (division; L<Cdiv|/Cdiv>)

=item **, **= (exponentiation; L<Cpow|/Cpow>)

=item atan2 (4-quadrant arc tangent)

=item <=> (nonsensical comparison operator; L<Ccmp|/Ccmp>)

=item sin (L<Csin|/Csin>)

=item cos (L<Ccos|/Ccos>)

=item exp (L<Cexp|/Cexp>)

=item abs (L<Cabs|/Cabs>)

=item log (L<Clog|/Clog>)

=item sqrt (L<Csqrt|/Csqrt>)

=item <, <=, ==, !=, >=, > (just as nonsensical as L<Ccmp|/Ccmp>)

=item ++, -- (increment, decrement; they affect the real part of the complex number only)

=item "" (stringification)

=back

=cut

my $i;
BEGIN { $i = bless pdl 0,1 }
sub i () { $i->copy };






=head1 FUNCTIONS



=cut





=head2 cplx

=for ref

Cast a real-valued piddle to the complex datatype.

The first dimension of the piddle must be of size 2. After this the
usual (complex) arithmetic operators are applied to this pdl, rather
than the normal elementwise pdl operators.  Dataflow to the complex
parent works. Use C<sever> on the result if you don't want this.

=for usage

 cplx($real_valued_pdl)

=head2 complex

=for ref

Cast a real-valued piddle to the complex datatype I<without> dataflow
and I<inplace>.

Achieved by merely reblessing a piddle. The first dimension of the
piddle must be of size 2.

=for usage

 complex($real_valued_pdl)

=head2 real

=for ref

Cast a complex valued pdl back to the "normal" pdl datatype.

Afterwards the normal elementwise pdl operators are used in
operations. Dataflow to the real parent works. Use C<sever> on the
result if you don't want this.

=for usage

 real($cplx_valued_pdl)

=cut

GENERATED/PDLA/Complex.pm  view on Meta::CPAN


Cproj does not process bad values.
It will set the bad-value flag of all output piddles if the flag is set for any of the input piddles.


=cut






BEGIN {*Cproj = \&PDLA::Complex::Cproj;
}




=head2 Croots

=for sig

  Signature: (a(m=2); [o]c(m=2,n); int n => n)

=for ref

Compute the C<n> roots of C<a>. C<n> must be a positive integer. The result will always be a complex type!

=for bad

Croots does not process bad values.
It will set the bad-value flag of all output piddles if the flag is set for any of the input piddles.


=cut




sub PDLA::Complex::Croots($$) {
           my ($pdl, $n) = @_;
           my $r = PDLA->null;
           &PDLA::Complex::_Croots_int($pdl, $r, $n);
           bless $r;
        }

BEGIN {*Croots = \&PDLA::Complex::Croots;
}



=head2 re, im

Return the real or imaginary part of the complex number(s) given.

These are slicing operators, so data flow works. The real and
imaginary parts are returned as piddles (ref eq PDLA).

=cut

sub re($) { bless $_[0]->slice("(0)"), 'PDLA'; }
sub im($) { bless $_[0]->slice("(1)"), 'PDLA'; }

*PDLA::Complex::re = \&re;
*PDLA::Complex::im = \&im;





=head2 rCpolynomial

=for sig

  Signature: (coeffs(n); x(c=2,m); [o]out(c=2,m))

=for ref

evaluate the polynomial with (real) coefficients C<coeffs> at the (complex) position(s) C<x>. C<coeffs[0]> is the constant term.

=for bad

rCpolynomial does not process bad values.
It will set the bad-value flag of all output piddles if the flag is set for any of the input piddles.


=cut





sub rCpolynomial {
    my $coeffs = shift;
    my $x = shift;
    my $out = $x->copy;
    _rCpolynomial_int($coeffs,$x,$out);
    return PDLA::complex($out);
    }


BEGIN {*rCpolynomial = \&PDLA::Complex::rCpolynomial;
}


;


# overload must be here, so that all the functions can be seen

# undocumented compatibility functions (thanks to Luis Mochan!)
sub Catan2($$) { Clog( $_[1] + i*$_[0])/i }
sub atan2($$) { Clog( $_[1] + i*$_[0])/i }


=begin comment

In _gen_biop, the '+' or '-' between the operator (e.g., '*') and the
function that it overloads (e.g., 'Cmul') flags whether the operation
is ('+') or is not ('-') commutative. See the discussion of argument
swapping in the section "Calling Conventions and Magic Autogeneration"
in "perldoc overload".

GENERATED/PDLA/Complex.pm  view on Meta::CPAN

      $sub = eval 'sub { my $y = ref $_[1] eq __PACKAGE__ ? $_[1] : r2C $_[1];
                       $_[2] ? '.$2.' $y, $_[0] : '.$2.' $_[0], $y }'; #need to swap?
   } else {
      die;
   }
   if($1 eq "atan2" || $1 eq "<=>") { return ($1, $sub) }
   ($1, $sub, "$1=", $sub);
}

sub _gen_unop {
   my ($op, $func) = ($_[0] =~ /(.+)@(\w+)/);
   *$op = \&$func if $op =~ /\w+/; # create an alias
   ($op, eval 'sub { '.$func.' $_[0] }');
}

#sub _gen_cpop {
#   ($_[0], eval 'sub { my $y = ref $_[1] eq __PACKAGE__ ? $_[1] : r2C $_[1];
#                 ($_[2] ? $y <=> $_[0] : $_[0] <=> $y) '.$_[0].' 0 }');
#}

sub initialize {
   # Bless a null PDLA into the supplied 1st arg package
   #   If 1st arg is a ref, get the package from it
   bless PDLA->null, ref($_[0]) ? ref($_[0]) : $_[0];
}

use overload
   (map _gen_biop($_), qw(++Cadd --Csub *+Cmul /-Cdiv **-Cpow atan2-Catan2 <=>-Ccmp)),
   (map _gen_unop($_), qw(sin@Csin cos@Ccos exp@Cexp abs@Cabs log@Clog sqrt@Csqrt)),
#   (map _gen_cpop($_), qw(< <= == != >= >)), #segfaults with infinite recursion of the operator.
#final ternary used to make result a scalar, not a PDLA:::Complex (thx CED!)
    "<" => sub { my $y = ref $_[1] eq __PACKAGE__ ? $_[1] : r2C $_[1];
		 PDLA::lt( ($_[2] ? $y <=> $_[0] : $_[0] <=> $y), 0, 0) ? 1 : 0;},
    "<=" => sub { my $y = ref $_[1] eq __PACKAGE__ ? $_[1] : r2C $_[1];
                 PDLA::le( ($_[2] ? $y <=> $_[0] : $_[0] <=> $y), 0, 0) ? 1 : 0;},
    "==" => sub { my $y = ref $_[1] eq __PACKAGE__ ? $_[1] : r2C $_[1];
                 PDLA::eq( ($_[2] ? $y <=> $_[0] : $_[0] <=> $y), 0, 0) ? 1 : 0;},
    "!=" => sub { my $y = ref $_[1] eq __PACKAGE__ ? $_[1] : r2C $_[1];
                 PDLA::ne( ($_[2] ? $y <=> $_[0] : $_[0] <=> $y), 0, 0) ? 1 : 0;},
    ">=" => sub { my $y = ref $_[1] eq __PACKAGE__ ? $_[1] : r2C $_[1];
                 PDLA::ge( ($_[2] ? $y <=> $_[0] : $_[0] <=> $y), 0, 0) ? 1 : 0;},
    ">" => sub { my $y = ref $_[1] eq __PACKAGE__ ? $_[1] : r2C $_[1];
                 PDLA::gt( ($_[2] ? $y <=> $_[0] : $_[0] <=> $y), 0, 0) ? 1 : 0;},
   '++' => sub { $_[0] += 1 },
   '--' => sub { $_[0] -= 1 },
   '""' => \&PDLA::Complex::string
;

# overwrite PDLA's overloading to honour subclass methods in + - * /
{ package PDLA;
        my $warningFlag;
        # This strange usage of BEGINs is to ensure the
        # warning messages get disabled and enabled in the
        # proper order. Without the BEGIN's the 'use overload'
        #  would be called first.
        BEGIN {$warningFlag = $^W; # Temporarily disable warnings caused by
               $^W = 0;            # redefining PDLA's subs
              }


sub cp(;@) {
	my $foo;
	if (ref $_[1]
		&& (ref $_[1] ne 'PDLA')
		&& defined ($foo = overload::Method($_[1],'+')))
		{ &$foo($_[1], $_[0], !$_[2])}
	else { PDLA::plus (@_)}
}

sub cm(;@) {
	my $foo;
	if (ref $_[1]
		&& (ref $_[1] ne 'PDLA')
		&& defined ($foo = overload::Method($_[1],'*')))
		{ &$foo($_[1], $_[0], !$_[2])}
	else { PDLA::mult (@_)}
}

sub cmi(;@) {
	my $foo;
	if (ref $_[1]
		&& (ref $_[1] ne 'PDLA')
		&& defined ($foo = overload::Method($_[1],'-')))
		{ &$foo($_[1], $_[0], !$_[2])}
	else { PDLA::minus (@_)}
}

sub cd(;@) {
	my $foo;
	if (ref $_[1]
		&& (ref $_[1] ne 'PDLA')
		&& defined ($foo = overload::Method($_[1],'/')))
		{ &$foo($_[1], $_[0], !$_[2])}
	else { PDLA::divide (@_)}
}


  # Used in overriding standard PDLA +, -, *, / ops in the complex subclass.
  use overload (
		 '+' => \&cp,
		 '*' => \&cm,
	         '-' => \&cmi,
		 '/' => \&cd,
		);



        BEGIN{ $^W = $warningFlag;} # Put Back Warnings
};


{

   our $floatformat  = "%4.4g";    # Default print format for long numbers
   our $doubleformat = "%6.6g";

   $PDLA::Complex::_STRINGIZING = 0;

   sub PDLA::Complex::string {
      my($self,$format1,$format2)=@_;
      my @dims = $self->dims;
      return PDLA::string($self) if ($dims[0] != 2);

      if($PDLA::Complex::_STRINGIZING) {
         return "ALREADY_STRINGIZING_NO_LOOPS";
      }
      local $PDLA::Complex::_STRINGIZING = 1;
      my $ndims = $self->getndims;
      if($self->nelem > $PDLA::toolongtoprint) {
         return "TOO LONG TO PRINT";
      }
      if ($ndims==0){
         PDLA::Core::string($self,$format1);
      }
      return "Null" if $self->isnull;
      return "Empty" if $self->isempty; # Empty piddle
      local $sep  = $PDLA::use_commas ? ", " : "  ";
      local $sep2 = $PDLA::use_commas ? ", " : "";
      if ($ndims < 3) {
         return str1D($self,$format1,$format2);
      }
      else{
         return strND($self,$format1,$format2,0);
      }
   }


   sub sum {



( run in 2.109 seconds using v1.01-cache-2.11-cpan-e1769b4cff6 )