comparison liboctave/chMatrix.cc @ 1573:403c60daa8c7

[project @ 1995-10-19 04:34:20 by jwe] Initial revision
author jwe
date Thu, 19 Oct 1995 04:34:20 +0000
parents
children 42b4f904f1af
comparison
equal deleted inserted replaced
1572:0d9e10d10bd7 1573:403c60daa8c7
1 // Matrix manipulations. -*- C++ -*-
2 /*
3
4 Copyright (C) 1992, 1993, 1994, 1995 John W. Eaton
5
6 This file is part of Octave.
7
8 Octave is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
11 later version.
12
13 Octave is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with Octave; see the file COPYING. If not, write to the Free
20 Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21
22 */
23
24 #if defined (__GNUG__)
25 #pragma implementation
26 #endif
27
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
31
32 #include <cstdio>
33 #include <cstring>
34
35 #include <iostream.h>
36
37 // #include <sys/types.h> // XXX FIXME XXX
38
39 #include "lo-error.h"
40 #include "mx-base.h"
41 #include "mx-inlines.cc"
42
43 // charMatrix class.
44
45 charMatrix::charMatrix (const char *s)
46 : MArray2<char> ((s ? 1 : 0), (s ? strlen (s) : 0))
47 {
48 int nc = cols ();
49 for (int i = 0; i < nc; i++)
50 elem (0, i) = s[i];
51 }
52
53 int
54 charMatrix::operator == (const charMatrix& a) const
55 {
56 if (rows () != a.rows () || cols () != a.cols ())
57 return 0;
58
59 return equal (data (), a.data (), length ());
60 }
61
62 int
63 charMatrix::operator != (const charMatrix& a) const
64 {
65 return !(*this == a);
66 }
67
68 charMatrix&
69 charMatrix::insert (const char *s, int r, int c)
70 {
71 if (s)
72 {
73 int s_len = strlen (s);
74
75 if (r < 0 || r >= rows () || c < 0 || c + s_len - 1 > cols ())
76 {
77 (*current_liboctave_error_handler) ("range error for insert");
78 return *this;
79 }
80
81 for (int i = 0; i < s_len; i++)
82 elem (r, c+i) = s[i];
83 }
84 return *this;
85 }
86
87 charMatrix&
88 charMatrix::insert (const charMatrix& a, int r, int c)
89 {
90 Array2<char>::insert (a, r, c);
91 return *this;
92 }
93
94 char *
95 charMatrix::row_as_string (int r) const
96 {
97 if (r < 0 || r >= rows ())
98 {
99 (*current_liboctave_error_handler) ("range error for row_as_string");
100 return 0;
101 }
102
103 int nc = cols ();
104
105 char *retval = new char [nc + 1];
106
107 retval[nc] = '\0';
108
109 for (int i = 0; i < nc; i++)
110 retval[i] = elem (r, i);
111
112 return retval;
113 }
114
115 #if 0
116 Matrix&
117 Matrix::insert (const RowVector& a, int r, int c)
118 {
119 int a_len = a.length ();
120 if (r < 0 || r >= rows () || c < 0 || c + a_len - 1 > cols ())
121 {
122 (*current_liboctave_error_handler) ("range error for insert");
123 return *this;
124 }
125
126 for (int i = 0; i < a_len; i++)
127 elem (r, c+i) = a.elem (i);
128
129 return *this;
130 }
131
132 Matrix&
133 Matrix::insert (const ColumnVector& a, int r, int c)
134 {
135 int a_len = a.length ();
136 if (r < 0 || r + a_len - 1 > rows () || c < 0 || c >= cols ())
137 {
138 (*current_liboctave_error_handler) ("range error for insert");
139 return *this;
140 }
141
142 for (int i = 0; i < a_len; i++)
143 elem (r+i, c) = a.elem (i);
144
145 return *this;
146 }
147
148 Matrix&
149 Matrix::insert (const DiagMatrix& a, int r, int c)
150 {
151 if (r < 0 || r + a.rows () - 1 > rows ()
152 || c < 0 || c + a.cols () - 1 > cols ())
153 {
154 (*current_liboctave_error_handler) ("range error for insert");
155 return *this;
156 }
157
158 for (int i = 0; i < a.length (); i++)
159 elem (r+i, c+i) = a.elem (i, i);
160
161 return *this;
162 }
163
164 Matrix&
165 Matrix::fill (double val)
166 {
167 int nr = rows ();
168 int nc = cols ();
169 if (nr > 0 && nc > 0)
170 for (int j = 0; j < nc; j++)
171 for (int i = 0; i < nr; i++)
172 elem (i, j) = val;
173
174 return *this;
175 }
176
177 Matrix&
178 Matrix::fill (double val, int r1, int c1, int r2, int c2)
179 {
180 int nr = rows ();
181 int nc = cols ();
182 if (r1 < 0 || r2 < 0 || c1 < 0 || c2 < 0
183 || r1 >= nr || r2 >= nr || c1 >= nc || c2 >= nc)
184 {
185 (*current_liboctave_error_handler) ("range error for fill");
186 return *this;
187 }
188
189 if (r1 > r2) { int tmp = r1; r1 = r2; r2 = tmp; }
190 if (c1 > c2) { int tmp = c1; c1 = c2; c2 = tmp; }
191
192 for (int j = c1; j <= c2; j++)
193 for (int i = r1; i <= r2; i++)
194 elem (i, j) = val;
195
196 return *this;
197 }
198
199 Matrix
200 Matrix::append (const Matrix& a) const
201 {
202 int nr = rows ();
203 int nc = cols ();
204 if (nr != a.rows ())
205 {
206 (*current_liboctave_error_handler) ("row dimension mismatch for append");
207 return Matrix ();
208 }
209
210 int nc_insert = nc;
211 Matrix retval (nr, nc + a.cols ());
212 retval.insert (*this, 0, 0);
213 retval.insert (a, 0, nc_insert);
214 return retval;
215 }
216
217 Matrix
218 Matrix::append (const RowVector& a) const
219 {
220 int nr = rows ();
221 int nc = cols ();
222 if (nr != 1)
223 {
224 (*current_liboctave_error_handler) ("row dimension mismatch for append");
225 return Matrix ();
226 }
227
228 int nc_insert = nc;
229 Matrix retval (nr, nc + a.length ());
230 retval.insert (*this, 0, 0);
231 retval.insert (a, 0, nc_insert);
232 return retval;
233 }
234
235 Matrix
236 Matrix::append (const ColumnVector& a) const
237 {
238 int nr = rows ();
239 int nc = cols ();
240 if (nr != a.length ())
241 {
242 (*current_liboctave_error_handler) ("row dimension mismatch for append");
243 return Matrix ();
244 }
245
246 int nc_insert = nc;
247 Matrix retval (nr, nc + 1);
248 retval.insert (*this, 0, 0);
249 retval.insert (a, 0, nc_insert);
250 return retval;
251 }
252
253 Matrix
254 Matrix::append (const DiagMatrix& a) const
255 {
256 int nr = rows ();
257 int nc = cols ();
258 if (nr != a.rows ())
259 {
260 (*current_liboctave_error_handler) ("row dimension mismatch for append");
261 return *this;
262 }
263
264 int nc_insert = nc;
265 Matrix retval (nr, nc + a.cols ());
266 retval.insert (*this, 0, 0);
267 retval.insert (a, 0, nc_insert);
268 return retval;
269 }
270
271 Matrix
272 Matrix::stack (const Matrix& a) const
273 {
274 int nr = rows ();
275 int nc = cols ();
276 if (nc != a.cols ())
277 {
278 (*current_liboctave_error_handler)
279 ("column dimension mismatch for stack");
280 return Matrix ();
281 }
282
283 int nr_insert = nr;
284 Matrix retval (nr + a.rows (), nc);
285 retval.insert (*this, 0, 0);
286 retval.insert (a, nr_insert, 0);
287 return retval;
288 }
289
290 Matrix
291 Matrix::stack (const RowVector& a) const
292 {
293 int nr = rows ();
294 int nc = cols ();
295 if (nc != a.length ())
296 {
297 (*current_liboctave_error_handler)
298 ("column dimension mismatch for stack");
299 return Matrix ();
300 }
301
302 int nr_insert = nr;
303 Matrix retval (nr + 1, nc);
304 retval.insert (*this, 0, 0);
305 retval.insert (a, nr_insert, 0);
306 return retval;
307 }
308
309 Matrix
310 Matrix::stack (const ColumnVector& a) const
311 {
312 int nr = rows ();
313 int nc = cols ();
314 if (nc != 1)
315 {
316 (*current_liboctave_error_handler)
317 ("column dimension mismatch for stack");
318 return Matrix ();
319 }
320
321 int nr_insert = nr;
322 Matrix retval (nr + a.length (), nc);
323 retval.insert (*this, 0, 0);
324 retval.insert (a, nr_insert, 0);
325 return retval;
326 }
327
328 Matrix
329 Matrix::stack (const DiagMatrix& a) const
330 {
331 int nr = rows ();
332 int nc = cols ();
333 if (nc != a.cols ())
334 {
335 (*current_liboctave_error_handler)
336 ("column dimension mismatch for stack");
337 return Matrix ();
338 }
339
340 int nr_insert = nr;
341 Matrix retval (nr + a.rows (), nc);
342 retval.insert (*this, 0, 0);
343 retval.insert (a, nr_insert, 0);
344 return retval;
345 }
346
347 Matrix
348 Matrix::transpose (void) const
349 {
350 int nr = rows ();
351 int nc = cols ();
352 Matrix result (nc, nr);
353 if (length () > 0)
354 {
355 for (int j = 0; j < nc; j++)
356 for (int i = 0; i < nr; i++)
357 result.elem (j, i) = elem (i, j);
358 }
359 return result;
360 }
361
362 Matrix
363 real (const ComplexMatrix& a)
364 {
365 int a_len = a.length ();
366 Matrix retval;
367 if (a_len > 0)
368 retval = Matrix (real_dup (a.data (), a_len), a.rows (), a.cols ());
369 return retval;
370 }
371
372 Matrix
373 imag (const ComplexMatrix& a)
374 {
375 int a_len = a.length ();
376 Matrix retval;
377 if (a_len > 0)
378 retval = Matrix (imag_dup (a.data (), a_len), a.rows (), a.cols ());
379 return retval;
380 }
381
382 Matrix
383 Matrix::extract (int r1, int c1, int r2, int c2) const
384 {
385 if (r1 > r2) { int tmp = r1; r1 = r2; r2 = tmp; }
386 if (c1 > c2) { int tmp = c1; c1 = c2; c2 = tmp; }
387
388 int new_r = r2 - r1 + 1;
389 int new_c = c2 - c1 + 1;
390
391 Matrix result (new_r, new_c);
392
393 for (int j = 0; j < new_c; j++)
394 for (int i = 0; i < new_r; i++)
395 result.elem (i, j) = elem (r1+i, c1+j);
396
397 return result;
398 }
399
400 // extract row or column i.
401
402 RowVector
403 Matrix::row (int i) const
404 {
405 int nc = cols ();
406 if (i < 0 || i >= rows ())
407 {
408 (*current_liboctave_error_handler) ("invalid row selection");
409 return RowVector ();
410 }
411
412 RowVector retval (nc);
413 for (int j = 0; j < nc; j++)
414 retval.elem (j) = elem (i, j);
415
416 return retval;
417 }
418
419 RowVector
420 Matrix::row (char *s) const
421 {
422 if (! s)
423 {
424 (*current_liboctave_error_handler) ("invalid row selection");
425 return RowVector ();
426 }
427
428 char c = *s;
429 if (c == 'f' || c == 'F')
430 return row (0);
431 else if (c == 'l' || c == 'L')
432 return row (rows () - 1);
433 else
434 {
435 (*current_liboctave_error_handler) ("invalid row selection");
436 return RowVector ();
437 }
438 }
439
440 ColumnVector
441 Matrix::column (int i) const
442 {
443 int nr = rows ();
444 if (i < 0 || i >= cols ())
445 {
446 (*current_liboctave_error_handler) ("invalid column selection");
447 return ColumnVector ();
448 }
449
450 ColumnVector retval (nr);
451 for (int j = 0; j < nr; j++)
452 retval.elem (j) = elem (j, i);
453
454 return retval;
455 }
456
457 ColumnVector
458 Matrix::column (char *s) const
459 {
460 if (! s)
461 {
462 (*current_liboctave_error_handler) ("invalid column selection");
463 return ColumnVector ();
464 }
465
466 char c = *s;
467 if (c == 'f' || c == 'F')
468 return column (0);
469 else if (c == 'l' || c == 'L')
470 return column (cols () - 1);
471 else
472 {
473 (*current_liboctave_error_handler) ("invalid column selection");
474 return ColumnVector ();
475 }
476 }
477
478 Matrix
479 Matrix::inverse (void) const
480 {
481 int info;
482 double rcond;
483 return inverse (info, rcond);
484 }
485
486 Matrix
487 Matrix::inverse (int& info) const
488 {
489 double rcond;
490 return inverse (info, rcond);
491 }
492
493 Matrix
494 Matrix::inverse (int& info, double& rcond) const
495 {
496 int nr = rows ();
497 int nc = cols ();
498 int len = length ();
499 if (nr != nc || nr == 0 || nc == 0)
500 {
501 (*current_liboctave_error_handler) ("inverse requires square matrix");
502 return Matrix ();
503 }
504
505 info = 0;
506
507 int *ipvt = new int [nr];
508 double *z = new double [nr];
509 double *tmp_data = dup (data (), len);
510
511 F77_FCN (dgeco, DGECO) (tmp_data, nr, nc, ipvt, rcond, z);
512
513 volatile double rcond_plus_one = rcond + 1.0;
514 if (rcond_plus_one == 1.0)
515 {
516 info = -1;
517 copy (tmp_data, data (), len); // Restore matrix contents.
518 }
519 else
520 {
521 double *dummy = 0;
522
523 F77_FCN (dgedi, DGEDI) (tmp_data, nr, nc, ipvt, dummy, z, 1);
524 }
525
526 delete [] ipvt;
527 delete [] z;
528
529 return Matrix (tmp_data, nr, nc);
530 }
531
532 Matrix
533 Matrix::pseudo_inverse (double tol)
534 {
535 SVD result (*this);
536
537 DiagMatrix S = result.singular_values ();
538 Matrix U = result.left_singular_matrix ();
539 Matrix V = result.right_singular_matrix ();
540
541 ColumnVector sigma = S.diag ();
542
543 int r = sigma.length () - 1;
544 int nr = rows ();
545 int nc = cols ();
546
547 if (tol <= 0.0)
548 {
549 if (nr > nc)
550 tol = nr * sigma.elem (0) * DBL_EPSILON;
551 else
552 tol = nc * sigma.elem (0) * DBL_EPSILON;
553 }
554
555 while (r >= 0 && sigma.elem (r) < tol)
556 r--;
557
558 if (r < 0)
559 return Matrix (nc, nr, 0.0);
560 else
561 {
562 Matrix Ur = U.extract (0, 0, nr-1, r);
563 DiagMatrix D = DiagMatrix (sigma.extract (0, r)) . inverse ();
564 Matrix Vr = V.extract (0, 0, nc-1, r);
565 return Vr * D * Ur.transpose ();
566 }
567 }
568
569 ComplexMatrix
570 Matrix::fourier (void) const
571 {
572 int nr = rows ();
573 int nc = cols ();
574 int npts, nsamples;
575 if (nr == 1 || nc == 1)
576 {
577 npts = nr > nc ? nr : nc;
578 nsamples = 1;
579 }
580 else
581 {
582 npts = nr;
583 nsamples = nc;
584 }
585
586 int nn = 4*npts+15;
587 Complex *wsave = new Complex [nn];
588 Complex *tmp_data = make_complex (data (), length ());
589
590 F77_FCN (cffti, CFFTI) (npts, wsave);
591
592 for (int j = 0; j < nsamples; j++)
593 F77_FCN (cfftf, CFFTF) (npts, &tmp_data[npts*j], wsave);
594
595 delete [] wsave;
596
597 return ComplexMatrix (tmp_data, nr, nc);
598 }
599
600 ComplexMatrix
601 Matrix::ifourier (void) const
602 {
603 int nr = rows ();
604 int nc = cols ();
605 int npts, nsamples;
606 if (nr == 1 || nc == 1)
607 {
608 npts = nr > nc ? nr : nc;
609 nsamples = 1;
610 }
611 else
612 {
613 npts = nr;
614 nsamples = nc;
615 }
616
617 int nn = 4*npts+15;
618 Complex *wsave = new Complex [nn];
619 Complex *tmp_data = make_complex (data (), length ());
620
621 F77_FCN (cffti, CFFTI) (npts, wsave);
622
623 for (int j = 0; j < nsamples; j++)
624 F77_FCN (cfftb, CFFTB) (npts, &tmp_data[npts*j], wsave);
625
626 for (int j = 0; j < npts*nsamples; j++)
627 tmp_data[j] = tmp_data[j] / (double) npts;
628
629 delete [] wsave;
630
631 return ComplexMatrix (tmp_data, nr, nc);
632 }
633
634 ComplexMatrix
635 Matrix::fourier2d (void) const
636 {
637 int nr = rows ();
638 int nc = cols ();
639 int npts, nsamples;
640 if (nr == 1 || nc == 1)
641 {
642 npts = nr > nc ? nr : nc;
643 nsamples = 1;
644 }
645 else
646 {
647 npts = nr;
648 nsamples = nc;
649 }
650
651 int nn = 4*npts+15;
652 Complex *wsave = new Complex [nn];
653 Complex *tmp_data = make_complex (data (), length ());
654
655 F77_FCN (cffti, CFFTI) (npts, wsave);
656
657 for (int j = 0; j < nsamples; j++)
658 F77_FCN (cfftf, CFFTF) (npts, &tmp_data[npts*j], wsave);
659
660 delete [] wsave;
661
662 npts = nc;
663 nsamples = nr;
664 nn = 4*npts+15;
665 wsave = new Complex [nn];
666 Complex *row = new Complex[npts];
667
668 F77_FCN (cffti, CFFTI) (npts, wsave);
669
670 for (int j = 0; j < nsamples; j++)
671 {
672 for (int i = 0; i < npts; i++)
673 row[i] = tmp_data[i*nr + j];
674
675 F77_FCN (cfftf, CFFTF) (npts, row, wsave);
676
677 for (int i = 0; i < npts; i++)
678 tmp_data[i*nr + j] = row[i];
679 }
680
681 delete [] wsave;
682 delete [] row;
683
684 return ComplexMatrix (tmp_data, nr, nc);
685 }
686
687 ComplexMatrix
688 Matrix::ifourier2d (void) const
689 {
690 int nr = rows ();
691 int nc = cols ();
692 int npts, nsamples;
693 if (nr == 1 || nc == 1)
694 {
695 npts = nr > nc ? nr : nc;
696 nsamples = 1;
697 }
698 else
699 {
700 npts = nr;
701 nsamples = nc;
702 }
703
704 int nn = 4*npts+15;
705 Complex *wsave = new Complex [nn];
706 Complex *tmp_data = make_complex (data (), length ());
707
708 F77_FCN (cffti, CFFTI) (npts, wsave);
709
710 for (int j = 0; j < nsamples; j++)
711 F77_FCN (cfftb, CFFTB) (npts, &tmp_data[npts*j], wsave);
712
713 delete [] wsave;
714
715 for (int j = 0; j < npts*nsamples; j++)
716 tmp_data[j] = tmp_data[j] / (double) npts;
717
718 npts = nc;
719 nsamples = nr;
720 nn = 4*npts+15;
721 wsave = new Complex [nn];
722 Complex *row = new Complex[npts];
723
724 F77_FCN (cffti, CFFTI) (npts, wsave);
725
726 for (int j = 0; j < nsamples; j++)
727 {
728 for (int i = 0; i < npts; i++)
729 row[i] = tmp_data[i*nr + j];
730
731 F77_FCN (cfftb, CFFTB) (npts, row, wsave);
732
733 for (int i = 0; i < npts; i++)
734 tmp_data[i*nr + j] = row[i] / (double) npts;
735 }
736
737 delete [] wsave;
738 delete [] row;
739
740 return ComplexMatrix (tmp_data, nr, nc);
741 }
742
743 DET
744 Matrix::determinant (void) const
745 {
746 int info;
747 double rcond;
748 return determinant (info, rcond);
749 }
750
751 DET
752 Matrix::determinant (int& info) const
753 {
754 double rcond;
755 return determinant (info, rcond);
756 }
757
758 DET
759 Matrix::determinant (int& info, double& rcond) const
760 {
761 DET retval;
762
763 int nr = rows ();
764 int nc = cols ();
765
766 if (nr == 0 || nc == 0)
767 {
768 double d[2];
769 d[0] = 1.0;
770 d[1] = 0.0;
771 retval = DET (d);
772 }
773 else
774 {
775 info = 0;
776 int *ipvt = new int [nr];
777
778 double *z = new double [nr];
779 double *tmp_data = dup (data (), length ());
780
781 F77_FCN (dgeco, DGECO) (tmp_data, nr, nr, ipvt, rcond, z);
782
783 volatile double rcond_plus_one = rcond + 1.0;
784 if (rcond_plus_one == 1.0)
785 {
786 info = -1;
787 retval = DET ();
788 }
789 else
790 {
791 double d[2];
792 F77_FCN (dgedi, DGEDI) (tmp_data, nr, nr, ipvt, d, z, 10);
793 retval = DET (d);
794 }
795
796 delete [] tmp_data;
797 delete [] ipvt;
798 delete [] z;
799 }
800
801 return retval;
802 }
803
804 Matrix
805 Matrix::solve (const Matrix& b) const
806 {
807 int info;
808 double rcond;
809 return solve (b, info, rcond);
810 }
811
812 Matrix
813 Matrix::solve (const Matrix& b, int& info) const
814 {
815 double rcond;
816 return solve (b, info, rcond);
817 }
818
819 Matrix
820 Matrix::solve (const Matrix& b, int& info, double& rcond) const
821 {
822 Matrix retval;
823
824 int nr = rows ();
825 int nc = cols ();
826 if (nr == 0 || nc == 0 || nr != nc || nr != b.rows ())
827 {
828 (*current_liboctave_error_handler)
829 ("matrix dimension mismatch solution of linear equations");
830 return Matrix ();
831 }
832
833 info = 0;
834 int *ipvt = new int [nr];
835
836 double *z = new double [nr];
837 double *tmp_data = dup (data (), length ());
838
839 F77_FCN (dgeco, DGECO) (tmp_data, nr, nr, ipvt, rcond, z);
840
841 volatile double rcond_plus_one = rcond + 1.0;
842 if (rcond_plus_one == 1.0)
843 {
844 info = -2;
845 }
846 else
847 {
848 double *result = dup (b.data (), b.length ());
849
850 int b_nc = b.cols ();
851 for (int j = 0; j < b_nc; j++)
852 F77_FCN (dgesl, DGESL) (tmp_data, nr, nr, ipvt, &result[nr*j], 0);
853
854 retval = Matrix (result, b.rows (), b_nc);
855 }
856
857 delete [] tmp_data;
858 delete [] ipvt;
859 delete [] z;
860
861 return retval;
862 }
863
864 ComplexMatrix
865 Matrix::solve (const ComplexMatrix& b) const
866 {
867 ComplexMatrix tmp (*this);
868 return tmp.solve (b);
869 }
870
871 ComplexMatrix
872 Matrix::solve (const ComplexMatrix& b, int& info) const
873 {
874 ComplexMatrix tmp (*this);
875 return tmp.solve (b, info);
876 }
877
878 ComplexMatrix
879 Matrix::solve (const ComplexMatrix& b, int& info, double& rcond) const
880 {
881 ComplexMatrix tmp (*this);
882 return tmp.solve (b, info, rcond);
883 }
884
885 ColumnVector
886 Matrix::solve (const ColumnVector& b) const
887 {
888 int info; double rcond;
889 return solve (b, info, rcond);
890 }
891
892 ColumnVector
893 Matrix::solve (const ColumnVector& b, int& info) const
894 {
895 double rcond;
896 return solve (b, info, rcond);
897 }
898
899 ColumnVector
900 Matrix::solve (const ColumnVector& b, int& info, double& rcond) const
901 {
902 ColumnVector retval;
903
904 int nr = rows ();
905 int nc = cols ();
906 if (nr == 0 || nc == 0 || nr != nc || nr != b.length ())
907 {
908 (*current_liboctave_error_handler)
909 ("matrix dimension mismatch solution of linear equations");
910 return ColumnVector ();
911 }
912
913 info = 0;
914 int *ipvt = new int [nr];
915
916 double *z = new double [nr];
917 double *tmp_data = dup (data (), length ());
918
919 F77_FCN (dgeco, DGECO) (tmp_data, nr, nr, ipvt, rcond, z);
920
921 volatile double rcond_plus_one = rcond + 1.0;
922 if (rcond_plus_one == 1.0)
923 {
924 info = -2;
925 }
926 else
927 {
928 int b_len = b.length ();
929
930 double *result = dup (b.data (), b_len);
931
932 F77_FCN (dgesl, DGESL) (tmp_data, nr, nr, ipvt, result, 0);
933
934 retval = ColumnVector (result, b_len);
935 }
936
937 delete [] tmp_data;
938 delete [] ipvt;
939 delete [] z;
940
941 return retval;
942 }
943
944 ComplexColumnVector
945 Matrix::solve (const ComplexColumnVector& b) const
946 {
947 ComplexMatrix tmp (*this);
948 return tmp.solve (b);
949 }
950
951 ComplexColumnVector
952 Matrix::solve (const ComplexColumnVector& b, int& info) const
953 {
954 ComplexMatrix tmp (*this);
955 return tmp.solve (b, info);
956 }
957
958 ComplexColumnVector
959 Matrix::solve (const ComplexColumnVector& b, int& info, double& rcond) const
960 {
961 ComplexMatrix tmp (*this);
962 return tmp.solve (b, info, rcond);
963 }
964
965 Matrix
966 Matrix::lssolve (const Matrix& b) const
967 {
968 int info;
969 int rank;
970 return lssolve (b, info, rank);
971 }
972
973 Matrix
974 Matrix::lssolve (const Matrix& b, int& info) const
975 {
976 int rank;
977 return lssolve (b, info, rank);
978 }
979
980 Matrix
981 Matrix::lssolve (const Matrix& b, int& info, int& rank) const
982 {
983 int nrhs = b.cols ();
984
985 int m = rows ();
986 int n = cols ();
987
988 if (m == 0 || n == 0 || m != b.rows ())
989 {
990 (*current_liboctave_error_handler)
991 ("matrix dimension mismatch in solution of least squares problem");
992 return Matrix ();
993 }
994
995 double *tmp_data = dup (data (), length ());
996
997 int nrr = m > n ? m : n;
998 Matrix result (nrr, nrhs);
999
1000 for (int j = 0; j < nrhs; j++)
1001 for (int i = 0; i < m; i++)
1002 result.elem (i, j) = b.elem (i, j);
1003
1004 double *presult = result.fortran_vec ();
1005
1006 int len_s = m < n ? m : n;
1007 double *s = new double [len_s];
1008 double rcond = -1.0;
1009 int lwork;
1010 if (m < n)
1011 lwork = 3*m + (2*m > nrhs ? (2*m > n ? 2*m : n) : (nrhs > n ? nrhs : n));
1012 else
1013 lwork = 3*n + (2*n > nrhs ? (2*n > m ? 2*n : m) : (nrhs > m ? nrhs : m));
1014
1015 double *work = new double [lwork];
1016
1017 F77_FCN (dgelss, DGELSS) (m, n, nrhs, tmp_data, m, presult, nrr, s,
1018 rcond, rank, work, lwork, info);
1019
1020 Matrix retval (n, nrhs);
1021 for (int j = 0; j < nrhs; j++)
1022 for (int i = 0; i < n; i++)
1023 retval.elem (i, j) = result.elem (i, j);
1024
1025 delete [] tmp_data;
1026 delete [] s;
1027 delete [] work;
1028
1029 return retval;
1030 }
1031
1032 ComplexMatrix
1033 Matrix::lssolve (const ComplexMatrix& b) const
1034 {
1035 ComplexMatrix tmp (*this);
1036 int info;
1037 int rank;
1038 return tmp.lssolve (b, info, rank);
1039 }
1040
1041 ComplexMatrix
1042 Matrix::lssolve (const ComplexMatrix& b, int& info) const
1043 {
1044 ComplexMatrix tmp (*this);
1045 int rank;
1046 return tmp.lssolve (b, info, rank);
1047 }
1048
1049 ComplexMatrix
1050 Matrix::lssolve (const ComplexMatrix& b, int& info, int& rank) const
1051 {
1052 ComplexMatrix tmp (*this);
1053 return tmp.lssolve (b, info, rank);
1054 }
1055
1056 ColumnVector
1057 Matrix::lssolve (const ColumnVector& b) const
1058 {
1059 int info;
1060 int rank;
1061 return lssolve (b, info, rank);
1062 }
1063
1064 ColumnVector
1065 Matrix::lssolve (const ColumnVector& b, int& info) const
1066 {
1067 int rank;
1068 return lssolve (b, info, rank);
1069 }
1070
1071 ColumnVector
1072 Matrix::lssolve (const ColumnVector& b, int& info, int& rank) const
1073 {
1074 int nrhs = 1;
1075
1076 int m = rows ();
1077 int n = cols ();
1078
1079 if (m == 0 || n == 0 || m != b.length ())
1080 {
1081 (*current_liboctave_error_handler)
1082 ("matrix dimension mismatch in solution of least squares problem");
1083 return ColumnVector ();
1084 }
1085
1086 double *tmp_data = dup (data (), length ());
1087
1088 int nrr = m > n ? m : n;
1089 ColumnVector result (nrr);
1090
1091 for (int i = 0; i < m; i++)
1092 result.elem (i) = b.elem (i);
1093
1094 double *presult = result.fortran_vec ();
1095
1096 int len_s = m < n ? m : n;
1097 double *s = new double [len_s];
1098 double rcond = -1.0;
1099 int lwork;
1100 if (m < n)
1101 lwork = 3*m + (2*m > nrhs ? (2*m > n ? 2*m : n) : (nrhs > n ? nrhs : n));
1102 else
1103 lwork = 3*n + (2*n > nrhs ? (2*n > m ? 2*n : m) : (nrhs > m ? nrhs : m));
1104
1105 double *work = new double [lwork];
1106
1107 F77_FCN (dgelss, DGELSS) (m, n, nrhs, tmp_data, m, presult, nrr, s,
1108 rcond, rank, work, lwork, info);
1109
1110 ColumnVector retval (n);
1111 for (int i = 0; i < n; i++)
1112 retval.elem (i) = result.elem (i);
1113
1114 delete [] tmp_data;
1115 delete [] s;
1116 delete [] work;
1117
1118 return retval;
1119 }
1120
1121 ComplexColumnVector
1122 Matrix::lssolve (const ComplexColumnVector& b) const
1123 {
1124 ComplexMatrix tmp (*this);
1125 return tmp.lssolve (b);
1126 }
1127
1128 ComplexColumnVector
1129 Matrix::lssolve (const ComplexColumnVector& b, int& info) const
1130 {
1131 ComplexMatrix tmp (*this);
1132 return tmp.lssolve (b, info);
1133 }
1134
1135 ComplexColumnVector
1136 Matrix::lssolve (const ComplexColumnVector& b, int& info, int& rank) const
1137 {
1138 ComplexMatrix tmp (*this);
1139 return tmp.lssolve (b, info, rank);
1140 }
1141
1142 Matrix&
1143 Matrix::operator += (const Matrix& a)
1144 {
1145 int nr = rows ();
1146 int nc = cols ();
1147 if (nr != a.rows () || nc != a.cols ())
1148 {
1149 (*current_liboctave_error_handler)
1150 ("nonconformant matrix += operation attempted");
1151 return *this;
1152 }
1153
1154 if (nr == 0 || nc == 0)
1155 return *this;
1156
1157 double *d = fortran_vec (); // Ensures only one reference to my privates!
1158
1159 add2 (d, a.data (), length ());
1160
1161 return *this;
1162 }
1163
1164 Matrix&
1165 Matrix::operator -= (const Matrix& a)
1166 {
1167 int nr = rows ();
1168 int nc = cols ();
1169 if (nr != a.rows () || nc != a.cols ())
1170 {
1171 (*current_liboctave_error_handler)
1172 ("nonconformant matrix -= operation attempted");
1173 return *this;
1174 }
1175
1176 if (nr == 0 || nc == 0)
1177 return *this;
1178
1179 double *d = fortran_vec (); // Ensures only one reference to my privates!
1180
1181 subtract2 (d, a.data (), length ());
1182
1183 return *this;
1184 }
1185
1186 Matrix&
1187 Matrix::operator += (const DiagMatrix& a)
1188 {
1189 if (rows () != a.rows () || cols () != a.cols ())
1190 {
1191 (*current_liboctave_error_handler)
1192 ("nonconformant matrix += operation attempted");
1193 return *this;
1194 }
1195
1196 for (int i = 0; i < a.length (); i++)
1197 elem (i, i) += a.elem (i, i);
1198
1199 return *this;
1200 }
1201
1202 Matrix&
1203 Matrix::operator -= (const DiagMatrix& a)
1204 {
1205 if (rows () != a.rows () || cols () != a.cols ())
1206 {
1207 (*current_liboctave_error_handler)
1208 ("nonconformant matrix += operation attempted");
1209 return *this;
1210 }
1211
1212 for (int i = 0; i < a.length (); i++)
1213 elem (i, i) -= a.elem (i, i);
1214
1215 return *this;
1216 }
1217
1218 // unary operations
1219
1220 Matrix
1221 Matrix::operator ! (void) const
1222 {
1223 int nr = rows ();
1224 int nc = cols ();
1225
1226 Matrix b (nr, nc);
1227
1228 for (int j = 0; j < nc; j++)
1229 for (int i = 0; i < nr; i++)
1230 b.elem (i, j) = ! elem (i, j);
1231
1232 return b;
1233 }
1234
1235 // column vector by row vector -> matrix operations
1236
1237 Matrix
1238 operator * (const ColumnVector& v, const RowVector& a)
1239 {
1240 int len = v.length ();
1241 int a_len = a.length ();
1242 if (len != a_len)
1243 {
1244 (*current_liboctave_error_handler)
1245 ("nonconformant vector multiplication attempted");
1246 return Matrix ();
1247 }
1248
1249 if (len == 0)
1250 return Matrix (len, len, 0.0);
1251
1252 double *c = new double [len * a_len];
1253
1254 F77_FCN (dgemm, DGEMM) ("N", "N", len, a_len, 1, 1.0, v.data (),
1255 len, a.data (), 1, 0.0, c, len, 1L, 1L);
1256
1257 return Matrix (c, len, a_len);
1258 }
1259
1260 // diagonal matrix by scalar -> matrix operations
1261
1262 Matrix
1263 operator + (const DiagMatrix& a, double s)
1264 {
1265 Matrix tmp (a.rows (), a.cols (), s);
1266 return a + tmp;
1267 }
1268
1269 Matrix
1270 operator - (const DiagMatrix& a, double s)
1271 {
1272 Matrix tmp (a.rows (), a.cols (), -s);
1273 return a + tmp;
1274 }
1275
1276 // scalar by diagonal matrix -> matrix operations
1277
1278 Matrix
1279 operator + (double s, const DiagMatrix& a)
1280 {
1281 Matrix tmp (a.rows (), a.cols (), s);
1282 return tmp + a;
1283 }
1284
1285 Matrix
1286 operator - (double s, const DiagMatrix& a)
1287 {
1288 Matrix tmp (a.rows (), a.cols (), s);
1289 return tmp - a;
1290 }
1291
1292 // matrix by diagonal matrix -> matrix operations
1293
1294 Matrix
1295 operator + (const Matrix& m, const DiagMatrix& a)
1296 {
1297 int nr = m.rows ();
1298 int nc = m.cols ();
1299 if (nr != a.rows () || nc != a.cols ())
1300 {
1301 (*current_liboctave_error_handler)
1302 ("nonconformant matrix addition attempted");
1303 return Matrix ();
1304 }
1305
1306 if (nr == 0 || nc == 0)
1307 return Matrix (nr, nc);
1308
1309 Matrix result (m);
1310 int a_len = a.length ();
1311 for (int i = 0; i < a_len; i++)
1312 result.elem (i, i) += a.elem (i, i);
1313
1314 return result;
1315 }
1316
1317 Matrix
1318 operator - (const Matrix& m, const DiagMatrix& a)
1319 {
1320 int nr = m.rows ();
1321 int nc = m.cols ();
1322 if (nr != a.rows () || nc != a.cols ())
1323 {
1324 (*current_liboctave_error_handler)
1325 ("nonconformant matrix subtraction attempted");
1326 return Matrix ();
1327 }
1328
1329 if (nr == 0 || nc == 0)
1330 return Matrix (nr, nc);
1331
1332 Matrix result (m);
1333 int a_len = a.length ();
1334 for (int i = 0; i < a_len; i++)
1335 result.elem (i, i) -= a.elem (i, i);
1336
1337 return result;
1338 }
1339
1340 Matrix
1341 operator * (const Matrix& m, const DiagMatrix& a)
1342 {
1343 int nr = m.rows ();
1344 int nc = m.cols ();
1345 int a_nr = a.rows ();
1346 int a_nc = a.cols ();
1347 if (nc != a_nr)
1348 {
1349 (*current_liboctave_error_handler)
1350 ("nonconformant matrix multiplication attempted");
1351 return Matrix ();
1352 }
1353
1354 if (nr == 0 || nc == 0 || a_nc == 0)
1355 return Matrix (nr, a_nc, 0.0);
1356
1357 double *c = new double [nr*a_nc];
1358 double *ctmp = 0;
1359
1360 int a_len = a.length ();
1361 for (int j = 0; j < a_len; j++)
1362 {
1363 int idx = j * nr;
1364 ctmp = c + idx;
1365 if (a.elem (j, j) == 1.0)
1366 {
1367 for (int i = 0; i < nr; i++)
1368 ctmp[i] = m.elem (i, j);
1369 }
1370 else if (a.elem (j, j) == 0.0)
1371 {
1372 for (int i = 0; i < nr; i++)
1373 ctmp[i] = 0.0;
1374 }
1375 else
1376 {
1377 for (int i = 0; i < nr; i++)
1378 ctmp[i] = a.elem (j, j) * m.elem (i, j);
1379 }
1380 }
1381
1382 if (a_nr < a_nc)
1383 {
1384 for (int i = nr * nc; i < nr * a_nc; i++)
1385 ctmp[i] = 0.0;
1386 }
1387
1388 return Matrix (c, nr, a_nc);
1389 }
1390
1391 // diagonal matrix by matrix -> matrix operations
1392
1393 Matrix
1394 operator + (const DiagMatrix& m, const Matrix& a)
1395 {
1396 int nr = m.rows ();
1397 int nc = m.cols ();
1398 if (nr != a.rows () || nc != a.cols ())
1399 {
1400 (*current_liboctave_error_handler)
1401 ("nonconformant matrix addition attempted");
1402 return Matrix ();
1403 }
1404
1405 if (nr == 0 || nc == 0)
1406 return Matrix (nr, nc);
1407
1408 Matrix result (a);
1409 for (int i = 0; i < m.length (); i++)
1410 result.elem (i, i) += m.elem (i, i);
1411
1412 return result;
1413 }
1414
1415 Matrix
1416 operator - (const DiagMatrix& m, const Matrix& a)
1417 {
1418 int nr = m.rows ();
1419 int nc = m.cols ();
1420 if (nr != a.rows () || nc != a.cols ())
1421 {
1422 (*current_liboctave_error_handler)
1423 ("nonconformant matrix subtraction attempted");
1424 return Matrix ();
1425 }
1426
1427 if (nr == 0 || nc == 0)
1428 return Matrix (nr, nc);
1429
1430 Matrix result (-a);
1431 for (int i = 0; i < m.length (); i++)
1432 result.elem (i, i) += m.elem (i, i);
1433
1434 return result;
1435 }
1436
1437 Matrix
1438 operator * (const DiagMatrix& m, const Matrix& a)
1439 {
1440 int nr = m.rows ();
1441 int nc = m.cols ();
1442 int a_nr = a.rows ();
1443 int a_nc = a.cols ();
1444 if (nc != a_nr)
1445 {
1446 (*current_liboctave_error_handler)
1447 ("nonconformant matrix multiplication attempted");
1448 return Matrix ();
1449 }
1450
1451 if (nr == 0 || nc == 0 || a_nc == 0)
1452 return Matrix (nr, a_nc, 0.0);
1453
1454 Matrix c (nr, a_nc);
1455
1456 for (int i = 0; i < m.length (); i++)
1457 {
1458 if (m.elem (i, i) == 1.0)
1459 {
1460 for (int j = 0; j < a_nc; j++)
1461 c.elem (i, j) = a.elem (i, j);
1462 }
1463 else if (m.elem (i, i) == 0.0)
1464 {
1465 for (int j = 0; j < a_nc; j++)
1466 c.elem (i, j) = 0.0;
1467 }
1468 else
1469 {
1470 for (int j = 0; j < a_nc; j++)
1471 c.elem (i, j) = m.elem (i, i) * a.elem (i, j);
1472 }
1473 }
1474
1475 if (nr > nc)
1476 {
1477 for (int j = 0; j < a_nc; j++)
1478 for (int i = a_nr; i < nr; i++)
1479 c.elem (i, j) = 0.0;
1480 }
1481
1482 return c;
1483 }
1484
1485 // matrix by matrix -> matrix operations
1486
1487 Matrix
1488 operator * (const Matrix& m, const Matrix& a)
1489 {
1490 int nr = m.rows ();
1491 int nc = m.cols ();
1492 int a_nr = a.rows ();
1493 int a_nc = a.cols ();
1494 if (nc != a_nr)
1495 {
1496 (*current_liboctave_error_handler)
1497 ("nonconformant matrix multiplication attempted");
1498 return Matrix ();
1499 }
1500
1501 if (nr == 0 || nc == 0 || a_nc == 0)
1502 return Matrix (nr, a_nc, 0.0);
1503
1504 int ld = nr;
1505 int lda = a_nr;
1506
1507 double *c = new double [nr*a_nc];
1508
1509 F77_FCN (dgemm, DGEMM) ("N", "N", nr, a_nc, nc, 1.0, m.data (),
1510 ld, a.data (), lda, 0.0, c, nr, 1L, 1L);
1511
1512 return Matrix (c, nr, a_nc);
1513 }
1514
1515 // other operations.
1516
1517 Matrix
1518 map (d_d_Mapper f, const Matrix& a)
1519 {
1520 Matrix b (a);
1521 b.map (f);
1522 return b;
1523 }
1524
1525 Matrix
1526 map (d_c_Mapper f, const ComplexMatrix& a)
1527 {
1528 int a_nc = a.cols ();
1529 int a_nr = a.rows ();
1530 Matrix b (a_nr, a_nc);
1531 for (int j = 0; j < a_nc; j++)
1532 for (int i = 0; i < a_nr; i++)
1533 b.elem (i, j) = f (a.elem (i, j));
1534 return b;
1535 }
1536
1537 void
1538 Matrix::map (d_d_Mapper f)
1539 {
1540 double *d = fortran_vec (); // Ensures only one reference to my privates!
1541
1542 for (int i = 0; i < length (); i++)
1543 d[i] = f (d[i]);
1544 }
1545
1546 // XXX FIXME XXX Do these really belong here? They should maybe be
1547 // cleaned up a bit, no? What about corresponding functions for the
1548 // Vectors?
1549
1550 Matrix
1551 Matrix::all (void) const
1552 {
1553 int nr = rows ();
1554 int nc = cols ();
1555 Matrix retval;
1556 if (nr > 0 && nc > 0)
1557 {
1558 if (nr == 1)
1559 {
1560 retval.resize (1, 1);
1561 retval.elem (0, 0) = 1.0;
1562 for (int j = 0; j < nc; j++)
1563 {
1564 if (elem (0, j) == 0.0)
1565 {
1566 retval.elem (0, 0) = 0.0;
1567 break;
1568 }
1569 }
1570 }
1571 else if (nc == 1)
1572 {
1573 retval.resize (1, 1);
1574 retval.elem (0, 0) = 1.0;
1575 for (int i = 0; i < nr; i++)
1576 {
1577 if (elem (i, 0) == 0.0)
1578 {
1579 retval.elem (0, 0) = 0.0;
1580 break;
1581 }
1582 }
1583 }
1584 else
1585 {
1586 retval.resize (1, nc);
1587 for (int j = 0; j < nc; j++)
1588 {
1589 retval.elem (0, j) = 1.0;
1590 for (int i = 0; i < nr; i++)
1591 {
1592 if (elem (i, j) == 0.0)
1593 {
1594 retval.elem (0, j) = 0.0;
1595 break;
1596 }
1597 }
1598 }
1599 }
1600 }
1601 return retval;
1602 }
1603
1604 Matrix
1605 Matrix::any (void) const
1606 {
1607 int nr = rows ();
1608 int nc = cols ();
1609 Matrix retval;
1610 if (nr > 0 && nc > 0)
1611 {
1612 if (nr == 1)
1613 {
1614 retval.resize (1, 1);
1615 retval.elem (0, 0) = 0.0;
1616 for (int j = 0; j < nc; j++)
1617 {
1618 if (elem (0, j) != 0.0)
1619 {
1620 retval.elem (0, 0) = 1.0;
1621 break;
1622 }
1623 }
1624 }
1625 else if (nc == 1)
1626 {
1627 retval.resize (1, 1);
1628 retval.elem (0, 0) = 0.0;
1629 for (int i = 0; i < nr; i++)
1630 {
1631 if (elem (i, 0) != 0.0)
1632 {
1633 retval.elem (0, 0) = 1.0;
1634 break;
1635 }
1636 }
1637 }
1638 else
1639 {
1640 retval.resize (1, nc);
1641 for (int j = 0; j < nc; j++)
1642 {
1643 retval.elem (0, j) = 0.0;
1644 for (int i = 0; i < nr; i++)
1645 {
1646 if (elem (i, j) != 0.0)
1647 {
1648 retval.elem (0, j) = 1.0;
1649 break;
1650 }
1651 }
1652 }
1653 }
1654 }
1655 return retval;
1656 }
1657
1658 Matrix
1659 Matrix::cumprod (void) const
1660 {
1661 Matrix retval;
1662
1663 int nr = rows ();
1664 int nc = cols ();
1665
1666 if (nr == 1)
1667 {
1668 retval.resize (1, nc);
1669 if (nc > 0)
1670 {
1671 double prod = elem (0, 0);
1672 for (int j = 0; j < nc; j++)
1673 {
1674 retval.elem (0, j) = prod;
1675 if (j < nc - 1)
1676 prod *= elem (0, j+1);
1677 }
1678 }
1679 }
1680 else if (nc == 1)
1681 {
1682 retval.resize (nr, 1);
1683 if (nr > 0)
1684 {
1685 double prod = elem (0, 0);
1686 for (int i = 0; i < nr; i++)
1687 {
1688 retval.elem (i, 0) = prod;
1689 if (i < nr - 1)
1690 prod *= elem (i+1, 0);
1691 }
1692 }
1693 }
1694 else
1695 {
1696 retval.resize (nr, nc);
1697 if (nr > 0 && nc > 0)
1698 {
1699 for (int j = 0; j < nc; j++)
1700 {
1701 double prod = elem (0, j);
1702 for (int i = 0; i < nr; i++)
1703 {
1704 retval.elem (i, j) = prod;
1705 if (i < nr - 1)
1706 prod *= elem (i+1, j);
1707 }
1708 }
1709 }
1710 }
1711 return retval;
1712 }
1713
1714 Matrix
1715 Matrix::cumsum (void) const
1716 {
1717 Matrix retval;
1718
1719 int nr = rows ();
1720 int nc = cols ();
1721
1722 if (nr == 1)
1723 {
1724 retval.resize (1, nc);
1725 if (nc > 0)
1726 {
1727 double sum = elem (0, 0);
1728 for (int j = 0; j < nc; j++)
1729 {
1730 retval.elem (0, j) = sum;
1731 if (j < nc - 1)
1732 sum += elem (0, j+1);
1733 }
1734 }
1735 }
1736 else if (nc == 1)
1737 {
1738 retval.resize (nr, 1);
1739 if (nr > 0)
1740 {
1741 double sum = elem (0, 0);
1742 for (int i = 0; i < nr; i++)
1743 {
1744 retval.elem (i, 0) = sum;
1745 if (i < nr - 1)
1746 sum += elem (i+1, 0);
1747 }
1748 }
1749 }
1750 else
1751 {
1752 retval.resize (nr, nc);
1753 if (nr > 0 && nc > 0)
1754 {
1755 for (int j = 0; j < nc; j++)
1756 {
1757 double sum = elem (0, j);
1758 for (int i = 0; i < nr; i++)
1759 {
1760 retval.elem (i, j) = sum;
1761 if (i < nr - 1)
1762 sum += elem (i+1, j);
1763 }
1764 }
1765 }
1766 }
1767 return retval;
1768 }
1769
1770 Matrix
1771 Matrix::prod (void) const
1772 {
1773 Matrix retval;
1774
1775 int nr = rows ();
1776 int nc = cols ();
1777
1778 if (nr == 1)
1779 {
1780 retval.resize (1, 1);
1781 retval.elem (0, 0) = 1.0;
1782 for (int j = 0; j < nc; j++)
1783 retval.elem (0, 0) *= elem (0, j);
1784 }
1785 else if (nc == 1)
1786 {
1787 retval.resize (1, 1);
1788 retval.elem (0, 0) = 1.0;
1789 for (int i = 0; i < nr; i++)
1790 retval.elem (0, 0) *= elem (i, 0);
1791 }
1792 else
1793 {
1794 if (nc == 0)
1795 {
1796 retval.resize (1, 1);
1797 retval.elem (0, 0) = 1.0;
1798 }
1799 else
1800 retval.resize (1, nc);
1801
1802 for (int j = 0; j < nc; j++)
1803 {
1804 retval.elem (0, j) = 1.0;
1805 for (int i = 0; i < nr; i++)
1806 retval.elem (0, j) *= elem (i, j);
1807 }
1808 }
1809 return retval;
1810 }
1811
1812 Matrix
1813 Matrix::sum (void) const
1814 {
1815 Matrix retval;
1816
1817 int nr = rows ();
1818 int nc = cols ();
1819
1820 if (nr == 1)
1821 {
1822 retval.resize (1, 1);
1823 retval.elem (0, 0) = 0.0;
1824 for (int j = 0; j < nc; j++)
1825 retval.elem (0, 0) += elem (0, j);
1826 }
1827 else if (nc == 1)
1828 {
1829 retval.resize (1, 1);
1830 retval.elem (0, 0) = 0.0;
1831 for (int i = 0; i < nr; i++)
1832 retval.elem (0, 0) += elem (i, 0);
1833 }
1834 else
1835 {
1836 if (nc == 0)
1837 {
1838 retval.resize (1, 1);
1839 retval.elem (0, 0) = 0.0;
1840 }
1841 else
1842 retval.resize (1, nc);
1843
1844 for (int j = 0; j < nc; j++)
1845 {
1846 retval.elem (0, j) = 0.0;
1847 for (int i = 0; i < nr; i++)
1848 retval.elem (0, j) += elem (i, j);
1849 }
1850 }
1851 return retval;
1852 }
1853
1854 Matrix
1855 Matrix::sumsq (void) const
1856 {
1857 Matrix retval;
1858
1859 int nr = rows ();
1860 int nc = cols ();
1861
1862 if (nr == 1)
1863 {
1864 retval.resize (1, 1);
1865 retval.elem (0, 0) = 0.0;
1866 for (int j = 0; j < nc; j++)
1867 {
1868 double d = elem (0, j);
1869 retval.elem (0, 0) += d * d;
1870 }
1871 }
1872 else if (nc == 1)
1873 {
1874 retval.resize (1, 1);
1875 retval.elem (0, 0) = 0.0;
1876 for (int i = 0; i < nr; i++)
1877 {
1878 double d = elem (i, 0);
1879 retval.elem (0, 0) += d * d;
1880 }
1881 }
1882 else
1883 {
1884 retval.resize (1, nc);
1885 for (int j = 0; j < nc; j++)
1886 {
1887 retval.elem (0, j) = 0.0;
1888 for (int i = 0; i < nr; i++)
1889 {
1890 double d = elem (i, j);
1891 retval.elem (0, j) += d * d;
1892 }
1893 }
1894 }
1895 return retval;
1896 }
1897
1898 ColumnVector
1899 Matrix::diag (void) const
1900 {
1901 return diag (0);
1902 }
1903
1904 ColumnVector
1905 Matrix::diag (int k) const
1906 {
1907 int nnr = rows ();
1908 int nnc = cols ();
1909 if (k > 0)
1910 nnc -= k;
1911 else if (k < 0)
1912 nnr += k;
1913
1914 ColumnVector d;
1915
1916 if (nnr > 0 && nnc > 0)
1917 {
1918 int ndiag = (nnr < nnc) ? nnr : nnc;
1919
1920 d.resize (ndiag);
1921
1922 if (k > 0)
1923 {
1924 for (int i = 0; i < ndiag; i++)
1925 d.elem (i) = elem (i, i+k);
1926 }
1927 else if ( k < 0)
1928 {
1929 for (int i = 0; i < ndiag; i++)
1930 d.elem (i) = elem (i-k, i);
1931 }
1932 else
1933 {
1934 for (int i = 0; i < ndiag; i++)
1935 d.elem (i) = elem (i, i);
1936 }
1937 }
1938 else
1939 cerr << "diag: requested diagonal out of range\n";
1940
1941 return d;
1942 }
1943
1944 ColumnVector
1945 Matrix::row_min (void) const
1946 {
1947 ColumnVector result;
1948
1949 int nr = rows ();
1950 int nc = cols ();
1951
1952 if (nr > 0 && nc > 0)
1953 {
1954 result.resize (nr);
1955
1956 for (int i = 0; i < nr; i++)
1957 {
1958 double res = elem (i, 0);
1959 for (int j = 1; j < nc; j++)
1960 if (elem (i, j) < res)
1961 res = elem (i, j);
1962 result.elem (i) = res;
1963 }
1964 }
1965
1966 return result;
1967 }
1968
1969 ColumnVector
1970 Matrix::row_min_loc (void) const
1971 {
1972 ColumnVector result;
1973
1974 int nr = rows ();
1975 int nc = cols ();
1976
1977 if (nr > 0 && nc > 0)
1978 {
1979 result.resize (nr);
1980
1981 for (int i = 0; i < nr; i++)
1982 {
1983 int res = 0;
1984 for (int j = 0; j < nc; j++)
1985 if (elem (i, j) < elem (i, res))
1986 res = j;
1987 result.elem (i) = (double) (res + 1);
1988 }
1989 }
1990
1991 return result;
1992 }
1993
1994 ColumnVector
1995 Matrix::row_max (void) const
1996 {
1997 ColumnVector result;
1998
1999 int nr = rows ();
2000 int nc = cols ();
2001
2002 if (nr > 0 && nc > 0)
2003 {
2004 result.resize (nr);
2005
2006 for (int i = 0; i < nr; i++)
2007 {
2008 double res = elem (i, 0);
2009 for (int j = 1; j < nc; j++)
2010 if (elem (i, j) > res)
2011 res = elem (i, j);
2012 result.elem (i) = res;
2013 }
2014 }
2015
2016 return result;
2017 }
2018
2019 ColumnVector
2020 Matrix::row_max_loc (void) const
2021 {
2022 ColumnVector result;
2023
2024 int nr = rows ();
2025 int nc = cols ();
2026
2027 if (nr > 0 && nc > 0)
2028 {
2029 result.resize (nr);
2030
2031 for (int i = 0; i < nr; i++)
2032 {
2033 int res = 0;
2034 for (int j = 0; j < nc; j++)
2035 if (elem (i, j) > elem (i, res))
2036 res = j;
2037 result.elem (i) = (double) (res + 1);
2038 }
2039 }
2040
2041 return result;
2042 }
2043
2044 RowVector
2045 Matrix::column_min (void) const
2046 {
2047 RowVector result;
2048
2049 int nr = rows ();
2050 int nc = cols ();
2051
2052 if (nr > 0 && nc > 0)
2053 {
2054 result.resize (nc);
2055
2056 for (int j = 0; j < nc; j++)
2057 {
2058 double res = elem (0, j);
2059 for (int i = 1; i < nr; i++)
2060 if (elem (i, j) < res)
2061 res = elem (i, j);
2062 result.elem (j) = res;
2063 }
2064 }
2065
2066 return result;
2067 }
2068 RowVector
2069 Matrix::column_min_loc (void) const
2070 {
2071 RowVector result;
2072
2073 int nr = rows ();
2074 int nc = cols ();
2075
2076 if (nr > 0 && nc > 0)
2077 {
2078 result.resize (nc);
2079
2080 for (int j = 0; j < nc; j++)
2081 {
2082 int res = 0;
2083 for (int i = 0; i < nr; i++)
2084 if (elem (i, j) < elem (res, j))
2085 res = i;
2086 result.elem (j) = (double) (res + 1);
2087 }
2088 }
2089
2090 return result;
2091 }
2092
2093
2094 RowVector
2095 Matrix::column_max (void) const
2096 {
2097 RowVector result;
2098
2099 int nr = rows ();
2100 int nc = cols ();
2101
2102 if (nr > 0 && nc > 0)
2103 {
2104 result.resize (nc);
2105
2106 for (int j = 0; j < nc; j++)
2107 {
2108 double res = elem (0, j);
2109 for (int i = 1; i < nr; i++)
2110 if (elem (i, j) > res)
2111 res = elem (i, j);
2112 result.elem (j) = res;
2113 }
2114 }
2115
2116 return result;
2117 }
2118
2119 RowVector
2120 Matrix::column_max_loc (void) const
2121 {
2122 RowVector result;
2123
2124 int nr = rows ();
2125 int nc = cols ();
2126
2127 if (nr > 0 && nc > 0)
2128 {
2129 result.resize (nc);
2130
2131 for (int j = 0; j < nc; j++)
2132 {
2133 int res = 0;
2134 for (int i = 0; i < nr; i++)
2135 if (elem (i, j) > elem (res, j))
2136 res = i;
2137 result.elem (j) = (double) (res + 1);
2138 }
2139 }
2140
2141 return result;
2142 }
2143
2144 ostream&
2145 operator << (ostream& os, const Matrix& a)
2146 {
2147 // int field_width = os.precision () + 7;
2148
2149 for (int i = 0; i < a.rows (); i++)
2150 {
2151 for (int j = 0; j < a.cols (); j++)
2152 os << " " /* setw (field_width) */ << a.elem (i, j);
2153 os << "\n";
2154 }
2155 return os;
2156 }
2157
2158 istream&
2159 operator >> (istream& is, Matrix& a)
2160 {
2161 int nr = a.rows ();
2162 int nc = a.cols ();
2163
2164 if (nr < 1 || nc < 1)
2165 is.clear (ios::badbit);
2166 else
2167 {
2168 double tmp;
2169 for (int i = 0; i < nr; i++)
2170 for (int j = 0; j < nc; j++)
2171 {
2172 is >> tmp;
2173 if (is)
2174 a.elem (i, j) = tmp;
2175 else
2176 break;
2177 }
2178 }
2179
2180 return is;
2181 }
2182
2183 // Read an array of data from a file in binary format.
2184
2185 int
2186 Matrix::read (FILE *fptr, const char *type)
2187 {
2188 // Allocate buffer pointers.
2189
2190 union
2191 {
2192 void *vd;
2193 char *ch;
2194 u_char *uc;
2195 short *sh;
2196 u_short *us;
2197 int *in;
2198 u_int *ui;
2199 long *ln;
2200 u_long *ul;
2201 float *fl;
2202 double *db;
2203 }
2204 buf;
2205
2206 // Convert data to double.
2207
2208 if (! type)
2209 {
2210 (*current_liboctave_error_handler)
2211 ("fread: invalid NULL type parameter");
2212 return 0;
2213 }
2214
2215 int count;
2216 int nitems = length ();
2217
2218 double *d = fortran_vec (); // Ensures only one reference to my privates!
2219
2220 #define DO_FREAD(TYPE,ELEM) \
2221 do \
2222 { \
2223 size_t size = sizeof (TYPE); \
2224 buf.ch = new char [size * nitems]; \
2225 count = fread (buf.ch, size, nitems, fptr); \
2226 for (int k = 0; k < count; k++) \
2227 d[k] = buf.ELEM[k]; \
2228 delete [] buf.ch; \
2229 } \
2230 while (0)
2231
2232 if (strcasecmp (type, "double") == 0)
2233 DO_FREAD (double, db);
2234 else if (strcasecmp (type, "char") == 0)
2235 DO_FREAD (char, ch);
2236 else if (strcasecmp (type, "uchar") == 0)
2237 DO_FREAD (u_char, uc);
2238 else if (strcasecmp (type, "short") == 0)
2239 DO_FREAD (short, sh);
2240 else if (strcasecmp (type, "ushort") == 0)
2241 DO_FREAD (u_short, us);
2242 else if (strcasecmp (type, "int") == 0)
2243 DO_FREAD (int, in);
2244 else if (strcasecmp (type, "uint") == 0)
2245 DO_FREAD (u_int, ui);
2246 else if (strcasecmp (type, "long") == 0)
2247 DO_FREAD (long, ul);
2248 else if (strcasecmp (type, "float") == 0)
2249 DO_FREAD (float, fl);
2250 else
2251 {
2252 (*current_liboctave_error_handler)
2253 ("fread: invalid NULL type parameter");
2254 return 0;
2255 }
2256
2257 return count;
2258 }
2259
2260 // Write the data array to a file in binary format.
2261
2262 int
2263 Matrix::write (FILE *fptr, const char *type)
2264 {
2265 // Allocate buffer pointers.
2266
2267 union
2268 {
2269 void *vd;
2270 char *ch;
2271 u_char *uc;
2272 short *sh;
2273 u_short *us;
2274 int *in;
2275 u_int *ui;
2276 long *ln;
2277 u_long *ul;
2278 float *fl;
2279 double *db;
2280 }
2281 buf;
2282
2283 int nitems = length ();
2284
2285 double *d = fortran_vec ();
2286
2287 // Convert from double to correct size.
2288
2289 if (! type)
2290 {
2291 (*current_liboctave_error_handler)
2292 ("fwrite: invalid NULL type parameter");
2293 return 0;
2294 }
2295
2296 size_t size;
2297 int count;
2298
2299 #define DO_FWRITE(TYPE,ELEM) \
2300 do \
2301 { \
2302 size = sizeof (TYPE); \
2303 buf.ELEM = new TYPE [nitems]; \
2304 for (int k = 0; k < nitems; k++) \
2305 buf.ELEM[k] = (TYPE) d[k]; \
2306 count = fwrite (buf.ELEM, size, nitems, fptr); \
2307 delete [] buf.ELEM; \
2308 } \
2309 while (0)
2310
2311 if (strcasecmp (type, "double") == 0)
2312 DO_FWRITE (double, db);
2313 else if (strcasecmp (type, "char") == 0)
2314 DO_FWRITE (char, ch);
2315 else if (strcasecmp (type, "uchar") == 0)
2316 DO_FWRITE (u_char, uc);
2317 else if (strcasecmp (type, "short") == 0)
2318 DO_FWRITE (short, sh);
2319 else if (strcasecmp (type, "ushort") == 0)
2320 DO_FWRITE (u_short, us);
2321 else if (strcasecmp (type, "int") == 0)
2322 DO_FWRITE (int, in);
2323 else if (strcasecmp (type, "uint") == 0)
2324 DO_FWRITE (u_int, ui);
2325 else if (strcasecmp (type, "long") == 0)
2326 DO_FWRITE (long, ln);
2327 else if (strcasecmp (type, "ulong") == 0)
2328 DO_FWRITE (u_long, ul);
2329 else if (strcasecmp (type, "float") == 0)
2330 DO_FWRITE (float, fl);
2331 else
2332 {
2333 (*current_liboctave_error_handler)
2334 ("fwrite: unrecognized type parameter %s", type);
2335 return 0;
2336 }
2337
2338 return count;
2339 }
2340 #endif
2341
2342 /*
2343 ;;; Local Variables: ***
2344 ;;; mode: C++ ***
2345 ;;; page-delimiter: "^/\\*" ***
2346 ;;; End: ***
2347 */