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

table.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 // table.h
00032 // numeric matrix classes
00033 //
00034 // Needs:
00035 //   table.cc   for function definitions
00036 //   a #defined constant macro DEFAULT_MATRIX_SIZE
00037 //      (creates its own otherwise)
00038 //
00039 // Includes: SIScmplx.h
00040 //
00041 // F. Rice 9/24/97
00042 //
00043 // 4/26/00:  added is_empty(), make_empty().
00044 // 7/6/99:   changed "table" to "matrix". Included typedefs for compatibility
00045 // 11/11/98: enhanced access operators; removed public "data"
00046 // 7/31/98:  added out_separator() static member functions
00047 // 7/30/98:  Enhanced show(), added <<
00048 // 7/7/98:   Made certain constructors explicit
00049 // 7/6/98:   Added reindex()
00050 // 2/5/98:   Added new constructor and operator = with datafile argument
00051 //           to real_table class
00052 // 12/18/97: Special version with show() member function
00053 // 12/12/97: "fully" tested with calc
00054 // 11/24/97: improved real_table resize(), added real() and imaginary(),
00055 //           fillrow() and fillcol(), and constructors using vectors.
00056 // 11/17/97: add(), sub()
00057 // 11/14/97: additional math functions
00058 // 11/12/97: changed void functions to return Lvalue *this
00059 // 11/11/97: Converting functions for compatibility with 11/11 vector.h
00060 //           and matmath.h -- NOT FINISHED
00061 // 11/8/97:  CHANGED DEFAULT MODE TO Index_1 instead of Index_C.
00062 //           added resize().
00063 // 11/7/97:  added checks for A = A and A.copy(A), so these constructs
00064 //           behave properly (oops!). Also fixed copy constructor.
00065 // 11/3/97:  New operator =, with an Rvalue RHS. Not fully tested yet.
00066 // 10/26/97: added additional functionality
00067 // 10/17/97: took out the ugly workaround; still bombs Sun CC.
00068 // 10/15/97: fixed some minor syntax bugs; added an ugly workaround in
00069 //           construct() to get it to compile with Sun CC.
00070 // 9/30/97: first version fully functional and tested.
00071 //
00072 // ************************************************************************
00073 //
00074 //               The real_matrix and complex_matrix Classes
00075 //
00076 // General:
00077 // -------
00078 // The *_matrix classes provide for manipulation of 2-dimensional array
00079 // data. A matrix object's data is allocated and referenced as a set of 1-D
00080 // data "rows", each in its own contiguous chunk of memory.  A 1-D array
00081 // contains pointers to each of the rows, providing for the row indexing.
00082 // Each row is in effect a numeric vector "record", whose location is
00083 // maintained in the pointer array. The real_matrix can store type double
00084 // data elements, the complex_matrix can store type Complex data elements.
00085 //
00086 // Even though implemented as a list of rows, the matrix classes require
00087 // that all rows have the same data capacity and indexing mode.  When
00088 // created, a matrix allocates a single, contiguous block of memory for the
00089 // data elements, which it divides up into the individual row arrays.  Upon
00090 // destruction, the entire block of memory is deleted.
00091 //
00092 //
00093 // Indexing and Capacity:
00094 // ---------------------
00095 // Indexing of the data elements in a matrix is accomplished using a pair of
00096 // int indexes.  There are three different indexing modes available, and
00097 // the row indexing and column indexing modes may differ in a given matrix
00098 // object.  The three indexing modes available are called Index_C, Index_1,
00099 // and Index_S, and are identical to the modes used for *_vector indexing,
00100 // described in vectors.h.
00101 //
00102 // Both controlled and uncontrolled (direct) indexed access to the data
00103 // elements are provided.  If "A" is a matrix object, then:
00104 //
00105 //
00106 // A.get(i,j);      Provides controlled, safe read and write access to
00107 //                  the data elements.  The indexes i and j may have any
00108 //                  integer values; i selects the row, and j selects the
00109 //                  element within the row (column). If (i,j) selects an
00110 //                  "element" beyond the limits of A's memory capacity,
00111 //                  A.get(i,j) returns a modifiable Lvalue containing 0.
00112 //                  The program can select a subset of the physically
00113 //                  allocated memory for controlled access -- see "Data
00114 //                  subset control" below.  The default is for all
00115 //                  allocated memory to be accessible. get returns an
00116 //                  Lvalue, so it can be used to modify a data element,
00117 //                  e.g.:   A.get(2,3) = 5.0;
00118 //                  If the matrix is declared const, returns a const
00119 //                  (read-only) Lvalue.
00120 //
00121 // A.read(i,j);     Like A.get(i,j), except returns an Rvalue, so it is
00122 //                  only useful for reading data values, not writing to
00123 //                  them.
00124 //
00125 // A[i][j];         Provides uncontrolled, direct Lvalue access to the data
00126 //                  elements. [i] selects a row pointer, [j] selects an
00127 //                  offset from element 0 within the row. If [i][j] addresses
00128 //                  a nonexistant element of A, a program crash is likely. If
00129 //                  a is declared const, then the Lvalue will be const.
00130 //
00131 // A[i];            Returns a const Lvalue pointer to the data in row i of matrix
00132 //                  A. Actually points to A[i][0], which is not necessarily
00133 //                  the first (lowest address) data element in row i. In
00134 //                  fact, if the right index mode is Index_1, then A[i]
00135 //                  does not directly point to any valid data element in
00136 //                  row i. See the section "Manipulating Matrix Rows as
00137 //                  Vector Objects" for a quite useful application of this
00138 //                  construct. If A is declared const, then the pointer
00139 //                  returned will be to const data.
00140 //
00141 // The controlled access modes simulate an "infinite" matrix, whose
00142 // elements become identically zero if an index gets close enough to +/-
00143 // infinity. How close is "close" depends on A's data capacity and the
00144 // indexing modes it uses for row and column indexing.
00145 //
00146 // Referring to the following indexing modes and limits matrix: 
00147 //
00148 //             Indexing Modes, Index Limits, and Capacities
00149 //
00150 //             n : size of an index (a nonnegative integer)
00151 //
00152 //          Index Mode        Index Range         Data Capacity
00153 //          ----------        -----------         -------------
00154 //           Index_C          { 0 .. n-1 }              n
00155 //
00156 //           Index_1           { 1 .. n }               n
00157 //
00158 //           Index_S         {-n .. 0 .. n }         2*n + 1
00159 //
00160 // If, for example, the left index (row) mode is Index_1 and its size is n,
00161 // while the right index (within a row) mode is Index_S, size m, then the
00162 // total data capacity of the matrix is (referring to the matrix above)
00163 // n * (2*m + 1). The sizes for the left and right indexes are specified at
00164 // construction or reallocation and are kept as read-only member variables. 
00165 // For matrix object A:
00166 //
00167 //
00168 // A.Lsize;         Current value of the size of the left index range
00169 //
00170 // A.Rsize;         Current value of the size of the right index range
00171 //
00172 //
00173 // To easily determine the valid index range for a given matrix object A,
00174 // the following member functions are provided:
00175 //
00176 //
00177 // A.Lmaxindex();   Returns the int value of the max valid left index
00178 // 
00179 // A.Rmaxindex();   Returns the int value of the max valid right index
00180 //
00181 // A.Lminindex();   Returns the int value of the min valid left index
00182 //
00183 // A.Rminindex();   Returns the int value of the min valid right index
00184 //
00185 //
00186 // The left index picks the row, the right index picks the element in the
00187 // row (or column).
00188 //
00189 // Many times a square matrix using the same addressing mode for each index
00190 // is required. the following member functions are particularly useful in
00191 // this case, though they may be called regardless of the matrix topology:
00192 //
00193 //
00194 // A.maxindex();    Returns the minimum of A.Lmaxindex() and A.Rmaxindex()
00195 //
00196 // A.minindex();    Returns the maximum of A.Lminindex() and A.Rminindex()
00197 //
00198 //
00199 // For a square matrix, these functions return the proper limits for both
00200 // row and column indexing. For other matrices, they would identify a valid
00201 // subset of the full matrix indexing range.
00202 //
00203 // As for the vector classes, a maxindex is guaranteed to be smaller than
00204 // its corresponding minindex if the data capacity of the matrix is 0.
00205 // Therefore, loop constructs such as:
00206 //
00207 //      for (int i = A.Lminindex(); i <= A.Lmaxindex(); ++i)
00208 //        for (int j = A.Rminindex(); j <= A.Rmaxindex(); ++j)
00209 //          A[i][j];
00210 //
00211 // will properly loop over the valid index values of the matrix A,
00212 // regardless of its index modes or data capacity.
00213 //
00214 // The following function will quickly tell you if a matrix has no valid
00215 // data elements:
00216 //
00217 // A.is_empty();    Returns 1 if there are no valid elements of A,
00218 //                  otherwise returns 0.
00219 //
00220 //
00221 // Specifying the Index Modes:
00222 // --------------------------
00223 // The default index mode for both the left and right indexes is Index_1.
00224 // This may be overridden by including one or two index mode values at the
00225 // end of a constructor's argument list, or at the end of the reallocate
00226 // member function's argument list.  If only one index mode value is
00227 // supplied, it will be used for both indexes.  If two values are supplied,
00228 // the first will be used for the left index, the other for the right
00229 // index. The index mode names are enumerations specified in an enumerated
00230 // type defined in this header file, called "v_index_mode".
00231 //
00232 // The index mode values for the left and right indexes for a matrix object
00233 // are maintained in read-only member variables.  For matrix object A:
00234 //
00235 //
00236 // A.Lmode;    current indexing mode value for the left index
00237 //
00238 // A.Rmode;    current indexing mode value for the right index
00239 //
00240 // The indexing mode may also be changed:
00241 //
00242 //
00243 // A.reindex(Lmode, Rmode);   change the index modes for this matrix
00244 //             without moving data or reallocating memeory (mostly). Turns
00245 //             off any data subset control, then changes internal pointers
00246 //             so that the allocated memory for the matrix is now indexed
00247 //             using the specified v_index_modes. The memory contents are
00248 //             not moved, so:   A[A.Lminindex()][A.Rminindex()]
00249 //             addresses the same data element before and after the mode
00250 //             change (assuming no data subset control before reindex() is
00251 //             executed). Note that changing to Index_S requires an odd
00252 //             number of allocated elements along that index direction;
00253 //             if the number is even, the matrix is first resized, adding
00254 //             an additional element.
00255 //
00256 //
00257 // Data Subset Control:
00258 // -------------------
00259 // At creation (L/R)minindex() and (L/R)maxindex() are set so that all
00260 // physically allocated matrix elements are available using controlled
00261 // access (except for the copy constructor, in which case they match the
00262 // values in the source matrix). The default behavior is therefore to allow
00263 // controlled access to all data elements. If only a subset of the matrix
00264 // near data[0][0] contains useful values, however, it may be wise to
00265 // temporarily limit access, so that looping over the relevant data will
00266 // not also include memory locations not currently needed, speeding up loop
00267 // execution. To implement this capability, both Lmaxindex() and
00268 // Rmaxindex() may be adjusted under program control; Lminindex() and
00269 // Rminindex() are determined by the index modes and the value of the
00270 // respective maxindex().
00271 //
00272 // Note that all data elements are always accessible using A[i][j].  For
00273 // any matrix object A:
00274 //
00275 //
00276 // A.Lmaxindex(i);  Set the maximum valid left index to i if possible. If
00277 //                  the result would be less than the resulting
00278 //                  Lminindex(), then set Lmaxindex such that Lmaxindex()
00279 //                  == Lminindex() (0 for Index_C and Index_S, 1 for
00280 //                  Index_1). If the result would exceed the allocated
00281 //                  memory, set Lmaxindex so that all allocated memory is
00282 //                  available (A.Lsize for Index_1 and Index_S, A.Lsize-1
00283 //                  for Index_C). If the size of the left index (A.Lsize)
00284 //                  is zero, A.Lmaxindex(i) will have no effect, regardless
00285 //                  of the value of i. Returns the resulting Lmaxindex()
00286 //                  value. To maximize Lmaxindex(), use:
00287 //                  A.Lmaxindex(A.Lsize);
00288 //
00289 //
00290 // A.Rmaxindex(i);  Set the maximum valid right index to i if possible.
00291 //                  Same notes as for Lmaxindex(i). To maximize
00292 //                  Rmaxindex(), use: A.Rmaxindex(A.Rsize);
00293 //
00294 //
00295 // A.maxindex(i);   Set the maximum vaild index for both the left and right
00296 //                  indexes to i if possible. Individually limit the
00297 //                  indexes to valid ranges as described for Lmaxindex(i)
00298 //                  and Rmaxindex(i); this may result in a nonsquare index
00299 //                  range if A.Lsize != A.Rsize or A.Lmode != A.Rmode.
00300 //                  Returns the resulting A.maxindex(). To simultaneously
00301 //                  maximize both index ranges, use:
00302 //
00303 // A.maximize();    Set Lmaxindex() and Rmaxindex() to the largest values
00304 //                  allowed by physically allocated memory and their modes.
00305 //                  Equivalent to:  A.maxindex(A.Lsize + A.Rsize);
00306 //
00307 // A.make_empty();  Set Lmaxindex() and Rmaxindex() and Lminindex() and  
00308 //                  Rminindex() to the values they would have were there to
00309 //                  be no memory allocated for A, so that each maxindex()
00310 //                  will be less than its corresponding minindex().
00311 //
00312 //
00313 // Construction, Memory Allocation and Reallocation:
00314 // ------------------------------------------------ 
00315 // Upon creation a matrix object's data memory will be allocated from the
00316 // heap. The sizes of each dimension (left index and right index) for the
00317 // matrix object are specifiable as constructor parameters. If no values for
00318 // the sizes are given, a square matrix is constructed using the value
00319 // defined by the macro DEFAULT_MATRIX_SIZE for both dimensions. This macro
00320 // will be defined by this header file if it is not already defined. The
00321 // constant member variables Lsize and Rsize are set to the matrix's sizes;
00322 // both will equal 0 if memory allocation fails.
00323 //
00324 // If required, the memory allocation and/or indexing modes for an
00325 // individual matrix object may be adjusted following creation, so a matrix
00326 // object may be created with initial sizes of 0, and then later
00327 // reallocated once the required sizes are known.
00328 //
00329 // Upon destruction, a matrix object will return its memory to the heap.
00330 //
00331 // Note for mode Index_S and (L/R)size: size == 0 should mean that one
00332 // valid index value is available in mode Index_S, namely 0. However, in
00333 // the event of a memory allocation failure, this one index value will
00334 // actually access the same location as that used for index out of range
00335 // operations, and so will not be very useful.  Note that in this case the
00336 // maxindex() value will be -1, and the minindex() value will be +1, so a
00337 // looping construct as described previously will access no values, which
00338 // is the correct action.
00339 //
00340 // A list of the basic constructor forms follows. In this list, *_ means a
00341 // prefix of real_ or complex_. Additionally: n and m are nonnegative int
00342 // sizes for the left and right indexes; t, tl, and tr are index mode
00343 // values of enumerated type v_index_mode and specify the index modes for
00344 // both indexes, the left index, and the right index respectively.
00345 //
00346 //
00347 // *_matrix A;           Construct a square matrix with size given by the
00348 //                       value of DEFAULT_MATRIX_SIZE and index mode Index_1
00349 //                       in each index.  Initialize all data elements to 0.
00350 //
00351 // *_matrix A(n);        Construct a matrix with left and right index sizes
00352 //                       both equal n, and use Index_1 mode for both
00353 //                       indexes. Initialize all data elements to 0.
00354 //
00355 // *_matrix A(n,t);      Construct a matrix with left and right index sizes
00356 //                       both equal n, and use index mode t for both
00357 //                       indexes. Initialize all data elements to 0.
00358 //
00359 // *_matrix A(n,m);      Construct a matrix with left and right index sizes
00360 //                       of n and m, respectively. Use Index_1 for both
00361 //                       indexes. Initialize all data elements to 0.
00362 //
00363 // *_matrix A(n,m,t);    Construct a matrix with left and right index sizes
00364 //                       of n and m, respectively. Use index mode t for
00365 //                       both indexes. Initialize all data elements to 0.
00366 //
00367 // *_matrix A(n,m,tl,tr); Construct a matrix with left and right index sizes
00368 //                       of n and m, respectively. Use index mode tl for
00369 //                       the left index, tr for the right index. Initialize
00370 //                       all data elements to 0.
00371 //
00372 // For all of the above constructors, the valid index range is initialized
00373 // to include all allocated data elements.
00374 //
00375 //
00376 // *_matrix A(B);        Construct a copy of the matrix B, with the same
00377 //                       sizes and index modes as B, and with the same
00378 //                       valid index ranges (maxindex and minindex). Copy
00379 //                       all data from B, even any elements beyond the
00380 //                       valid index ranges.  If A is a complex_matrix, then
00381 //                       B may be either a complex_matrix or a real_matrix
00382 //                       object. If A is a real_matrix, then B must also be
00383 //                       a real_matrix.
00384 //
00385 // *_matrix A(v);        Construct a matrix which is a copy of the vector v.
00386 //                       The matrix will have one column, ie: Rsize == 1,
00387 //                       and will have Rmode == Index_1. The Left indexing
00388 //                       will match the indexing of the vector v, and all
00389 //                       physical elements of v will be copied. Finally,
00390 //                       set Lmaxindex() == v.maxindex(). If A is complex,
00391 //                       v may be either a complex_vector or a real_vector
00392 //                       object. If A is a real_matrix, then v must be a
00393 //                       real_vector.
00394 //
00395 // real_matrix A(D);     Construct a real_matrix which is a copy of the
00396 //                       data matrix in the datafile class object D.
00397 //
00398 // To reallocate the memory or change the indexing modes of an existing
00399 // matrix object, the resize and reallocate member functions are
00400 // provided. When a matrix is reallocated, it copies the maximum amount of
00401 // data from the old A into the new A, given the new index sizes and modes
00402 // of A, and such that each data element keeps its same index locations. If
00403 // data subset control is being used, then the new valid index range will
00404 // match as closely as possible the old valid index range, but all physical
00405 // data will be copied, not just the data in the valid index range. If data
00406 // subset control is not being used (the maxindex and minindex values
00407 // include all allocated memory), then the new maxindex and minindex values
00408 // will include all of the newly allocated memory. The resize() member
00409 // function is useful if you know the resulting index range you want. The
00410 // reallocate() function is a more primitive construct which is called by
00411 // resize(). If A is a matrix object, then:
00412 //
00413 // A.resize(n,m);        Reallocate the memory for A so that its size will
00414 //                       just fit left and right maximum index values of n
00415 //                       and m, respectively.  Keep the current indexing
00416 //                       modes.
00417 //
00418 // A.resize(n);          Reallocate the memory for A so that its size will
00419 //                       just fit left and right maximum index values of n.
00420 //                       Keep the current indexing modes.
00421 //
00422 // A.resize(B);          Reallocate the memory for A so that its index
00423 //                       modes match those of matrix B, and its size will
00424 //                       just fit the valid index ranges of B, as
00425 //                       determined by B's data subset control.
00426 //
00427 // A.reallocate(n);      Reallocate the memory for A to change it into a
00428 //                       matrix with size n for each index.  Keep the
00429 //                       current indexing modes.
00430 //
00431 // A.reallocate(n,m);    Reallocate the memory for A to change it into a
00432 //                       matrix with left and right index sizes n and m,
00433 //                       respectively. Keep the current indexing modes.
00434 //
00435 // A.reallocate(n,m,tl,tr);   Reallocate the memory for A to change its
00436 //                       left index size and mode to n and tl, and the
00437 //                       right index size and mode to m and tr.
00438 //
00439 // In addition to the reallocate member function, the assignment operator
00440 // '=' may result in memory reallocation.  This behavior is described in
00441 // the next section.
00442 //
00443 //
00444 // Assignment and Copying Data:
00445 // ---------------------------
00446 // The following member functions are provided for bulk data transfer from
00447 // one matrix object into another existing object: = and copy.  Both
00448 // functions attempt to preserve the source matrix's data subset control,
00449 // and both set unused elements in the destination matrix to 0.  There is a
00450 // major difference, however, between the two operations: = may reallocate
00451 // memory for the receiving matrix, while copy leaves the sizes and modes of
00452 // the receiving matrix unchanged.  Note that self assignment ( A = A ) and
00453 // self copy ( A.copy(A) ) are not "do nothing" operations.
00454 //
00455 //
00456 // A = B;          If A has insufficient memory to hold all of B's valid
00457 //                 (data subset control) data, or if the index modes of A
00458 //                 differ from those of B, reallocate the memory for A so
00459 //                 that it has the same index modes as B, with sizes just
00460 //                 sufficient to hold all of the valid data elements of B.
00461 //                 Copy all of B's valid data elements into A, and set any
00462 //                 remaining elements of A to 0. Set the data subset control
00463 //                 for A so that its valid index ranges match the valid
00464 //                 index ranges for B.  When finished, A will be a (possibly
00465 //                 larger) copy of the valid data elements of B, with the
00466 //                 same valid index ranges and index modes. Note that = only
00467 //                 copies data within B's currently valid index range, so
00468 //                 data subset control on B will reduce the number of
00469 //                 elements copied.  If A and B are the SAME matrix, just
00470 //                 perform A.clean().
00471 //
00472 // A = D;          Perform the above operator = using the real_matrix data
00473 //                 in datafile object D. A must be a real_matrix. 
00474 //
00475 // A.copy(B);      Copy as many of the valid data elements of B into the
00476 //                 corresponding elements of A as the memory allocation and
00477 //                 indexing modes of A will allow.  In other words, copy
00478 //                 the data elements with indexes in the intersection of
00479 //                 the indexing ranges of A and B.  Only copies data within
00480 //                 B's currently valid index range, so data subset control
00481 //                 on B will reduce the number of elements copied. Ignores
00482 //                 any data subset control previously set for A. Sets the
00483 //                 remaining elements of A to 0, and sets A data subset
00484 //                 control to match as closely as possible B's valid index
00485 //                 range.  If A and B are the SAME matrix, just perform
00486 //                 A.clean().
00487 //
00488 // As with the copy constructor, B may be either a real_matrix or a
00489 // complex_matrix if A is of type complex_matrix; B must be of type
00490 // real_matrix if A is of type real_matrix.  D is of type datafile (defined in
00491 // datafile.h); for A = D, A must be of type real_matrix.
00492 //
00493 //
00494 // Other Member Functions:
00495 // ----------------------
00496 // The remaining member functions defined for matrix objects are:
00497 //
00498 //
00499 // A.fill(s);      Fill all elements in the valid index range of A with the
00500 //                 scalar value s. The fill is subject to data subset
00501 //                 control.
00502 //
00503 // A = s;          For scalar s, the same as A.fill(s). s may not be
00504 //                 Complex if A is of type real_matrix.
00505 //
00506 // A.fillall(s);   Fill all physically allocated elements of A with the
00507 //                 scalar value s. Ignores data subset control.
00508 //
00509 // A.fillrow(n,v); Fill row n of A using the contents of vector v. Only
00510 //                 copies data into the valid index range of A from the
00511 //                 corresponding elements in the valid index range of v;
00512 //                 any valid elements of A without a corresponding valid
00513 //                 element in v are set to 0.  If A is real, so must be v.
00514 //
00515 // A.fillcol(n,v); Fill column n of A using the contents of vector v. Only
00516 //                 copies data into the valid index range of A from the
00517 //                 corresponding elements in the valid index range of v;
00518 //                 any valid elements of A without a corresponding valid
00519 //                 element in v are set to 0.  If A is real, so must be v.
00520 //
00521 // A.clean();      Reset to 0 all elements of A beyond the valid index
00522 //                 range as determined by data subset control.
00523 //
00524 // A.diagonal(s);  Set A.get(i,i) = s; for all valid diagonal elements of A.
00525 //                 Sets all other elements of A to 0. Uses data subset
00526 //                 control to determine the valid diagonal elements of A.
00527 //
00528 // A.rowswap(n,m); Swap rows n and m of A. Actually performs the swap by
00529 //                 exchanging the values of the pointers stored in A[n]
00530 //                 and A[m], so the execution is very fast.  If either
00531 //                 index is outside the valid left index range, then fills
00532 //                 the other row with zeroes.  If both are outside the
00533 //                 valid left index range, then has no effect.
00534 //
00535 // A.apply(f);     Apply the scalar function f to each valid element of
00536 //                 A. f() will be called once for each valid element of A.
00537 //                 f must be a function taking either:
00538 //                  (1) a single numeric argument of the same type as the
00539 //                      data elements of A: f(double x) or f(Complex x).
00540 //                  (2) a numeric argument and and two int arguments:
00541 //                      f(double x,int i,int j) or f(Complex x,int i,int j)
00542 //                 f() must return a single numeric value of the same type
00543 //                 as the data elements of A. As apply() iterates through
00544 //                 the vector elements, it calls f() with the value of each
00545 //                 element and, if f() is of type (2) above, the value of
00546 //                 the left index and the right index of the element.
00547 //                 Equivalent to:
00548 //
00549 //                 for (int i = A.Lminindex(); i <= A.Lmaxindex(); ++i)
00550 //                   for (int j = A.Rminindex(); j <= A.Rmaxindex(); ++j)
00551 //                     A[i][j] = f(A[i][j]);
00552 //                       /* OR */
00553 //                     A[i][j] = f(A[i][j], i, j);
00554 //
00555 //
00556 // Matrix Arithmetic Member Functions:
00557 // ----------------------------------
00558 //
00559 //
00560 // A += s;  A -= s;  A *= s;  A /= s;
00561 //                 Perform the indicated assignment operator operation to
00562 //                 each element of A within its valid index range, using
00563 //                 data subset control.  The scalar s may not be Complex if
00564 //                 A is a real_matrix.
00565 //
00566 // A += B; A -= B;  First perform A.clean(), then perform the indicated
00567 //                 assignment operation as a vector addition or subtraction
00568 //                 using only valid elements of B (data subset control on
00569 //                 B).  Increases the data subset range of A if necessary
00570 //                 so that its valid index range includes the valid index
00571 //                 range of B as a subset, unless limited by the physical
00572 //                 capacity of A. Does not reallocate any memory for A or
00573 //                 change A's index modes. B must be a real_matrix if A is
00574 //                 a real_matrix.
00575 //
00576 // A.add(B,C);     sets A = B + C (matrix sum), where zeroes are padded to
00577 //                 rows and or columns of B and C to make them have equal
00578 //                 index ranges for the purposes of the sum (B and C are
00579 //                 not actually modified).  Only includes elements in the
00580 //                 valid index ranges of B and C.  If A is not originally
00581 //                 large enough to hold all elements of the result, it is
00582 //                 reallocated. B and C must both be real_matrix if A is a
00583 //                 real_matrix.
00584 //
00585 // A.sub(B,C);     sets A = B - C (matrix), otherwise like A.add(B,C).
00586 //
00587 //
00588 // A.real(B);      sets each element of A equal to the real part of the
00589 //                 corresponding element of complex_matrix B. Performs
00590 //                 A.resize(B) first, so that it is just big enough to
00591 //                 hold the valid elements of B.  A may be either a
00592 //                 real_matrix or a complex_matrix; B must be a complex_
00593 //                 matrix. (The resize is not performed if B is the same
00594 //                 matrix as A)
00595 //
00596 // A.imaginary(B); sets each element of A equal to the imaginary part of
00597 //                 the corresponding element of complex_matrix B. Performs
00598 //                 A.resize(B) first, so that it is just big enough to
00599 //                 hold the valid elements of B.  A may be either a
00600 //                 real_matrix or a complex_matrix; B must be a complex_
00601 //                 matrix. (The resize is not performed if B is the same
00602 //                 matrix as A)
00603 //
00604 //
00605 // Manipulating Matrix Rows as Vector Objects
00606 // -----------------------------------------
00607 // Because the *_vector classes include an alias constructor, and because
00608 // each row of a matrix object is stored as a contiguous block of memory, it
00609 // is easy to manipulate any row of a matrix as a true vector object.  Some
00610 // examples follow (you must use the same data type for both the matrix and
00611 // vector objects, ie: both of type real or type complex):
00612 //
00613 //
00614 // complex_matrix A(10,7,Index_S,Index_1);
00615 //           // each row of A is like a complex_vector(7,Index_1)
00616 //
00617 // complex_vector y(complex_vector(A[3], A.Rsize, A.Rmode));
00618 //           // y is an independent copy of the data in row 3 of A
00619 //
00620 // complex_vector x(A[3], A.Rsize, A.Rmode);
00621 //           // x aliases row 3 of A, with the same size and index mode.
00622 //           // any changes to elements of x will result in changes to
00623 //           // A, such as:
00624 //
00625 // x.copy(v);   // copy elements of v into x (and row 3 of A)
00626 //
00627 // x.copy(y);   // restores x (and row 3 of A) to its original values
00628 //
00629 //            
00630 //
00631 // Matrix Output/Display Functions:
00632 // ------------------------------
00633 //
00634 // ostream << A;   send the contents of matrix A to the output stream ostream,
00635 //                 using "ostream << v" to output each row in the valid
00636 //                 index range of A as a vector v.  Multiple valid rows of
00637 //                 A are separated by the C++ string whose value is controlled
00638 //                 by the static member function out_separator(); the default
00639 //                 value is a single newline character '\n'.  The value of
00640 //                 ostream.width() is used to set the field width for each
00641 //                 row output; it is not used for the field width of the row
00642 //                 separator string. Note that << is not a member function of
00643 //                 any class. See vector.h for details on how each row of
00644 //                 output is formatted.
00645 //
00646 // A.show(ostream); output equivalent to:  ostream << endl << A << endl;
00647 //
00648 // A.show();       equivalent to A.show(cout);
00649 //
00650 // real_matrix::out_separator(s); or: complex_matrix::out_separator(s);
00651 //                 either function sets the output separator string for
00652 //                 both real_matrix and complex_matrix output. s may be a
00653 //                 C++ string, a C-style string, or a single char. The
00654 //                 function returns the previous value of the separator as
00655 //                 a C++ string. If no argument is specified, then the
00656 //                 function simply returns the current separator value. The
00657 //                 default value is a single newline. If no output separator
00658 //                 character is desired, use a null string "" for s.
00659 //
00660 // ************************************************************************
00661 
00662 #ifndef MATRIX_H
00663 #define MATRIX_H
00664 
00665 #ifndef DEFAULT_MATRIX_SIZE
00666 #define DEFAULT_MATRIX_SIZE   16   /* a default matrix size */
00667 #endif  /* DEFAULT_MATRIX_SIZE */
00668 
00669 #ifndef V_INDEX_MODE_DEFINED
00670 #define  V_INDEX_MODE_DEFINED
00671 enum v_index_mode { Index_C, Index_1, Index_S }; // same as in vectors.h
00672 #endif /* V_INDEX_MODE_DEFINED */
00673 
00674 #include "SIScmplx.h"
00675 #include <string>
00676 
00677 class real_vector;
00678 class complex_vector;
00679 class complex_matrix;
00680 class datafile;
00681 class ostream;
00682 
00683 //-------------------------------------------------------------------------
00684 class real_matrix {
00685 
00686 public:
00687 
00688   // data (all are read-only aliases of private data members):
00689 
00690   const int     &Lsize;             // the size of the left index
00691   const int     &Rsize;             // the size of the right index
00692   const v_index_mode   &Lmode;      // the indexing mode for the left index
00693   const v_index_mode   &Rmode;      // the indexing mode for the right index
00694 
00695 
00696   // constructors:
00697 
00698   explicit real_matrix(const int n = DEFAULT_MATRIX_SIZE)
00699     : Lsize(internal_Lsize), Rsize(internal_Rsize), 
00700       Lmode(internal_Lmode), Rmode(internal_Rmode)
00701   { construct(n, n, Index_1, Index_1); constfill(0.0); }
00702 
00703   real_matrix(const int n, const v_index_mode t)
00704     : Lsize(internal_Lsize), Rsize(internal_Rsize), 
00705       Lmode(internal_Lmode), Rmode(internal_Rmode)
00706   { construct(n, n, t, t); constfill(0.0); }
00707 
00708   real_matrix(const int n, const int m)
00709     : Lsize(internal_Lsize), Rsize(internal_Rsize), 
00710       Lmode(internal_Lmode), Rmode(internal_Rmode)
00711   { construct(n, m, Index_1, Index_1); constfill(0.0); }
00712 
00713   real_matrix(const int n, const int m, const v_index_mode t)
00714     : Lsize(internal_Lsize), Rsize(internal_Rsize), 
00715       Lmode(internal_Lmode), Rmode(internal_Rmode)
00716   { construct(n, m, t, t); constfill(0.0); }
00717 
00718   real_matrix(const int n, const int m, 
00719              const v_index_mode tl, const v_index_mode tr)
00720     : Lsize(internal_Lsize), Rsize(internal_Rsize), 
00721       Lmode(internal_Lmode), Rmode(internal_Rmode)
00722   { construct(n, m, tl, tr); constfill(0.0); }
00723 
00724   real_matrix(const real_matrix & B);
00725   real_matrix(const real_vector & v);
00726   real_matrix(const datafile & D);
00727 
00728 
00729   // destructor:
00730 
00731   ~real_matrix(void)
00732   { delete [] delete_pointer_data; delete [] delete_pointer_rows; }
00733 
00734 
00735   // data subset contol:
00736 
00737   inline int Lminindex(void) const  { return Lminindexvalue; }
00738   inline int Lmaxindex(void) const  { return Lmaxindexvalue; }
00739   int Lmaxindex(const int n);
00740   inline int Rminindex(void) const  { return Rminindexvalue; }
00741   inline int Rmaxindex(void) const  { return Rmaxindexvalue; }
00742   int Rmaxindex(const int n);
00743   inline int minindex(void) const
00744   {
00745     return (Lminindexvalue > Rminindexvalue) ?
00746       Lminindexvalue : Rminindexvalue;
00747   }
00748   inline int maxindex(void) const
00749   {
00750     return (Lmaxindexvalue < Rmaxindexvalue) ?
00751       Lmaxindexvalue : Rmaxindexvalue;
00752   }
00753   inline int maxindex(int n)
00754   { Lmaxindex(n); Rmaxindex(n); return maxindex(); }
00755   inline int maximize(void)
00756   { return maxindex(Lsize+Rsize); }
00757   inline int is_empty() const
00758   { return (Lmaxindex() < Lminindex())||(Rmaxindex() < Rminindex());}
00759   real_matrix & make_empty();
00760 
00761 
00762   // data access:
00763 
00764   inline double read(const int i, const int j) const
00765   { 
00766     if((i > Lmaxindex())||(j > Rmaxindex())||
00767        (i < Lminindex())||(j < Rminindex())  )
00768       return 0.0;
00769     else 
00770       return data[i][j];
00771   }
00772 
00773   inline double & get(const int i, const int j)
00774   { 
00775     if((i > Lmaxindex())||(j > Rmaxindex())||
00776        (i < Lminindex())||(j < Rminindex())  )
00777       return (trash = 0.0);
00778     else 
00779       return data[i][j];
00780   }
00781 
00782   inline const double & get(const int i, const int j) const
00783   { 
00784     if((i > Lmaxindex())||(j > Rmaxindex())||
00785        (i < Lminindex())||(j < Rminindex())  )
00786       return (trash = 0.0);
00787     else 
00788       return data[i][j];
00789   }
00790 
00791   inline double *const & operator [] (const int i)
00792   { return data[i]; }
00793 
00794   inline const double *const & operator [] (const int i) const
00795   {
00796     // These extra steps are necessary to work around a compiler bug
00797     // in gcc version 2.96 20000731 (Red Hat Linux 7.1 2.96-81)
00798     // return data[i];
00799     double const * const * p = data + i;
00800     return *p;
00801   }
00802 
00803 
00804   // change the index modes:
00805 
00806   real_matrix & reindex(const v_index_mode, const v_index_mode);
00807 
00808 
00809   // reallocation:
00810 
00811   real_matrix & reallocate(const int n, const int m,
00812                           const v_index_mode tl, const v_index_mode tr);
00813   inline real_matrix & reallocate(const int n)  
00814   { return reallocate(n, n, Lmode, Rmode); }
00815   inline real_matrix & reallocate(const int n, const int m)
00816   { return reallocate(n, m, Lmode, Rmode); }
00817   inline real_matrix & resize(const int Lmax, const int Rmax)
00818   {
00819     int Lsize = (Lmode == Index_C) ? Lmax+1: Lmax;
00820     int Rsize = (Rmode == Index_C) ? Rmax+1: Rmax;
00821     return reallocate(Lsize, Rsize);
00822   }
00823   inline real_matrix & resize(const int Max) { return resize(Max, Max); }
00824   inline real_matrix & resize(const real_matrix & B)
00825   {
00826     int Lsize = (B.Lmode == Index_C) ? B.Lmaxindex()+1: B.Lmaxindex();
00827     int Rsize = (B.Rmode == Index_C) ? B.Rmaxindex()+1: B.Rmaxindex();
00828     return reallocate(Lsize, Rsize, B.Lmode, B.Rmode);
00829   }
00830   real_matrix & resize(const complex_matrix & B);
00831 
00832 
00833   // copy and assignment:
00834 
00835   real_matrix & copy(const real_matrix & B);
00836   real_matrix & operator = (const real_matrix & B);
00837   real_matrix & operator = (const datafile & D);
00838 
00839 
00840   // other member functions:
00841 
00842   real_matrix & clean(void);
00843   inline real_matrix & fill(const double s) { constfill(s); return *this; }
00844   inline real_matrix & operator = (const double s) { return fill(s); }
00845   real_matrix & fillall(const double s);
00846   real_matrix & fillrow(const int n, const real_vector & v);
00847   real_matrix & fillcol(const int n, const real_vector & v);
00848   real_matrix & diagonal(const double s);
00849   real_matrix & rowswap(const int n, const int m);
00850   real_matrix & apply(double (*f)(double));
00851   real_matrix & apply(double (*f)(const double &));
00852   real_matrix & apply(double (*f)(double, int, int));
00853   real_matrix & apply(double (*f)(const double &, int, int));
00854 
00855   // matrix arithmetic member functions:
00856 
00857   real_matrix & operator += (const double s);
00858   real_matrix & operator -= (const double s);
00859   real_matrix & operator *= (const double s);
00860   real_matrix & operator /= (const double s);
00861   real_matrix & operator += (const real_matrix & B);
00862   real_matrix & operator -= (const real_matrix & B);
00863 
00864   real_matrix & add(const real_matrix & B, const real_matrix & C);
00865   real_matrix & sub(const real_matrix & B, const real_matrix & C);
00866   real_matrix & real(const complex_matrix & B);
00867   real_matrix & imaginary(const complex_matrix & B);
00868 
00869   // matrix output member functions:
00870 
00871   real_matrix & show(ostream &);
00872   real_matrix & show(void);
00873   const real_matrix & show(ostream &) const;
00874   const real_matrix & show(void) const;
00875   static string out_separator(); // return the current output separator
00876   static string out_separator(const string &);
00877   static string out_separator(const char * const);
00878   static string out_separator(const char);
00879 
00880 
00881 private:
00882 
00883   int            internal_Lsize;    // aliased by Lsize
00884   int            internal_Rsize;    // aliased by Rsize
00885   v_index_mode   internal_Lmode;    // aliased by Lmode
00886   v_index_mode   internal_Rmode;    // aliased by Rmode
00887   int            Lmaxindexvalue;    // the left index upper limit
00888   int            Lminindexvalue;    // the left index lower limit
00889   int            Rmaxindexvalue;    // the right index upper limit
00890   int            Rminindexvalue;    // the right index lower limit
00891   double     * * data;              // points to pointer to [0][0]
00892   double     * * delete_pointer_data; // used by destructor to delete memory
00893   double       * delete_pointer_rows; // used by destructor to delete memory
00894   mutable double trash;             // Where index-out-of-bounds wind up
00895   double       * trashptr;          // Will point to trash ico alloc failure
00896 
00897   // these functions are called by other member functions:
00898   void construct(const int n, const int m,
00899                  const v_index_mode tl,
00900                  const v_index_mode tr);  //allocate memory
00901   void constfill(const double f); // fill with a constant value
00902 
00903 };  // class real_matrix 
00904 
00905 ostream & operator << (ostream &, const real_matrix &);
00906 
00907 //-------------------------------------------------------------------------
00908 
00909 class complex_matrix {
00910 
00911 public:
00912 
00913   // data (all are read-only aliases of private data members):
00914 
00915   const int     &Lsize;             // the size of the left index
00916   const int     &Rsize;             // the size of the right index
00917   const v_index_mode   &Lmode;      // the indexing mode for the left index
00918   const v_index_mode   &Rmode;      // the indexing mode for the right index
00919 
00920 
00921   // constructors:
00922 
00923   explicit complex_matrix(const int n = DEFAULT_MATRIX_SIZE)
00924     : Lsize(internal_Lsize), Rsize(internal_Rsize), 
00925       Lmode(internal_Lmode), Rmode(internal_Rmode)
00926   { construct(n, n, Index_1, Index_1); constfill(0.0); }
00927 
00928   complex_matrix(const int n, const v_index_mode t)
00929     : Lsize(internal_Lsize), Rsize(internal_Rsize), 
00930       Lmode(internal_Lmode), Rmode(internal_Rmode)
00931   { construct(n, n, t, t); constfill(0.0); }
00932 
00933   complex_matrix(const int n, const int m)
00934     : Lsize(internal_Lsize), Rsize(internal_Rsize), 
00935       Lmode(internal_Lmode), Rmode(internal_Rmode)
00936   { construct(n, m, Index_1, Index_1); constfill(0.0); }
00937 
00938   complex_matrix(const int n, const int m, const v_index_mode t)
00939     : Lsize(internal_Lsize), Rsize(internal_Rsize), 
00940       Lmode(internal_Lmode), Rmode(internal_Rmode)
00941   { construct(n, m, t, t); constfill(0.0); }
00942 
00943   complex_matrix(const int n, const int m, 
00944              const v_index_mode tl, const v_index_mode tr)
00945     : Lsize(internal_Lsize), Rsize(internal_Rsize), 
00946       Lmode(internal_Lmode), Rmode(internal_Rmode)
00947   { construct(n, m, tl, tr); constfill(0.0); }
00948 
00949   complex_matrix(const complex_matrix & B);
00950   complex_matrix(const real_matrix & B);
00951   complex_matrix(const real_vector & v);
00952   complex_matrix(const complex_vector & v);
00953 
00954   // destructor:
00955 
00956   ~complex_matrix(void)
00957   { delete [] delete_pointer_data; delete [] delete_pointer_rows; }
00958 
00959 
00960   // data subset contol:
00961 
00962   inline int Lminindex(void) const  { return Lminindexvalue; }
00963   inline int Lmaxindex(void) const  { return Lmaxindexvalue; }
00964   int Lmaxindex(const int n);
00965   inline int Rminindex(void) const  { return Rminindexvalue; }
00966   inline int Rmaxindex(void) const  { return Rmaxindexvalue; }
00967   int Rmaxindex(const int n);
00968   inline int minindex(void) const
00969   {
00970     return (Lminindexvalue > Rminindexvalue) ?
00971       Lminindexvalue : Rminindexvalue;
00972   }
00973   inline int maxindex(void) const
00974   {
00975     return (Lmaxindexvalue < Rmaxindexvalue) ?
00976       Lmaxindexvalue : Rmaxindexvalue;
00977   }
00978   inline int maxindex(int n)
00979   { Lmaxindex(n); Rmaxindex(n); return maxindex(); }
00980   inline int maximize(void)
00981   { return maxindex(Lsize+Rsize); }
00982   inline int is_empty() const
00983   { return (Lmaxindex() < Lminindex())||(Rmaxindex() < Rminindex());}
00984   complex_matrix & make_empty();
00985 
00986 
00987   // data access:
00988 
00989   inline Complex read(const int i, const int j) const
00990   { 
00991     if((i > Lmaxindex())||(j > Rmaxindex())||
00992        (i < Lminindex())||(j < Rminindex())  )
00993       return 0.0;
00994     else 
00995       return data[i][j];
00996   }
00997 
00998   inline Complex & get(const int i, const int j)
00999   { 
01000     if((i > Lmaxindex())||(j > Rmaxindex())||
01001        (i < Lminindex())||(j < Rminindex())  )
01002       return (trash = 0.0);
01003     else 
01004       return data[i][j];
01005   }
01006 
01007   inline const Complex & get(const int i, const int j) const
01008   { 
01009     if((i > Lmaxindex())||(j > Rmaxindex())||
01010        (i < Lminindex())||(j < Rminindex())  )
01011       return (trash = 0.0);
01012     else 
01013       return data[i][j];
01014   }
01015 
01016   inline Complex *const & operator [] (const int i)
01017   { return data[i]; }
01018 
01019   inline const Complex *const & operator [] (const int i) const
01020   {
01021     // These extra steps are necessary to work around a compiler bug
01022     // in gcc version 2.96 20000731 (Red Hat Linux 7.1 2.96-81)
01023     // return data[i];
01024     Complex const * const * p = data + i;
01025     return *p;
01026   }
01027 
01028 
01029   // change the index modes:
01030 
01031   complex_matrix & reindex(const v_index_mode, const v_index_mode);
01032 
01033 
01034   // reallocation:
01035 
01036   complex_matrix & reallocate(const int n, const int m,
01037                              const v_index_mode tl, const v_index_mode tr);
01038   inline complex_matrix & reallocate(const int n)  
01039   { return reallocate(n, n, Lmode, Rmode); }
01040   inline complex_matrix & reallocate(const int n, const int m)
01041   { return reallocate(n, m, Lmode, Rmode); }
01042   inline complex_matrix & resize(const int Lmax, const int Rmax)
01043   {
01044     int Lsize = (Lmode == Index_C) ? Lmax+1: Lmax;
01045     int Rsize = (Rmode == Index_C) ? Rmax+1: Rmax;
01046     return reallocate(Lsize, Rsize);
01047   }
01048   inline complex_matrix & resize(const int Max) 
01049   { return resize(Max, Max); }
01050   inline complex_matrix & resize(const complex_matrix & B)
01051   {
01052     int Lsize = (B.Lmode == Index_C) ? B.Lmaxindex()+1: B.Lmaxindex();
01053     int Rsize = (B.Rmode == Index_C) ? B.Rmaxindex()+1: B.Rmaxindex();
01054     return reallocate(Lsize, Rsize, B.Lmode, B.Rmode);
01055   }
01056   inline complex_matrix & resize(const real_matrix & B)
01057   {
01058     int Lsize = (B.Lmode == Index_C) ? B.Lmaxindex()+1: B.Lmaxindex();
01059     int Rsize = (B.Rmode == Index_C) ? B.Rmaxindex()+1: B.Rmaxindex();
01060     return reallocate(Lsize, Rsize, B.Lmode, B.Rmode);
01061   }
01062 
01063   // copy and assignment:
01064 
01065   complex_matrix & copy(const complex_matrix & B);
01066   complex_matrix & copy(const real_matrix & B);
01067   complex_matrix & operator = (const complex_matrix & B);
01068   complex_matrix & operator = (const real_matrix & B);
01069 
01070 
01071   // other member functions:
01072 
01073   complex_matrix & clean(void);
01074   inline complex_matrix & fill(const Complex s) { constfill(s); return *this; }
01075   inline complex_matrix & operator = (const Complex s) { return fill(s); }
01076   inline complex_matrix & operator = (const double s) 
01077   { return fill(Complex(s)); }
01078   complex_matrix & fillall(const Complex s);
01079   complex_matrix & fillrow(const int n, const real_vector & v);
01080   complex_matrix & fillrow(const int n, const complex_vector & v);
01081   complex_matrix & fillcol(const int n, const real_vector & v);
01082   complex_matrix & fillcol(const int n, const complex_vector & v);
01083   complex_matrix & diagonal(const Complex s);
01084   complex_matrix & rowswap(const int n, const int m);
01085   complex_matrix & apply(Complex (*f)(Complex));
01086   complex_matrix & apply(Complex (*f)(const Complex &));
01087   complex_matrix & apply(Complex (*f)(Complex, int, int));
01088   complex_matrix & apply(Complex (*f)(const Complex &, int, int));
01089 
01090   // matrix arithmetic member functions:
01091 
01092   complex_matrix & operator += (const Complex s);
01093   complex_matrix & operator -= (const Complex s);
01094   complex_matrix & operator *= (const Complex s);
01095   complex_matrix & operator /= (const Complex s);
01096   complex_matrix & operator += (const complex_matrix & B);
01097   complex_matrix & operator -= (const complex_matrix & B);
01098   complex_matrix & operator += (const real_matrix & B);
01099   complex_matrix & operator -= (const real_matrix & B);
01100 
01101   complex_matrix & add(const complex_matrix & B, const complex_matrix & C);
01102   complex_matrix & add(const complex_matrix & B, const real_matrix & C);
01103   inline complex_matrix & add(const real_matrix & B, const complex_matrix & C)
01104   { return add(C,B); }
01105   complex_matrix & add(const real_matrix & B, const real_matrix & C);
01106   complex_matrix & sub(const complex_matrix & B, const complex_matrix & C);
01107   complex_matrix & sub(const complex_matrix & B, const real_matrix & C);
01108   complex_matrix & sub(const real_matrix & B, const complex_matrix & C);
01109   complex_matrix & sub(const real_matrix & B, const real_matrix & C);
01110   complex_matrix & real(const complex_matrix & B);
01111   complex_matrix & imaginary(const complex_matrix & B);
01112 
01113   // matrix output member functions:
01114 
01115   complex_matrix & show(ostream &);
01116   complex_matrix & show(void);
01117   const complex_matrix & show(ostream &) const;
01118   const complex_matrix & show(void) const;
01119   static string out_separator(); // return the current output separator
01120   static string out_separator(const string &);
01121   static string out_separator(const char * const);
01122   static string out_separator(const char);
01123 
01124 
01125 private:
01126 
01127   int            internal_Lsize;     // aliased by Lsize
01128   int            internal_Rsize;     // aliased by Rsize
01129   v_index_mode   internal_Lmode;     // aliased by Lmode
01130   v_index_mode   internal_Rmode;     // aliased by Rmode
01131   int            Lmaxindexvalue;     // the left index upper limit
01132   int            Lminindexvalue;     // the left index lower limit
01133   int            Rmaxindexvalue;     // the right index upper limit
01134   int            Rminindexvalue;     // the right index lower limit
01135   Complex     * * data;              // points to pointer to [0][0]
01136   Complex     * * delete_pointer_data; // used by destructor to delete memory
01137   Complex       * delete_pointer_rows; // used by destructor to delete memory
01138   mutable Complex trash;             // Where index-out-of-bounds wind up
01139   Complex       * trashptr;          // Will point to trash ico alloc failure
01140 
01141   // these functions are called by other member functions:
01142   void construct(const int n, const int m,
01143                  const v_index_mode tl,
01144                  const v_index_mode tr);  //allocate memory
01145   void constfill(const Complex f); // fill with a constant value
01146 
01147 };  // class complex_matrix 
01148 
01149 ostream & operator << (ostream &, const complex_matrix &);
01150 
01151 //-------------------------------------------------------------------------
01152 
01153 typedef real_matrix real_table;
01154 typedef complex_matrix complex_table;
01155 
01156 #endif  /* MATRIX_H */

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