Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

table.cc

Go to the documentation of this file.
00001 // table.cc
00002 // SuperMix version 1.0  C++ source file
00003 //
00004 // Copyright (c) 1999 California Institute of Technology.
00005 // All rights reserved.
00006 //
00007 // Redistribution and use in source and binary forms for noncommercial
00008 // purposes are permitted provided that the above copyright notice and
00009 // this paragraph are duplicated in all such forms and that any
00010 // documentation and other materials related to such distribution and
00011 // use acknowledge that the software was developed by California
00012 // Institute of Technology. Redistribution and/or use in source or
00013 // binary forms is not permitted for any commercial purpose. Use of
00014 // this software does not include a permitted use of the Institute's
00015 // name or trademark for any purpose.
00016 //
00017 // DISCLAIMER:
00018 // THIS SOFTWARE AND/OR RELATED MATERIALS ARE PROVIDED "AS-IS" WITHOUT
00019 // WARRANTY OF ANY KIND INCLUDING ANY WARRANTIES OF PERFORMANCE OR
00020 // MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE OR PURPOSE (AS SET
00021 // FORTH IN UCC 23212-2313) OR FOR ANY PURPOSE WHATSOEVER, FOR THE
00022 // LICENSED PRODUCT, HOWEVER USED.  IN NO EVENT SHALL CALTECH/JPL BE
00023 // LIABLE FOR ANY DAMAGES AND/OR COSTS, INCLUDING BUT NOT LIMITED TO
00024 // INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING ECONOMIC
00025 // DAMAGE OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF
00026 // WHETHER CALTECH/JPL SHALL BE ADVISED, HAVE REASON TO KNOW, OR IN
00027 // FACT SHALL KNOW OF THE POSSIBILITY.  THE USER BEARS ALL RISK
00028 // RELATING TO QUALITY AND PERFORMANCE OF THE SOFTWARE AND/OR RELATED
00029 // MATERIALS.
00030 //
00031 // Change history:
00032 // 4/26/00:  changed to support copying of empty matrices, make_empty()
00033 // 7/6/99:   changed "table" to "matrix". Included typedefs for compatibility
00034 // 11/11/98: Changed table access to new syntax
00035 // 7/31/98:  added out_separator() static member functions
00036 // 7/30/98:  Enhanced show(), added <<
00037 // 7/28/98:  Added <iostream.h>, since SIScmplx.h doesn't any more
00038 // 7/7/98:   Added reindex(); code fully tested
00039 // 2/5/98:   Added new constructor and operator = with datafile argument
00040 //           to real_table class
00041 // 12/18/97: Special version with show() member function
00042 // 12/12/97: "fully" tested with calc
00043 // 12/10/97: fixed a bug in complex_table::imaginary(). tests o.k. w/ calc
00044 // 11/24/97: improved real_table resize(), added real() and imaginary(),
00045 //           fillrow() and fillcol(), and constructors using vectors.
00046 // 11/17/97: improved rowswap(), added sum()
00047 // 11/12/97: changed void functions to return Lvalue *this
00048 // 11/8/97:  fixed pointer bugs in +=, -=, etc. Improved reallocate.
00049 // 11/7/97:  added checks for A = A and A.copy(A), so these constructs
00050 //           behave properly (oops!). Also fixed copy constructor.
00051 // 11/3/97:  New operator =, with an Rvalue RHS. Not fully tested yet.
00052 // 10/26/97: added additional functionality; compiles o.k.
00053 // 10/17/97: took out the ugly workaround; minor change and compiles o.k.
00054 // 10/15/97: fixed some minor syntax bugs; added an ugly workaround in
00055 //           construct() to get it to compile with Sun CC.
00056 
00057 #include "table.h"
00058 #include "vector.h"
00059 #include "datafile.h"
00060 #include <iostream.h>
00061 #include <iomanip.h>
00062 
00063 // Useful functions:
00064 
00065 static inline int min(int a, int b)  { return (a < b)? a : b; }
00066 static inline int max(int a, int b)  { return (a > b)? a : b; }
00067 static inline int length(int a, int b)
00068 { int n = b - a + 1; return (n < 0)? 0 : n; }
00069 
00070 // Determine the result index mode which maximizes number of elements:
00071 static v_index_mode ResultModeMax(const v_index_mode a, const v_index_mode b)
00072 {
00073   if((a == Index_S)||(b == Index_S)) return Index_S;
00074   else if ((a == Index_C)||(b == Index_C)) return Index_C;
00075   else return Index_1;
00076 }
00077 
00078 // i/o formatting static variable
00079 
00080 static string _out_separator("\n");
00081 
00082 
00083 // ************************************************************************
00084 // real_matrix definitions:
00085 
00086 
00087 // matrix output:
00088 
00089 ostream & operator << (ostream & s, const real_matrix & A)
00090 {
00091   ios::streamsize w = s.width();
00092   if (A.Lminindex() <= A.Lmaxindex()) { // matrix isn't empty
00093     { // output first row (using a row alias)
00094       real_vector v(const_cast<double *>(A[A.Lminindex()]), A.Rsize, A.Rmode);
00095       v.maxindex(A.Rmaxindex());  // set same valid index range
00096       s << v;
00097     }
00098     // output remaining rows
00099     for (int i = A.Lminindex() + 1; i <= A.Lmaxindex(); ++i) {
00100       real_vector v(const_cast<double *>(A[i]), A.Rsize, A.Rmode);
00101       v.maxindex(A.Rmaxindex());
00102       s << _out_separator << setw(w) << v;
00103     }
00104   }
00105   return s << setw(0);  // just in case no output was generated
00106 }
00107 
00108 real_matrix & real_matrix::show(ostream & s)
00109 {
00110   s << endl << *this << endl;
00111   return *this;
00112 }
00113 
00114 real_matrix & real_matrix::show()
00115 {
00116   return show(cout);
00117 }
00118 
00119 const real_matrix & real_matrix::show(ostream & s) const
00120 {
00121   s << endl << *this << endl;
00122   return *this;
00123 }
00124 
00125 const real_matrix & real_matrix::show() const
00126 {
00127   return show(cout);
00128 }
00129 
00130 string real_matrix::out_separator()
00131 { return _out_separator; }
00132 
00133 string real_matrix::out_separator(const string & s)
00134 { string temp = _out_separator; _out_separator = s; return temp; }
00135 
00136 string real_matrix::out_separator(const char * const s)
00137 { string temp = _out_separator; _out_separator = s; return temp; }
00138 
00139 string real_matrix::out_separator(const char s)
00140 { string temp = _out_separator; _out_separator = s; return temp; }
00141 
00142 //-------------------------------------------------------------------------
00143 // construct() do the real work of matrix construction
00144 
00145 void real_matrix::construct(const int n, const int m,
00146                            const v_index_mode tl,
00147                            const v_index_mode tr)
00148 {
00149   // set up matrix private member variables
00150   internal_Lsize = (n >= 0) ? n : 0;
00151   internal_Rsize = (m >= 0) ? m : 0;
00152   internal_Lmode = tl;
00153   internal_Rmode = tr;
00154   trashptr = & trash;
00155 
00156   // determine number of columns and rows requested:
00157   int nrows = Lsize; if (Lmode == Index_S) nrows += (nrows + 1);
00158   int ncols = Rsize; if (Rmode == Index_S) ncols += (ncols + 1);
00159 
00160   // allocate memory for the array of pointers to rows, if required:
00161   data = delete_pointer_data = (nrows) ? new double *[nrows] : 0;
00162 
00163   // allocate memory for the array of data elements, if required:
00164   int nelem = ncols * nrows;
00165   if (nelem) {
00166     // need to allocate memory
00167     delete_pointer_rows = new double[nelem];
00168     if (delete_pointer_rows == 0) {
00169       // memory alloc failed, so give back pointer array as well
00170       delete [] delete_pointer_data;
00171       data = delete_pointer_data = 0;
00172     }
00173   }
00174   else {
00175     // no allocation necessary, nelem == 0
00176     delete_pointer_rows = 0;
00177   }
00178 
00179   // now that allocation has been attempted, update sizes and index limits
00180   if (data == 0) {
00181     // no pointer array
00182     internal_Lsize = nrows = 0; // in case they weren't already
00183     if (Lmode == Index_S) data = & trashptr; //so **data = trash
00184     Lmaxindexvalue = (Lmode == Index_1) ? 0 : -1;
00185   }
00186   else {
00187     // pointer array exists, original Lsize and nrows o.k.
00188     switch (Lmode) {
00189     case Index_C: {
00190       Lmaxindexvalue = Lsize - 1;
00191       break;
00192     }
00193     case Index_1: {
00194       Lmaxindexvalue = Lsize;
00195       --data;        // so *delete_pointer_data = data[1]
00196       break;
00197     }
00198     case Index_S: {
00199       Lmaxindexvalue = Lsize;
00200       data += Lsize; // so *delete_pointer_data = data[-Lsize]
00201       break;
00202     }
00203     } //switch
00204   } //else
00205   // final left index setup step is to set Lminindexvalue:
00206   switch (Lmode) {
00207   case Index_C: { Lminindexvalue = 0; break; }
00208   case Index_1: { Lminindexvalue = 1; break; }
00209   case Index_S: { Lminindexvalue = -Lmaxindexvalue; break; }
00210   }
00211   // setup of left index complete
00212 
00213   // now for the right index:
00214   if (delete_pointer_rows == 0) {
00215     // no data elements
00216     internal_Rsize = ncols = 0; // in case they weren't already
00217     Rmaxindexvalue = (Rmode == Index_1) ? 0 : -1;
00218   }
00219   else {
00220     // data array exists, original Rsize and ncols o.k.
00221     Rmaxindexvalue = (Rmode == Index_C) ? Rsize - 1 : Rsize;
00222   }
00223   switch (Rmode) {
00224   case Index_C: { Rminindexvalue = 0; break; }
00225   case Index_1: { Rminindexvalue = 1; break; }
00226   case Index_S: { Rminindexvalue = -Rmaxindexvalue; break; }
00227   }
00228   // setup of right index complete
00229 
00230     
00231   // now fill pointer array with pointers to the [0] element of each row
00232   int i, offset; // offset is the pointer offset into each row due to Rmode
00233   switch (Rmode) {
00234   default:
00235   case Index_C: { offset = 0; break; }
00236   case Index_1: { offset = -1; break; }
00237   case Index_S: { offset = Rsize; break; }
00238   }
00239   if (ncols == 0) offset = 0; // no offset if no data
00240   for(i = Lminindexvalue; i <= Lmaxindexvalue; ++i, offset += ncols)
00241     // this loop will only execute if pointer memory was allocated
00242     data[i] = delete_pointer_rows + offset;
00243 
00244 } // construct()
00245 
00246 //-------------------------------------------------------------------------
00247 // copy constructors:
00248 
00249 real_matrix::real_matrix(const real_matrix & B)
00250   : Lsize(internal_Lsize), Rsize(internal_Rsize), 
00251     Lmode(internal_Lmode), Rmode(internal_Rmode)
00252 {
00253   construct(B.Lsize, B.Rsize, B.Lmode, B.Rmode);
00254   int i,j;
00255   // the following loop will work even if alloc for B failed and
00256   // B.Lmode == Index_S.  In this case, the contents of trash will be
00257   // copied.
00258   for (i = Lminindex(); i <= Lmaxindex(); ++i)
00259     for (j = Rminindex(); j <= Rmaxindex(); ++j)
00260       data[i][j] = B[i][j];
00261 
00262   if(B.is_empty())
00263     make_empty();
00264   else {
00265     Lmaxindex(B.Lmaxindex());
00266     Rmaxindex(B.Rmaxindex());
00267   }
00268 }
00269 
00270 real_matrix::real_matrix(const real_vector & v)
00271   : Lsize(internal_Lsize), Rsize(internal_Rsize), 
00272     Lmode(internal_Lmode), Rmode(internal_Rmode)
00273 {
00274   construct(v.size, 1, v.mode, Index_1);
00275   // the following loop will work even if alloc for v failed and
00276   // v.mode == Index_S.  In this case, the contents of trash will be
00277   // copied.
00278   for (int i = Lminindex(); i <= Lmaxindex(); ++i)
00279     data[i][1] = v[i];
00280 
00281   Lmaxindexvalue = v.maxindex();
00282   Lminindexvalue = v.minindex();
00283 }
00284 
00285 real_matrix::real_matrix(const datafile & D)
00286   : Lsize(internal_Lsize), Rsize(internal_Rsize), 
00287     Lmode(internal_Lmode), Rmode(internal_Rmode)
00288 {
00289   const real_matrix * p = D.table();
00290   construct(p->Lsize, p->Rsize, p->Lmode, p->Rmode);
00291   int i,j;
00292   for (i = Lminindex(); i <= Lmaxindex(); ++i)
00293     for (j = Rminindex(); j <= Rmaxindex(); ++j)
00294       data[i][j] = p->data[i][j];
00295 
00296   if(p->is_empty())
00297     make_empty();
00298   else {
00299     Lmaxindex(p->Lmaxindex());
00300     Rmaxindex(p->Rmaxindex());
00301   }
00302 }
00303 
00304 //-------------------------------------------------------------------------
00305 // reindex()  change the index modes
00306 
00307 real_matrix & real_matrix::reindex(const v_index_mode Lnew, const v_index_mode Rnew)
00308 {
00309   if (Lnew == Lmode && Rnew == Rmode) return *this;
00310 
00311   // some index change is needed; calculate dimensions of matrix
00312   int nrows = (Lmode == Index_S) ? 2*Lsize + 1 : Lsize;
00313   int ncols = (Rmode == Index_S) ? 2*Rsize + 1 : Rsize;
00314   
00315   // any dimension with new Index_S needs an odd number of values
00316   if (Lnew == Index_S && (nrows>>1)<<1 == nrows) {  // nrows even
00317     // since nrows even, Lmode can't be Index_S
00318     reallocate(Lsize+1,Rsize,Lmode,Rmode);
00319     nrows = Lsize; // the new Lsize
00320   }
00321   if (Rnew == Index_S && (ncols>>1)<<1 == ncols) {  // ncols even
00322     reallocate(Lsize,Rsize+1,Lmode,Rmode);
00323     ncols = Rsize; // the new Rsize
00324   }
00325 
00326   // finally, if resulting matrix is empty, just reallocate to fix modes
00327   if (delete_pointer_rows == 0)  {
00328     reallocate(0,0,Lnew,Rnew);
00329     return *this;
00330   }
00331 
00332   // if here, the matrix has some elements
00333 
00334   // set up new left indexing:
00335   if (Lnew != Lmode) { // reindexing required of Left Index
00336     int ptr_offset; // offset into row pointer array for data[0]
00337     switch (Lnew) {
00338     default:
00339       { return *this; } // unknown mode, so do nothing
00340     case Index_C:
00341       { ptr_offset = 0; break; }
00342     case Index_1:
00343       { ptr_offset = -1; break; }
00344     case Index_S:
00345       { ptr_offset = (nrows - 1)/2; break; }
00346     } // switch
00347     internal_Lsize = (Lnew == Index_S) ? ptr_offset : nrows;
00348     Lminindexvalue = -ptr_offset; 
00349     Lmaxindexvalue = Lminindexvalue + nrows - 1;
00350     data = delete_pointer_data + ptr_offset;
00351     internal_Lmode = Lnew;
00352   }
00353 
00354   // now for the right indexing:
00355   if (Rnew != Rmode) {
00356     int ptr_offset; // pointer offset into a row to data[][0]
00357 
00358     switch (Rnew) { // the new offset
00359     default:
00360       { return *this; } // unknown mode, so do nothing
00361     case Index_C:
00362       { ptr_offset = 0; break; }
00363     case Index_1:
00364       { ptr_offset = -1; break; }
00365     case Index_S:
00366       { ptr_offset = (ncols - 1)/2; break; }
00367     } // switch
00368     int old_Rsize = Rsize;  // save for switch below
00369     internal_Rsize = (Rnew == Index_S) ? ptr_offset : ncols;
00370     Rminindexvalue = -ptr_offset; 
00371     Rmaxindexvalue = Rminindexvalue + ncols - 1;
00372     switch (Rmode) { // subtract off the old offset
00373     default:
00374     case Index_C:
00375       { ptr_offset -= 0; break; }
00376     case Index_1:
00377       { ptr_offset -= -1; break; }
00378     case Index_S:
00379       { ptr_offset -= old_Rsize; break; }
00380     }
00381     // now ptr_offset is how far we must adjust each row pointer
00382     for (int i = Lminindexvalue; i <= Lmaxindexvalue; ++i)
00383       data[i] += ptr_offset;
00384     internal_Rmode = Rnew;
00385   } // if (Rnew != Rmode)  
00386 
00387   return *this;
00388 }
00389 
00390 //-------------------------------------------------------------------------
00391 // constfill()  fill the matrix with a constant value
00392 //              Note: data subset control will affect elements copied
00393 
00394 void real_matrix::constfill(const double f)
00395 {
00396   for (int i = Lminindex(); i <= Lmaxindex(); ++i)
00397     for (int j = Rminindex(); j <= Rmaxindex(); ++j)
00398       data[i][j] = f;
00399 }
00400 
00401 //-------------------------------------------------------------------------
00402 // fillall()  fill regardless of data subset control
00403 
00404 real_matrix & real_matrix::fillall(const double f)
00405 {
00406   int save_Lmax = Lmaxindexvalue; 
00407   int save_Rmax = Rmaxindexvalue;
00408   int save_Lmin = Lminindexvalue; 
00409   int save_Rmin = Rminindexvalue;
00410 
00411   maxindex(Lsize+Rsize); // access full matrix
00412   constfill(f);
00413   Lmaxindexvalue = save_Lmax; Rmaxindexvalue = save_Rmax;  // restore subset
00414   Lminindexvalue = save_Lmin; Rminindexvalue = save_Rmin;
00415   return *this;
00416 }
00417 
00418 //-------------------------------------------------------------------------
00419 // fill a row or column from a vector
00420 
00421 real_matrix & real_matrix::fillrow(const int n, const real_vector & v)
00422 {
00423   if ((n >= Lminindex())&&(n <= Lmaxindex())) {  // then n is o.k.
00424     for (int i = Rminindex(); i <= Rmaxindex(); ++i)
00425       data[n][i] = v.read(i);
00426   }
00427   return *this;
00428 }
00429 
00430 real_matrix & real_matrix::fillcol(const int n, const real_vector & v)
00431 {
00432   if ((n >= Rminindex())&&(n <= Rmaxindex())) {  // then n is o.k.
00433     for (int i = Lminindex(); i <= Lmaxindex(); ++i)
00434       data[i][n] = v.read(i);
00435   }
00436   return *this;
00437 }
00438 
00439 //-------------------------------------------------------------------------
00440 // Lmaxindex(n), Rmaxindex(n), make_empty()
00441 
00442 int real_matrix::Lmaxindex(const int n)
00443 {
00444   if (Lsize == 0 && Lmode != Index_S)
00445     // can't change the maxindex if no data elements
00446     return Lmaxindex();
00447   else {
00448     switch (Lmode) {
00449     case Index_C: {
00450       Lmaxindexvalue = min((Lsize - 1), max(0,n));
00451       break;
00452     }
00453     case Index_1: {
00454       Lmaxindexvalue = min(Lsize, max(1,n));
00455       break;
00456     }
00457     case Index_S: {
00458       Lmaxindexvalue = min(Lsize, max(0,n));
00459       Lminindexvalue = -Lmaxindexvalue;
00460       break;
00461     }
00462     } //switch
00463     return Lmaxindexvalue;
00464   } //else
00465 }
00466 
00467 int real_matrix::Rmaxindex(const int n)
00468 {
00469   if (Rsize == 0 && Rmode != Index_S)
00470     // can't change the maxindex if no data elements
00471     return Rmaxindex();
00472   else {
00473     switch (Rmode) {
00474     case Index_C: {
00475       Rmaxindexvalue = min((Rsize - 1), max(0,n));
00476       break;
00477     }
00478     case Index_1: {
00479       Rmaxindexvalue = min(Rsize, max(1,n));
00480       break;
00481     }
00482     case Index_S: {
00483       Rmaxindexvalue = min(Rsize, max(0,n));
00484       Rminindexvalue = -Rmaxindexvalue;
00485       break;
00486     }
00487     } //switch
00488     return Rmaxindexvalue;
00489   } //else
00490 }
00491 
00492 real_matrix & real_matrix::make_empty()
00493 {
00494   switch (Lmode) {
00495   case Index_C:
00496     Lmaxindexvalue = -1;
00497     Lminindexvalue = 0;
00498     break;
00499 
00500   case Index_1:
00501     Lmaxindexvalue = 0;
00502     Lminindexvalue = 1;
00503     break;
00504 
00505   case Index_S:
00506     Lmaxindexvalue = -1;
00507     Lminindexvalue = 1;
00508     break;
00509 
00510   }
00511   
00512   switch (Rmode) {
00513   case Index_C:
00514     Rmaxindexvalue = -1;
00515     Rminindexvalue = 0;
00516     break;
00517 
00518   case Index_1:
00519     Rmaxindexvalue = 0;
00520     Rminindexvalue = 1;
00521     break;
00522 
00523   case Index_S:
00524     Rmaxindexvalue = -1;
00525     Rminindexvalue = 1;
00526     break;
00527 
00528   }
00529   
00530   return *this;
00531 }
00532 
00533 
00534 //-------------------------------------------------------------------------
00535 // copy() copy contents of another matrix
00536 
00537 real_matrix & real_matrix::copy(const real_matrix & B)
00538 {
00539   // check for self copy: "A.copy(A)", and do something intelligent:
00540   if (this == & B) { clean(); return *this; }
00541 
00542   // otherwise, not a self copy, so:
00543   maxindex(Lsize+Rsize);  // make all data accessible
00544   constfill(0);           // and clear the matrix
00545   // now set data subset on the result:
00546   if(B.is_empty())
00547     make_empty();
00548   else {
00549     Lmaxindex(B.Lmaxindex());
00550     Rmaxindex(B.Rmaxindex());
00551     // loop over the index range intersection and copy:
00552     int Lmax = min(Lmaxindex(), B.Lmaxindex());
00553     int Lmin = max(Lminindex(), B.Lminindex());
00554     int Rmax = min(Rmaxindex(), B.Rmaxindex());
00555     int Rmin = max(Rminindex(), B.Rminindex());
00556     int i,j;
00557     for (i = Lmin; i <= Lmax; ++i)
00558       for (j = Rmin; j <= Rmax; ++j)
00559         data[i][j] = B[i][j];
00560   }
00561   return *this;
00562 }
00563 
00564 //-------------------------------------------------------------------------
00565 // reallocate() change size or indexing modes
00566 
00567 real_matrix & real_matrix::reallocate
00568   (const int n, const int m, const v_index_mode tl, const v_index_mode tr)
00569 {
00570   // just return if reallocation is unnecessary:
00571   if ((Lsize == n)&&(Rsize == m)&&(Lmode == tl)&&(Rmode == tr)) return *this;
00572 
00573   // if we're here, we have to reallocate:
00574   // save the data subset control values and then maximize:
00575   int new_Lmax = Lmaxindexvalue;
00576   int new_Rmax = Rmaxindexvalue;
00577   maxindex(Lsize + Rsize);
00578 
00579   // check if data subset control was turned off; if so, keep turned off
00580   if (new_Lmax == Lmaxindexvalue) new_Lmax = n; 
00581   if (new_Rmax == Rmaxindexvalue) new_Rmax = m; 
00582 
00583   // now save the necessary private data members:
00584   int Lmax = Lmaxindexvalue;
00585   int Lmin = Lminindexvalue;
00586   int Rmax = Rmaxindexvalue;
00587   int Rmin = Rminindexvalue;
00588   double **old_data = data; 
00589   double **delete1 = delete_pointer_data;
00590   double  *delete2 = delete_pointer_rows;
00591 
00592   // with this done, now construct the new matrix:
00593   construct(n, m, tl, tr);
00594   constfill(0);
00595 
00596   // now copy in the data using the saved private data members:
00597   Lmax = min(Lmaxindex(), Lmax);
00598   Lmin = max(Lminindex(), Lmin);
00599   Rmax = min(Rmaxindex(), Rmax);
00600   Rmin = max(Rminindex(), Rmin);
00601   int i,j;
00602   for (i = Lmin; i <= Lmax; ++i)
00603     for (j = Rmin; j <= Rmax; ++j)
00604       data[i][j] = old_data[i][j];
00605 
00606   // set data subset control
00607   Lmaxindex(new_Lmax);
00608   Rmaxindex(new_Rmax);
00609 
00610   // finally delete the old memory allocation:
00611   delete [] delete1;
00612   delete [] delete2;
00613 
00614   return *this;
00615 }
00616 
00617 //-------------------------------------------------------------------------
00618 // resize: the only one which couldn't be defined in the header file
00619 
00620 real_matrix & real_matrix::resize(const complex_matrix & B)
00621 {
00622   int Lsize = (B.Lmode == Index_C) ? B.Lmaxindex()+1: B.Lmaxindex();
00623   int Rsize = (B.Rmode == Index_C) ? B.Rmaxindex()+1: B.Rmaxindex();
00624   return reallocate(Lsize, Rsize, B.Lmode, B.Rmode);
00625 }
00626 
00627 //-------------------------------------------------------------------------
00628 // Basic assignment operators
00629 
00630 real_matrix & real_matrix::operator = (const real_matrix & B)
00631 {
00632   // check for self assignment: "A = A", and do something intelligent:
00633   if (this == & B) { clean(); return *this; }
00634 
00635   // reallocate memory if needed:
00636   maximize();
00637   if ((B.Lmode != Lmode)||(B.Rmode != Rmode)||
00638       (B.Lmaxindex() > Lmaxindexvalue)||(B.Rmaxindex() > Rmaxindexvalue)) {
00639     delete [] delete_pointer_data; delete [] delete_pointer_rows;
00640     int newLsize = (B.Lmode == Index_C) ? B.Lmaxindex()+1: B.Lmaxindex();
00641     int newRsize = (B.Rmode == Index_C) ? B.Rmaxindex()+1: B.Rmaxindex();
00642     construct(newLsize, newRsize, B.Lmode, B.Rmode);
00643   }
00644 
00645   copy(B);
00646   return *this;
00647 }
00648 
00649 real_matrix & real_matrix::operator = (const datafile & D)
00650 {
00651   return (*this = *D.table());
00652 }
00653 
00654 //---------------------------------------------------------------------
00655 // other assignment operators (no memory reallocation for these):
00656 
00657 real_matrix & real_matrix::operator += (const double s)
00658 {
00659   register double *d, *limit;  // local pointers within a row
00660   register int i;
00661   for(i = Lminindexvalue; i <= Lmaxindexvalue; ++i) {
00662     // make local pointers to the first and last elements in the row:
00663     limit = d = data[i];
00664     d += Rminindexvalue; limit += Rmaxindexvalue;
00665     // use the pointer to the first element as the loop variable:
00666     while (d <= limit) *(d++) += s;
00667   }
00668   return *this;
00669 }
00670 
00671 real_matrix & real_matrix::operator -= (const double s)
00672 {
00673   register double *d, *limit;  // local pointers within a row
00674   register int i;
00675   for(i = Lminindexvalue; i <= Lmaxindexvalue; ++i) {
00676     // make local pointers to the first and last elements in the row:
00677     limit = d = data[i];
00678     d += Rminindexvalue; limit += Rmaxindexvalue;
00679     // use the pointer to the first element as the loop variable:
00680     while (d <= limit) *(d++) -= s;
00681   }
00682   return *this;
00683 }
00684 
00685 real_matrix & real_matrix::operator *= (const double s)
00686 {
00687   register double *d, *limit;  // local pointers within a row
00688   register int i;
00689   for(i = Lminindexvalue; i <= Lmaxindexvalue; ++i) {
00690     // make local pointers to the first and last elements in the row:
00691     limit = d = data[i];
00692     d += Rminindexvalue; limit += Rmaxindexvalue;
00693     // use the pointer to the first element as the loop variable:
00694     while (d <= limit) *(d++) *= s;
00695   }
00696   return *this;
00697 }
00698 
00699 real_matrix & real_matrix::operator /= (const double s)
00700 {
00701   register double *d, *limit;  // local pointers within a row
00702   register int i;
00703   for(i = Lminindexvalue; i <= Lmaxindexvalue; ++i) {
00704     // make local pointers to the first and last elements in the row:
00705     limit = d = data[i];
00706     d += Rminindexvalue; limit += Rmaxindexvalue;
00707     // use the pointer to the first element as the loop variable:
00708     while (d <= limit) *(d++) /= s;
00709   }
00710   return *this;
00711 }
00712 
00713 real_matrix & real_matrix::operator += (const real_matrix & B)
00714 {
00715   clean();  // ensure nonvalid elements are 0
00716   // increase target's valid data range if necessary:
00717   if (Lmaxindexvalue < B.Lmaxindex()) Lmaxindex(B.Lmaxindex());
00718   if (Rmaxindexvalue < B.Rmaxindex()) Rmaxindex(B.Rmaxindex());
00719   // find the intersection of the valid data ranges:
00720   int Lmax = min(Lmaxindex(), B.Lmaxindex());
00721   int Lmin = max(Lminindex(), B.Lminindex());
00722   int Rmax = min(Rmaxindex(), B.Rmaxindex());
00723   int Rmin = max(Rminindex(), B.Rminindex());
00724   // loop over the intersection of the ranges:
00725   register int i,j;
00726   for (i = Lmin; i <= Lmax; ++i)
00727     for (j = Rmin; j <= Rmax; ++j)
00728       data[i][j] += B[i][j];
00729   return *this;
00730 }
00731 
00732 real_matrix & real_matrix::operator -= (const real_matrix & B)
00733 {
00734   clean();  // ensure nonvalid elements are 0
00735   // increase target's valid data range if necessary:
00736   if (Lmaxindexvalue < B.Lmaxindex()) Lmaxindex(B.Lmaxindex());
00737   if (Rmaxindexvalue < B.Rmaxindex()) Rmaxindex(B.Rmaxindex());
00738   // find the intersection of the valid data ranges:
00739   int Lmax = min(Lmaxindex(), B.Lmaxindex());
00740   int Lmin = max(Lminindex(), B.Lminindex());
00741   int Rmax = min(Rmaxindex(), B.Rmaxindex());
00742   int Rmin = max(Rminindex(), B.Rminindex());
00743   // loop over the intersection of the ranges:
00744   register int i,j;
00745   for (i = Lmin; i <= Lmax; ++i)
00746     for (j = Rmin; j <= Rmax; ++j)
00747       data[i][j] -= B[i][j];
00748   return *this;
00749 }
00750 
00751 //-------------------------------------------------------------------------
00752 // matrix math member fcns (other than assignment)
00753 
00754 real_matrix & real_matrix::add(const real_matrix & B, const real_matrix & C)
00755 {
00756   // first check that neither B nor C is this matrix:
00757   if ((&B != this)&&(&C != this)) {
00758     // make the size of the result correct, and initiallize to all zeroes:
00759     maximize();
00760     v_index_mode Lm = ResultModeMax(B.Lmode, C.Lmode);
00761     v_index_mode Rm = ResultModeMax(B.Rmode, C.Rmode);
00762     int Ls = max(B.Lmaxindex(), C.Lmaxindex());
00763     int Rs = max(B.Rmaxindex(), C.Rmaxindex());
00764     if ((Lmode!=Lm)||(Rmode!=Rm)||(Lmaxindex()<Ls)||(Rmaxindex()<Rs)) {
00765       // fix up the result matrix in two steps: index modes first, then sizes
00766       // the result will automatically be zeroed
00767       reallocate(0,0,Lm,Rm); get(0,0) = 0; resize(Ls,Rs);
00768       // we need the above get() = 0 in case Lm == Rm == Index_S
00769     }
00770     else {
00771       // result's modes and sizes o.k., just zero and set maxindexes
00772       fill(0.0);
00773       Lmaxindex(Ls); Rmaxindex(Rs);
00774     }
00775     // Now do the sum:
00776     (*this) += B; (*this) += C;
00777   }
00778   else if (&B == this) { // the first argument is this matrix
00779     // if necessary, resize this matrix to hold all elements in the sum
00780     int Ls = max(Lmaxindex(), C.Lmaxindex());
00781     int Rs = max(Rmaxindex(), C.Rmaxindex());
00782     if ((Lmaxindex() < Ls)||(Rmaxindex() < Rs)) {
00783       clean(); maximize();
00784     }
00785     v_index_mode Lm = ResultModeMax(Lmode, C.Lmode);
00786     v_index_mode Rm = ResultModeMax(Rmode, C.Rmode);
00787     if ((Lmode!=Lm)||(Rmode!=Rm)||(Lmaxindex()<Ls)||(Rmaxindex()<Rs)) {
00788       int sL = (Lm == Index_C) ? Ls + 1 : Ls;
00789       int sR = (Rm == Index_C) ? Rs + 1 : Rs;
00790       reallocate(sL,sR,Lm,Rm);
00791     }
00792     Lmaxindex(Ls); Rmaxindex(Rs);
00793     // Now do the sum:
00794     (*this) += C;
00795   }
00796   else { // the second argument is this matrix
00797     // if necessary, resize this matrix to hold all elements in the sum
00798     int Ls = max(Lmaxindex(), B.Lmaxindex());
00799     int Rs = max(Rmaxindex(), B.Rmaxindex());
00800     if ((Lmaxindex() < Ls)||(Rmaxindex() < Rs)) {
00801       clean(); maximize();
00802     }
00803     v_index_mode Lm = ResultModeMax(Lmode, B.Lmode);
00804     v_index_mode Rm = ResultModeMax(Rmode, B.Rmode);
00805     if ((Lmode!=Lm)||(Rmode!=Rm)||(Lmaxindex()<Ls)||(Rmaxindex()<Rs)) {
00806       int sL = (Lm == Index_C) ? Ls + 1 : Ls;
00807       int sR = (Rm == Index_C) ? Rs + 1 : Rs;
00808       reallocate(sL,sR,Lm,Rm);
00809     }
00810     Lmaxindex(Ls); Rmaxindex(Rs);
00811     // Now do the sum:
00812     (*this) += B;
00813   }
00814   return *this;
00815 }
00816 
00817 real_matrix & real_matrix::sub(const real_matrix & B, const real_matrix & C)
00818 {
00819   // first check that neither B nor C is this matrix:
00820   if ((&B != this)&&(&C != this)) {
00821     // make the size of the result correct, and initiallize to all zeroes:
00822     maximize();
00823     v_index_mode Lm = ResultModeMax(B.Lmode, C.Lmode);
00824     v_index_mode Rm = ResultModeMax(B.Rmode, C.Rmode);
00825     int Ls = max(B.Lmaxindex(), C.Lmaxindex());
00826     int Rs = max(B.Rmaxindex(), C.Rmaxindex());
00827     if ((Lmode!=Lm)||(Rmode!=Rm)||(Lmaxindex()<Ls)||(Rmaxindex()<Rs)) {
00828       // fix up the result matrix in two steps: index modes first, then sizes
00829       // the result will automatically be zeroed
00830       reallocate(0,0,Lm,Rm); get(0,0) = 0; resize(Ls,Rs);
00831       // we need the above get() = 0 in case Lm == Rm == Index_S
00832     }
00833     else {
00834       // result's modes and sizes o.k., just zero and set maxindexes
00835       fill(0.0);
00836       Lmaxindex(Ls); Rmaxindex(Rs);
00837     }
00838     // Now do the subtraction:
00839     (*this) += B; (*this) -= C;
00840   }
00841   else if (&B == this) { // the first argument is this matrix
00842     // if necessary, resize this matrix to hold all elements
00843     int Ls = max(Lmaxindex(), C.Lmaxindex());
00844     int Rs = max(Rmaxindex(), C.Rmaxindex());
00845     if ((Lmaxindex() < Ls)||(Rmaxindex() < Rs)) {
00846       clean(); maximize();
00847     }
00848     v_index_mode Lm = ResultModeMax(Lmode, C.Lmode);
00849     v_index_mode Rm = ResultModeMax(Rmode, C.Rmode);
00850     if ((Lmode!=Lm)||(Rmode!=Rm)||(Lmaxindex()<Ls)||(Rmaxindex()<Rs)) {
00851       int sL = (Lm == Index_C) ? Ls + 1 : Ls;
00852       int sR = (Rm == Index_C) ? Rs + 1 : Rs;
00853       reallocate(sL,sR,Lm,Rm);
00854     }
00855     Lmaxindex(Ls); Rmaxindex(Rs);
00856     // Now do the subtraction:
00857     (*this) -= C;
00858   }
00859   else { // the second argument is this matrix
00860     (*this) *= -1;  // since it's the 2nd argument
00861     // if necessary, resize this matrix to hold all elements
00862     int Ls = max(Lmaxindex(), B.Lmaxindex());
00863     int Rs = max(Rmaxindex(), B.Rmaxindex());
00864     if ((Lmaxindex() < Ls)||(Rmaxindex() < Rs)) {
00865       clean(); maximize();
00866     }
00867     v_index_mode Lm = ResultModeMax(Lmode, B.Lmode);
00868     v_index_mode Rm = ResultModeMax(Rmode, B.Rmode);
00869     if ((Lmode!=Lm)||(Rmode!=Rm)||(Lmaxindex()<Ls)||(Rmaxindex()<Rs)) {
00870       int sL = (Lm == Index_C) ? Ls + 1 : Ls;
00871       int sR = (Rm == Index_C) ? Rs + 1 : Rs;
00872       reallocate(sL,sR,Lm,Rm);
00873     }
00874     Lmaxindex(Ls); Rmaxindex(Rs);
00875     // Now do the sum:
00876     (*this) += B;
00877   }
00878   return *this;
00879 }
00880 
00881 real_matrix & real_matrix::real(const complex_matrix & B)
00882 {
00883   resize(B);
00884   if(B.is_empty())
00885     make_empty();
00886   else {
00887     Lmaxindex(B.Lmaxindex());
00888     Rmaxindex(B.Rmaxindex());
00889     int i,j;
00890     for (i = Lminindex(); i <= Lmaxindex(); ++i)
00891       for (j = Rminindex(); j <= Rmaxindex(); ++j)
00892         data[i][j] = B[i][j].real;
00893   }
00894   return *this;
00895 }
00896 
00897 real_matrix & real_matrix::imaginary(const complex_matrix & B)
00898 {
00899   resize(B);
00900   if(B.is_empty())
00901     make_empty();
00902   else {
00903     Lmaxindex(B.Lmaxindex());
00904     Rmaxindex(B.Rmaxindex());
00905     int i,j;
00906     for (i = Lminindex(); i <= Lmaxindex(); ++i)
00907       for (j = Rminindex(); j <= Rmaxindex(); ++j)
00908         data[i][j] = B[i][j].imaginary;
00909   }
00910   return *this;
00911 }
00912 
00913 //-------------------------------------------------------------------------
00914 // clean() clear elements beyond the valid index range
00915 
00916 real_matrix & real_matrix::clean(void)
00917 {
00918   // save index limits and maximize:
00919   int Lmax = Lmaxindexvalue;
00920   int Lmin = Lminindexvalue;
00921   int Rmax = Rmaxindexvalue;
00922   int Rmin = Rminindexvalue;
00923   maxindex(Lsize + Rsize);
00924 
00925   // now zero excess elements:
00926   int i,j;
00927   for (j = Rminindex(); j < Rmin; ++j)
00928     for (i = Lminindex(); i <= Lmaxindex(); ++i)
00929       data[i][j] = 0;
00930   for (j = Rmaxindex(); j > Rmax; --j)
00931     for (i = Lminindex(); i <= Lmaxindex(); ++i)
00932       data[i][j] = 0;
00933   for (i = Lmaxindex(); i > Lmax; --i)
00934     for (j = Rmin; j <= Rmax; ++j)
00935       data[i][j] = 0;
00936   for (i = Lminindex(); i < Lmin; ++i)
00937     for (j = Rmin; j <= Rmax; ++j)
00938       data[i][j] = 0;
00939 
00940   // restore index limits and return:
00941   Lmaxindex(Lmax);
00942   Rmaxindex(Rmax);
00943   return *this;
00944 }
00945 
00946 //---------------------------------------------------------------------
00947 // other miscellaneous funtions:
00948 
00949 real_matrix & real_matrix::diagonal(const double s)
00950 {
00951   fill(0.0);
00952   int min = minindex();
00953   int max = maxindex();
00954   for(register int i = min; i <= max; ++i)
00955     get(i,i) = s;
00956   return *this;
00957 }
00958 
00959 real_matrix & real_matrix::rowswap(const int n, const int m)
00960 {
00961   // check for do nothing n == m case first:
00962   if (n == m) return *this;
00963 
00964   // n != m if we get here:
00965   const int nBad = 1; // flag values for n or m out of limits
00966   const int mBad = 2;
00967   int nCheck = 0;     // flags set if n or m out of limits
00968   int mCheck = 0;
00969   if ((n < Lminindexvalue)||(n > Lmaxindexvalue)) nCheck = nBad;
00970   if ((m < Lminindexvalue)||(m > Lmaxindexvalue)) mCheck = mBad;
00971   switch (nCheck + mCheck) {
00972   case 0: {
00973     // then both n and m are valid
00974     double * temp = data[n];
00975     data[n] = data[m];
00976     data[m] = temp;
00977     break;
00978   }
00979   case nBad: {
00980     // only m is valid, so fill with zeros
00981     real_vector y(data[m], Rsize, Rmode);  // alias the row as a vector
00982     y.fill(0.0);
00983     break;
00984   }
00985   case mBad: {
00986     // only n is valid, so fill with zeros
00987     real_vector y(data[n], Rsize, Rmode);  // alias the row as a vector
00988     y.fill(0.0);
00989     break;
00990   }
00991   case (nBad+mBad): {
00992     // both indexes are invalid, so do nothing
00993     break;
00994   }
00995   } // switch
00996   return *this;
00997 }
00998 
00999 real_matrix & real_matrix::apply(double (*f)(double))
01000 {
01001   register double *d, *limit;  // local pointers within a row
01002   register int i;
01003   for(i = Lminindexvalue; i <= Lmaxindexvalue; ++i) {
01004     // make local pointers to the first and last elements in the row:
01005     limit = d = data[i];
01006     d += Rminindexvalue; limit += Rmaxindexvalue;
01007     // use the pointer to the first element as the loop variable:
01008     for ( ; d <= limit; ++d) *d = f(*d);
01009   }
01010   return *this;
01011 }
01012 
01013 real_matrix & real_matrix::apply(double (*f)(const double &))
01014 {
01015   register double *d, *limit;  // local pointers within a row
01016   register int i;
01017   for(i = Lminindexvalue; i <= Lmaxindexvalue; ++i) {
01018     // make local pointers to the first and last elements in the row:
01019     limit = d = data[i];
01020     d += Rminindexvalue; limit += Rmaxindexvalue;
01021     // use the pointer to the first element as the loop variable:
01022     for ( ; d <= limit; ++d) *d = f(*d);
01023   }
01024   return *this;
01025 }
01026 
01027 real_matrix & real_matrix::apply(double (*f)(double, int, int))
01028 {
01029   int i;                     // row counter (left index)
01030   register double *d;       // inner loop pointer within a row
01031   register int j, limit;     // inner loop counter and a limit
01032   for(i = Lminindexvalue; i <= Lmaxindexvalue; ++i) {
01033     j = Rminindexvalue; limit = Rmaxindexvalue;
01034     for (d = data[i] + j; j <= limit; ++d, ++j) *d = f(*d, i, j);
01035   }
01036   return *this;
01037 }
01038 
01039 real_matrix & real_matrix::apply(double (*f)(const double &, int, int))
01040 {
01041   int i;                     // row counter (left index)
01042   register double *d;       // inner loop pointer within a row
01043   register int j, limit;     // inner loop counter and a limit
01044   for(i = Lminindexvalue; i <= Lmaxindexvalue; ++i) {
01045     j = Rminindexvalue; limit = Rmaxindexvalue;
01046     for (d = data[i] + j; j <= limit; ++d, ++j) *d = f(*d, i, j);
01047   }
01048   return *this;
01049 }
01050 
01051 // end of real_matrix definitions
01052 
01053 
01054 // ************************************************************************
01055 // complex_matrix definitions:
01056 
01057 
01058 // matrix output:
01059 
01060 ostream & operator << (ostream & s, const complex_matrix & A)
01061 {
01062   ios::streamsize w = s.width();
01063   if (A.Lminindex() <= A.Lmaxindex()) { // matrix isn't empty
01064     { // output first row (using a row alias)
01065       complex_vector v(const_cast<Complex *>(A[A.Lminindex()]), A.Rsize, A.Rmode);
01066       v.maxindex(A.Rmaxindex());  // set same valid index range
01067       s << v;
01068     }
01069     // output remaining rows
01070     for (int i = A.Lminindex() + 1; i <= A.Lmaxindex(); ++i) {
01071       complex_vector v(const_cast<Complex *>(A[i]), A.Rsize, A.Rmode);
01072       v.maxindex(A.Rmaxindex());
01073       s << _out_separator << setw(w) << v;
01074     }
01075   }
01076   return s << setw(0);  // just in case no output was generated
01077 }
01078 
01079 complex_matrix & complex_matrix::show(ostream & s)
01080 {
01081   s << endl << *this << endl;
01082   return *this;
01083 }
01084 
01085 complex_matrix & complex_matrix::show()
01086 {
01087   return show(cout);
01088 }
01089 
01090 const complex_matrix & complex_matrix::show(ostream & s) const
01091 {
01092   s << endl << *this << endl;
01093   return *this;
01094 }
01095 
01096 const complex_matrix & complex_matrix::show() const
01097 {
01098   return show(cout);
01099 }
01100 
01101 string complex_matrix::out_separator()
01102 { return _out_separator; }
01103 
01104 string complex_matrix::out_separator(const string & s)
01105 { string temp = _out_separator; _out_separator = s; return temp; }
01106 
01107 string complex_matrix::out_separator(const char * const s)
01108 { string temp = _out_separator; _out_separator = s; return temp; }
01109 
01110 string complex_matrix::out_separator(const char s)
01111 { string temp = _out_separator; _out_separator = s; return temp; }
01112 
01113 //-------------------------------------------------------------------------
01114 // construct() do the real work of matrix construction
01115 
01116 void complex_matrix::construct(const int n, const int m,
01117                            const v_index_mode tl,
01118                            const v_index_mode tr)
01119 {
01120   // set up some internal constants
01121   internal_Lsize = (n >= 0) ? n : 0;
01122   internal_Rsize = (m >= 0) ? m : 0;
01123   internal_Lmode = tl;
01124   internal_Rmode = tr;
01125   trashptr = & trash;
01126 
01127   // determine number of columns and rows requested:
01128   int nrows = Lsize; if (Lmode == Index_S) nrows += (nrows + 1);
01129   int ncols = Rsize; if (Rmode == Index_S) ncols += (ncols + 1);
01130 
01131   // allocate memory for the array of pointers to rows, if required:
01132   data = delete_pointer_data = (nrows) ?  new Complex *[nrows] : 0;
01133 
01134   // allocate memory for the array of data elements, if required:
01135   int nelem = ncols * nrows;
01136   if (nelem) {
01137     // need to allocate memory
01138     delete_pointer_rows = new Complex[nelem];
01139     if (delete_pointer_rows == 0) {
01140       // memory alloc failed, so give back pointer array as well
01141       delete [] delete_pointer_data;
01142       data = delete_pointer_data = 0;
01143     }
01144   }
01145   else {
01146     // no allocation necessary, nelem == 0
01147     delete_pointer_rows = 0;
01148   }
01149 
01150   // now that allocation has been attempted, update sizes and index limits
01151   if (data == 0) {
01152     // no pointer array
01153     internal_Lsize = nrows = 0; // in case they weren't already
01154     if (Lmode == Index_S) data = & trashptr; //so **data = trash
01155     Lmaxindexvalue = (Lmode == Index_1) ? 0 : -1;
01156   }
01157   else {
01158     // pointer array exists, original Lsize and nrows o.k.
01159     switch (Lmode) {
01160     case Index_C: {
01161       Lmaxindexvalue = Lsize - 1;
01162       break;
01163     }
01164     case Index_1: {
01165       Lmaxindexvalue = Lsize;
01166       --data;        // so *delete_pointer_data = data[1]
01167       break;
01168     }
01169     case Index_S: {
01170       Lmaxindexvalue = Lsize;
01171       data += Lsize; // so *delete_pointer_data = data[-Lsize]
01172       break;
01173     }
01174     } //switch
01175   } //else
01176   // final left index setup step is to set Lminindexvalue:
01177   switch (Lmode) {
01178   case Index_C: { Lminindexvalue = 0; break; }
01179   case Index_1: { Lminindexvalue = 1; break; }
01180   case Index_S: { Lminindexvalue = -Lmaxindexvalue; break; }
01181   }
01182   // setup of left index complete
01183   // now for the right index:
01184   if (delete_pointer_rows == 0) {
01185     // no data elements
01186     internal_Rsize = ncols = 0; // in case they weren't already
01187     Rmaxindexvalue = (Rmode == Index_1) ? 0 : -1;
01188   }
01189   else {
01190     // data array exists, original Rsize and ncols o.k.
01191     Rmaxindexvalue = (Rmode == Index_C) ? Rsize - 1 : Rsize;
01192   }
01193   switch (Rmode) {
01194   case Index_C: { Rminindexvalue = 0; break; }
01195   case Index_1: { Rminindexvalue = 1; break; }
01196   case Index_S: { Rminindexvalue = -Rmaxindexvalue; break; }
01197   }
01198   // setup of right index complete
01199 
01200     
01201   // now fill pointer array with pointers to the [0] element of each row
01202   int i, offset; // offset is the pointer offset into each row due to Rmode
01203   switch (Rmode) {
01204   default:
01205   case Index_C: { offset = 0; break; }
01206   case Index_1: { offset = -1; break; }
01207   case Index_S: { offset = Rsize; break; }
01208   }
01209   if (ncols == 0) offset = 0; // no offset if no data
01210   for(i = Lminindexvalue; i <= Lmaxindexvalue; ++i, offset += ncols)
01211     // this loop will only execute if pointer memory was allocated
01212     data[i] = delete_pointer_rows + offset;
01213 
01214 } // construct()
01215 
01216 //-------------------------------------------------------------------------
01217 // copy constructors:
01218 
01219 complex_matrix::complex_matrix(const complex_matrix & B)
01220   : Lsize(internal_Lsize), Rsize(internal_Rsize), 
01221     Lmode(internal_Lmode), Rmode(internal_Rmode)
01222 {
01223   construct(B.Lsize, B.Rsize, B.Lmode, B.Rmode);
01224   int i,j;
01225   // the following loop will work even if alloc for B failed and
01226   // B.Lmode == Index_S.  In this case, the contents of trash will be
01227   // copied.
01228   for (i = Lminindex(); i <= Lmaxindex(); ++i)
01229     for (j = Rminindex(); j <= Rmaxindex(); ++j)
01230       data[i][j] = B[i][j];
01231 
01232   if(B.is_empty())
01233     make_empty();
01234   else {
01235     Lmaxindex(B.Lmaxindex());
01236     Rmaxindex(B.Rmaxindex());
01237   }
01238 }
01239 
01240 complex_matrix::complex_matrix(const real_matrix & B)
01241   : Lsize(internal_Lsize), Rsize(internal_Rsize), 
01242     Lmode(internal_Lmode), Rmode(internal_Rmode)
01243 {
01244   construct(B.Lsize, B.Rsize, B.Lmode, B.Rmode);
01245   int i,j;
01246   // the following loop will work even if alloc for B failed and
01247   // B.Lmode == Index_S.  In this case, the contents of trash will be
01248   // copied.
01249   for (i = Lminindex(); i <= Lmaxindex(); ++i)
01250     for (j = Rminindex(); j <= Rmaxindex(); ++j)
01251       data[i][j] = B[i][j];
01252 
01253   if(B.is_empty())
01254     make_empty();
01255   else {
01256     Lmaxindex(B.Lmaxindex());
01257     Rmaxindex(B.Rmaxindex());
01258   }
01259 }
01260 
01261 complex_matrix::complex_matrix(const real_vector & v)
01262   : Lsize(internal_Lsize), Rsize(internal_Rsize), 
01263     Lmode(internal_Lmode), Rmode(internal_Rmode)
01264 {
01265   construct(v.size, 1, v.mode, Index_1);
01266   // the following loop will work even if alloc for v failed and
01267   // v.mode == Index_S.  In this case, the contents of trash will be
01268   // copied.
01269   for (int i = Lminindex(); i <= Lmaxindex(); ++i)
01270     data[i][1] = v[i];
01271 
01272   Lmaxindexvalue = v.maxindex();
01273   Lminindexvalue = v.minindex();
01274 }
01275 
01276 complex_matrix::complex_matrix(const complex_vector & v)
01277   : Lsize(internal_Lsize), Rsize(internal_Rsize), 
01278     Lmode(internal_Lmode), Rmode(internal_Rmode)
01279 {
01280   construct(v.size, 1, v.mode, Index_1);
01281   // the following loop will work even if alloc for v failed and
01282   // v.mode == Index_S.  In this case, the contents of trash will be
01283   // copied.
01284   for (int i = Lminindex(); i <= Lmaxindex(); ++i)
01285     data[i][1] = v[i];
01286 
01287   Lmaxindexvalue = v.maxindex();
01288   Lminindexvalue = v.minindex();
01289 }
01290 
01291 //-------------------------------------------------------------------------
01292 // reindex()  change the index modes
01293 
01294 complex_matrix & complex_matrix::reindex(const v_index_mode Lnew, const v_index_mode Rnew)
01295 {
01296   if (Lnew == Lmode && Rnew == Rmode) return *this;
01297 
01298   // some index change is needed; calculate dimensions of matrix
01299   int nrows = (Lmode == Index_S) ? 2*Lsize + 1 : Lsize;
01300   int ncols = (Rmode == Index_S) ? 2*Rsize + 1 : Rsize;
01301   
01302   // any dimension with new Index_S needs an odd number of values
01303   if (Lnew == Index_S && (nrows>>1)<<1 == nrows) {  // nrows even
01304     // since nrows even, Lmode can't be Index_S
01305     reallocate(Lsize+1,Rsize,Lmode,Rmode);
01306     nrows = Lsize; // the new Lsize
01307   }
01308   if (Rnew == Index_S && (ncols>>1)<<1 == ncols) {  // ncols even
01309     reallocate(Lsize,Rsize+1,Lmode,Rmode);
01310     ncols = Rsize; // the new Rsize
01311   }
01312 
01313   // finally, if resulting matrix is empty, just reallocate to fix modes
01314   if (delete_pointer_rows == 0)  {
01315     reallocate(0,0,Lnew,Rnew);
01316     return *this;
01317   }
01318 
01319   // if here, the matrix has some elements
01320 
01321   // set up new left indexing:
01322   if (Lnew != Lmode) { // reindexing required of Left Index
01323     int ptr_offset; // offset into row pointer array for data[0]
01324     switch (Lnew) {
01325     default:
01326       { return *this; } // unknown mode, so do nothing
01327     case Index_C:
01328       { ptr_offset = 0; break; }
01329     case Index_1:
01330       { ptr_offset = -1; break; }
01331     case Index_S:
01332       { ptr_offset = (nrows - 1)/2; break; }
01333     } // switch
01334     internal_Lsize = (Lnew == Index_S) ? ptr_offset : nrows;
01335     Lminindexvalue = -ptr_offset; 
01336     Lmaxindexvalue = Lminindexvalue + nrows - 1;
01337     data = delete_pointer_data + ptr_offset;
01338     internal_Lmode = Lnew;
01339   }
01340 
01341   // now for the right indexing:
01342   if (Rnew != Rmode) {
01343     int ptr_offset; // pointer offset into a row to data[][0]
01344 
01345     switch (Rnew) { // the new offset
01346     default:
01347       { return *this; } // unknown mode, so do nothing
01348     case Index_C:
01349       { ptr_offset = 0; break; }
01350     case Index_1:
01351       { ptr_offset = -1; break; }
01352     case Index_S:
01353       { ptr_offset = (ncols - 1)/2; break; }
01354     } // switch
01355     int old_Rsize = Rsize;  // save for switch below
01356     internal_Rsize = (Rnew == Index_S) ? ptr_offset : ncols;
01357     Rminindexvalue = -ptr_offset; 
01358     Rmaxindexvalue = Rminindexvalue + ncols - 1;
01359     switch (Rmode) { // subtract off the old offset
01360     default:
01361     case Index_C:
01362       { ptr_offset -= 0; break; }
01363     case Index_1:
01364       { ptr_offset -= -1; break; }
01365     case Index_S:
01366       { ptr_offset -= old_Rsize; break; }
01367     }
01368     // now ptr_offset is how far we must adjust each row pointer
01369     for (int i = Lminindexvalue; i <= Lmaxindexvalue; ++i)
01370       data[i] += ptr_offset;
01371     internal_Rmode = Rnew;
01372   } // if (Rnew != Rmode)  
01373 
01374   return *this;
01375 }
01376 
01377 //-------------------------------------------------------------------------
01378 // constfill()  fill the matrix with a constant value
01379 //              Note: data subset control will affect elements copied
01380 
01381 void complex_matrix::constfill(const Complex f)
01382 {
01383   for (int i = Lminindex(); i <= Lmaxindex(); ++i)
01384     for (int j = Rminindex(); j <= Rmaxindex(); ++j)
01385       data[i][j] = f;
01386 }
01387 
01388 //-------------------------------------------------------------------------
01389 // fillall()  fill regardless of data subset control
01390 
01391 complex_matrix & complex_matrix::fillall(const Complex f)
01392 {
01393   int save_Lmax = Lmaxindexvalue; 
01394   int save_Rmax = Rmaxindexvalue;
01395   int save_Lmin = Lminindexvalue; 
01396   int save_Rmin = Rminindexvalue;
01397 
01398   maxindex(Lsize+Rsize); // access full matrix
01399   constfill(f);
01400   Lmaxindexvalue = save_Lmax; Rmaxindexvalue = save_Rmax;  // restore subset
01401   Lminindexvalue = save_Lmin; Rminindexvalue = save_Rmin;
01402   return *this;
01403 }
01404 
01405 //-------------------------------------------------------------------------
01406 // fill a row or column from a vector
01407 
01408 complex_matrix & complex_matrix::fillrow(const int n, const real_vector & v)
01409 {
01410   if ((n >= Lminindex())&&(n <= Lmaxindex())) {  // then n is o.k.
01411     for (int i = Rminindex(); i <= Rmaxindex(); ++i)
01412       data[n][i] = v.read(i);
01413   }
01414   return *this;
01415 }
01416 
01417 complex_matrix & complex_matrix::fillrow(const int n, const complex_vector & v)
01418 {
01419   if ((n >= Lminindex())&&(n <= Lmaxindex())) {  // then n is o.k.
01420     for (int i = Rminindex(); i <= Rmaxindex(); ++i)
01421       data[n][i] = v.read(i);
01422   }
01423   return *this;
01424 }
01425 
01426 complex_matrix & complex_matrix::fillcol(const int n, const real_vector & v)
01427 {
01428   if ((n >= Rminindex())&&(n <= Rmaxindex())) {  // then n is o.k.
01429     for (int i = Lminindex(); i <= Lmaxindex(); ++i)
01430       data[i][n] = v.read(i);
01431   }
01432   return *this;
01433 }
01434 
01435 complex_matrix & complex_matrix::fillcol(const int n, const complex_vector & v)
01436 {
01437   if ((n >= Rminindex())&&(n <= Rmaxindex())) {  // then n is o.k.
01438     for (int i = Lminindex(); i <= Lmaxindex(); ++i)
01439       data[i][n] = v.read(i);
01440   }
01441   return *this;
01442 }
01443 
01444 //-------------------------------------------------------------------------
01445 // Lmaxindex(n), Rmaxindex(n), make_empty()
01446 
01447 int complex_matrix::Lmaxindex(const int n)
01448 {
01449   if (Lsize == 0 && Lmode != Index_S)
01450     // can't change the maxindex if no data elements
01451     return Lmaxindex();
01452   else {
01453     switch (Lmode) {
01454     case Index_C: {
01455       Lmaxindexvalue = min((Lsize - 1), max(0,n));
01456       break;
01457     }
01458     case Index_1: {
01459       Lmaxindexvalue = min(Lsize, max(1,n));
01460       break;
01461     }
01462     case Index_S: {
01463       Lmaxindexvalue = min(Lsize, max(0,n));
01464       Lminindexvalue = -Lmaxindexvalue;
01465       break;
01466     }
01467     } //switch
01468     return Lmaxindexvalue;
01469   } //else
01470 }
01471 
01472 int complex_matrix::Rmaxindex(const int n)
01473 {
01474   if (Rsize == 0 && Rmode != Index_S)
01475     // can't change the maxindex if no data elements
01476     return Rmaxindex();
01477   else {
01478     switch (Rmode) {
01479     case Index_C: {
01480       Rmaxindexvalue = min((Rsize - 1), max(0,n));
01481       break;
01482     }
01483     case Index_1: {
01484       Rmaxindexvalue = min(Rsize, max(1,n));
01485       break;
01486     }
01487     case Index_S: {
01488       Rmaxindexvalue = min(Rsize, max(0,n));
01489       Rminindexvalue = -Rmaxindexvalue;
01490       break;
01491     }
01492     } //switch
01493     return Rmaxindexvalue;
01494   } //else
01495 }
01496 
01497 complex_matrix & complex_matrix::make_empty()
01498 {
01499   switch (Lmode) {
01500   case Index_C:
01501     Lmaxindexvalue = -1;
01502     Lminindexvalue = 0;
01503     break;
01504 
01505   case Index_1:
01506     Lmaxindexvalue = 0;
01507     Lminindexvalue = 1;
01508     break;
01509 
01510   case Index_S:
01511     Lmaxindexvalue = -1;
01512     Lminindexvalue = 1;
01513     break;
01514 
01515   }
01516   
01517   switch (Rmode) {
01518   case Index_C:
01519     Rmaxindexvalue = -1;
01520     Rminindexvalue = 0;
01521     break;
01522 
01523   case Index_1:
01524     Rmaxindexvalue = 0;
01525     Rminindexvalue = 1;
01526     break;
01527 
01528   case Index_S:
01529     Rmaxindexvalue = -1;
01530     Rminindexvalue = 1;
01531     break;
01532 
01533   }
01534   
01535   return *this;
01536 }
01537 
01538 
01539 //-------------------------------------------------------------------------
01540 // copy() copy contents of another matrix
01541 
01542 complex_matrix & complex_matrix::copy(const complex_matrix & B)
01543 {
01544   // check for self copy: "A.copy(A)", and do something intelligent:
01545   if (this == & B) { clean(); return *this; }
01546 
01547   // otherwise, not a self copy, so:
01548   maxindex(Lsize+Rsize);  // make all data accessible
01549   constfill(0);           // and clear the matrix
01550   // now set data subset on the result:
01551   if(B.is_empty())
01552     make_empty();
01553   else {
01554     Lmaxindex(B.Lmaxindex());
01555     Rmaxindex(B.Rmaxindex());
01556     // loop over the index range intersection and copy:
01557     int Lmax = min(Lmaxindex(), B.Lmaxindex());
01558     int Lmin = max(Lminindex(), B.Lminindex());
01559     int Rmax = min(Rmaxindex(), B.Rmaxindex());
01560     int Rmin = max(Rminindex(), B.Rminindex());
01561     int i,j;
01562     for (i = Lmin; i <= Lmax; ++i)
01563       for (j = Rmin; j <= Rmax; ++j)
01564         data[i][j] = B[i][j];
01565   }
01566   return *this;
01567 }
01568 
01569 complex_matrix & complex_matrix::copy(const real_matrix & B)
01570 {
01571   maxindex(Lsize+Rsize);  // make all data accessible
01572   constfill(0);           // and clear the matrix
01573   // now set data subset on the result:
01574   if(B.is_empty())
01575     make_empty();
01576   else {
01577     Lmaxindex(B.Lmaxindex());
01578     Rmaxindex(B.Rmaxindex());
01579     // loop over the index range intersection and copy:
01580     int Lmax = min(Lmaxindex(), B.Lmaxindex());
01581     int Lmin = max(Lminindex(), B.Lminindex());
01582     int Rmax = min(Rmaxindex(), B.Rmaxindex());
01583     int Rmin = max(Rminindex(), B.Rminindex());
01584     int i,j;
01585     for (i = Lmin; i <= Lmax; ++i)
01586       for (j = Rmin; j <= Rmax; ++j)
01587         data[i][j] = B[i][j];
01588   }
01589   return *this;
01590 }
01591 
01592 //-------------------------------------------------------------------------
01593 // reallocate() change size or indexing modes
01594 
01595 complex_matrix & complex_matrix::reallocate
01596   (const int n, const int m, const v_index_mode tl, const v_index_mode tr)
01597 {
01598   // just return if reallocation is unnecessary:
01599   if ((Lsize == n)&&(Rsize == m)&&(Lmode == tl)&&(Rmode == tr)) return *this;
01600 
01601   // if we're here, we have to reallocate:
01602   // save the data subset control values and then maximize:
01603   int new_Lmax = Lmaxindexvalue;
01604   int new_Rmax = Rmaxindexvalue;
01605   maxindex(Lsize + Rsize);
01606 
01607   // check if data subset control was turned off; if so, keep turned off
01608   if (new_Lmax == Lmaxindexvalue) new_Lmax = n; 
01609   if (new_Rmax == Rmaxindexvalue) new_Rmax = m; 
01610 
01611   // now save the necessary private data members:
01612   int Lmax = Lmaxindexvalue;
01613   int Lmin = Lminindexvalue;
01614   int Rmax = Rmaxindexvalue;
01615   int Rmin = Rminindexvalue;
01616   Complex **old_data = data; 
01617   Complex **delete1 = delete_pointer_data;
01618   Complex  *delete2 = delete_pointer_rows;
01619 
01620   // with this done, now construct the new matrix:
01621   construct(n, m, tl, tr);
01622   constfill(0);
01623 
01624   // now copy in the data using the saved private data members:
01625   Lmax = min(Lmaxindex(), Lmax);
01626   Lmin = max(Lminindex(), Lmin);
01627   Rmax = min(Rmaxindex(), Rmax);
01628   Rmin = max(Rminindex(), Rmin);
01629   int i,j;
01630   for (i = Lmin; i <= Lmax; ++i)
01631     for (j = Rmin; j <= Rmax; ++j)
01632       data[i][j] = old_data[i][j];
01633 
01634   // set data subset control
01635   Lmaxindex(new_Lmax);
01636   Rmaxindex(new_Rmax);
01637 
01638   // finally delete the old memory allocation:
01639   delete [] delete1;
01640   delete [] delete2;
01641 
01642   return *this;
01643 }
01644 
01645 //-------------------------------------------------------------------------
01646 // Basic assignment operator
01647 
01648 complex_matrix & complex_matrix::operator = (const complex_matrix & B)
01649 {
01650   // check for self assignment: "A = A", and do something intelligent:
01651   if (this == & B) { clean(); return *this; }
01652 
01653   // reallocate memory if needed:
01654   maximize();
01655   if ((B.Lmode != Lmode)||(B.Rmode != Rmode)||
01656       (B.Lmaxindex() > Lmaxindexvalue)||(B.Rmaxindex() > Rmaxindexvalue)) {
01657     delete [] delete_pointer_data; delete [] delete_pointer_rows;
01658     int newLsize = (B.Lmode == Index_C) ? B.Lmaxindex()+1: B.Lmaxindex();
01659     int newRsize = (B.Rmode == Index_C) ? B.Rmaxindex()+1: B.Rmaxindex();
01660     construct(newLsize, newRsize, B.Lmode, B.Rmode);
01661   }
01662 
01663   copy(B);
01664   return *this;
01665 }
01666 
01667 complex_matrix & complex_matrix::operator = (const real_matrix & B)
01668 {
01669   // reallocate memory if needed:
01670   maximize();
01671   if ((B.Lmode != Lmode)||(B.Rmode != Rmode)||
01672       (B.Lmaxindex() > Lmaxindexvalue)||(B.Rmaxindex() > Rmaxindexvalue)) {
01673     delete [] delete_pointer_data; delete [] delete_pointer_rows;
01674     int newLsize = (B.Lmode == Index_C) ? B.Lmaxindex()+1: B.Lmaxindex();
01675     int newRsize = (B.Rmode == Index_C) ? B.Rmaxindex()+1: B.Rmaxindex();
01676     construct(newLsize, newRsize, B.Lmode, B.Rmode);
01677   }
01678 
01679   copy(B);
01680   return *this;
01681 }
01682 
01683 //---------------------------------------------------------------------
01684 // other assignment operators (no memory reallocation for these):
01685 
01686 complex_matrix & complex_matrix::operator += (const Complex s)
01687 {
01688   register Complex *d, *limit;  // local pointers within a row
01689   register int i;
01690   for(i = Lminindexvalue; i <= Lmaxindexvalue; ++i) {
01691     // make local pointers to the first and last elements in the row:
01692     limit = d = data[i];
01693     d += Rminindexvalue; limit += Rmaxindexvalue;
01694     // use the pointer to the first element as the loop variable:
01695     while (d <= limit) *(d++) += s;
01696   }
01697   return *this;
01698 }
01699 
01700 complex_matrix & complex_matrix::operator -= (const Complex s)
01701 {
01702   register Complex *d, *limit;  // local pointers within a row
01703   register int i;
01704   for(i = Lminindexvalue; i <= Lmaxindexvalue; ++i) {
01705     // make local pointers to the first and last elements in the row:
01706     limit = d = data[i];
01707     d += Rminindexvalue; limit += Rmaxindexvalue;
01708     // use the pointer to the first element as the loop variable:
01709     while (d <= limit) *(d++) -= s;
01710   }
01711   return *this;
01712 }
01713 
01714 complex_matrix & complex_matrix::operator *= (const Complex s)
01715 {
01716   register Complex *d, *limit;  // local pointers within a row
01717   register int i;
01718   for(i = Lminindexvalue; i <= Lmaxindexvalue; ++i) {
01719     // make local pointers to the first and last elements in the row:
01720     limit = d = data[i];
01721     d += Rminindexvalue; limit += Rmaxindexvalue;
01722     // use the pointer to the first element as the loop variable:
01723     while (d <= limit) *(d++) *= s;
01724   }
01725   return *this;
01726 }
01727 
01728 complex_matrix & complex_matrix::operator /= (const Complex s)
01729 {
01730   register Complex *d, *limit;  // local pointers within a row
01731   register int i;
01732   for(i = Lminindexvalue; i <= Lmaxindexvalue; ++i) {
01733     // make local pointers to the first and last elements in the row:
01734     limit = d = data[i];
01735     d += Rminindexvalue; limit += Rmaxindexvalue;
01736     // use the pointer to the first element as the loop variable:
01737     while (d <= limit) *(d++) /= s;
01738   }
01739   return *this;
01740 }
01741 
01742 complex_matrix & complex_matrix::operator += (const complex_matrix & B)
01743 {
01744   clean();  // ensure nonvalid elements are 0
01745   // increase target's valid data range if necessary:
01746   if (Lmaxindexvalue < B.Lmaxindex()) Lmaxindex(B.Lmaxindex());
01747   if (Rmaxindexvalue < B.Rmaxindex()) Rmaxindex(B.Rmaxindex());
01748   // find the intersection of the valid data ranges:
01749   int Lmax = min(Lmaxindex(), B.Lmaxindex());
01750   int Lmin = max(Lminindex(), B.Lminindex());
01751   int Rmax = min(Rmaxindex(), B.Rmaxindex());
01752   int Rmin = max(Rminindex(), B.Rminindex());
01753   // loop over the intersection of the ranges:
01754   register int i,j;
01755   for (i = Lmin; i <= Lmax; ++i)
01756     for (j = Rmin; j <= Rmax; ++j)
01757       data[i][j] += B[i][j];
01758   return *this;
01759 }
01760 
01761 complex_matrix & complex_matrix::operator -= (const complex_matrix & B)
01762 {
01763   clean();  // ensure nonvalid elements are 0
01764   // increase target's valid data range if necessary:
01765   if (Lmaxindexvalue < B.Lmaxindex()) Lmaxindex(B.Lmaxindex());
01766   if (Rmaxindexvalue < B.Rmaxindex()) Rmaxindex(B.Rmaxindex());
01767   // find the intersection of the valid data ranges:
01768   int Lmax = min(Lmaxindex(), B.Lmaxindex());
01769   int Lmin = max(Lminindex(), B.Lminindex());
01770   int Rmax = min(Rmaxindex(), B.Rmaxindex());
01771   int Rmin = max(Rminindex(), B.Rminindex());
01772   // loop over the intersection of the ranges:
01773   register int i,j;
01774   for (i = Lmin; i <= Lmax; ++i)
01775     for (j = Rmin; j <= Rmax; ++j)
01776       data[i][j] -= B[i][j];
01777   return *this;
01778 }
01779 
01780 complex_matrix & complex_matrix::operator += (const real_matrix & B)
01781 {
01782   clean();  // ensure nonvalid elements are 0
01783   // increase target's valid data range if necessary:
01784   if (Lmaxindexvalue < B.Lmaxindex()) Lmaxindex(B.Lmaxindex());
01785   if (Rmaxindexvalue < B.Rmaxindex()) Rmaxindex(B.Rmaxindex());
01786   // find the intersection of the valid data ranges:
01787   int Lmax = min(Lmaxindex(), B.Lmaxindex());
01788   int Lmin = max(Lminindex(), B.Lminindex());
01789   int Rmax = min(Rmaxindex(), B.Rmaxindex());
01790   int Rmin = max(Rminindex(), B.Rminindex());
01791   // loop over the intersection of the ranges:
01792   register int i,j;
01793   for (i = Lmin; i <= Lmax; ++i)
01794     for (j = Rmin; j <= Rmax; ++j)
01795       data[i][j] += B[i][j];
01796   return *this;
01797 }
01798 
01799 complex_matrix & complex_matrix::operator -= (const real_matrix & B)
01800 {
01801   clean();  // ensure nonvalid elements are 0
01802   // increase target's valid data range if necessary:
01803   if (Lmaxindexvalue < B.Lmaxindex()) Lmaxindex(B.Lmaxindex());
01804   if (Rmaxindexvalue < B.Rmaxindex()) Rmaxindex(B.Rmaxindex());
01805   // find the intersection of the valid data ranges:
01806   int Lmax = min(Lmaxindex(), B.Lmaxindex());
01807   int Lmin = max(Lminindex(), B.Lminindex());
01808   int Rmax = min(Rmaxindex(), B.Rmaxindex());
01809   int Rmin = max(Rminindex(), B.Rminindex());
01810   // loop over the intersection of the ranges:
01811   register int i,j;
01812   for (i = Lmin; i <= Lmax; ++i)
01813     for (j = Rmin; j <= Rmax; ++j)
01814       data[i][j] -= B[i][j];
01815   return *this;
01816 }
01817 
01818 //-------------------------------------------------------------------------
01819 // matrix math member fcns (other than assignment)
01820 
01821 complex_matrix & complex_matrix::add
01822 (const complex_matrix & B, const complex_matrix & C)
01823 {
01824   // first check that neither B nor C is this matrix:
01825   if ((&B != this)&&(&C != this)) {
01826     // make the size of the result correct, and initiallize to all zeroes:
01827     maximize();
01828     v_index_mode Lm = ResultModeMax(B.Lmode, C.Lmode);
01829     v_index_mode Rm = ResultModeMax(B.Rmode, C.Rmode);
01830     int Ls = max(B.Lmaxindex(), C.Lmaxindex());
01831     int Rs = max(B.Rmaxindex(), C.Rmaxindex());
01832     if ((Lmode!=Lm)||(Rmode!=Rm)||(Lmaxindex()<Ls)||(Rmaxindex()<Rs)) {
01833       // fix up the result matrix in two steps: index modes first, then sizes
01834       // the result will automatically be zeroed
01835       reallocate(0,0,Lm,Rm); get(0,0) = 0; resize(Ls,Rs);
01836       // we need the above get() = 0 in case Lm == Rm == Index_S
01837     }
01838     else {
01839       // result's modes and sizes o.k., just zero and set maxindexes
01840       fill(0.0);
01841       Lmaxindex(Ls); Rmaxindex(Rs);
01842     }
01843     // Now do the sum:
01844     (*this) += B; (*this) += C;
01845   }
01846   else if (&B == this) { // the first argument is this matrix
01847     // if necessary, resize this matrix to hold all elements in the sum
01848     int Ls = max(Lmaxindex(), C.Lmaxindex());
01849     int Rs = max(Rmaxindex(), C.Rmaxindex());
01850     if ((Lmaxindex() < Ls)||(Rmaxindex() < Rs)) {
01851       clean(); maximize();
01852     }
01853     v_index_mode Lm = ResultModeMax(Lmode, C.Lmode);
01854     v_index_mode Rm = ResultModeMax(Rmode, C.Rmode);
01855     if ((Lmode!=Lm)||(Rmode!=Rm)||(Lmaxindex()<Ls)||(Rmaxindex()<Rs)) {
01856       int sL = (Lm == Index_C) ? Ls + 1 : Ls;
01857       int sR = (Rm == Index_C) ? Rs + 1 : Rs;
01858       reallocate(sL,sR,Lm,Rm);
01859     }
01860     Lmaxindex(Ls); Rmaxindex(Rs);
01861     // Now do the sum:
01862     (*this) += C;
01863   }
01864   else { // the second argument is this matrix
01865     // if necessary, resize this matrix to hold all elements in the sum
01866     int Ls = max(Lmaxindex(), B.Lmaxindex());
01867     int Rs = max(Rmaxindex(), B.Rmaxindex());
01868     if ((Lmaxindex() < Ls)||(Rmaxindex() < Rs)) {
01869       clean(); maximize();
01870     }
01871     v_index_mode Lm = ResultModeMax(Lmode, B.Lmode);
01872     v_index_mode Rm = ResultModeMax(Rmode, B.Rmode);
01873     if ((Lmode!=Lm)||(Rmode!=Rm)||(Lmaxindex()<Ls)||(Rmaxindex()<Rs)) {
01874       int sL = (Lm == Index_C) ? Ls + 1 : Ls;
01875       int sR = (Rm == Index_C) ? Rs + 1 : Rs;
01876       reallocate(sL,sR,Lm,Rm);
01877     }
01878     Lmaxindex(Ls); Rmaxindex(Rs);
01879     // Now do the sum:
01880     (*this) += B;
01881   }
01882   return *this;
01883 }
01884 
01885 complex_matrix & complex_matrix::add
01886 (const complex_matrix & B, const real_matrix & C)
01887 {
01888   // first check that B is not this matrix:
01889   if (&B != this) {
01890     // make the size of the result correct, and initiallize to all zeroes:
01891     maximize();
01892     v_index_mode Lm = ResultModeMax(B.Lmode, C.Lmode);
01893     v_index_mode Rm = ResultModeMax(B.Rmode, C.Rmode);
01894     int Ls = max(B.Lmaxindex(), C.Lmaxindex());
01895     int Rs = max(B.Rmaxindex(), C.Rmaxindex());
01896     if ((Lmode!=Lm)||(Rmode!=Rm)||(Lmaxindex()<Ls)||(Rmaxindex()<Rs)) {
01897       // fix up the result matrix in two steps: index modes first, then sizes
01898       // the result will automatically be zeroed
01899       reallocate(0,0,Lm,Rm); get(0,0) = 0; resize(Ls,Rs);
01900       // we need the above get() = 0 in case Lm == Rm == Index_S
01901     }
01902     else {
01903       // result's modes and sizes o.k., just zero and set maxindexes
01904       fill(0.0);
01905       Lmaxindex(Ls); Rmaxindex(Rs);
01906     }
01907     // Now do the sum:
01908     (*this) += B; (*this) += C;
01909   }
01910   else { // B is this matrix
01911     // if necessary, resize this matrix to hold all elements in the sum
01912     int Ls = max(Lmaxindex(), C.Lmaxindex());
01913     int Rs = max(Rmaxindex(), C.Rmaxindex());
01914     if ((Lmaxindex() < Ls)||(Rmaxindex() < Rs)) {
01915       clean(); maximize();
01916     }
01917     v_index_mode Lm = ResultModeMax(Lmode, C.Lmode);
01918     v_index_mode Rm = ResultModeMax(Rmode, C.Rmode);
01919     if ((Lmode!=Lm)||(Rmode!=Rm)||(Lmaxindex()<Ls)||(Rmaxindex()<Rs)) {
01920       int sL = (Lm == Index_C) ? Ls + 1 : Ls;
01921       int sR = (Rm == Index_C) ? Rs + 1 : Rs;
01922       reallocate(sL,sR,Lm,Rm);
01923     }
01924     Lmaxindex(Ls); Rmaxindex(Rs);
01925     // Now do the sum:
01926     (*this) += C;
01927   }
01928   return *this;
01929 }
01930 
01931 complex_matrix & complex_matrix::add
01932 (const real_matrix & B, const real_matrix & C)
01933 {
01934   // make the size of the result correct, and initiallize to all zeroes:
01935   maximize();
01936   v_index_mode Lm = ResultModeMax(B.Lmode, C.Lmode);
01937   v_index_mode Rm = ResultModeMax(B.Rmode, C.Rmode);
01938   int Ls = max(B.Lmaxindex(), C.Lmaxindex());
01939   int Rs = max(B.Rmaxindex(), C.Rmaxindex());
01940   if ((Lmode != Lm)||(Rmode != Rm)||(Lmaxindex() < Ls)||(Rmaxindex() < Rs)) {
01941     // fix up the result matrix in two steps: index modes first, then sizes
01942     // the result will automatically be zeroed
01943     reallocate(0,0,Lm,Rm); get(0,0) = 0; resize(Ls,Rs);
01944     // we need the above get() = 0 in case Lm == Rm == Index_S
01945   }
01946   else {
01947     // result's modes and sizes o.k., just zero and set maxindexes
01948     fill(0.0);
01949     Lmaxindex(Ls); Rmaxindex(Rs);
01950   }
01951 
01952   // Now do the sum and return:
01953   (*this) += B; (*this) += C;
01954   return *this;
01955 }
01956 
01957 complex_matrix & complex_matrix::sub
01958 (const complex_matrix & B, const complex_matrix & C)
01959 {
01960   // first check that neither B nor C is this matrix:
01961   if ((&B != this)&&(&C != this)) {
01962     // make the size of the result correct, and initiallize to all zeroes:
01963     maximize();
01964     v_index_mode Lm = ResultModeMax(B.Lmode, C.Lmode);
01965     v_index_mode Rm = ResultModeMax(B.Rmode, C.Rmode);
01966     int Ls = max(B.Lmaxindex(), C.Lmaxindex());
01967     int Rs = max(B.Rmaxindex(), C.Rmaxindex());
01968     if ((Lmode!=Lm)||(Rmode!=Rm)||(Lmaxindex()<Ls)||(Rmaxindex()<Rs)) {
01969       // fix up the result matrix in two steps: index modes first, then sizes
01970       // the result will automatically be zeroed
01971       reallocate(0,0,Lm,Rm); get(0,0) = 0; resize(Ls,Rs);
01972       // we need the above get() = 0 in case Lm == Rm == Index_S
01973     }
01974     else {
01975       // result's modes and sizes o.k., just zero and set maxindexes
01976       fill(0.0);
01977       Lmaxindex(Ls); Rmaxindex(Rs);
01978     }
01979     // Now do the subtraction:
01980     (*this) += B; (*this) -= C;
01981   }
01982   else if (&B == this) { // the first argument is this matrix
01983     // if necessary, resize this matrix to hold all elements
01984     int Ls = max(Lmaxindex(), C.Lmaxindex());
01985     int Rs = max(Rmaxindex(), C.Rmaxindex());
01986     if ((Lmaxindex() < Ls)||(Rmaxindex() < Rs)) {
01987       clean(); maximize();
01988     }
01989     v_index_mode Lm = ResultModeMax(Lmode, C.Lmode);
01990     v_index_mode Rm = ResultModeMax(Rmode, C.Rmode);
01991     if ((Lmode!=Lm)||(Rmode!=Rm)||(Lmaxindex()<Ls)||(Rmaxindex()<Rs)) {
01992       int sL = (Lm == Index_C) ? Ls + 1 : Ls;
01993       int sR = (Rm == Index_C) ? Rs + 1 : Rs;
01994       reallocate(sL,sR,Lm,Rm);
01995     }
01996     Lmaxindex(Ls); Rmaxindex(Rs);
01997     // Now do the subtraction:
01998     (*this) -= C;
01999   }
02000   else { // the second argument is this matrix
02001     (*this) *= -1;  // since it's the 2nd argument
02002     // if necessary, resize this matrix to hold all elements
02003     int Ls = max(Lmaxindex(), B.Lmaxindex());
02004     int Rs = max(Rmaxindex(), B.Rmaxindex());
02005     if ((Lmaxindex() < Ls)||(Rmaxindex() < Rs)) {
02006       clean(); maximize();
02007     }
02008     v_index_mode Lm = ResultModeMax(Lmode, B.Lmode);
02009     v_index_mode Rm = ResultModeMax(Rmode, B.Rmode);
02010     if ((Lmode!=Lm)||(Rmode!=Rm)||(Lmaxindex()<Ls)||(Rmaxindex()<Rs)) {
02011       int sL = (Lm == Index_C) ? Ls + 1 : Ls;
02012       int sR = (Rm == Index_C) ? Rs + 1 : Rs;
02013       reallocate(sL,sR,Lm,Rm);
02014     }
02015     Lmaxindex(Ls); Rmaxindex(Rs);
02016     // Now do the sum:
02017     (*this) += B;
02018   }
02019   return *this;
02020 }
02021 
02022 complex_matrix & complex_matrix::sub
02023 (const complex_matrix & B, const real_matrix & C)
02024 {
02025   // first check that B is not this matrix:
02026   if (&B != this) {
02027     // make the size of the result correct, and initiallize to all zeroes:
02028     maximize();
02029     v_index_mode Lm = ResultModeMax(B.Lmode, C.Lmode);
02030     v_index_mode Rm = ResultModeMax(B.Rmode, C.Rmode);
02031     int Ls = max(B.Lmaxindex(), C.Lmaxindex());
02032     int Rs = max(B.Rmaxindex(), C.Rmaxindex());
02033     if ((Lmode!=Lm)||(Rmode!=Rm)||(Lmaxindex()<Ls)||(Rmaxindex()<Rs)) {
02034       // fix up the result matrix in two steps: index modes first, then sizes
02035       // the result will automatically be zeroed
02036       reallocate(0,0,Lm,Rm); get(0,0) = 0; resize(Ls,Rs);
02037       // we need the above get() = 0 in case Lm == Rm == Index_S
02038     }
02039     else {
02040       // result's modes and sizes o.k., just zero and set maxindexes
02041       fill(0.0);
02042       Lmaxindex(Ls); Rmaxindex(Rs);
02043     }
02044     // Now do the subtraction:
02045     (*this) += B; (*this) -= C;
02046   }
02047   else { // B is this matrix
02048     // if necessary, resize this matrix to hold all elements
02049     int Ls = max(Lmaxindex(), C.Lmaxindex());
02050     int Rs = max(Rmaxindex(), C.Rmaxindex());
02051     if ((Lmaxindex() < Ls)||(Rmaxindex() < Rs)) {
02052       clean(); maximize();
02053     }
02054     v_index_mode Lm = ResultModeMax(Lmode, C.Lmode);
02055     v_index_mode Rm = ResultModeMax(Rmode, C.Rmode);
02056     if ((Lmode!=Lm)||(Rmode!=Rm)||(Lmaxindex()<Ls)||(Rmaxindex()<Rs)) {
02057       int sL = (Lm == Index_C) ? Ls + 1 : Ls;
02058       int sR = (Rm == Index_C) ? Rs + 1 : Rs;
02059       reallocate(sL,sR,Lm,Rm);
02060     }
02061     Lmaxindex(Ls); Rmaxindex(Rs);
02062     // Now do the subtraction:
02063     (*this) -= C;
02064   }
02065   return *this;
02066 }
02067 
02068 complex_matrix & complex_matrix::sub
02069 (const real_matrix & B, const complex_matrix & C)
02070 {
02071   // first check that C is not this matrix:
02072   if (&C != this) {
02073     // make the size of the result correct, and initiallize to all zeroes:
02074     maximize();
02075     v_index_mode Lm = ResultModeMax(B.Lmode, C.Lmode);
02076     v_index_mode Rm = ResultModeMax(B.Rmode, C.Rmode);
02077     int Ls = max(B.Lmaxindex(), C.Lmaxindex());
02078     int Rs = max(B.Rmaxindex(), C.Rmaxindex());
02079     if ((Lmode!=Lm)||(Rmode!=Rm)||(Lmaxindex()<Ls)||(Rmaxindex()<Rs)) {
02080       // fix up the result matrix in two steps: index modes first, then sizes
02081       // the result will automatically be zeroed
02082       reallocate(0,0,Lm,Rm); get(0,0) = 0; resize(Ls,Rs);
02083       // we need the above get() = 0 in case Lm == Rm == Index_S
02084     }
02085     else {
02086       // result's modes and sizes o.k., just zero and set maxindexes
02087       fill(0.0);
02088       Lmaxindex(Ls); Rmaxindex(Rs);
02089     }
02090     // Now do the subtraction:
02091     (*this) += B; (*this) -= C;
02092   }
02093   else { // C is this matrix
02094     (*this) *= -1;  // since it's the 2nd argument
02095     // if necessary, resize this matrix to hold all elements
02096     int Ls = max(Lmaxindex(), B.Lmaxindex());
02097     int Rs = max(Rmaxindex(), B.Rmaxindex());
02098     if ((Lmaxindex() < Ls)||(Rmaxindex() < Rs)) {
02099       clean(); maximize();
02100     }
02101     v_index_mode Lm = ResultModeMax(Lmode, B.Lmode);
02102     v_index_mode Rm = ResultModeMax(Rmode, B.Rmode);
02103     if ((Lmode!=Lm)||(Rmode!=Rm)||(Lmaxindex()<Ls)||(Rmaxindex()<Rs)) {
02104       int sL = (Lm == Index_C) ? Ls + 1 : Ls;
02105       int sR = (Rm == Index_C) ? Rs + 1 : Rs;
02106       reallocate(sL,sR,Lm,Rm);
02107     }
02108     Lmaxindex(Ls); Rmaxindex(Rs);
02109     // Now do the sum:
02110     (*this) += B;
02111   }
02112   return *this;
02113 }
02114 
02115 complex_matrix & complex_matrix::sub
02116 (const real_matrix & B, const real_matrix & C)
02117 {
02118   // make the size of the result correct, and initiallize to all zeroes:
02119   maximize();
02120   v_index_mode Lm = ResultModeMax(B.Lmode, C.Lmode);
02121   v_index_mode Rm = ResultModeMax(B.Rmode, C.Rmode);
02122   int Ls = max(B.Lmaxindex(), C.Lmaxindex());
02123   int Rs = max(B.Rmaxindex(), C.Rmaxindex());
02124   if ((Lmode != Lm)||(Rmode != Rm)||(Lmaxindex() < Ls)||(Rmaxindex() < Rs)) {
02125     // fix up the result matrix in two steps: index modes first, then sizes
02126     // the result will automatically be zeroed
02127     reallocate(0,0,Lm,Rm); get(0,0) = 0; resize(Ls,Rs);
02128     // we need the above get() = 0 in case Lm == Rm == Index_S
02129   }
02130   else {
02131     // result's modes and sizes o.k., just zero and set maxindexes
02132     fill(0.0);
02133     Lmaxindex(Ls); Rmaxindex(Rs);
02134   }
02135 
02136   // Now do the sum and return:
02137   (*this) += B; (*this) -= C;
02138   return *this;
02139 }
02140 
02141 complex_matrix & complex_matrix::real(const complex_matrix & B)
02142 {
02143   if (this != &B) {    // don't resize if B is this matrix
02144     resize(B);
02145     if(B.is_empty())
02146       make_empty();
02147     else {
02148       Lmaxindex(B.Lmaxindex());
02149       Rmaxindex(B.Rmaxindex());
02150     }
02151   }
02152   int i,j;
02153   for (i = Lminindex(); i <= Lmaxindex(); ++i)
02154     for (j = Rminindex(); j <= Rmaxindex(); ++j)
02155       data[i][j] = B[i][j].real;
02156   return *this;
02157 }
02158 
02159 complex_matrix & complex_matrix::imaginary(const complex_matrix & B)
02160 {
02161   if (this != &B) {    // don't resize if B is this matrix
02162     resize(B);
02163     if(B.is_empty())
02164       make_empty();
02165     else {
02166       Lmaxindex(B.Lmaxindex());
02167       Rmaxindex(B.Rmaxindex());
02168     }
02169   }
02170   int i,j;
02171   for (i = Lminindex(); i <= Lmaxindex(); ++i)
02172     for (j = Rminindex(); j <= Rmaxindex(); ++j)
02173       data[i][j] = B[i][j].imaginary;
02174   return *this;
02175 }
02176 
02177 //-------------------------------------------------------------------------
02178 // clean() clear elements beyond the valid index range
02179 
02180 complex_matrix & complex_matrix::clean(void)
02181 {
02182   // save index limits and maximize:
02183   int Lmax = Lmaxindexvalue;
02184   int Lmin = Lminindexvalue;
02185   int Rmax = Rmaxindexvalue;
02186   int Rmin = Rminindexvalue;
02187   maxindex(Lsize + Rsize);
02188 
02189   // now zero excess elements:
02190   int i,j;
02191   for (j = Rminindex(); j < Rmin; ++j)
02192     for (i = Lminindex(); i <= Lmaxindex(); ++i)
02193       data[i][j] = 0;
02194   for (j = Rmaxindex(); j > Rmax; --j)
02195     for (i = Lminindex(); i <= Lmaxindex(); ++i)
02196       data[i][j] = 0;
02197   for (i = Lmaxindex(); i > Lmax; --i)
02198     for (j = Rmin; j <= Rmax; ++j)
02199       data[i][j] = 0;
02200   for (i = Lminindex(); i < Lmin; ++i)
02201     for (j = Rmin; j <= Rmax; ++j)
02202       data[i][j] = 0;
02203 
02204   // restore index limits and return:
02205   Lmaxindex(Lmax);
02206   Rmaxindex(Rmax);
02207   return *this;
02208 }
02209 
02210 //---------------------------------------------------------------------
02211 // other miscellaneous funtions:
02212 
02213 complex_matrix & complex_matrix::diagonal(const Complex s)
02214 {
02215   fill(0.0);
02216   int min = minindex();
02217   int max = maxindex();
02218   for(register int i = min; i <= max; ++i)
02219     get(i,i) = s;
02220   return *this;
02221 }
02222 
02223 complex_matrix & complex_matrix::rowswap(const int n, const int m)
02224 {
02225   // check for do nothing n == m case first:
02226   if (n == m) return *this;
02227 
02228   // n != m if we get here:
02229   const int nBad = 1;
02230   const int mBad = 2;
02231   int nCheck = 0;
02232   int mCheck = 0;
02233   if ((n < Lminindexvalue)||(n > Lmaxindexvalue)) nCheck = nBad;
02234   if ((m < Lminindexvalue)||(m > Lmaxindexvalue)) mCheck = mBad;
02235   switch (nCheck + mCheck) {
02236   case 0: {
02237     // then both n and m are valid
02238     Complex * temp = data[n];
02239     data[n] = data[m];
02240     data[m] = temp;
02241     break;
02242   }
02243   case nBad: {
02244     // only m is valid, so fill with zeros
02245     complex_vector y(data[m], Rsize, Rmode);  // alias the row as a vector
02246     y.fill(0.0);
02247     break;
02248   }
02249   case mBad: {
02250     // only n is valid, so fill with zeros
02251     complex_vector y(data[n], Rsize, Rmode);  // alias the row as a vector
02252     y.fill(0.0);
02253     break;
02254   }
02255   case (nBad+mBad): {
02256     // both indexes are invalid, so do nothing
02257     break;
02258   }
02259   } // switch
02260   return *this;
02261 }
02262 
02263 complex_matrix & complex_matrix::apply(Complex (*f)(Complex))
02264 {
02265   register Complex *d, *limit;  // local pointers within a row
02266   register int i;
02267   for(i = Lminindexvalue; i <= Lmaxindexvalue; ++i) {
02268     // make local pointers to the first and last elements in the row:
02269     limit = d = data[i];
02270     d += Rminindexvalue; limit += Rmaxindexvalue;
02271     // use the pointer to the first element as the loop variable:
02272     for ( ; d <= limit; ++d) *d = f(*d);
02273   }
02274   return *this;
02275 }
02276 
02277 complex_matrix & complex_matrix::apply(Complex (*f)(const Complex &))
02278 {
02279   register Complex *d, *limit;  // local pointers within a row
02280   register int i;
02281   for(i = Lminindexvalue; i <= Lmaxindexvalue; ++i) {
02282     // make local pointers to the first and last elements in the row:
02283     limit = d = data[i];
02284     d += Rminindexvalue; limit += Rmaxindexvalue;
02285     // use the pointer to the first element as the loop variable:
02286     for ( ; d <= limit; ++d) *d = f(*d);
02287   }
02288   return *this;
02289 }
02290 
02291 complex_matrix & complex_matrix::apply(Complex (*f)(Complex, int, int))
02292 {
02293   int i;                     // row counter (left index)
02294   register Complex *d;       // inner loop pointer within a row
02295   register int j, limit;     // inner loop counter and a limit
02296   for(i = Lminindexvalue; i <= Lmaxindexvalue; ++i) {
02297     j = Rminindexvalue; limit = Rmaxindexvalue;
02298     for (d = data[i] + j; j <= limit; ++d, ++j) *d = f(*d, i, j);
02299   }
02300   return *this;
02301 }
02302 
02303 complex_matrix & complex_matrix::apply(Complex (*f)(const Complex &, int, int))
02304 {
02305   int i;                     // row counter (left index)
02306   register Complex *d;       // inner loop pointer within a row
02307   register int j, limit;     // inner loop counter and a limit
02308   for(i = Lminindexvalue; i <= Lmaxindexvalue; ++i) {
02309     j = Rminindexvalue; limit = Rmaxindexvalue;
02310     for (d = data[i] + j; j <= limit; ++d, ++j) *d = f(*d, i, j);
02311   }
02312   return *this;
02313 }
02314 
02315 // end of complex_matrix definitions

Please direct comments and corrections to supermix@submm.caltech.edu
Go to the supermix home page
Generated by doxygen1.2.7