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

vector.cc

Go to the documentation of this file.
00001 // vector.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 // 9/8/00:   added some STL compatibility functions
00033 // 4/26/00:  changed to support copying of empty vectors, make_empty()
00034 // 11/11/98: Changed table access to new syntax
00035 // 10/28/98: removed int_vector stuff
00036 // 7/31/98:  added out_separator() static member functions
00037 // 7/30/98:  Enhanced show(), added <<
00038 // 7/28/98:  Added <iostream.h>, since SIScmplx.h doesn't any more
00039 // 7/6/98:   Added reindex()
00040 // 1/9/98:   Changed shrink to return a reference to the vector, vice int
00041 // 12/18/97: Special version with show() member function
00042 // 12/12/97: "fully" tested with calc
00043 // 12/10/97: tests o.k. with calc.
00044 // 11/24/97: added additional versions of resize();
00045 // 11/11/97: real_vector and complex_vector test o.k. with vcalc.
00046 // 11/10/97: Fixed maxindex(n) bug. real_vector tests o.k. with vcalc.
00047 // 11/10/97: Many previously void member functions now return an Lvalue.
00048 // 11/8/97:  improved reallocate().
00049 // 11/7/97:  fixed a lingering bug in the copy constructor: it didn't set
00050 //           data subset control on the target!
00051 // 11/4/97:  added checks for v = v and v.copy(v), so these constructs
00052 //           behave properly (oops!).
00053 // 11/3/97:  New operator =, with an Rvalue RHS. Also made copy() faster.
00054 //           Not fully tested yet.
00055 // 10/15/97: added many new member functions and math functions; fixed
00056 //           to compile with CC
00057 // 10/6/97:  added int_vector definitions; cleaned up some others
00058 // 9/25/97:  renamed to vector.cc
00059 // 9/23/97:  fully functional and tested real and complex vectors
00060 // 9/17/97:  yet more revisions. NOT READY.
00061 // 9/15/97:  major changes to functions. Tests o.k.
00062 // 8/15/97:  fixed size when copy constructor has insufficient memory;
00063 //           now refers to vectors.h vice nonlin2.h
00064 // 8/15/97:  added handling of out-of-memory.
00065 // 8/12/97:  added complex_vector fcns
00066 // 8/12/97:  pulled definitions from nonlin2.h  Tests o.k.
00067 
00068 #include "vector.h"
00069 #include <iostream.h>
00070 #include <iomanip.h>
00071 
00072 // Useful functions:
00073 
00074 static inline int min(int a, int b)  { return (a < b)? a : b; }
00075 static inline int max(int a, int b)  { return (a > b)? a : b; }
00076 static inline int length(int a, int b) 
00077 { int n = b - a + 1; return (n < 0)? 0 : n; }
00078 
00079 // i/o formatting static variable
00080 
00081 static string _out_separator(" ");
00082 
00083 
00084 // ********************************************************************
00085 // real_vector definitions:
00086 
00087 
00088 // vector output:
00089 
00090 ostream & operator << (ostream & s, const real_vector & v)
00091 {
00092   ios::streamsize w = s.width();
00093   if (v.minindex() <= v.maxindex())  s << v[v.minindex()]; // v not empty
00094   for (int i = v.minindex() + 1; i <= v.maxindex(); ++i)
00095     s << _out_separator << setw(w) << v[i];
00096   return s << setw(0);  // just in case no output was generated
00097 }
00098 
00099 real_vector & real_vector::show(ostream & s)
00100 {
00101   s << endl << *this << endl;
00102   return *this;
00103 }
00104 
00105 real_vector & real_vector::show()
00106 {
00107   return show(cout);
00108 }
00109 
00110 const real_vector & real_vector::show(ostream & s) const
00111 {
00112   s << endl << *this << endl;
00113   return *this;
00114 }
00115 
00116 const real_vector & real_vector::show() const
00117 {
00118   return show(cout);
00119 }
00120 
00121 string real_vector::out_separator()
00122 { return _out_separator; }
00123 
00124 string real_vector::out_separator(const string & s)
00125 { string temp = _out_separator; _out_separator = s; return temp; }
00126 
00127 string real_vector::out_separator(const char * const s)
00128 { string temp = _out_separator; _out_separator = s; return temp; }
00129 
00130 string real_vector::out_separator(const char s)
00131 { string temp = _out_separator; _out_separator = s; return temp; }
00132 
00133 //-------------------------------------------------------------------------
00134 // construct() do the real work of vector construction: 
00135 
00136 void real_vector::construct(const int n, const v_index_mode t)
00137 {
00138   internal_size = (n >= 0) ? n : 0;
00139   internal_mode = t;
00140   switch(t) {
00141   default:
00142   case Index_C: {
00143     if (internal_size) {    // != 0: must allocate memory
00144       data = delete_pointer = new double[internal_size];
00145       if (delete_pointer == 0) internal_size = 0; // out of memory
00146     }
00147     else {    // must not allocate memory
00148       data = delete_pointer = 0;
00149     }
00150     minindexvalue = 0; maxindexvalue = internal_size - 1;
00151     break;
00152   }
00153   case Index_1: {
00154     if (internal_size) {    // != 0: must allocate memory
00155       data = delete_pointer = new double[internal_size];
00156       if (delete_pointer == 0)
00157         internal_size = 0; // out of memory
00158       else
00159         --data;   // so data[1] is the first element
00160     }
00161     else {    // must not allocate memory
00162       data = delete_pointer = 0;
00163     }
00164     minindexvalue = 1; maxindexvalue = internal_size;
00165     break;
00166   }
00167   case Index_S: {
00168     // must always try to allocate memory, even if size == 0:
00169     delete_pointer = new double[2*internal_size + 1];
00170     if (delete_pointer == 0) {
00171       data = & trash; // out of memory, so send requests here
00172       internal_size = 0;
00173       maxindexvalue = -1;  // this is the "out of memory" flag
00174     }
00175     else {  // memory allocation succeeded
00176       data = delete_pointer + internal_size; //location of v[0]
00177       maxindexvalue = internal_size;
00178     }
00179     minindexvalue = -maxindexvalue;
00180     break;
00181   }
00182   } // switch
00183 } // construct(const int n, const v_index_mode t = Index_C)
00184 
00185 //---------------------------------------------------------------------
00186 // constfill() fill the vector with a constant:
00187 
00188 void real_vector::constfill(const double f)
00189 { for (int i = minindex(); i <= maxindex(); ++i) data[i] = f; }
00190  
00191 
00192 //---------------------------------------------------------------------
00193 // copy constructor:
00194 
00195 real_vector::real_vector(const real_vector & v1)
00196   : size(internal_size), mode(internal_mode)
00197 {
00198   construct(v1.size, v1.mode);
00199   // the following loop will work even if alloc for v1 failed and
00200   // v1.mode == Index_S.  In this case, the contents of trash will be
00201   // copied.
00202   for (int i = minindex(); i <= maxindex(); ++i)
00203     data[i] = v1[i];
00204   if(v1.is_empty())
00205     make_empty();
00206   else
00207     maxindex(v1.maxindex());
00208 }
00209 
00210 //---------------------------------------------------------------------
00211 // alias constructor:
00212 
00213 real_vector::real_vector(double *const ptr, const int n,
00214                          const v_index_mode t)
00215   : size(internal_size), mode(internal_mode)
00216 {
00217   data = ptr;
00218   delete_pointer = 0; // don't destroy memory on destruction
00219   internal_mode = t;
00220   if (n >= 0) {
00221     // n is a useful value (could hold 1 element if t = Index_S)
00222     internal_size = n;
00223     maxindexvalue = (mode == Index_C) ? (size - 1) : size;
00224   }
00225   else {
00226     // n isn't useful; no memory available at ptr
00227     internal_size = 0;
00228     maxindexvalue = (mode == Index_1) ? 0 : -1;
00229   }
00230   switch (mode) {  // set minindexvalue
00231   case Index_C: { minindexvalue = 0; break; }
00232   case Index_1: { minindexvalue = 1; break; }
00233   case Index_S: { minindexvalue = -maxindexvalue; break; }
00234   }
00235 }
00236 
00237 //-------------------------------------------------------------------------
00238 // reindex()  change the index modes
00239 
00240 real_vector & real_vector::reindex(const v_index_mode M)
00241 {
00242   // first check for do nothings: new mode same as old, or
00243   // vector is an alias
00244   if (M == mode) return *this;
00245   if (delete_pointer == 0 && data != 0 && data != &trash) return *this;
00246 
00247   // If here, reindexing necessary
00248 
00249   // calculate number of data elements
00250   int n = (mode == Index_S) ? 2*size + 1 : size;
00251   
00252   // new Index_S needs an odd number of elements
00253   if (M == Index_S && (n>>1)<<1 == n) {  // n even
00254     reallocate(size+1,mode);
00255     n = size; // the new size
00256   }
00257 
00258   // now handle the no allocated data case:
00259   if (delete_pointer == 0) { reallocate(0,M); return *this; }
00260 
00261   // set up new indexing:
00262   int ptr_offset; // offset into array for data[0]
00263   switch (M) {
00264   default:
00265     { return *this; } // unknown mode, so do nothing
00266   case Index_C:
00267     { ptr_offset = 0; break; }
00268   case Index_1:
00269     { ptr_offset = -1; break; }
00270   case Index_S:
00271     { ptr_offset = (n - 1)/2; break; }
00272   } // switch
00273   internal_size = (M == Index_S) ? ptr_offset : n;
00274   minindexvalue = -ptr_offset; 
00275   maxindexvalue = minindexvalue + n - 1;
00276   data = delete_pointer + ptr_offset;
00277   internal_mode = M;
00278 
00279   return *this;
00280 }
00281 
00282 //---------------------------------------------------------------------
00283 // change maxindex(), make_empty():
00284 
00285 int real_vector::maxindex(int n)
00286 {
00287   if (size == 0 && mode != Index_S)
00288     // can't change the maxindex if no data elements
00289     return maxindex();
00290   else {
00291     switch (mode) {
00292     case Index_1: {
00293       if (n < 1) n = 1;
00294       maxindexvalue = (n > size) ? size : n;
00295       break;
00296     }
00297     case Index_S: {
00298       if (n < 0) n = 0;
00299       maxindexvalue = (n > size) ? size : n;
00300       minindexvalue = -maxindexvalue;
00301       break;
00302     }
00303     case Index_C: {
00304       if (n < 0) n = 0;
00305       maxindexvalue = (n >= size) ? (size - 1) : n;
00306       break;
00307     }
00308     default:
00309       ; // do nothing
00310     } //switch
00311     return maxindexvalue;
00312   } //else
00313 }
00314 
00315 real_vector & real_vector::make_empty()
00316 {
00317   switch (mode) {
00318   case Index_C:
00319     maxindexvalue = -1;
00320     minindexvalue = 0;
00321     break;
00322 
00323   case Index_1:
00324     maxindexvalue = 0;
00325     minindexvalue = 1;
00326     break;
00327 
00328   case Index_S:
00329     maxindexvalue = -1;
00330     minindexvalue = 1;
00331     break;
00332 
00333   }
00334   
00335   return *this;
00336 }
00337 
00338 //---------------------------------------------------------------------
00339 // clean up unused elements:
00340 
00341 real_vector & real_vector::clean()
00342 {
00343   int savemax = maxindex();
00344   int savemin = minindex();
00345   int i;
00346   maxindex(size); // make all memory visible
00347   for (i = savemax + 1; i <= maxindex(); ++i) data[i] = 0;
00348   for (i = savemin - 1; i >= minindex(); --i) data[i] = 0;
00349   maxindex(savemax);
00350   return *this;
00351 }
00352 
00353 //---------------------------------------------------------------------
00354 // shrink index range to ignore tiny values:
00355 
00356 real_vector & real_vector::shrink(double s)
00357 {
00358   int i;       // the index
00359   double sum;  // accumulator of the sum of the magnitude squared's
00360   s *= s;      // magnitude squared for s: our tolerance value
00361 
00362   if (mode != Index_S)
00363     // Index_C and Index_1: just compare the sum at the positive indexes
00364     for (i = maxindexvalue, sum = 0; i > 0; --i) {
00365       sum += data[i]*data[i];
00366       if (sum >= s) break;  // found the limit
00367     }
00368   else {
00369     // Index_S must look at sum for negative indexes, too
00370     double nsum;  // accumulate negative index sum
00371     for (i = maxindexvalue, nsum = sum = 0; i > 0; --i) {
00372       sum += data[i]*data[i];
00373       nsum += data[-i]*data[-i];
00374       if ((sum >= s)||(nsum >= s)) break;
00375     }
00376   }
00377 
00378   maxindex(i);  // set the new index and return
00379   return *this;
00380 }
00381 
00382 //---------------------------------------------------------------------
00383 // fill all elements, regardless of data subset control:
00384 
00385 real_vector & real_vector::fillall(const double s)
00386 {
00387   int savemax = maxindexvalue;
00388   int savemin = minindexvalue;
00389   maximize();
00390   constfill(s);
00391   maxindexvalue = savemax; minindexvalue = savemin;
00392   return *this;
00393 }
00394 
00395 //---------------------------------------------------------------------
00396 // copy data from another vector:
00397 
00398 real_vector & real_vector::copy(const real_vector & v1)
00399 {
00400   // check for self copy: "v.copy(v)", and do something intelligent:
00401   if (data == v1.data) { clean(); return *this; }
00402 
00403   // otherwise, not a self copy, so:
00404   maxindex(size);  constfill(0);  // maximize the index range and clear
00405   // now set data subset on the result:
00406   if(v1.is_empty())
00407     make_empty();
00408   else {
00409     maxindex(v1.maxindex());
00410     // copy over the index range intersection:
00411     int minimum = max(minindexvalue, v1.minindex());
00412     int maximum = min(maxindexvalue, v1.maxindex());
00413     for (register int i = minimum; i <= maximum; ++i)
00414       data[i] = v1[i];
00415   }
00416   return *this;
00417 }
00418 
00419 //---------------------------------------------------------------------
00420 // reallocate memory:
00421 
00422 real_vector & real_vector::reallocate(const int n, const v_index_mode t)
00423 {
00424   // just return if reallocation is unnecessary:
00425   if ((size == n)&&(mode == t)) return *this;
00426 
00427   // if we're here, we have to reallocate:
00428   real_vector old(data, size, mode); // alias the current vector
00429   double * save_delete_pointer = delete_pointer;
00430   int newmax;  // will hold the new maxindexvalue
00431   newmax = (maxindexvalue < old.maxindex()) ? maxindexvalue : n ;
00432 
00433   construct(n,t);
00434   copy(old);
00435   maxindex(newmax);
00436   delete [] save_delete_pointer;
00437   return *this;
00438 }
00439 
00440 //---------------------------------------------------------------------
00441 // resize: the ones which couldn't be defined in the header file
00442 
00443 real_vector & real_vector::resize(const complex_vector & v)
00444 {
00445   int Size = (v.mode == Index_C) ? v.maxindex()+1: v.maxindex();
00446   return reallocate(Size, v.mode);
00447 }
00448 
00449 //---------------------------------------------------------------------
00450 // basic assignment operator:
00451 
00452 real_vector & real_vector::operator = (const real_vector & v1)
00453 {
00454   // check for self assignment: "v = v", and do something intelligent:
00455   if (data == v1.data) { clean(); return *this; }
00456 
00457   // otherwise, not a self assignment, so:
00458   maximize();
00459   if ((mode != v1.mode)||(maxindexvalue < v1.maxindex())) {
00460     // make the vector compatible with v1's data
00461     delete [] delete_pointer;
00462     int newsize = (v1.mode == Index_C) ? v1.maxindex()+1: v1.maxindex();
00463     construct(newsize,v1.mode);
00464   }
00465   copy(v1);
00466   return *this;
00467 }
00468 
00469 //---------------------------------------------------------------------
00470 // other assignment operators (no memory reallocation for these):
00471 
00472 real_vector & real_vector::operator += (const double s)
00473 {
00474   // make local pointers to the first and last elements:
00475   register double * d = data + minindexvalue;
00476   register double * limit = data + maxindexvalue;
00477   // use the pointer to the first element as the loop variable:
00478   while (d <= limit) *(d++) += s;
00479   return *this;
00480 }
00481 
00482 real_vector & real_vector::operator -= (const double s)
00483 {
00484   register double * d = data + minindexvalue;
00485   register double * limit = data + maxindexvalue;
00486   while (d <= limit) *(d++) -= s;
00487   return *this;
00488 }
00489 
00490 real_vector & real_vector::operator *= (const double s)
00491 {
00492   register double * d = data + minindexvalue;
00493   register double * limit = data + maxindexvalue;
00494   while (d <= limit) *(d++) *= s;
00495   return *this;
00496 }
00497 
00498 real_vector & real_vector::operator /= (const double s)
00499 {
00500   register double * d = data + minindexvalue;
00501   register double * limit = data + maxindexvalue;
00502   while (d <= limit) *(d++) /= s;
00503   return *this;
00504 }
00505 
00506 real_vector & real_vector::operator += (const real_vector & v1)
00507 {
00508   clean();  // ensure nonvalid elements are set to 0
00509   // increase the target's valid range if necessary:
00510   if (maxindexvalue < v1.maxindex()) maxindex(v1.maxindex());
00511   // loop over the intersection of the vectors' valid ranges:
00512   int minimum = max(minindexvalue, v1.minindex());
00513   int maximum = min(maxindexvalue, v1.maxindex());
00514   for (register int i = minimum; i <= maximum; ++i)
00515     data[i] += v1[i];
00516   return *this;
00517 }
00518 
00519 real_vector & real_vector::operator -= (const real_vector & v1)
00520 {
00521   clean();
00522   if (maxindexvalue < v1.maxindex()) maxindex(v1.maxindex());
00523   int minimum = max(minindexvalue, v1.minindex());
00524   int maximum = min(maxindexvalue, v1.maxindex());
00525   for (register int i = minimum; i <= maximum; ++i)
00526     data[i] -= v1[i];
00527   return *this;
00528 }
00529 
00530 //---------------------------------------------------------------------
00531 // other miscellaneous funtions:
00532 
00533 real_vector & real_vector::real(const complex_vector & v)
00534 {
00535   resize(v);
00536   if(v.is_empty())
00537     make_empty();
00538   else {
00539     maxindex(v.maxindex());
00540     int i;
00541     for (i = minindex(); i <= maxindex(); ++i)
00542       data[i] = v[i].real;
00543   }
00544   return *this;
00545 }
00546 
00547 real_vector & real_vector::imaginary(const complex_vector & v)
00548 {
00549   resize(v);
00550   if(v.is_empty())
00551     make_empty();
00552   else {
00553     maxindex(v.maxindex());
00554     int i;
00555     for (i = minindex(); i <= maxindex(); ++i)
00556       data[i] = v[i].imaginary;
00557   }
00558   return *this;
00559 }
00560 
00561 int real_vector::findmax() const
00562 {
00563   if(maxindexvalue < minindexvalue) return 0;
00564   double norm;                // magnitude squared
00565   double max;                 // max norm so far 
00566   int index = minindexvalue;  // index to return
00567 
00568   norm = data[minindexvalue]; max = norm * norm;  // initialize
00569   for (int i = minindexvalue + 1; i <= maxindexvalue; ++i) {
00570     norm = data[i]; norm *= norm;
00571     if ( norm > max ) {
00572       max = norm; index = i;
00573     }
00574   }
00575   return index;
00576 }
00577 
00578 real_vector & real_vector::apply(double (*f)(double))
00579 {
00580   // make local pointers to the first and last elements:
00581   register double * d = data + minindexvalue;
00582   register double * limit = data + maxindexvalue;
00583   // use the pointer to the first element as the loop variable:
00584   for ( ; d <= limit; ++d) *d = f(*d);
00585   return *this;
00586 }
00587 
00588 real_vector & real_vector::apply(double (*f)(const double &))
00589 {
00590   // make local pointers to the first and last elements:
00591   register double * d = data + minindexvalue;
00592   register double * limit = data + maxindexvalue;
00593   // use the pointer to the first element as the loop variable:
00594   for ( ; d <= limit; ++d) *d = f(*d);
00595   return *this;
00596 }
00597 
00598 real_vector & real_vector::apply(double (*f)(double, int))
00599 {
00600   register int i = minindexvalue; 
00601   register double * d = data;
00602   register int limit = maxindexvalue;
00603   for ( d += i; i <= limit; ++i, ++d) *d = f(*d, i);
00604   return *this;
00605 }
00606 
00607 real_vector & real_vector::apply(double (*f)(const double &, int))
00608 {
00609   register int i = minindexvalue; 
00610   register double * d = data;
00611   register int limit = maxindexvalue;
00612   for ( d += i; i <= limit; ++i, ++d) *d = f(*d, i);
00613   return *this;
00614 }
00615 
00616 //---------------------------------------------------------------------
00617 // STL compatibility:
00618 
00619 void real_vector::reserve(int n)
00620 {
00621   if(n <= size) return;
00622   bool e = empty(); int m = maxindexvalue;
00623   reallocate(n);
00624   if (e)
00625     make_empty();
00626   else
00627     maxindex(m);
00628 }
00629 
00630 void real_vector::push_back(double s)
00631 {
00632   // adjust memory allocation, if necessary
00633   int i = maxindex()+1;
00634   if (maxindex(i) != i) {
00635     // then incrementing maxindex didn't work; must reallocate
00636     reallocate(2*(size+1));  // grow size by a factor of 2
00637     maxindex(i);
00638   }
00639   data[i] = s;
00640 }
00641 
00642 void real_vector::pop_back()
00643 {
00644   if(empty()) return;
00645   int i = maxindex(maxindex()-1);
00646   if (maxindex() == i) {
00647     // then attempting to decrement maxindex didn't work;
00648     // vector is now empty
00649     make_empty();
00650   }
00651 }
00652 
00653 // end of real_vector definitions
00654 
00655 // ********************************************************************
00656 // complex_vector definitions:
00657 
00658 
00659 // vector output:
00660 
00661 ostream & operator << (ostream & s, const complex_vector & v)
00662 {
00663   ios::streamsize w = s.width();
00664   if (v.minindex() <= v.maxindex())  s << v[v.minindex()]; // v not empty
00665   for (int i = v.minindex() + 1; i <= v.maxindex(); ++i)
00666     s << _out_separator << setw(w) << v[i];
00667   return s << setw(0);  // just in case no output was generated
00668 }
00669 
00670 complex_vector & complex_vector::show(ostream & s)
00671 {
00672   s << endl << *this << endl;
00673   return *this;
00674 }
00675 
00676 complex_vector & complex_vector::show()
00677 {
00678   return show(cout);
00679 }
00680 
00681 const complex_vector & complex_vector::show(ostream & s) const
00682 {
00683   s << endl << *this << endl;
00684   return *this;
00685 }
00686 
00687 const complex_vector & complex_vector::show() const
00688 {
00689   return show(cout);
00690 }
00691 
00692 string complex_vector::out_separator()
00693 { return _out_separator; }
00694 
00695 string complex_vector::out_separator(const string & s)
00696 { string temp = _out_separator; _out_separator = s; return temp; }
00697 
00698 string complex_vector::out_separator(const char * const s)
00699 { string temp = _out_separator; _out_separator = s; return temp; }
00700 
00701 string complex_vector::out_separator(const char s)
00702 { string temp = _out_separator; _out_separator = s; return temp; }
00703 
00704 //-------------------------------------------------------------------------
00705 // construct() do the real work of vector construction: 
00706 
00707 void complex_vector::construct(const int n, const v_index_mode t)
00708 {
00709   internal_size = (n >= 0) ? n : 0;
00710   internal_mode = t;
00711   switch(t) {
00712   default:
00713   case Index_C: {
00714     if (internal_size) {    // != 0: must allocate memory
00715       data = delete_pointer = new Complex[internal_size];
00716       if (delete_pointer == 0) internal_size = 0; // out of memory
00717     }
00718     else {    // must not allocate memory
00719       data = delete_pointer = 0;
00720     }
00721     minindexvalue = 0; maxindexvalue = internal_size - 1;
00722     break;
00723   }
00724   case Index_1: {
00725     if (internal_size) {    // != 0: must allocate memory
00726       data = delete_pointer = new Complex[internal_size];
00727       if (delete_pointer == 0)
00728         internal_size = 0; // out of memory
00729       else
00730         --data;   // so data[1] is the first element
00731     }
00732     else {    // must not allocate memory
00733       data = delete_pointer = 0;
00734     }
00735     minindexvalue = 1; maxindexvalue = internal_size;
00736     break;
00737   }
00738   case Index_S: {
00739     // must always try to allocate memory, even if size == 0:
00740     delete_pointer = new Complex[2*internal_size + 1];
00741     if (delete_pointer == 0) {
00742       data = & trash; // out of memory, so send requests here
00743       internal_size = 0;
00744       maxindexvalue = -1;  // this is the "out of memory" flag
00745     }
00746     else {  // memory allocation succeeded
00747       data = delete_pointer + internal_size; //location of v[0]
00748       maxindexvalue = internal_size;
00749     }
00750     minindexvalue = -maxindexvalue;
00751     break;
00752   }
00753   } // switch
00754 } // construct(const int n, const v_index_mode t = Index_C)
00755 
00756 //---------------------------------------------------------------------
00757 // constfill() fill the vector with a constant:
00758 
00759 void complex_vector::constfill(const Complex f)
00760 { for (int i = minindex(); i <= maxindex(); ++i) data[i] = f; }
00761 
00762 //---------------------------------------------------------------------
00763 // copy constructor:
00764 
00765 complex_vector::complex_vector(const complex_vector & v1)
00766   : size(internal_size), mode(internal_mode)
00767 {
00768   construct(v1.size, v1.mode);
00769   // the following loop will work even if alloc for v1 failed and
00770   // v1.mode == Index_S.  In this case, the contents of trash will be
00771   // copied.
00772   for (int i = minindex(); i <= maxindex(); ++i)
00773     data[i] = v1[i];
00774   if(v1.is_empty())
00775     make_empty();
00776   else
00777     maxindex(v1.maxindex());
00778 }
00779 
00780 complex_vector::complex_vector(const real_vector & v1)
00781   : size(internal_size), mode(internal_mode)
00782 {
00783   construct(v1.size, v1.mode);
00784   for (int i = minindex(); i <= maxindex(); ++i)
00785     data[i] = v1[i];
00786   if(v1.is_empty())
00787     make_empty();
00788   else
00789     maxindex(v1.maxindex());
00790 }
00791 
00792 //---------------------------------------------------------------------
00793 // alias constructor:
00794 
00795 complex_vector::complex_vector(Complex *const ptr, const int n,
00796                          const v_index_mode t)
00797   : size(internal_size), mode(internal_mode)
00798 {
00799   data = ptr;
00800   delete_pointer = 0; // don't destroy memory on destruction
00801   internal_mode = t;
00802   if (n >= 0) {
00803     // n is a useful value (could hold 1 element if t = Index_S)
00804     internal_size = n;
00805     maxindexvalue = (mode == Index_C) ? (size - 1) : size;
00806   }
00807   else {
00808     // n isn't useful; no memory available at ptr
00809     internal_size = 0;
00810     maxindexvalue = (mode == Index_1) ? 0 : -1;
00811   }
00812   switch (mode) {  // set minindexvalue
00813   case Index_C: { minindexvalue = 0; break; }
00814   case Index_1: { minindexvalue = 1; break; }
00815   case Index_S: { minindexvalue = -maxindexvalue; break; }
00816   }
00817 }
00818 
00819 //-------------------------------------------------------------------------
00820 // reindex()  change the index modes
00821 
00822 complex_vector & complex_vector::reindex(const v_index_mode M)
00823 {
00824   // first check for do nothings: new mode same as old, or
00825   // vector is an alias
00826   if (M == mode) return *this;
00827   if (delete_pointer == 0 && data != 0 && data != &trash) return *this;
00828 
00829   // If here, reindexing necessary
00830 
00831   // calculate number of data elements
00832   int n = (mode == Index_S) ? 2*size + 1 : size;
00833   
00834   // new Index_S needs an odd number of elements
00835   if (M == Index_S && (n>>1)<<1 == n) {  // n even
00836     reallocate(size+1,mode);
00837     n = size; // the new size
00838   }
00839 
00840   // now handle the no allocated data case:
00841   if (delete_pointer == 0) { reallocate(0,M); return *this; }
00842 
00843   // set up new indexing:
00844   int ptr_offset; // offset into array for data[0]
00845   switch (M) {
00846   default:
00847     { return *this; } // unknown mode, so do nothing
00848   case Index_C:
00849     { ptr_offset = 0; break; }
00850   case Index_1:
00851     { ptr_offset = -1; break; }
00852   case Index_S:
00853     { ptr_offset = (n - 1)/2; break; }
00854   } // switch
00855   internal_size = (M == Index_S) ? ptr_offset : n;
00856   minindexvalue = -ptr_offset; 
00857   maxindexvalue = minindexvalue + n - 1;
00858   data = delete_pointer + ptr_offset;
00859   internal_mode = M;
00860 
00861   return *this;
00862 }
00863 
00864 //---------------------------------------------------------------------
00865 // change maxindex(), make_empty():
00866 
00867 int complex_vector::maxindex(int n)
00868 {
00869   if (size == 0 && mode != Index_S)
00870     // can't change the maxindex if no data elements
00871     return maxindex();
00872   else {
00873     switch (mode) {
00874     case Index_1: {
00875       if (n < 1) n = 1;
00876       maxindexvalue = (n > size) ? size : n;
00877       break;
00878     }
00879     case Index_S: {
00880       if (n < 0) n = 0;
00881       maxindexvalue = (n > size) ? size : n;
00882       minindexvalue = -maxindexvalue;
00883       break;
00884     }
00885     case Index_C: {
00886       if (n < 0) n = 0;
00887       maxindexvalue = (n >= size) ? (size - 1) : n;
00888       break;
00889     }
00890     default:
00891       ; // do nothing
00892     } //switch
00893     return maxindexvalue;
00894   } //else
00895 }
00896 
00897 complex_vector & complex_vector::make_empty()
00898 {
00899   switch (mode) {
00900   case Index_C:
00901     maxindexvalue = -1;
00902     minindexvalue = 0;
00903     break;
00904 
00905   case Index_1:
00906     maxindexvalue = 0;
00907     minindexvalue = 1;
00908     break;
00909 
00910   case Index_S:
00911     maxindexvalue = -1;
00912     minindexvalue = 1;
00913     break;
00914 
00915   }
00916   
00917   return *this;
00918 }
00919 
00920 //---------------------------------------------------------------------
00921 // clean up unused elements:
00922 
00923 complex_vector & complex_vector::clean()
00924 {
00925   int savemax = maxindex();
00926   int savemin = minindex();
00927   int i;
00928   maxindex(size); // make all memory visible
00929   for (i = savemax + 1; i <= maxindex(); ++i) data[i] = 0;
00930   for (i = savemin - 1; i >= minindex(); --i) data[i] = 0;
00931   maxindex(savemax);
00932   return *this;
00933 }
00934 
00935 //---------------------------------------------------------------------
00936 // shrink index range to ignore tiny values:
00937 
00938 complex_vector & complex_vector::shrink(Complex s)
00939 {
00940   int i;       // the index
00941   double sum;  // accumulator of the sum of the magnitude squared's
00942   double ss = norm(s);  // magnitude squared for s: our tolerance value
00943 
00944   if (mode != Index_S)
00945     // Index_C and Index_1: just compare the sum at the positive indexes
00946     for (i = maxindexvalue, sum = 0; i > 0; --i) {
00947       sum += norm(data[i]);
00948       if (sum >= ss) break;  // found the limit
00949     }
00950   else {
00951     // Index_S must look at sum for negative indexes, too
00952     double nsum;  // accumulate negative index sum
00953     for (i = maxindexvalue, nsum = sum = 0; i > 0; --i) {
00954       sum += norm(data[i]);
00955       nsum += norm(data[-i]);
00956       if ((sum >= ss)||(nsum >= ss)) break;
00957     }
00958   }
00959 
00960   maxindex(i);  // set the new index and return
00961   return *this;
00962 }
00963 
00964 //---------------------------------------------------------------------
00965 // fill all elements, regardless of data subset control:
00966 
00967 complex_vector & complex_vector::fillall(const Complex s)
00968 {
00969   int savemax = maxindexvalue;
00970   int savemin = minindexvalue; 
00971   maximize();
00972   constfill(s);
00973   maxindexvalue = savemax; minindexvalue = savemin;
00974   return *this;
00975 }
00976 
00977 //---------------------------------------------------------------------
00978 // copy data from another vector:
00979 
00980 complex_vector & complex_vector::copy(const complex_vector & v1)
00981 {
00982   // check for self copy: "v.copy(v)", and do something intelligent:
00983   if (data == v1.data) { clean(); return *this; }
00984 
00985   // otherwise, not a self copy, so:
00986   maxindex(size);  constfill(0);  // maximize the index range and clear
00987   // now set data subset on the result:
00988   if(v1.is_empty())
00989     make_empty();
00990   else {
00991     maxindex(v1.maxindex());
00992     // copy over the index range intersection:
00993     int minimum = max(minindexvalue, v1.minindex());
00994     int maximum = min(maxindexvalue, v1.maxindex());
00995     for (register int i = minimum; i <= maximum; ++i)
00996       data[i] = v1[i];
00997   }
00998   return *this;
00999 }
01000 
01001 complex_vector & complex_vector::copy(const real_vector & v1)
01002 {
01003   maxindex(size);  constfill(0);  // maximize the index range and clear
01004   // now set data subset on the result:
01005   if(v1.is_empty())
01006     make_empty();
01007   else {
01008     maxindex(v1.maxindex());
01009     // copy over the index range intersection:
01010     int minimum = max(minindexvalue, v1.minindex());
01011     int maximum = min(maxindexvalue, v1.maxindex());
01012     for (register int i = minimum; i <= maximum; ++i)
01013       data[i] = v1[i];
01014   }
01015   return *this;
01016 }
01017 
01018 //---------------------------------------------------------------------
01019 // reallocate memory:
01020 
01021 complex_vector & complex_vector::reallocate(const int n, const v_index_mode t)
01022 {
01023   // just return if reallocation is unnecessary:
01024   if ((size == n)&&(mode == t)) return *this;
01025 
01026   // if we're here, we have to reallocate:
01027   complex_vector old(data, size, mode); // alias the current vector
01028   Complex * save_delete_pointer = delete_pointer;
01029   int newmax;  // will hold the new maxindexvalue
01030   newmax = (maxindexvalue < old.maxindex()) ? maxindexvalue : n ;
01031 
01032   construct(n,t);
01033   copy(old);
01034   maxindex(newmax);
01035   delete [] save_delete_pointer;
01036   return *this;
01037 }
01038 
01039 //---------------------------------------------------------------------
01040 // assignment operator:
01041 
01042 complex_vector & complex_vector::operator = (const complex_vector & v1)
01043 {
01044   // check for self assignment: "v = v", and do something intelligent:
01045   if (data == v1.data) { clean(); return *this; }
01046 
01047   // otherwise, not a self assignment, so:
01048   maximize();
01049   if ((mode != v1.mode)||(maxindexvalue < v1.maxindex())) {
01050     // make the vector compatible with v1's data
01051     delete [] delete_pointer;
01052     int newsize = (v1.mode == Index_C) ? v1.maxindex()+1: v1.maxindex();
01053     construct(newsize,v1.mode);
01054   }
01055   copy(v1);
01056   return *this;
01057 }
01058 
01059 complex_vector & complex_vector::operator = (const real_vector & v1)
01060 {
01061   maximize();
01062   if ((mode != v1.mode)||(maxindexvalue < v1.maxindex())) {
01063     // make the vector compatible with v1's data
01064     delete [] delete_pointer;
01065     int newsize = (v1.mode == Index_C) ? v1.maxindex()+1: v1.maxindex();
01066     construct(newsize,v1.mode);
01067   }
01068   copy(v1);
01069   return *this;
01070 }
01071 
01072 //---------------------------------------------------------------------
01073 // other assignment operators (no memory reallocation for these):
01074 
01075 complex_vector & complex_vector::operator += (const Complex s)
01076 {
01077   // make local pointers to the first and last elements:
01078   register Complex * d = data + minindexvalue;
01079   register Complex * limit = data + maxindexvalue;
01080   // use the pointer to the first element as the loop variable:
01081   while (d <= limit) *(d++) += s;
01082   return *this;
01083 }
01084 
01085 complex_vector & complex_vector::operator -= (const Complex s)
01086 {
01087   register Complex * d = data + minindexvalue;
01088   register Complex * limit = data + maxindexvalue;
01089   while (d <= limit) *(d++) -= s;
01090   return *this;
01091 }
01092 
01093 complex_vector & complex_vector::operator *= (const Complex s)
01094 {
01095   register Complex * d = data + minindexvalue;
01096   register Complex * limit = data + maxindexvalue;
01097   while (d <= limit) *(d++) *= s;
01098   return *this;
01099 }
01100 
01101 complex_vector & complex_vector::operator /= (const Complex s)
01102 {
01103   register Complex * d = data + minindexvalue;
01104   register Complex * limit = data + maxindexvalue;
01105   while (d <= limit) *(d++) /= s;
01106   return *this;
01107 }
01108 
01109 complex_vector & complex_vector::operator += (const complex_vector & v1)
01110 {
01111   clean();  // ensure nonvalid elements are set to 0
01112   // increase the target's valid range if necessary:
01113   if (maxindexvalue < v1.maxindex()) maxindex(v1.maxindex());
01114   // loop over the intersection of the vectors' valid ranges:
01115   int minimum = max(minindexvalue, v1.minindex());
01116   int maximum = min(maxindexvalue, v1.maxindex());
01117   for (register int i = minimum; i <= maximum; ++i)
01118     data[i] += v1[i];
01119   return *this;
01120 }
01121 
01122 complex_vector & complex_vector::operator -= (const complex_vector & v1)
01123 {
01124   clean();
01125   if (maxindexvalue < v1.maxindex()) maxindex(v1.maxindex());
01126   int minimum = max(minindexvalue, v1.minindex());
01127   int maximum = min(maxindexvalue, v1.maxindex());
01128   for (register int i = minimum; i <= maximum; ++i)
01129     data[i] -= v1[i];
01130   return *this;
01131 }
01132 
01133 complex_vector & complex_vector::operator += (const real_vector & v1)
01134 {
01135   clean();  // ensure nonvalid elements are set to 0
01136   // increase the target's valid range if necessary:
01137   if (maxindexvalue < v1.maxindex()) maxindex(v1.maxindex());
01138   // loop over the intersection of the vectors' valid ranges:
01139   int minimum = max(minindexvalue, v1.minindex());
01140   int maximum = min(maxindexvalue, v1.maxindex());
01141   for (register int i = minimum; i <= maximum; ++i)
01142     data[i].real += v1[i];
01143   return *this;
01144 }
01145 
01146 complex_vector & complex_vector::operator -= (const real_vector & v1)
01147 {
01148   clean();
01149   if (maxindexvalue < v1.maxindex()) maxindex(v1.maxindex());
01150   int minimum = max(minindexvalue, v1.minindex());
01151   int maximum = min(maxindexvalue, v1.maxindex());
01152   for (register int i = minimum; i <= maximum; ++i)
01153     data[i].real -= v1[i];
01154   return *this;
01155 }
01156 
01157 //---------------------------------------------------------------------
01158 // other miscellaneous funtions:
01159 
01160 complex_vector & complex_vector::real(const complex_vector & v)
01161 {
01162   if (data != v.data) {  // only resize if v is not this or an alias 
01163     resize(v);
01164     if(v.is_empty())
01165       make_empty();
01166     else
01167       maxindex(v.maxindex());
01168   }
01169   int i;
01170   for (i = minindex(); i <= maxindex(); ++i)
01171     data[i] = v[i].real;
01172   return *this;
01173 }
01174 
01175 complex_vector & complex_vector::imaginary(const complex_vector & v)
01176 {
01177   if (data != v.data) {  // only resize if v is not this or an alias 
01178     resize(v);
01179     if(v.is_empty())
01180       make_empty();
01181     else
01182       maxindex(v.maxindex());
01183   }
01184   int i;
01185   for (i = minindex(); i <= maxindex(); ++i)
01186     data[i] = v[i].imaginary;
01187   return *this;
01188 }
01189 
01190 int complex_vector::findmax() const
01191 {
01192   if(maxindexvalue < minindexvalue) return 0;
01193   double mag;                 // magnitude squared
01194   double max;                 // max mag so far 
01195   int index = minindexvalue;  // index to return
01196 
01197   max = norm(data[minindexvalue]);  // initialize
01198   for (int i = minindexvalue + 1; i <= maxindexvalue; ++i) {
01199     mag = norm(data[i]);
01200     if ( mag > max ) {
01201       max = mag; index = i;
01202     }
01203   }
01204   return index;
01205 }
01206 
01207 complex_vector & complex_vector::apply(Complex (*f)(Complex))
01208 {
01209   // make local pointers to the first and last elements:
01210   register Complex * d = data + minindexvalue;
01211   register Complex * limit = data + maxindexvalue;
01212   // use the pointer to the first element as the loop variable:
01213   for ( ; d <= limit; ++d) *d = f(*d);
01214   return *this;
01215 }
01216 
01217 complex_vector & complex_vector::apply(Complex (*f)(const Complex &))
01218 {
01219   // make local pointers to the first and last elements:
01220   register Complex * d = data + minindexvalue;
01221   register Complex * limit = data + maxindexvalue;
01222   // use the pointer to the first element as the loop variable:
01223   for ( ; d <= limit; ++d) *d = f(*d);
01224   return *this;
01225 }
01226 
01227 complex_vector & complex_vector::apply(Complex (*f)(Complex, int))
01228 {
01229   register int i = minindexvalue; 
01230   register Complex * d = data;
01231   register int limit = maxindexvalue;
01232   for ( d += i; i <= limit; ++i, ++d) *d = f(*d, i);
01233   return *this;
01234 }
01235 
01236 complex_vector & complex_vector::apply(Complex (*f)(const Complex &, int))
01237 {
01238   register int i = minindexvalue; 
01239   register Complex * d = data;
01240   register int limit = maxindexvalue;
01241   for ( d += i; i <= limit; ++i, ++d) *d = f(*d, i);
01242   return *this;
01243 }
01244 
01245 //---------------------------------------------------------------------
01246 // STL compatibility:
01247 
01248 void complex_vector::reserve(int n)
01249 {
01250   if(n <= size) return;
01251   bool e = empty(); int m = maxindexvalue;
01252   reallocate(n);
01253   if (e)
01254     make_empty();
01255   else
01256     maxindex(m);
01257 }
01258 
01259 void complex_vector::push_back(Complex s)
01260 {
01261   // adjust memory allocation, if necessary
01262   int i = maxindex()+1;
01263   if (maxindex(i) != i) {
01264     // then incrementing maxindex didn't work; must reallocate
01265     reallocate(2*(size+1));  // grow size by a factor of 2
01266     maxindex(i);
01267   }
01268   data[i] = s;
01269 }
01270 
01271 void complex_vector::pop_back()
01272 {
01273   if(empty()) return;
01274   int i = maxindex(maxindex()-1);
01275   if (maxindex() == i) {
01276     // then attempting to decrement maxindex didn't work;
01277     // vector is now empty
01278     make_empty();
01279   }
01280 }
01281 
01282 // end of complex_vector definitions

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