Fix swig files, now compiles on gsl-1.11 AND gsl-1.12
[Math-GSL.git] / pod / MatrixComplex.pod
blob2d2e3325adf7cd6d8d310b3cf34c30283aa8d97b
1 %perlcode %{
3 use Carp qw/croak/;
4 use Scalar::Util 'blessed';
5 use Math::GSL qw/:all/;
6 use Math::GSL::Complex qw/:all/;
7 use Math::GSL::Errno qw/:all/;
8 use Math::GSL::Permutation;
9 use Math::GSL::Eigen qw/:all/;
10 use Math::GSL::VectorComplex qw/:all/;
11 use Math::Complex;
12 use Data::Dumper;
13 use Math::GSL::BLAS qw/gsl_blas_zgemm/;
14 use Math::GSL::CBLAS qw/$CblasNoTrans/;
15 use Math::GSL::Linalg qw/
16     gsl_linalg_complex_LU_decomp
17     gsl_linalg_complex_LU_det
18     gsl_linalg_complex_LU_lndet
19     gsl_linalg_complex_LU_invert
21 use overload
22     '*'      => \&_multiplication,
23     '+'      => \&_addition,
24     '-'      => \&_subtract,
25     '=='     => \&_equal,
26     '!='     => \&_not_equal,
27 #    'abs'    => \&_abs,
28     fallback => 1;
29 <<<<<<< HEAD:pod/MatrixComplex.pod
30 =======
31 use Array::Compare;
32 >>>>>>> b2d551f34dd60416d7f1a3d7ee572e078ea7986c:pod/MatrixComplex.pod
33 #use strict;
34 @EXPORT_OK = qw/
35                 gsl_matrix_complex_alloc
36                 gsl_matrix_complex_calloc
37                 gsl_matrix_complex_alloc_from_block
38                 gsl_matrix_complex_alloc_from_matrix
39                 gsl_vector_complex_alloc_row_from_matrix
40                 gsl_vector_complex_alloc_col_from_matrix
41                 gsl_matrix_complex_free
42                 gsl_matrix_complex_submatrix
43                 gsl_matrix_complex_row
44                 gsl_matrix_complex_column
45                 gsl_matrix_complex_diagonal
46                 gsl_matrix_complex_subdiagonal
47                 gsl_matrix_complex_superdiagonal
48                 gsl_matrix_complex_subrow
49                 gsl_matrix_complex_subcolumn
50                 gsl_matrix_complex_view_array
51                 gsl_matrix_complex_view_array_with_tda
52                 gsl_matrix_complex_view_vector
53                 gsl_matrix_complex_view_vector_with_tda
54                 gsl_matrix_complex_const_submatrix
55                 gsl_matrix_complex_const_row
56                 gsl_matrix_complex_const_column
57                 gsl_matrix_complex_const_diagonal
58                 gsl_matrix_complex_const_subdiagonal
59                 gsl_matrix_complex_const_superdiagonal
60                 gsl_matrix_complex_const_subrow
61                 gsl_matrix_complex_const_subcolumn 
62                 gsl_matrix_complex_const_view_array
63                 gsl_matrix_complex_const_view_array_with_tda
64                 gsl_matrix_complex_const_view_vector
65                 gsl_matrix_complex_const_view_vector_with_tda
66                 gsl_matrix_complex_get
67                 gsl_matrix_complex_set
68                 gsl_matrix_complex_ptr
69                 gsl_matrix_complex_const_ptr
70                 gsl_matrix_complex_set_zero
71                 gsl_matrix_complex_set_identity
72                 gsl_matrix_complex_set_all
73                 gsl_matrix_complex_fread
74                 gsl_matrix_complex_fwrite
75                 gsl_matrix_complex_fscanf
76                 gsl_matrix_complex_fprintf
77                 gsl_matrix_complex_memcpy
78                 gsl_matrix_complex_swap
79                 gsl_matrix_complex_swap_rows
80                 gsl_matrix_complex_swap_columns
81                 gsl_matrix_complex_swap_rowcol
82                 gsl_matrix_complex_transpose
83                 gsl_matrix_complex_transpose_memcpy
84                 gsl_matrix_complex_isnull
85                 gsl_matrix_complex_ispos
86                 gsl_matrix_complex_isneg
87                 gsl_matrix_complex_add
88                 gsl_matrix_complex_sub
89                 gsl_matrix_complex_mul_elements
90                 gsl_matrix_complex_div_elements
91                 gsl_matrix_complex_scale
92                 gsl_matrix_complex_add_constant
93                 gsl_matrix_complex_add_diagonal
94                 gsl_matrix_complex_get_row
95                 gsl_matrix_complex_get_col
96                 gsl_matrix_complex_set_row
97                 gsl_matrix_complex_set_col
100 sub _multiplication {
101     my ($left,$right) = @_;
102     my $lcopy = $left->copy;
104     if ( blessed $right && $right->isa('Math::GSL::MatrixComplex') ) {
105         if ( $left->cols == $right->cols && $left->rows == $right->rows ) {
106             return _dot_product($left,$right);
107             #gsl_matrix_complex_mul_elements($lcopy->raw, $right->raw);
108         } else {
109             croak "Math::GSL::MatrixComplex - multiplication of elements of matrices must be called with two objects matrices and must have the same number of columns and rows";
110         } 
111     } else {
112         gsl_matrix_complex_scale($lcopy->raw, $right);
113     }
114     return $lcopy;
117 sub _dot_product {
118     my ($left,$right) = @_;
120     croak "Math::GSL::Matrix - incompatible matrices in multiplication"
121         unless ( blessed $right && $right->isa('Math::GSL::MatrixComplex') and $left->rows == $right->cols );
122     my $C = Math::GSL::MatrixComplex->new($left->rows, $right->cols);
123     my $complex = gsl_complex_rect(1,0);
124     gsl_blas_zgemm($CblasNoTrans, $CblasNoTrans, $complex, $left->raw, $right->raw, $complex, $C->raw);
125     return $C;
128 sub _addition {
129     my ($left, $right) = @_;
131     my $lcopy = $left->copy;
133     if ( blessed $right && $right->isa('Math::GSL::MatrixComplex') && blessed $left && $left->isa('Math::GSL::MatrixComplex') ) {
134         if ( $left->cols == $right->cols && $left->rows == $right->rows ) {
135             gsl_matrix_complex_add($lcopy->raw, $right->raw);
136         } else {
137             croak "Math::GSL - addition of matrices must be called with two objects matrices and must have the same number of columns and rows";
138         }
139     } else {
140         gsl_matrix_complex_add_constant($lcopy->raw, $right);
141     }
142     return $lcopy;
145 sub _subtract {
146     my ($left, $right) = @_;
148     my $lcopy = $left->copy;
150     if ( blessed $right && $right->isa('Math::GSL::MatrixComplex') && blessed $left && $left->isa('Math::GSL::MatrixComplex') ) {
151         if ( $left->cols == $right->cols && $left->rows == $right->rows ) {
152             gsl_matrix_complex_sub($lcopy->raw, $right->raw);
153         } else {
154             croak "Math::GSL - subtraction of matrices must be called with two objects matrices and must have the same number of columns and rows";
155         }
156     } else {
157         gsl_matrix_complex_add_constant($lcopy->raw, $right*-1);
158     }
159     return $lcopy;
162 sub _equal {
163     my ($left, $right) = @_;
164 <<<<<<< HEAD:pod/MatrixComplex.pod
165     return 0;
166 =======
167     my $comp = Array::Compare->new;
168     return ($comp->compare([$left->as_list], [$right->as_list]));
169 >>>>>>> b2d551f34dd60416d7f1a3d7ee572e078ea7986c:pod/MatrixComplex.pod
172 sub _not_equal {
173     my ($left, $right) = @_;
174 <<<<<<< HEAD:pod/MatrixComplex.pod
175     return 0;
176 =======
177     return !(&_equal($left, $right));
178 >>>>>>> b2d551f34dd60416d7f1a3d7ee572e078ea7986c:pod/MatrixComplex.pod
181 sub copy {
182     my $self = shift;
183     my $copy = Math::GSL::MatrixComplex->new( $self->rows, $self->cols );
184     if ( gsl_matrix_complex_memcpy($copy->raw, $self->raw) != $GSL_SUCCESS ) {
185         croak "Math::GSL - error copying memory, aborting";
186     }
187     return $copy;
189 %EXPORT_TAGS = ( all => \@EXPORT_OK  );
191 =head1 NAME
193 Math::GSL::MatrixComplex - Complex Matrices
195 =head1 SYNOPSIS
197     use Math::GSL::MatrixComplex qw/:all/;
198     my $matrix1 = Math::GSL::MatrixComplex->new(5,5);  # OO interface
199     my $matrix3 = $matrix1 + $matrix1;
200     my $matrix4 = $matrix1 - $matrix1;
201     if($matrix1 == $matrix4) ...
202     if($matrix1 != $matrix3) ...
204     my $matrix2 = gsl_matrix_complex_alloc(5,5);        # standard interface
206 =head1 Objected Oriented Interface to GSL Math::GSL::MatrixComplex
208 =head2 new()
210 Creates a new MatrixComplex object of the given size.
212     my $matrix = Math::GSL::MatrixComplex->new(10,10);
213 =cut
215 sub new 
217     my ($class, $rows, $cols) = @_;
218     my $this = {}; 
219     my $matrix;
220     if ( defined $rows       && defined $cols && 
221         $rows > 0            && $cols > 0     && 
222         (int $rows == $rows) && (int $cols == $cols)){
224         $matrix  = gsl_matrix_complex_alloc($rows,$cols);
225     } else {
226         croak( __PACKAGE__.'::new($x,$y) - $x and $y must be positive integers');
227     }
228     gsl_matrix_complex_set_zero($matrix);
229     $this->{_matrix} = $matrix; 
230     ($this->{_rows}, $this->{_cols}) = ($rows,$cols);
231     bless $this, $class;
233 =head2 raw()
235 Get the underlying GSL matrix object created by SWIG, useful for using gsl_matrix_* functions which do not have an OO counterpart.
237     my $matrix     = Math::GSL::MatrixComplex->new(3,3);
238     my $gsl_matrix = $matrix->raw;
239     my $stuff      = gsl_matrix_complex_get($gsl_matrix, 1, 2);
241 =cut
242 sub raw  { (shift)->{_matrix} }
243 =head2 rows()
245 Returns the number of rows in the matrix.
247     my $rows = $matrix->rows;
248 =cut
250 sub rows { (shift)->{_rows}   }
252 =head2 cols()
254 Returns the number of columns in the matrix.
256     my $cols = $matrix->cols;
257 =cut
259 sub cols { (shift)->{_cols}   }
261 =head2 as_vector()
263 Returns a 1xN or Nx1 matrix as a Math::GSL::VectorComplex object. Dies if called on a matrix that is not a single row or column. Useful for turning the output of C<col()> or C<row()> into a vector, like so:
265     my $vector1 = $matrix->col(0)->as_vector;
266     my $vector2 = $matrix->row(1)->as_vector;
268 =cut
270 sub as_vector($)
272     my ($self) = @_;
273     croak(__PACKAGE__.'::as_vector() - must be a single row or column matrix') unless ($self->cols == 1 or $self->rows == 1);
275     # TODO: there is a faster way to do this
276     return Math::GSL::VectorComplex->new([ $self->as_list ] );
280 =head2  as_list() 
282 Get the contents of a Math::GSL::Matrix object as a Perl list.
284     my $matrix = Math::GSL::MatrixComplex->new(3,3);
285     ...
286     my @matrix = $matrix->as_list;
287 =cut
289 sub as_list($)
291     my $self = shift;
292     my @matrix;
293     for my $row ( 0 .. $self->rows-1) {
294        push @matrix, map { gsl_matrix_complex_get($self->raw, $row, $_) } (0 .. $self->cols-1 );
295     }
296     return map {
297             Math::Complex->make(
298                 gsl_real($_),
299                 gsl_imag($_))
300             } @matrix;
303 =head2 row()
305 Returns a row matrix of the row you enter.
307     my $matrix = Math::GSL::MatrixComplex->new(3,3);
308     ...
309     my $matrix_row = $matrix->row(0);
311 =cut
313 sub row
315     my ($self, $row) = @_;
316     croak (__PACKAGE__.'::$matrix->row($row) - invalid $row value') 
317         unless (($row < $self->rows) and $row >= 0);  
319    my $rowmat = Math::GSL::MatrixComplex->new(1,$self->cols);
321    for my $n (0 .. $self->cols-1) {
322         gsl_matrix_complex_set( $rowmat->raw, 0, $n,
323             gsl_matrix_complex_get($self->raw, $row, $n)
324         );
325    }
327     return $rowmat;
330 =head2 col()
332 Returns a col matrix of the column you enter.
334     my $matrix = Math::GSL::MatrixComplex->new(3,3);
335     ...
336     my $matrix_col = $matrix->col(0);
338 =cut
340 sub col
342     my ($self, $col) = @_;
343     croak (__PACKAGE__."::\$matrix->col(\$col) - $col not a valid column")
344         unless (defined $col && $col < $self->cols and $col >= 0);
346     my $colmat = Math::GSL::MatrixComplex->new($self->rows, 1);
348     map { gsl_matrix_complex_set($colmat->raw, $_, 0,
349             gsl_matrix_complex_get($self->raw, $_, $col),
350             )
351         } (0 .. $self->rows-1);
353     return $colmat;
356 =head2 set_row()
358 Sets a the values of a row with the elements of an array.
360     my $matrix = Math::GSL::MatrixComplex->new(3,3);
361     $matrix->set_row(0, [8, 6, 2]);
363 You can also set multiple rows at once with chained calls:
364     my $matrix = Math::GSL::MatrixComplex->new(3,3);
365     $matrix->set_row(0, [8, 6, 2])
366            ->set_row(1, [2, 4, 1]);
367     ...
369 =cut
371 sub set_row {
372     my ($self, $row, $values) = @_;
373     my $length = $#$values;
374     die __PACKAGE__.'::set_row($x, $values) - $values must be a nonempty array reference' if $length == -1;
375     die __PACKAGE__.'::set_row($x, $values) - $x must be a valid row number' if ($row < 0 || $row >= $self->rows);
376     die __PACKAGE__.'::set_row($x, $values) - $values must contains the same number of elements as there is columns in the matrix' if($length != $self->cols-1);
377     # $values may have Math::Complex objects
378     @$values = map { Math::GSL::Complex::gsl_complex_rect(Re($_), Im($_)) } @$values;
379     # warn Dumper [ @$values ];
380     map { gsl_matrix_complex_set($self->raw, $row, $_, $values->[$_]) } (0..$length);
381     return $self;
384 =head2 set_col()
386 Sets a the values of a column with the elements of an array.
388     my $matrix = Math::GSL::MatrixComplex->new(3,3);
389     $matrix->set_col(0, [8, 6, 2]);
391 You can also set multiple columns at once with chained calls:
392     my $matrix = Math::GSL::MatrixComplex->new(3,3);
393     $matrix->set_col(0, [8, 6, 2])
394            ->set_col(1, [2, 4, 1]);
395     ...
397 =cut
399 sub set_col {
400     my ($self, $col, $values) = @_;
401     my $length = $#$values;
402     die __PACKAGE__.'::set_col($x, $values) - $values must be a nonempty array reference' if $length == -1;
403     die __PACKAGE__.'::set_col($x, $values) - $x must be a valid column number' if ($col < 0 || $col >= $self->cols);
404     die __PACKAGE__.'::set_col($x, $values) - $values must contains the same number of elements as there is rowss in the matrix' if($length != $self->rows-1);
405     # $values may have Math::Complex objects
406     @$values = map { gsl_complex_rect(Re($_), Im($_)) } @$values;
407     map { gsl_matrix_complex_set($self->raw, $_, $col, $values->[$_]) } (0..$length);
408     return $self;
411 =head2 is_square()
413 Returns true if a matrix is square, i.e. it has the same number of rows as columns, false otherwise.
415 =cut
417 sub is_square($)
419     my $self = shift;
420     return ($self->rows == $self->cols) ? 1 : 0 ;
423 =head2 det()
425 Returns the determinant of a matrix (computed by LU decomposition) or dies if called on a non-square matrix.
427     my $det = $matrix->det();
429 =cut
431 sub det($)
433     my $self = shift;
434     croak(__PACKAGE__."- determinant only exists for square matrices") unless $self->is_square;
436     my $p  = Math::GSL::Permutation->new( $self->rows );
437     my $LU = $self->copy;
439     my $s = gsl_linalg_complex_LU_decomp($LU->raw, $p->raw);
441     # $z is a gsl_complex
442     my $z = gsl_linalg_complex_LU_det($LU->raw, $s );
443     return Math::Complex->make( gsl_real($z), gsl_imag($z) );
446 =head2 zero()
448 Set a matrix to the zero matrix.
450     $matrix->zero;
452 =cut
454 sub zero # brrr!
456     my $self=shift;
457     gsl_matrix_complex_set_zero($self->raw);
458     return $self;
461 =head2 identity()
463 Set a matrix to the identity matrix, i.e. one on the diagonal and zero elsewhere.
465     my $I = $matrix->identity;
467 =cut
469 sub identity
471     my $self=shift;
472     gsl_matrix_complex_set_identity($self->raw);
473     return $self;
476 =head2 inverse()
478 Returns the inverse of a matrix or dies when called on a non-square matrix.
480     my $inverse = $matrix->inverse;
482 =cut
484 sub inverse($)
486     my $self = shift;
487     croak(__PACKAGE__."- inverse only exists for square matrices") unless $self->is_square;
489     my $p  = Math::GSL::Permutation->new( $self->rows );
490     my $LU = $self->copy;
491     my $inverse = $self->copy;
493     # should check return status
494     gsl_linalg_complex_LU_decomp($LU->raw, $p->raw);
495     gsl_linalg_complex_LU_invert($LU->raw, $p->raw,$inverse->raw);
497     return $inverse;
501 =head2 is_hermitian()
503 Returns true if the matrix is hermitian, false otherwise
505     my $test = $matrix->is_hermitian;
507 =cut
509 sub is_hermitian()
511     my ($self) = @_;
512     my $test = $self->is_square;
513     my $transpose = $self->copy;
514     gsl_matrix_complex_transpose($transpose->raw);
515     
516     if($test == 1) {
517         for my $row (0..$self->rows - 1) {
518             map { gsl_matrix_complex_set($transpose->raw, $row, $_, gsl_complex_conjugate(gsl_matrix_complex_get($transpose->raw, $row, $_))) } (0..$self->cols - 1);
519         }
520         if($self != $transpose){
521             $test = 0;
522         }
523     }
524     return $test;
526 =head2 eigenvalues()
528 =cut
531 sub eigenvalues($)
533     my $self=shift;
534     my ($r,$c) = ($self->rows,$self->cols);
535     croak "Math::GSL::MatrixComplex : \$matrix->eigenvalues - \$matrix must be square" unless ($r == $c);
536     my $evec   = gsl_matrix_complex_alloc($r,$c);
537     my $eigen  = gsl_eigen_nonsymmv_alloc($r);
538     my $vector = gsl_vector_complex_alloc($r);
541     # GSL has no generalized complex matrix routines
542     # can only continue if the matrix is hermitian
543     croak (__PACKAGE__."::eigenvalues : non-hermitian matrices are not currently supported")  unless $self->is_hermitian;
544     gsl_eigen_nonsymmv($self->raw, $vector, $evec, $eigen);
546     my $x = gsl_vector_complex_real($vector); # vector of real components
547     my $y = gsl_vector_complex_imag($vector); # vector of imaginary components
549     return map {
550                 _as_complex( gsl_vector_get($x->{vector}, $_) ,
551                              gsl_vector_get($y->{vector}, $_) )
552                 } (0 .. $r-1);
556 =head2 lndet()
558 Returns the natural log of the absolute value of the determinant of a matrix (computed by LU decomposition) or dies if called on a non-square matrix.
560     my $lndet = $matrix->lndet();
562 =cut
564 sub lndet($)
566     my $self = shift;
567     croak(__PACKAGE__."- log determinant only exists for square matrices") unless $self->is_square;
569     my $p  = Math::GSL::Permutation->new( $self->rows );
570     my $LU = $self->copy;
572     gsl_linalg_complex_LU_decomp($LU->raw, $p->raw);
573     return gsl_linalg_complex_LU_lndet($LU->raw);
575 =head1 DESCRIPTION
577 =over 1
579 =item C<gsl_matrix_complex_alloc >
581 =item C<gsl_matrix_complex_calloc >
583 =item C<gsl_matrix_complex_alloc_from_block >
585 =item C<gsl_matrix_complex_alloc_from_matrix >
587 =item C<gsl_vector_complex_alloc_row_from_matrix >
589 =item C<gsl_vector_complex_alloc_col_from_matrix >
591 =item C<gsl_matrix_complex_free >
593 =item C<gsl_matrix_complex_submatrix >
595 =item C<gsl_matrix_complex_row >
597 =item C<gsl_matrix_complex_column >
599 =item C<gsl_matrix_complex_diagonal >
601 =item C<gsl_matrix_complex_subdiagonal >
603 =item C<gsl_matrix_complex_superdiagonal >
605 =item C<gsl_matrix_complex_subrow >
607 =item C<gsl_matrix_complex_subcolumn >
609 =item C<gsl_matrix_complex_view_array >
611 =item C<gsl_matrix_complex_view_array_with_tda >
613 =item C<gsl_matrix_complex_view_vector >
615 =item C<gsl_matrix_complex_view_vector_with_tda >
617 =item C<gsl_matrix_complex_const_submatrix >
619 =item C<gsl_matrix_complex_const_row >
621 =item C<gsl_matrix_complex_const_column >
623 =item C<gsl_matrix_complex_const_diagonal >
625 =item C<gsl_matrix_complex_const_subdiagonal >
627 =item C<gsl_matrix_complex_const_superdiagonal >
629 =item C<gsl_matrix_complex_const_subrow >
631 =item C<gsl_matrix_complex_const_subcolumn >
633 =item C<gsl_matrix_complex_const_view_array >
635 =item C<gsl_matrix_complex_const_view_array_with_tda >
637 =item C<gsl_matrix_complex_const_view_vector >
639 =item C<gsl_matrix_complex_const_view_vector_with_tda >
641 =item C<gsl_matrix_complex_get>
643 =item C<gsl_matrix_complex_set>
645 =item C<gsl_matrix_complex_ptr>
647 =item C<gsl_matrix_complex_const_ptr>
649 =item C<gsl_matrix_complex_set_zero >
651 =item C<gsl_matrix_complex_set_identity >
653 =item C<gsl_matrix_complex_set_all >
655 =item C<gsl_matrix_complex_fread >
657 =item C<gsl_matrix_complex_fwrite >
659 =item C<gsl_matrix_complex_fscanf >
661 =item C<gsl_matrix_complex_fprintf >
663 =item C<gsl_matrix_complex_memcpy>
665 =item C<gsl_matrix_complex_swap>
667 =item C<gsl_matrix_complex_swap_rows>
669 =item C<gsl_matrix_complex_swap_columns>
671 =item C<gsl_matrix_complex_swap_rowcol>
673 =item C<gsl_matrix_complex_transpose >
675 =item C<gsl_matrix_complex_transpose_memcpy >
677 =item C<gsl_matrix_complex_isnull >
679 =item C<gsl_matrix_complex_ispos >
681 =item C<gsl_matrix_complex_isneg >
683 =item C<gsl_matrix_complex_add >
685 =item C<gsl_matrix_complex_sub >
687 =item C<gsl_matrix_complex_mul_elements >
689 =item C<gsl_matrix_complex_div_elements >
691 =item C<gsl_matrix_complex_scale >
693 =item C<gsl_matrix_complex_add_constant >
695 =item C<gsl_matrix_complex_add_diagonal >
697 =item C<gsl_matrix_complex_get_row>
699 =item C<gsl_matrix_complex_get_col>
701 =item C<gsl_matrix_complex_set_row>
703 =item C<gsl_matrix_complex_set_col>
705 =back 
707 For more informations on the functions, we refer you to the GSL offcial documentation
708 L<http://www.gnu.org/software/gsl/manual/html_node/>
711 =head1 AUTHORS
713 Jonathan Leto <jonathan@leto.net> and Thierry Moisan <thierry.moisan@gmail.com>
715 =head1 COPYRIGHT AND LICENSE
717 Copyright (C) 2008 Jonathan Leto and Thierry Moisan
719 This program is free software; you can redistribute it and/or modify it
720 under the same terms as Perl itself.
722 =cut