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

vector.h

Go to the documentation of this file.
00001 // SuperMix version 1.0  C++ source file
00002 //
00003 // Copyright (c) 1999 California Institute of Technology.
00004 // All rights reserved.
00005 //
00006 // Redistribution and use in source and binary forms for noncommercial
00007 // purposes are permitted provided that the above copyright notice and
00008 // this paragraph are duplicated in all such forms and that any
00009 // documentation and other materials related to such distribution and
00010 // use acknowledge that the software was developed by California
00011 // Institute of Technology. Redistribution and/or use in source or
00012 // binary forms is not permitted for any commercial purpose. Use of
00013 // this software does not include a permitted use of the Institute's
00014 // name or trademark for any purpose.
00015 //
00016 // DISCLAIMER:
00017 // THIS SOFTWARE AND/OR RELATED MATERIALS ARE PROVIDED "AS-IS" WITHOUT
00018 // WARRANTY OF ANY KIND INCLUDING ANY WARRANTIES OF PERFORMANCE OR
00019 // MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE OR PURPOSE (AS SET
00020 // FORTH IN UCC 23212-2313) OR FOR ANY PURPOSE WHATSOEVER, FOR THE
00021 // LICENSED PRODUCT, HOWEVER USED.  IN NO EVENT SHALL CALTECH/JPL BE
00022 // LIABLE FOR ANY DAMAGES AND/OR COSTS, INCLUDING BUT NOT LIMITED TO
00023 // INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING ECONOMIC
00024 // DAMAGE OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF
00025 // WHETHER CALTECH/JPL SHALL BE ADVISED, HAVE REASON TO KNOW, OR IN
00026 // FACT SHALL KNOW OF THE POSSIBILITY.  THE USER BEARS ALL RISK
00027 // RELATING TO QUALITY AND PERFORMANCE OF THE SOFTWARE AND/OR RELATED
00028 // MATERIALS.
00029 //
00030 // ************************************************************************
00031 // vector.h
00032 // numeric vector classes
00033 //
00034 // Needs:
00035 //   vector.cc   for function definitions
00036 //   a #defined constant macro DEFAULT_VECTOR_SIZE
00037 //      (creates its own otherwise)
00038 //
00039 // Includes: SIScmplx.h
00040 //
00041 // F. Rice 8/15/97
00042 // 10/12/00: more STL compatibility: types and iterators
00043 // 9/8/00:   added some STL compatibility functions
00044 // 4/26/00:  added is_empty(), make_empty().
00045 // 11/11/98: enhanced access operators; removed public "data"
00046 // 10/28/98: removed int_vector stuff
00047 // 7/31/98:  added out_separator() static member functions
00048 // 7/30/98:  Enhanced show(), added <<
00049 // 7/7/98:   Made certain constructors explicit
00050 // 7/6/98:   Added reindex()
00051 // 1/9/98:   Changed shrink to return a reference to the vector, vice int
00052 // 12/18/97: Special version with show() member function
00053 // 12/12/97: "fully" tested with calc
00054 // 11/24/97: added additional versions of resize(); real(), imaginary().
00055 // 11/17/97: improved swap()
00056 // 11/11/97: real_vector and complex_vector test o.k. with vcalc.
00057 // 11/11/97: Fixed an ambiguity in vector = scalar definitions.
00058 // 11/10/97: Fixed maxindex(n) bug. real_vector tests o.k. with vcalc.
00059 // 11/10/97: Many previously void member functions now return an Lvalue.
00060 // 11/8/97:  CHANGED DEFAULT MODE TO Index_1 instead of Index_C. added
00061 //           resize().
00062 // 11/7/97:  fixed a lingering bug in the copy constructor: it didn't set
00063 //           data subset control on the target!
00064 // 11/4/97:  added checks for v = v and v.copy(v), so these constructs
00065 //           behave properly (oops!).
00066 // 11/3/97:  New operator =, with an Rvalue RHS. Not fully tested yet.
00067 // 10/15/97: added many additional functions, including math functions;
00068 //           fixed to compile with CC.
00069 // 10/1/97: first fully functional version
00070 // 9/25/97: renamed to vector.h
00071 // 9/23/97: fully functional and tested real and complex vectors
00072 // 9/17/97: Yet more major revisions to the class. NOT READY.
00073 // 9/15/97: Tests o.k.
00074 // 9/15/97: major revisions to operation and functionality
00075 // 8/15/97: pulled vector class definitions out of nonlin2.h, made a
00076 //          standalone header (with  SIScmplx.h and vector.cc, of course).
00077 // 
00078 // ************************************************************************
00079 //
00080 //              The real_vector and complex_vector Classes
00081 //
00082 // General:
00083 // -------
00084 // The *_vector classes provide for manipulation of 1-dimensional array
00085 // data. A vector object's data is stored in a contiguous chunk of memory,
00086 // whose data elements may be indexed in various ways. The real_vector type
00087 // gives a vector of doubles and complex_vector gives a vector containing
00088 // Complex.
00089 //
00090 //
00091 // Indexing and Capacity:
00092 // ---------------------
00093 // Indexing of the data elements in a vector is accomplished using an int
00094 // index. There are three different indexing modes available, called
00095 // Index_C, Index_1, and Index_S.  They will be described in detail below.
00096 //
00097 // Both controlled and uncontrolled (raw) indexed access to the data
00098 // elements are provided.  If v is a vector object, then:
00099 //
00100 //          
00101 // v.get(i);    Provides controlled, safe read and write access to the data
00102 //              elements. The index i may be any integer value; if i
00103 //              addresses an "element" beyond the limits of v's memory
00104 //              capacity, this construct returns a modifiable Lvalue
00105 //              containing 0. The program can select a subset of the
00106 //              physically allocated memory for controlled access -- see
00107 //              "Data subset control" below. The default is for all
00108 //              actually allocated memory to be accessible. If the vector
00109 //              is declared const, returns a const (read-only) Lvalue.
00110 //
00111 // v.read(i);   Like v.get(i), except always returns an Rvalue, so it is only
00112 //              useful for reading data values, not writing to them.
00113 //
00114 // v[i];        Provides uncontrolled, direct Lvalue access to the data
00115 //              elements.  If i addresses an "element" beyond the limits of
00116 //              v's memory allocation, a program crash is likely. If v is
00117 //              declared const, then the Lvalue will be const.
00118 //
00119 // The controlled access mode simulates an "infinite" vector, whose
00120 // elements become identically zero if you get close enough to +/-
00121 // infinity.  How close is "close" depends on v's capacity and indexing
00122 // mode, and will be discussed next.
00123 //
00124 // The limits on i for accessing valid data members depends on the "size"
00125 // of v and v's indexing mode. The size of v, along with the indexing mode,
00126 // also determine v's capacity: the total number of data elements it can
00127 // store.  Upon creation or reallocation, both the size and indexing mode
00128 // may be specified (default values for each are also provided). The
00129 // indexing limits and data capacities are described in the following
00130 // table:
00131 //
00132 //             Indexing Modes, Index Limits, and Capacities
00133 //
00134 //    n : size of vector v (a nonnegative integer)
00135 //
00136 //      Index Mode        Index Range(*)      Data Capacity(**)
00137 //      ----------        --------------      -----------------
00138 //       Index_C           { 0 .. n-1 }              n
00139 //
00140 //       Index_1            { 1 .. n }               n
00141 //
00142 //       Index_S        {-n .. 0 .. n }           2*n + 1
00143 //
00144 // (*) Note on index range: { 0 .. n-1 } means that the index goes from
00145 //     0 to n-1.  If the stated limits are exceeded using direct access
00146 //     (v[i]), a runtime program crash is likely; if exceeded using
00147 //     controlled access (v[i] or v.read(i)), a 0 will be returned, and no
00148 //     error will result.
00149 //
00150 // (**)Data Capacity: the total number of data elements allocated.
00151 //
00152 // So the data capacity equals the size for all but the Index_S mode.  For
00153 // an Index_S mode vector, even a size of 0 implies that one data element
00154 // is allocated: v[0]. The Index_C mode provides tradional C-style
00155 // indexing. The Index_1 mode (that's a "one", not an "el") starts indexing
00156 // at 1 vice 0 and is the default mode if none is specified at creation.
00157 // The Index_S mode provides for symmetric indexing around 0, v[0] being
00158 // the middle element.  To determine the size of a vector object (the value
00159 // of n used in the table above), simply examine:
00160 //
00161 //
00162 // v.size;         current size of the vector v
00163 //
00164 //
00165 // To easily determine the available index range for any vector object, the
00166 // following member functions are provided (for a vector v):
00167 //
00168 //
00169 // v.maxindex();   returns the int value of the maximum valid index
00170 //
00171 // v.minindex();   returns the int value of the minimum valid index
00172 //
00173 //
00174 // If the data capacity of the vector is 0, v.maxindex is guaranteed to be
00175 // less than v.minindex for all index modes, so a loop construct such as:
00176 //
00177 //   for( int i = v.minindex(); i <= v.maxindex(); ++i)
00178 //     v[i];
00179 //
00180 // will always loop i over the valid index range of the vector v,
00181 // regardless of v's size or index mode. The index range may be optionally
00182 // adjusted to less than that determined by vector memory capacity -- refer
00183 // to "Data subset control" for details.
00184 //
00185 // The following function will quickly tell you if a vector has no valid
00186 // data elements:
00187 //
00188 // v.is_empty();    Returns 1 if there are no valid elements of v,
00189 //                  otherwise returns 0.
00190 //
00191 //
00192 // Specifying the Index Mode:
00193 // -------------------------
00194 // The default index mode is Index_1. This may be overridden by including
00195 // an index mode value at the end of a constructor's argument list, or at
00196 // the end of the reallocate member function's argument list. The index
00197 // mode names are enumerations specified in an enumerated type defined in
00198 // this header file, called "v_index_mode".
00199 // 
00200 // The indexing mode for a given vector object may be determined by
00201 // examining a read-only member variable, of type v_index_mode:
00202 //
00203 //
00204 // v.mode;          current indexing mode for vector v
00205 //
00206 //
00207 // The indexing mode may also be changed:
00208 //
00209 //
00210 // v.reindex(mode); change the index mode for this vector without moving
00211 //                  data or reallocating memeory (mostly). Turns off any
00212 //                  data subset control, then changes internal pointers
00213 //                  so that the allocated memory for the vector is now
00214 //                  indexed using the specified v_index_mode. The
00215 //                  memory contents are not moved, so v[v.minindex()]
00216 //                  addresses the same data element before and after the
00217 //                  mode change (assuming no data subset control before
00218 //                  reindex() is executed). Note that changing to Index_S
00219 //                  requires an odd number of allocated elements; if the
00220 //                  number is even, the vector is first resized, adding an
00221 //                  additional element. This function has no effect if the
00222 //                  vector aliases a preexisting memory block; such a
00223 //                  vector's index mode cannot be changed with this fcn.
00224 //
00225 // Data Subset Control:
00226 // -------------------
00227 // At creation minindex() and maxindex() are set so that all physically
00228 // allocated vector elements are available using controlled access (except
00229 // for the copy constructor, in which case they match the values in the
00230 // source vector). The default behavior is therefore to allow controlled
00231 // access to all data elements. If only a subset of the vector near data[0]
00232 // contains useful values, however, it may be wise to temporarily limit
00233 // access, so that looping over the relevant data will not also include
00234 // memory locations not currently needed, speeding up loop execution. To
00235 // implement this capability, maxindex() may be adjusted under program
00236 // control; minindex()is determined by the index mode and the value of
00237 // maxindex(), as in the previous table regarding indexing modes.
00238 //
00239 // Note that all data elements are always accessible using data[i]. For any
00240 // vector object v:
00241 //
00242 //
00243 // v.maxindex(i);  Set the maximum valid index to i if possible. If the
00244 //                 result would be less than the resulting minindex(), then
00245 //                 set maxindex such that maxindex() == minindex() (0 for
00246 //                 Index_C and Index_S, 1 for Index_1). If the result would
00247 //                 exceed the allocated memory, set maxindex() so that all
00248 //                 allocated memory is available (v.size for Index_1 and
00249 //                 Index_S, v.size-1 for Index_C). If the size of the
00250 //                 vector (v.size) is zero, maxindex(i) will have no
00251 //                 effect, regardless of the value of i. Returns the
00252 //                 resulting maxindex() value. To maximize maxindex(), use:
00253 //
00254 // v.maximize();   Adjusts maxindex() and minindex() so that all physically
00255 //                 allocated data elements are accessible using controlled
00256 //                 access; equivalent to:
00257 //
00258 //                        v.maxindex(v.size);
00259 //
00260 //
00261 // v.shrink(s);    Shrinks the data subset range of v to ignore tiny
00262 //                 values. Uses the scalar s as a tolerance defining
00263 //                 "tiny". Starts at v[maxindex()]; accumulates the sum of
00264 //                 the magnitude squared's of the elements going down
00265 //                 towards v[0], and stops when this sum exceeds the square
00266 //                 magnitude of s. Sets the new maxindex to the index at
00267 //                 which this sum exceeds the threshold set by s.  If v is
00268 //                 mode Index_S, separately accumulates sums for indexes
00269 //                 near maxindex() and for indexes near minindex(); stops
00270 //                 when either sum exceeds the square magnitude of s.
00271 //
00272 // v.make_empty();  Set maxindex() and minindex() to the values they would have
00273 //                  were there to be no memory allocated for v, so that
00274 //                  maxindex() will be less than minindex().
00275 //
00276 //
00277 // Construction, Memory Allocation and Reallocation:
00278 // ------------------------------------------------
00279 // Upon creation a vector object's data memory will be allocated from the
00280 // heap or, optionally, may use an already existing chunk of memory. The
00281 // size of the vector object is specifiable as a constructor parameter.  If
00282 // no value for size is given, the value defined by the macro
00283 // DEFAULT_VECTOR_SIZE is used.  This macro will be defined by this header
00284 // file if it is not already defined. The constant member variable v.size
00285 // is set to the vector's size; it will equal 0 if memory allocation fails.
00286 //
00287 // If required, the memory allocation and/or indexing mode for a vector
00288 // object may be adjusted following creation, so a vector object may be
00289 // created with an initial size of 0, and then later reallocated once the
00290 // required size is known.
00291 //
00292 // Upon destruction, a vector object will return memory to the heap only if
00293 // it was allocated by the object, so the constructor which uses an already
00294 // existing memory area is safe.  Using this feature, for example, allows
00295 // functions to create local vector objects to manipulate data identified
00296 // by a pointer argument without copying, or to create member vector
00297 // objects which use memory allocated by the parent class object.
00298 //
00299 // Note for mode Index_S and v.size: v.size == 0 should mean that one data
00300 // element is available in mode Index_S, namely v[0]. However, in the
00301 // event of a memory allocation failure, this one element will be the same
00302 // as that used for index out of range operations, and so will not be very
00303 // useful. Note that in this case the maxindex() value will be -1, and the
00304 // minindex() value will be +1, so a looping construct as described
00305 // previously will access no values, which is the correct action.
00306 //
00307 // A list of the basic constructor forms follows. In this list, *_ means a
00308 // prefix of real_ or complex_. Additionally: n is a nonnegative size; t is
00309 // an index mode value of enumerated type v_index_mode; ptr is a pointer to
00310 // data of the same type as the vector data type (e.g.: double ico a
00311 // real_vector).
00312 //
00313 //
00314 // *_vector v;             Create a vector with the size specified in
00315 //                         DEFAULT_VECTOR_SIZE.  Use mode
00316 //                         Index_1. Initializes all data elements to 0.
00317 //
00318 // *_vector v(t);          Another default size constructor, but with index
00319 //                         mode specified by t. Initializes all data
00320 //                         elements to 0.
00321 //
00322 // *_vector v(n);          Create a vector of size n, index mode Index_1. 
00323 //                         (if n < 0, creates a default-sized vector)
00324 //                         v[i] are all set to 0.
00325 //
00326 // *_vector v(n,t);        Create a vector of size n, index mode t. (if n <
00327 //                         0, creates a default-sized vector) v[i] are
00328 //                         all set to 0.
00329 //
00330 // *_vector v(ptr,n,t);    Use a memory block around the element pointed
00331 //                         to by ptr for the vector data, with v[0] = 
00332 //                         *ptr (in other words, set v.data = ptr). set
00333 //                         v.size = n, v.mode = t. Do not initialize any
00334 //                         data values, do not delete the block on
00335 //                         destruction (No data memory is allocated from
00336 //                         the heap). BE CAREFUL WITH THIS ONE! If t !=
00337 //                         Index_C, ptr does not point to the beginning of
00338 //                         the memory block! There is no default index mode,
00339 //                         one must be specified. If n <= 0, set v.size = 0,
00340 //                         treat as a memory allocation failure.
00341 //
00342 // For all of the above constructors, the valid index range is initialized
00343 // to include all allocated data elements.
00344 //
00345 //
00346 // *_vector v(v1);         Create a copy of vector v1: v.mode = v1.mode;
00347 //                         v.size = v1.size. Copy all data elements, even
00348 //                         those beyond the valid index range if data
00349 //                         subset control is in use on vector v1. Set data
00350 //                         subset control on v to the same limits in use on
00351 //                         v1. If creating a real_vector, v1 must also be a
00352 //                         real_vector.  If creating a complex_vector, v1
00353 //                         may be of types real_vector or complex_vector.
00354 //
00355 // To reallocate the memory or change the indexing modes of an existing
00356 // vector object, the resize and reallocate member functions are
00357 // provided. When a vector is reallocated, it copies the maximum amount of
00358 // data from the old v into the new v, given the new index size and mode
00359 // of v, and such that each data element keeps its same index location. If
00360 // data subset control is being used, then the new valid index range will
00361 // match as closely as possible the old valid index range, but all physical
00362 // data will be copied, not just the data in the valid index range. If data
00363 // subset control is not being used (the maxindex and minindex values
00364 // include all allocated memory), then the new maxindex and minindex values
00365 // will include all of the newly allocated memory. The resize() member
00366 // function is useful if you know the resulting index range you want. The
00367 // reallocate() function is a more primitive construct which is called by
00368 // resize(). If v is a vector object, then:
00369 //
00370 //
00371 // v.resize(n);          Reallocate the memory for v so that its size will
00372 //                       just fit a  maximum index value of n. Keep the
00373 //                       current indexing mode.
00374 //
00375 // v.resize(v1);         Reallocate the memory for v so that its index
00376 //                       mode matches that of vector v1, and its size will
00377 //                       just fit the valid index range of v1, as
00378 //                       determined by v1's data subset control.
00379 //
00380 // v.reallocate(n);      Reallocate the memory for v to change it into a
00381 //                       vector with size n.  Keep the current indexing
00382 //                       mode.
00383 //
00384 // v.reallocate(n,t);    Reallocate the memory for v to change its size
00385 //                       and mode to n and t.
00386 //
00387 // In addition to the reallocate member function, the assignment operator
00388 // '=' may result in memory reallocation.  This behavior is described in
00389 // the next section.
00390 //
00391 //
00392 // Assignment and Copying Data:
00393 // ---------------------------
00394 // The following member functions are provided for bulk data transfer from
00395 // one vector object into another existing object: = and copy.  Both
00396 // functions attempt to preserve the source vector's data subset control,
00397 // and both set unused elements in the destination vector to 0.  There is a
00398 // major difference, however, between the two operations: = may reallocate
00399 // memory for the receiving vector, while copy leaves the size and mode of
00400 // the receiving vector unchanged.  Note that self assignment ( v = v ) and
00401 // self copy ( v.copy(v) ) are not "do nothing" operations.
00402 //
00403 //
00404 // v = v1;         If v has insufficient memory to hold all of v1's valid
00405 //                 (data subset control) data, or if the index mode of v
00406 //                 differs from that of v1, reallocate the memory for v so
00407 //                 that it has the same index mode as v1, with a size just
00408 //                 sufficient to hold all of the valid data elements of v1.
00409 //                 Copy all of v1's valid data elements into v, and set any
00410 //                 remaining elements of v to 0. Set the data subset control
00411 //                 for v so that its valid index range matches the valid
00412 //                 index range for v1.  When finished, v will be a (possibly
00413 //                 larger) copy of the valid data elements of v1, with the
00414 //                 same valid index range and index mode.  If v1 and v are
00415 //                 the SAME vector (even if one is an alias of the other),
00416 //                 just perform v.clean().
00417 //
00418 // v.copy(v1);     Copy as many of the valid data elements of v1 into the
00419 //                 corresponding elements of v as the memory allocation and
00420 //                 indexing mode of v will allow.  In other words, copy the
00421 //                 data elements with indexes in the intersection of the
00422 //                 indexing ranges of v and v1.  Only copies data within
00423 //                 v1's currently valid index range, so data subset control
00424 //                 on v1 may reduce the number of elements copied. Ignores
00425 //                 any data subset control previously set for v. Sets the
00426 //                 remaining elements of v to 0, and sets v data subset
00427 //                 control to match as closely as possible v1's valid index
00428 //                 range.  If v1 and v are the SAME vector (even if one is
00429 //                 an alias of the other), just perform v.clean().
00430 //
00431 // As with the copy constructor, v1 may be a real_vector or a
00432 // complex_vector if v is of type complex_vector; v1 must be of type
00433 // real_vector if v is of type real_vector.
00434 //
00435 //
00436 // Some Other Basic Vector Member Functions:
00437 // ----------------------------------------
00438 //
00439 //
00440 // v.fill(s);      Fill all elements in the valid index range of v with the
00441 //                 scalar value s. The fill is subject to data subset
00442 //                 control.
00443 //
00444 // v = s;          For scalar s, the same as v.fill(s). s may not be
00445 //                 Complex if v is of type real_vector.
00446 //
00447 // v.fillall(s);   Fill all physically allocated elements of v with the
00448 //                 scalar value s. Ignores data subset control.
00449 //
00450 // v.clean();      Resets to 0 all allocated data elements beyond the
00451 //                 boundaries set by v.minindex() and v.maxindex()
00452 //
00453 // v.unit(n);      Set v[n] = 1, if n is a valid index for v. Set all other
00454 //                 elements of v to 0. Uses data subset to determine if n
00455 //                 is a valid index; if n isn't valid, all elements are set
00456 //                 to zero.
00457 //
00458 // v.findmax();    Return the int index of the element of v with the
00459 //                 largest magnitude within v's valid index range (data
00460 //                 subset control), or 0 if v contains no elements.
00461 //
00462 // v.swap(n,m);    Swap the contents of v[n] and v[m]. Use 0 as the value
00463 //                 of a data element for an index outside the valid index
00464 //                 range (data subset control).
00465 //
00466 // v.apply(f);     Apply the scalar function f to each valid element of
00467 //                 v. f() will be called once for each valid element of v.
00468 //                 f must be a function taking either:
00469 //                  (1) a single numeric argument of the same type as the
00470 //                      data elements of v: f(double x) or f(Complex x).
00471 //                  (2) a numeric argument and an int argument:
00472 //                      f(double x, int i) or f(Complex x, int i)
00473 //                 f() must return a single numeric value of the same type
00474 //                 as the data elements of v. As apply() iterates through
00475 //                 the vector elements, it calls f() with the value of each
00476 //                 element and, if f() is of type (2) above, the value of
00477 //                 the index of the element.  Equivalent to:
00478 //
00479 //                   for (int i = v.minindex(); i <= v.maxindex(); ++i)
00480 //                     v[i] = f(v[i]); /* OR */ v[i] = f(v[i],i);
00481 //
00482 //
00483 // Vector Arithmetic Member Functions:
00484 // ----------------------------------
00485 //
00486 //
00487 // v += s;  v -= s;  v *= s;  v /= s;
00488 //                 Perform the indicated assignment operator operation to
00489 //                 each element of v within its valid index range, using
00490 //                 data subset control.  The scalar s may not be Complex if
00491 //                 v is a real_vector.
00492 //
00493 // v += v1; v -= v1;  First perform v.clean(), then perform the indicated
00494 //                 assignment operation as a vector addition or subtraction
00495 //                 using only valid elements of v1 (data subset control on
00496 //                 v1).  Increases the data subset range of v if necessary
00497 //                 so that its valid index range includes the valid index
00498 //                 range of v1 as a subset, unless limited by the physical
00499 //                 capacity of v. Does not reallocate any memory for v or
00500 //                 change v's index mode.
00501 //
00502 // v.real(v1);     sets each element of v equal to the real part of the
00503 //                 corresponding element of complex_vector v1. Performs
00504 //                 v.resize(v1) first, so that it is just big enough to
00505 //                 hold the valid elements of v1.  v may be either a
00506 //                 real_vector or a complex_vector; v1 must be a complex_
00507 //                 vector. (The resize is not performed if v1 is the same
00508 //                 vector as v)
00509 //
00510 // v.imaginary(v1); sets each element of v equal to the imaginary part of
00511 //                 the corresponding element of complex_vector v1. Performs
00512 //                 v.resize(v1) first, so that it is just big enough to
00513 //                 hold the valid elements of v1.  v may be either a
00514 //                 real_vector or a complex_vector; v1 must be a complex_
00515 //                 vector. (The resize is not performed if v is the same
00516 //                 vector as v1)
00517 //
00518 //
00519 // STL Compatibility:
00520 // -----------------
00521 //
00522 // The following types and functions are provided to mimic as closely as
00523 // possible the behavior of the similarly-named objects which operate on the
00524 // Standar Template Library vector<double> and vector<Complex> classes. They
00525 // may be used with STL generic algorithms, for example.
00526 //
00527 // v.push_back(s); Add scalar s just beyond the last element in the valid
00528 //                 index range of v, increasing v.maxindex() by 1. If v is
00529 //                 not large enough to hold this additional element, resize
00530 //                 v so that it will hold about twice as many elements as 
00531 //                 before.
00532 //
00533 // v.pop_back();   Attempt to reduce maxindex() by 1. If maxindex()<=minindex(),
00534 //                 then make v empty using make_empty().
00535 //
00536 // v.capacity();   Just return v.size.
00537 //
00538 // v.reserve(n);   Similar to v.reallocate(n), unless the size of v already
00539 //                 exceeds n, in which case do nothing. Unlike reallocate(),
00540 //                 v.maxindex() is always unaffected by reserve().
00541 //
00542 // v.empty();      Like is_empty(), except returns a bool rather than int.
00543 //
00544 // v.front();      Returns a reference to v[v.minindex()];
00545 //
00546 // v.back();       Returns a reference to v[v.maxindex()];
00547 //
00548 //
00549 // Types:
00550 //
00551 // real_vector::value_type;         double
00552 // complex_vector::value_type;      Complex
00553 //
00554 // real_vector::reference;          double &
00555 // complex_vector::reference;       Complex &
00556 //
00557 // real_vector::const_reference;    const double &
00558 // complex_vector::const_reference; const Complex &
00559 //
00560 // real_vector::iterator;           double*
00561 // complex_vector::iterator;        Complex*
00562 //
00563 // real_vector::const_iterator;     const double*
00564 // complex_vector::const_iterator;  const Complex*
00565 //
00566 // real_vector::difference_type;    int  (ditto for complex_vector)
00567 // real_vector::size_type;          int  (since indexes can be negative)
00568 //
00569 // The iterators are all STL "random access" iterators, with all the requisite
00570 // operations defined for them. reverse_iterator types may be added in a future
00571 // release.
00572 //
00573 // Given the above types, including iterators, we also have the functions:
00574 //
00575 // v.begin();      Iterator pointing to v[v.minindex()]
00576 //
00577 // v.end();        Iterator pointing to v[v.maxindex()+1]
00578 //
00579 // Note that as with STL vector<> class, any operation which may result in
00580 // reallocation of the vector's memory will invalidate all iterators to that
00581 // vector. 
00582 //
00583 //
00584 // Vector Output/Display Functions:
00585 // -------------------------------
00586 //
00587 // ostream << v;   send the contents of v to the output stream ostream. Note
00588 //                 that << is not a member function of any class.  The
00589 //                 elements of v in its valid index range are sent to ostream
00590 //                 in index order. The elements of v are separated by the
00591 //                 C++ string whose value is controlled by the static member
00592 //                 function out_separator(); the default value is a single
00593 //                 space character ' '.  The output of each element is into a
00594 //                 field of width determined by ostream.width(); the separator
00595 //                 string is not affected by the ostream.width() value. Note
00596 //                 that << is used to output each individual element.
00597 //
00598 // v.show(ostream); output equivalent to:  ostream << endl << v << endl;
00599 //
00600 // v.show();       equivalent to v.show(cout);
00601 //
00602 // real_vector::out_separator(s); or: complex_vector::out_separator(s);
00603 //                 either function sets the output separator string for
00604 //                 both real_vector and complex_vector output. s may be a
00605 //                 C++ string, a C-style string, or a single char. The
00606 //                 function returns the previous value of the separator as
00607 //                 a C++ string. If no argument is specified, then the
00608 //                 function simply returns the current separator value. The
00609 //                 default value is a single space. If no output separator
00610 //                 character is desired, use a null string "" for s.
00611 //
00612 // ************************************************************************
00613 
00614 #ifndef VECTOR_H
00615 #define VECTOR_H
00616 
00617 #ifndef DEFAULT_VECTOR_SIZE
00618 #define DEFAULT_VECTOR_SIZE   16   /* a default vector size */
00619 #endif  /* DEFAULT_VECTOR_SIZE */
00620 
00621 #ifndef V_INDEX_MODE_DEFINED
00622 #define  V_INDEX_MODE_DEFINED
00623 enum v_index_mode { Index_C, Index_1, Index_S };
00624 #endif /* V_INDEX_MODE_DEFINED */
00625 
00626 #include "SIScmplx.h"
00627 #include <string>
00628 
00629 class real_vector;
00630 class complex_vector;
00631 class ostream;
00632 
00633 //---------------------------------------------------------------------
00634 
00635 class real_vector {
00636 
00637 public:
00638 
00639   // data:
00640 
00641   const int     &size;             // the size of v
00642   const v_index_mode   &mode;      // the indexing mode for v
00643 
00644 
00645   // constructors:
00646 
00647   explicit real_vector(const v_index_mode t = Index_1)
00648     : size(internal_size), mode(internal_mode)
00649   { construct(DEFAULT_VECTOR_SIZE, t); constfill(0.0); }
00650 
00651   explicit real_vector(const int n, const v_index_mode t = Index_1)
00652     : size(internal_size), mode(internal_mode)
00653   { construct(n, t); constfill(0.0); }
00654 
00655   real_vector(const real_vector & v1);
00656 
00657   real_vector(double *const ptr, const int n, const v_index_mode t);
00658 
00659   // destructor:
00660 
00661   ~real_vector(void) { delete [] delete_pointer; }
00662 
00663   // data subset contol:
00664 
00665   int minindex(void) const  { return minindexvalue; }
00666   int maxindex(void) const  { return maxindexvalue; }
00667   int maxindex(int n);
00668   int maximize(void) { return maxindex(size); }
00669   real_vector & shrink(double s);
00670   int is_empty() const  { return maxindex() < minindex(); }
00671   real_vector & make_empty();
00672 
00673   // change index mode:
00674 
00675   real_vector & reindex(const v_index_mode);
00676 
00677   // data access:
00678   
00679   double read (const int i) const
00680   { return ((i > maxindex())||(i < minindex())) ? 0.0 : data[i]; }
00681 
00682   double & get (const int i)
00683   { return ((i > maxindex())||(i < minindex())) ? (trash = 0.0) : data[i]; }
00684 
00685   const double & get (const int i) const
00686   { return ((i > maxindex())||(i < minindex())) ? (trash = 0.0) : data[i]; }
00687 
00688   double & operator [] (const int i) 
00689   { return data[i]; }
00690 
00691   const double & operator [] (const int i) const
00692   { return data[i]; }
00693 
00694   // data copying, assignment, and reallocation:
00695 
00696   real_vector & copy(const real_vector & v1);
00697   real_vector & operator = (const real_vector & v1);
00698   real_vector & reallocate(const int n, const v_index_mode t);
00699   real_vector & reallocate(const int n)  { return reallocate(n,mode); }
00700   real_vector & resize(const int Max)
00701   { int Size = (mode == Index_C) ? Max+1: Max; return reallocate(Size); }
00702   real_vector & resize(const real_vector & v)
00703   {
00704     int Size = (v.mode == Index_C) ? v.maxindex()+1: v.maxindex();
00705     return reallocate(Size, v.mode);
00706   }
00707   real_vector & resize(const complex_vector & v);
00708 
00709   // other basic vector member functions:
00710 
00711   real_vector & clean(void);
00712   real_vector & fill(const double s) { constfill(s); return *this; }
00713   real_vector & operator = (const double s) { return fill(s); }
00714   real_vector & fillall(const double s);
00715   real_vector & unit(int n) { fillall(0); get(n) = 1; return *this; }
00716   int findmax() const;
00717   real_vector & swap(const int n, const int m)
00718   { 
00719     if (n != m) { double temp = get(n); get(n) = get(m); get(m) = temp; }
00720     return *this;
00721   }
00722   real_vector & apply(double (*f)(double));
00723   real_vector & apply(double (*f)(const double & x));
00724   real_vector & apply(double (*f)(double, int));
00725   real_vector & apply(double (*f)(const double &, int));
00726 
00727   // vector arithmetic member functions:
00728 
00729   real_vector & operator += (const double s);
00730   real_vector & operator -= (const double s);
00731   real_vector & operator *= (const double s);
00732   real_vector & operator /= (const double s);
00733   real_vector & operator += (const real_vector & v1);
00734   real_vector & operator -= (const real_vector & v1);
00735   real_vector & real(const complex_vector & v);
00736   real_vector & imaginary(const complex_vector & v);
00737   
00738   // vector output member functions:
00739 
00740   real_vector & show(ostream &);
00741   real_vector & show(void);
00742   const real_vector & show(ostream &) const;
00743   const real_vector & show(void) const;
00744   static string out_separator(); // return the current output separator
00745   static string out_separator(const string &);
00746   static string out_separator(const char * const);
00747   static string out_separator(const char);
00748 
00749 
00750   // STL Types:
00751 
00752   typedef   double                 value_type;
00753   typedef   value_type &           reference;
00754   typedef   const reference        const_reference;
00755   typedef   value_type *           iterator;
00756   typedef   const value_type *     const_iterator;
00757   typedef   int                    difference_type;
00758   typedef   int                    size_type;
00759 
00760   // STL compatibility declarations:
00761 
00762   bool empty() const  { return bool(is_empty()); }
00763   int capacity() const  { return size; }
00764   void reserve(int n);
00765   double & front() { return data[minindexvalue]; }
00766   const double & front() const  { return data[minindexvalue]; }
00767   double & back() { return data[maxindexvalue]; }
00768   const double & back() const  { return data[maxindexvalue]; }
00769   void push_back(double s);
00770   void pop_back();
00771   iterator begin() { return & data[minindexvalue]; }
00772   iterator end()   { return & data[maxindexvalue+1]; }
00773   const_iterator begin() const { return & data[minindexvalue]; }
00774   const_iterator end()   const { return & data[maxindexvalue+1]; }
00775 
00776 private:
00777 
00778   int            internal_size;    // aliased by size
00779   v_index_mode   internal_mode;    // aliased by mode
00780   int            maxindexvalue;    // the index upper limit
00781   int            minindexvalue;    // the index lower limit
00782   double        *data;             // The vector raw data pointer
00783   double        *delete_pointer;   // used by destructor to delete memory
00784   mutable double trash;            // Where index-out-of-bounds wind up
00785 
00786   // these functions are called by the constructors:
00787   void construct(const int n, const v_index_mode t); //allocate memory
00788   void constfill(const double f); // fill with a constant value
00789 
00790 };  // class real_vector
00791 
00792 ostream & operator << (ostream &, const real_vector &);
00793 
00794 //---------------------------------------------------------------------
00795 
00796 class complex_vector {
00797 
00798 public:
00799 
00800   // data:
00801 
00802   const int     &size;             // the size of v
00803   const v_index_mode   &mode;      // the indexing mode for v
00804 
00805 
00806   // constructors:
00807 
00808   explicit complex_vector(const v_index_mode t = Index_1)
00809     : size(internal_size), mode(internal_mode)
00810   { construct(DEFAULT_VECTOR_SIZE, t); constfill(0.0); }
00811 
00812   explicit complex_vector(const int n, const v_index_mode t = Index_1)
00813     : size(internal_size), mode(internal_mode)
00814   { construct(n, t); constfill(0.0); }
00815 
00816   complex_vector(const complex_vector & v1);
00817   complex_vector(const real_vector & v1);
00818 
00819   complex_vector(complex *const ptr, const int n, const v_index_mode t);
00820 
00821 
00822   // destructor:
00823 
00824   ~complex_vector(void) { delete [] delete_pointer; }
00825 
00826   // data subset contol:
00827 
00828   int minindex(void) const  { return minindexvalue; }
00829   int maxindex(void) const  { return maxindexvalue; }
00830   int maxindex(int n);
00831   int maximize(void) { return maxindex(size); }
00832   complex_vector & shrink(Complex s);
00833   int is_empty() const  { return maxindex() < minindex(); }
00834   complex_vector & make_empty();
00835 
00836   // change index mode:
00837 
00838   complex_vector & reindex(const v_index_mode);
00839 
00840   // data access:
00841   
00842   Complex read (const int i) const
00843   { return ((i > maxindex())||(i < minindex())) ? 0.0 : data[i]; }
00844 
00845   Complex & get (const int i)
00846   { return ((i > maxindex())||(i < minindex())) ? (trash = 0.0) : data[i]; }
00847 
00848   const Complex & get (const int i) const
00849   { return ((i > maxindex())||(i < minindex())) ? (trash = 0.0) : data[i]; }
00850 
00851   Complex & operator [] (const int i) 
00852   { return data[i]; }
00853 
00854   const Complex & operator [] (const int i) const
00855   { return data[i]; }
00856 
00857   // data copying and reallocation:
00858 
00859   complex_vector & copy(const complex_vector & v1);
00860   complex_vector & copy(const real_vector & v1);
00861   complex_vector & operator = (const complex_vector & v1);
00862   complex_vector & operator = (const real_vector & v1);
00863   complex_vector & reallocate(const int n, const v_index_mode t);
00864   complex_vector & reallocate(const int n)
00865   { return reallocate(n,mode); }
00866   complex_vector & resize(const int Max)
00867   { int Size = (mode == Index_C) ? Max+1: Max; return reallocate(Size); }
00868   complex_vector & resize(const real_vector & v)
00869   {
00870     int Size = (v.mode == Index_C) ? v.maxindex()+1: v.maxindex();
00871     return reallocate(Size, v.mode);
00872   }
00873   complex_vector & resize(const complex_vector & v)
00874   {
00875     int Size = (v.mode == Index_C) ? v.maxindex()+1: v.maxindex();
00876     return reallocate(Size, v.mode);
00877   }
00878 
00879   // other basic vector member functions:
00880 
00881   complex_vector & clean(void);
00882   complex_vector & fill(const Complex s) { constfill(s); return *this; }
00883   complex_vector & operator = (const Complex s) { return fill(s); }
00884   complex_vector & operator = (const double s) 
00885   { return fill(Complex(s)); }
00886   complex_vector & fillall(const Complex s);
00887   complex_vector & unit(int n) { fillall(0); get(n) = 1; return *this; }
00888   int findmax() const;
00889   complex_vector & swap(const int n, const int m)
00890   {
00891     if (n != m) { Complex temp = get(n); get(n) = get(m); get(m) = temp; }
00892     return *this;
00893   }
00894   complex_vector & apply(Complex (*f)(Complex));
00895   complex_vector & apply(Complex (*f)(const Complex &));
00896   complex_vector & apply(Complex (*f)(Complex, int));
00897   complex_vector & apply(Complex (*f)(const Complex &, int));
00898 
00899   // vector arithmetic member functions:
00900 
00901   complex_vector & operator += (const Complex s);
00902   complex_vector & operator -= (const Complex s);
00903   complex_vector & operator *= (const Complex s);
00904   complex_vector & operator /= (const Complex s);
00905   complex_vector & operator += (const complex_vector & v1);
00906   complex_vector & operator -= (const complex_vector & v1);
00907   complex_vector & operator += (const real_vector & v1);
00908   complex_vector & operator -= (const real_vector & v1);
00909   complex_vector & real(const complex_vector & v);
00910   complex_vector & imaginary(const complex_vector & v);
00911 
00912   // vector output member functions:
00913 
00914   complex_vector & show(ostream &);
00915   complex_vector & show(void);
00916   const complex_vector & show(ostream &) const;
00917   const complex_vector & show(void) const;
00918   static string out_separator(); // return the current output separator
00919   static string out_separator(const string &);
00920   static string out_separator(const char * const);
00921   static string out_separator(const char);
00922 
00923 
00924   // STL Types:
00925 
00926   typedef   Complex                value_type;
00927   typedef   value_type &           reference;
00928   typedef   const reference        const_reference;
00929   typedef   value_type *           iterator;
00930   typedef   const value_type *     const_iterator;
00931   typedef   int                    difference_type;
00932   typedef   int                    size_type;
00933 
00934   // STL compatibility declarations:
00935 
00936   bool empty() const  { return bool(is_empty()); }
00937   int capacity() const  { return size; }
00938   void reserve(int n);
00939   Complex & front() { return data[minindexvalue]; }
00940   const Complex & front() const  { return data[minindexvalue]; }
00941   Complex & back() { return data[maxindexvalue]; }
00942   const Complex & back() const  { return data[maxindexvalue]; }
00943   void push_back(Complex s);
00944   void pop_back();
00945   iterator begin() { return & data[minindexvalue]; }
00946   iterator end()   { return & data[maxindexvalue+1]; }
00947   const_iterator begin() const { return & data[minindexvalue]; }
00948   const_iterator end()   const { return & data[maxindexvalue+1]; }
00949 
00950 
00951 private:
00952 
00953   int            internal_size;    // aliased by size
00954   v_index_mode   internal_mode;    // aliased by mode
00955   int            maxindexvalue;    // the index upper limit
00956   int            minindexvalue;    // the index lower limit
00957   Complex       *data;             // The vector raw data pointer
00958   Complex       *delete_pointer;   // used by destructor to delete memory
00959   mutable Complex trash;           // Where index-out-of-bounds wind up
00960 
00961   // these functions are called by the constructors:
00962   void construct(const int n, const v_index_mode t); //allocate memory
00963   void constfill(const Complex f); // fill with a constant value
00964 
00965 };  // class complex_vector 
00966 
00967 ostream & operator << (ostream &, const complex_vector &);
00968 
00969 //---------------------------------------------------------------------
00970 
00971 #endif  /* VECTOR_H */

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