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
1.2.7