On 2023-09-30 at 17:07:20 -0700, systemdl...@fastmail.com wrote:
> Could you provide an example of how to call the polyroots() function in
> PDL::Math?
> 
> In Math::Polynomial, I can solve the roots for something like 'x^3 - x^2
> + 4x + 4' by calling its routine:
> 
> my(@roots) = poly_roots(1,1,4,4);
> 
> which will return the roots of that equation in a perl list, @roots, above.
> 
> The polyroots() function in PDL::Math seems to want two piddles, if I am
> reading this correctly, one for reals and one for imaginaries.   But I
> don't understand how I would use it this way, or what I would be getting
> in the output from the function.

Hello,

Yes, that function takes separate ndarrays for the real and complex
parts of the polynomial coefficients then returns output in the same
form. PDL now has support for "native complex" floating point data types
which can be accessed via `cdouble` and `cfloat`.

  $ pdldoc cdouble
  $ pdldoc r2C

To help with going between the different representations (separate
ndarrays for real and imaginary or `cdouble`/`cfloat`), you should use
the following:

  $ pdldoc re
  $ pdldoc im
  $ pdldoc czip

Here's an example using what you gave:

  $ perl -E '
  use PDL;
  use PDL::Math;
  use Math::Polynomial::Solve qw(poly_roots coefficients);

  my @coeff = ( 1,1,4,4 );
  my $data = {
    pdl => do {
      my $p_coeff = cdouble(@coeff);
      czip( polyroots( $p_coeff->re, $p_coeff->im ) )
    },
    mps => do {
      coefficients order => 'descending';
      [ poly_roots( @coeff ) ]
    }
  };
  use DDP; p $data;
  '

which gives the output on my machine:

  ## {
  ##     mps   [
  ##         [0] 2.22044604925031e-16-2i (Math::Complex),
  ##         [1] 2.22044604925031e-16+2i (Math::Complex),
  ##         [2] -0.999999999999999
  ##     ],
  ##     pdl   PDL {
  ##         Data     : [-1+1.26217744835362e-29i 2i -2i]
  ##         Type     : complex double
  ##         Shape    : [3]
  ##         Nelem    : 3
  ##         Min      : -1
  ##         Max      : 0
  ##         Badflag  : No
  ##         Has Bads : No
  ##     }
  ## }

This is probably the easiest way to do this now.

Bonus: If you want to remove small values from each, you can:

   ```perl
   use PDL; use PDL::Math; use DDP; use feature qw(say);

   my $p_coeff = cdouble(1,1,4,4);
   my $roots = czip( polyroots( $p_coeff->re, $p_coeff->im ) );
   my $eps = 1e-26;

   # set small values to zero
   $roots->$_->where( $roots->$_->abs < $eps ) .= 0 for qw(re im);

   say $roots;
   # [-1 2i -2i]
   ```

Hope that helps! I'll see what I can do for the documentation, but if
you would like to add some POD based on this, that would be very much
appreciated.

Cheers,
- Zaki Mughal

> 
> Maybe you can use my simple example above since my use case will
> unlikely need much more complexity than that, although there may be many
> more terms.
> 
> Thanks if you could, and maybe add your example(s) to the man page for
> PDL::Math?


> _______________________________________________
> pdl-general mailing list
> pdl-general@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/pdl-general



_______________________________________________
pdl-general mailing list
pdl-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/pdl-general

Reply via email to