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
1.2.7