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