home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 9 / FreshFishVol9-CD2.bin / bbs / gnu / octave-1.1.1-src.lha / octave-1.1.1 / liboctave / dMatrix.cc < prev    next >
Encoding:
C/C++ Source or Header  |  1995-02-03  |  47.6 KB  |  2,536 lines

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