sparse-xdiv.cc

Go to the documentation of this file.
00001 /*
00002 
00003 Copyright (C) 2004-2012 David Bateman
00004 Copyright (C) 1998-2004 Andy Adler
00005 
00006 This file is part of Octave.
00007 
00008 Octave is free software; you can redistribute it and/or modify it
00009 under the terms of the GNU General Public License as published by the
00010 Free Software Foundation; either version 3 of the License, or (at your
00011 option) any later version.
00012 
00013 Octave is distributed in the hope that it will be useful, but WITHOUT
00014 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00015 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00016 for more details.
00017 
00018 You should have received a copy of the GNU General Public License
00019 along with Octave; see the file COPYING.  If not, see
00020 <http://www.gnu.org/licenses/>.
00021 
00022 */
00023 
00024 #ifdef HAVE_CONFIG_H
00025 #include <config.h>
00026 #endif
00027 
00028 #include <cassert>
00029 
00030 #include "Array-util.h"
00031 #include "oct-cmplx.h"
00032 #include "quit.h"
00033 #include "error.h"
00034 #include "lo-ieee.h"
00035 
00036 #include "dSparse.h"
00037 #include "dDiagMatrix.h"
00038 #include "CSparse.h"
00039 #include "CDiagMatrix.h"
00040 #include "oct-spparms.h"
00041 #include "sparse-xdiv.h"
00042 
00043 static void
00044 solve_singularity_warning (double rcond)
00045 {
00046   warning ("matrix singular to machine precision, rcond = %g", rcond);
00047   warning ("attempting to find minimum norm solution");
00048 }
00049 
00050 template <class T1, class T2>
00051 bool
00052 mx_leftdiv_conform (const T1& a, const T2& b)
00053 {
00054   octave_idx_type a_nr = a.rows ();
00055   octave_idx_type b_nr = b.rows ();
00056 
00057   if (a_nr != b_nr)
00058     {
00059       octave_idx_type a_nc = a.cols ();
00060       octave_idx_type b_nc = b.cols ();
00061 
00062       gripe_nonconformant ("operator \\", a_nr, a_nc, b_nr, b_nc);
00063       return false;
00064     }
00065 
00066   return true;
00067 }
00068 
00069 #define INSTANTIATE_MX_LEFTDIV_CONFORM(T1, T2) \
00070   template bool mx_leftdiv_conform (const T1&, const T2&)
00071 
00072 INSTANTIATE_MX_LEFTDIV_CONFORM (SparseMatrix, SparseMatrix);
00073 INSTANTIATE_MX_LEFTDIV_CONFORM (SparseMatrix, SparseComplexMatrix);
00074 INSTANTIATE_MX_LEFTDIV_CONFORM (SparseComplexMatrix, SparseMatrix);
00075 INSTANTIATE_MX_LEFTDIV_CONFORM (SparseComplexMatrix, SparseComplexMatrix);
00076 INSTANTIATE_MX_LEFTDIV_CONFORM (SparseMatrix, Matrix);
00077 INSTANTIATE_MX_LEFTDIV_CONFORM (SparseMatrix, ComplexMatrix);
00078 INSTANTIATE_MX_LEFTDIV_CONFORM (SparseComplexMatrix, Matrix);
00079 INSTANTIATE_MX_LEFTDIV_CONFORM (SparseComplexMatrix, ComplexMatrix);
00080 INSTANTIATE_MX_LEFTDIV_CONFORM (DiagMatrix, SparseMatrix);
00081 INSTANTIATE_MX_LEFTDIV_CONFORM (DiagMatrix, SparseComplexMatrix);
00082 INSTANTIATE_MX_LEFTDIV_CONFORM (ComplexDiagMatrix, SparseMatrix);
00083 INSTANTIATE_MX_LEFTDIV_CONFORM (ComplexDiagMatrix, SparseComplexMatrix);
00084 
00085 template <class T1, class T2>
00086 bool
00087 mx_div_conform (const T1& a, const T2& b)
00088 {
00089   octave_idx_type a_nc = a.cols ();
00090   octave_idx_type b_nc = b.cols ();
00091 
00092   if (a_nc != b_nc)
00093     {
00094       octave_idx_type a_nr = a.rows ();
00095       octave_idx_type b_nr = b.rows ();
00096 
00097       gripe_nonconformant ("operator /", a_nr, a_nc, b_nr, b_nc);
00098       return false;
00099     }
00100 
00101   return true;
00102 }
00103 
00104 #define INSTANTIATE_MX_DIV_CONFORM(T1, T2) \
00105   template bool mx_div_conform (const T1&, const T2&)
00106 
00107 INSTANTIATE_MX_DIV_CONFORM (SparseMatrix, SparseMatrix);
00108 INSTANTIATE_MX_DIV_CONFORM (SparseMatrix, SparseComplexMatrix);
00109 INSTANTIATE_MX_DIV_CONFORM (SparseComplexMatrix, SparseMatrix);
00110 INSTANTIATE_MX_DIV_CONFORM (SparseComplexMatrix, SparseComplexMatrix);
00111 INSTANTIATE_MX_DIV_CONFORM (Matrix, SparseMatrix);
00112 INSTANTIATE_MX_DIV_CONFORM (Matrix, SparseComplexMatrix);
00113 INSTANTIATE_MX_DIV_CONFORM (ComplexMatrix, SparseMatrix);
00114 INSTANTIATE_MX_DIV_CONFORM (ComplexMatrix, SparseComplexMatrix);
00115 INSTANTIATE_MX_DIV_CONFORM (SparseMatrix, DiagMatrix);
00116 INSTANTIATE_MX_DIV_CONFORM (SparseMatrix, ComplexDiagMatrix);
00117 INSTANTIATE_MX_DIV_CONFORM (SparseComplexMatrix, DiagMatrix);
00118 INSTANTIATE_MX_DIV_CONFORM (SparseComplexMatrix, ComplexDiagMatrix);
00119 
00120 // Right division functions.  X / Y = X * inv(Y) = (inv (Y') * X')'
00121 //
00122 //                  Y / X:   m   cm   sm  scm
00123 //                   +--   +---+----+----+----+
00124 //   sparse matrix         | 1 |  3 |  5 |  7 |
00125 //                         +---+----+----+----+
00126 //   sparse complex_matrix | 2 |  4 |  6 |  8 |
00127 //                         +---+----+----+----+
00128 //   diagonal matrix                |  9 | 11 |
00129 //                                  +----+----+
00130 //   complex diag. matrix           | 10 | 12 |
00131 //                                  +----+----+
00132 
00133 // -*- 1 -*-
00134 Matrix
00135 xdiv (const Matrix& a, const SparseMatrix& b, MatrixType &typ)
00136 {
00137   if (! mx_div_conform (a, b))
00138     return Matrix ();
00139 
00140   Matrix atmp = a.transpose ();
00141   SparseMatrix btmp = b.transpose ();
00142   MatrixType btyp = typ.transpose ();
00143 
00144   octave_idx_type info;
00145   double rcond = 0.0;
00146   Matrix result = btmp.solve (btyp, atmp, info, rcond,
00147                               solve_singularity_warning);
00148 
00149   typ = btyp.transpose ();
00150   return result.transpose ();
00151 }
00152 
00153 // -*- 2 -*-
00154 ComplexMatrix
00155 xdiv (const Matrix& a, const SparseComplexMatrix& b, MatrixType &typ)
00156 {
00157   if (! mx_div_conform (a, b))
00158     return ComplexMatrix ();
00159 
00160   Matrix atmp = a.transpose ();
00161   SparseComplexMatrix btmp = b.hermitian ();
00162   MatrixType btyp = typ.transpose ();
00163 
00164   octave_idx_type info;
00165   double rcond = 0.0;
00166   ComplexMatrix result
00167     = btmp.solve (btyp, atmp, info, rcond, solve_singularity_warning);
00168 
00169   typ = btyp.transpose ();
00170   return result.hermitian ();
00171 }
00172 
00173 // -*- 3 -*-
00174 ComplexMatrix
00175 xdiv (const ComplexMatrix& a, const SparseMatrix& b, MatrixType &typ)
00176 {
00177   if (! mx_div_conform (a, b))
00178     return ComplexMatrix ();
00179 
00180   ComplexMatrix atmp = a.hermitian ();
00181   SparseMatrix btmp = b.transpose ();
00182   MatrixType btyp = typ.transpose ();
00183 
00184   octave_idx_type info;
00185   double rcond = 0.0;
00186   ComplexMatrix result
00187     = btmp.solve (btyp, atmp, info, rcond, solve_singularity_warning);
00188 
00189   typ = btyp.transpose ();
00190   return result.hermitian ();
00191 }
00192 
00193 // -*- 4 -*-
00194 ComplexMatrix
00195 xdiv (const ComplexMatrix& a, const SparseComplexMatrix& b, MatrixType &typ)
00196 {
00197   if (! mx_div_conform (a, b))
00198     return ComplexMatrix ();
00199 
00200   ComplexMatrix atmp = a.hermitian ();
00201   SparseComplexMatrix btmp = b.hermitian ();
00202   MatrixType btyp = typ.transpose ();
00203 
00204   octave_idx_type info;
00205   double rcond = 0.0;
00206   ComplexMatrix result
00207     = btmp.solve (btyp, atmp, info, rcond, solve_singularity_warning);
00208 
00209   typ = btyp.transpose ();
00210   return result.hermitian ();
00211 }
00212 
00213 // -*- 5 -*-
00214 SparseMatrix
00215 xdiv (const SparseMatrix& a, const SparseMatrix& b, MatrixType &typ)
00216 {
00217   if (! mx_div_conform (a, b))
00218     return SparseMatrix ();
00219 
00220   SparseMatrix atmp = a.transpose ();
00221   SparseMatrix btmp = b.transpose ();
00222   MatrixType btyp = typ.transpose ();
00223 
00224   octave_idx_type info;
00225   double rcond = 0.0;
00226   SparseMatrix result = btmp.solve (btyp, atmp, info, rcond,
00227                                     solve_singularity_warning);
00228 
00229   typ = btyp.transpose ();
00230   return result.transpose ();
00231 }
00232 
00233 // -*- 6 -*-
00234 SparseComplexMatrix
00235 xdiv (const SparseMatrix& a, const SparseComplexMatrix& b, MatrixType &typ)
00236 {
00237   if (! mx_div_conform (a, b))
00238     return SparseComplexMatrix ();
00239 
00240   SparseMatrix atmp = a.transpose ();
00241   SparseComplexMatrix btmp = b.hermitian ();
00242   MatrixType btyp = typ.transpose ();
00243 
00244   octave_idx_type info;
00245   double rcond = 0.0;
00246   SparseComplexMatrix result
00247     = btmp.solve (btyp, atmp, info, rcond, solve_singularity_warning);
00248 
00249   typ = btyp.transpose ();
00250   return result.hermitian ();
00251 }
00252 
00253 // -*- 7 -*-
00254 SparseComplexMatrix
00255 xdiv (const SparseComplexMatrix& a, const SparseMatrix& b, MatrixType &typ)
00256 {
00257   if (! mx_div_conform (a, b))
00258     return SparseComplexMatrix ();
00259 
00260   SparseComplexMatrix atmp = a.hermitian ();
00261   SparseMatrix btmp = b.transpose ();
00262   MatrixType btyp = typ.transpose ();
00263 
00264   octave_idx_type info;
00265   double rcond = 0.0;
00266   SparseComplexMatrix result
00267     = btmp.solve (btyp, atmp, info, rcond, solve_singularity_warning);
00268 
00269   typ = btyp.transpose ();
00270   return result.hermitian ();
00271 }
00272 
00273 // -*- 8 -*-
00274 SparseComplexMatrix
00275 xdiv (const SparseComplexMatrix& a, const SparseComplexMatrix& b, MatrixType &typ)
00276 {
00277   if (! mx_div_conform (a, b))
00278     return SparseComplexMatrix ();
00279 
00280   SparseComplexMatrix atmp = a.hermitian ();
00281   SparseComplexMatrix btmp = b.hermitian ();
00282   MatrixType btyp = typ.transpose ();
00283 
00284   octave_idx_type info;
00285   double rcond = 0.0;
00286   SparseComplexMatrix result
00287     = btmp.solve (btyp, atmp, info, rcond, solve_singularity_warning);
00288 
00289   typ = btyp.transpose ();
00290   return result.hermitian ();
00291 }
00292 
00293 template <typename RT, typename SM, typename DM>
00294 RT do_rightdiv_sm_dm (const SM& a, const DM& d)
00295 {
00296   const octave_idx_type d_nr = d.rows ();
00297 
00298   const octave_idx_type a_nr = a.rows ();
00299   const octave_idx_type a_nc = a.cols ();
00300 
00301   using std::min;
00302   const octave_idx_type nc = min (d_nr, a_nc);
00303 
00304   if ( ! mx_div_conform (a, d))
00305     return RT ();
00306 
00307   const octave_idx_type nz = a.nnz ();
00308   RT r (a_nr, nc, nz);
00309 
00310   typedef typename DM::element_type DM_elt_type;
00311   const DM_elt_type zero = DM_elt_type ();
00312 
00313   octave_idx_type k_result = 0;
00314   for (octave_idx_type j = 0; j < nc; ++j)
00315     {
00316       octave_quit ();
00317       const DM_elt_type s = d.dgelem (j);
00318       const octave_idx_type colend = a.cidx (j+1);
00319       r.xcidx (j) = k_result;
00320       if (s != zero)
00321         for (octave_idx_type k = a.cidx (j); k < colend; ++k)
00322           {
00323             r.xdata (k_result) = a.data (k) / s;
00324             r.xridx (k_result) = a.ridx (k);
00325             ++k_result;
00326           }
00327     }
00328   r.xcidx (nc) = k_result;
00329 
00330   r.maybe_compress (true);
00331   return r;
00332 }
00333 
00334 // -*- 9 -*-
00335 SparseMatrix
00336 xdiv (const SparseMatrix& a, const DiagMatrix& b, MatrixType &)
00337 {
00338   return do_rightdiv_sm_dm<SparseMatrix> (a, b);
00339 }
00340 
00341 // -*- 10 -*-
00342 SparseComplexMatrix
00343 xdiv (const SparseMatrix& a, const ComplexDiagMatrix& b, MatrixType &)
00344 {
00345   return do_rightdiv_sm_dm<SparseComplexMatrix> (a, b);
00346 }
00347 
00348 // -*- 11 -*-
00349 SparseComplexMatrix
00350 xdiv (const SparseComplexMatrix& a, const DiagMatrix& b, MatrixType &)
00351 {
00352   return do_rightdiv_sm_dm<SparseComplexMatrix> (a, b);
00353 }
00354 
00355 // -*- 12 -*-
00356 SparseComplexMatrix
00357 xdiv (const SparseComplexMatrix& a, const ComplexDiagMatrix& b, MatrixType &)
00358 {
00359   return do_rightdiv_sm_dm<SparseComplexMatrix> (a, b);
00360 }
00361 
00362 // Funny element by element division operations.
00363 //
00364 //       op2 \ op1:   s   cs
00365 //            +--   +---+----+
00366 //   matrix         | 1 |  3 |
00367 //                  +---+----+
00368 //   complex_matrix | 2 |  4 |
00369 //                  +---+----+
00370 
00371 Matrix
00372 x_el_div (double a, const SparseMatrix& b)
00373 {
00374   octave_idx_type nr = b.rows ();
00375   octave_idx_type nc = b.cols ();
00376 
00377   Matrix result;
00378   if (a == 0.)
00379     result = Matrix (nr, nc, octave_NaN);
00380   else if (a > 0.)
00381     result = Matrix (nr, nc, octave_Inf);
00382   else
00383     result = Matrix (nr, nc, -octave_Inf);
00384 
00385 
00386   for (octave_idx_type j = 0; j < nc; j++)
00387     for (octave_idx_type i = b.cidx(j); i < b.cidx(j+1); i++)
00388       {
00389         octave_quit ();
00390         result.elem (b.ridx(i), j) = a / b.data (i);
00391       }
00392 
00393   return result;
00394 }
00395 
00396 ComplexMatrix
00397 x_el_div (double a, const SparseComplexMatrix& b)
00398 {
00399   octave_idx_type nr = b.rows ();
00400   octave_idx_type nc = b.cols ();
00401 
00402   ComplexMatrix  result (nr, nc, Complex(octave_NaN, octave_NaN));
00403 
00404   for (octave_idx_type j = 0; j < nc; j++)
00405     for (octave_idx_type i = b.cidx(j); i < b.cidx(j+1); i++)
00406       {
00407         octave_quit ();
00408         result.elem (b.ridx(i), j) = a / b.data (i);
00409       }
00410 
00411   return result;
00412 }
00413 
00414 ComplexMatrix
00415 x_el_div (const Complex a, const SparseMatrix& b)
00416 {
00417   octave_idx_type nr = b.rows ();
00418   octave_idx_type nc = b.cols ();
00419 
00420   ComplexMatrix result (nr, nc, (a / 0.0));
00421 
00422   for (octave_idx_type j = 0; j < nc; j++)
00423     for (octave_idx_type i = b.cidx(j); i < b.cidx(j+1); i++)
00424       {
00425         octave_quit ();
00426         result.elem (b.ridx(i), j) = a / b.data (i);
00427       }
00428 
00429   return result;
00430 }
00431 
00432 ComplexMatrix
00433 x_el_div (const Complex a, const SparseComplexMatrix& b)
00434 {
00435   octave_idx_type nr = b.rows ();
00436   octave_idx_type nc = b.cols ();
00437 
00438   ComplexMatrix result (nr, nc, (a / 0.0));
00439 
00440   for (octave_idx_type j = 0; j < nc; j++)
00441     for (octave_idx_type i = b.cidx(j); i < b.cidx(j+1); i++)
00442       {
00443         octave_quit ();
00444         result.elem (b.ridx(i), j) = a / b.data (i);
00445       }
00446 
00447   return result;
00448 }
00449 
00450 // Left division functions.  X \ Y = inv(X) * Y
00451 //
00452 //               Y  \  X :   sm  scm  dm  dcm
00453 //                   +--   +---+----+
00454 //   matrix                | 1 |  5 |
00455 //                         +---+----+
00456 //   complex_matrix        | 2 |  6 |
00457 //                         +---+----+----+----+
00458 //   sparse matrix         | 3 |  7 |  9 | 11 |
00459 //                         +---+----+----+----+
00460 //   sparse complex_matrix | 4 |  8 | 10 | 12 |
00461 //                         +---+----+----+----+
00462 
00463 // -*- 1 -*-
00464 Matrix
00465 xleftdiv (const SparseMatrix& a, const Matrix& b, MatrixType &typ)
00466 {
00467   if (! mx_leftdiv_conform (a, b))
00468     return Matrix ();
00469 
00470   octave_idx_type info;
00471   double rcond = 0.0;
00472   return a.solve (typ, b, info, rcond, solve_singularity_warning);
00473 }
00474 
00475 // -*- 2 -*-
00476 ComplexMatrix
00477 xleftdiv (const SparseMatrix& a, const ComplexMatrix& b, MatrixType &typ)
00478 {
00479   if (! mx_leftdiv_conform (a, b))
00480     return ComplexMatrix ();
00481 
00482   octave_idx_type info;
00483   double rcond = 0.0;
00484   return a.solve (typ, b, info, rcond, solve_singularity_warning);
00485 }
00486 
00487 // -*- 3 -*-
00488 SparseMatrix
00489 xleftdiv (const SparseMatrix& a, const SparseMatrix& b, MatrixType &typ)
00490 {
00491   if (! mx_leftdiv_conform (a, b))
00492     return SparseMatrix ();
00493 
00494   octave_idx_type info;
00495   double rcond = 0.0;
00496   return a.solve (typ, b, info, rcond, solve_singularity_warning);
00497 }
00498 
00499 // -*- 4 -*-
00500 SparseComplexMatrix
00501 xleftdiv (const SparseMatrix& a, const SparseComplexMatrix& b, MatrixType &typ)
00502 {
00503   if (! mx_leftdiv_conform (a, b))
00504     return SparseComplexMatrix ();
00505 
00506   octave_idx_type info;
00507   double rcond = 0.0;
00508   return a.solve (typ, b, info, rcond, solve_singularity_warning);
00509 }
00510 
00511 // -*- 5 -*-
00512 ComplexMatrix
00513 xleftdiv (const SparseComplexMatrix& a, const Matrix& b, MatrixType &typ)
00514 {
00515   if (! mx_leftdiv_conform (a, b))
00516     return ComplexMatrix ();
00517 
00518   octave_idx_type info;
00519   double rcond = 0.0;
00520   return a.solve (typ, b, info, rcond, solve_singularity_warning);
00521 }
00522 
00523 // -*- 6 -*-
00524 ComplexMatrix
00525 xleftdiv (const SparseComplexMatrix& a, const ComplexMatrix& b, MatrixType &typ)
00526 {
00527   if (! mx_leftdiv_conform (a, b))
00528     return ComplexMatrix ();
00529 
00530   octave_idx_type info;
00531   double rcond = 0.0;
00532   return a.solve (typ, b, info, rcond, solve_singularity_warning);
00533 }
00534 
00535 // -*- 7 -*-
00536 SparseComplexMatrix
00537 xleftdiv (const SparseComplexMatrix& a, const SparseMatrix& b, MatrixType &typ)
00538 {
00539   if (! mx_leftdiv_conform (a, b))
00540     return SparseComplexMatrix ();
00541 
00542   octave_idx_type info;
00543   double rcond = 0.0;
00544   return a.solve (typ, b, info, rcond, solve_singularity_warning);
00545 }
00546 
00547 // -*- 8 -*-
00548 SparseComplexMatrix
00549 xleftdiv (const SparseComplexMatrix& a, const SparseComplexMatrix& b,
00550           MatrixType &typ)
00551 {
00552   if (! mx_leftdiv_conform (a, b))
00553     return SparseComplexMatrix ();
00554 
00555   octave_idx_type info;
00556   double rcond = 0.0;
00557   return a.solve (typ, b, info, rcond, solve_singularity_warning);
00558 }
00559 
00560 template <typename RT, typename DM, typename SM>
00561 RT do_leftdiv_dm_sm (const DM& d, const SM& a)
00562 {
00563   const octave_idx_type a_nr = a.rows ();
00564   const octave_idx_type a_nc = a.cols ();
00565 
00566   const octave_idx_type d_nc = d.cols ();
00567 
00568   using std::min;
00569   const octave_idx_type nr = min (d_nc, a_nr);
00570 
00571   if ( ! mx_leftdiv_conform (d, a))
00572     return RT ();
00573 
00574   const octave_idx_type nz = a.nnz ();
00575   RT r (nr, a_nc, nz);
00576 
00577   typedef typename DM::element_type DM_elt_type;
00578   const DM_elt_type zero = DM_elt_type ();
00579 
00580   octave_idx_type k_result = 0;
00581   for (octave_idx_type j = 0; j < a_nc; ++j)
00582     {
00583       octave_quit ();
00584       const octave_idx_type colend = a.cidx (j+1);
00585       r.xcidx (j) = k_result;
00586       for (octave_idx_type k = a.cidx (j); k < colend; ++k)
00587         {
00588           const octave_idx_type i = a.ridx (k);
00589           if (i < nr)
00590             {
00591               const DM_elt_type s = d.dgelem (i);
00592               if (s != zero)
00593                 {
00594                   r.xdata (k_result) = a.data (k) / s;
00595                   r.xridx (k_result) = i;
00596                   ++k_result;
00597                 }
00598             }
00599         }
00600     }
00601   r.xcidx (a_nc) = k_result;
00602 
00603   r.maybe_compress (true);
00604   return r;
00605 }
00606 
00607 // -*- 9 -*-
00608 SparseMatrix
00609 xleftdiv (const DiagMatrix& d, const SparseMatrix& a,  MatrixType&)
00610 {
00611   return do_leftdiv_dm_sm<SparseMatrix> (d, a);
00612 }
00613 
00614 // -*- 10 -*-
00615 SparseComplexMatrix
00616 xleftdiv (const DiagMatrix& d, const SparseComplexMatrix& a,  MatrixType&)
00617 {
00618   return do_leftdiv_dm_sm<SparseComplexMatrix> (d, a);
00619 }
00620 
00621 // -*- 11 -*-
00622 SparseComplexMatrix
00623 xleftdiv (const ComplexDiagMatrix& d, const SparseMatrix& a,  MatrixType&)
00624 {
00625   return do_leftdiv_dm_sm<SparseComplexMatrix> (d, a);
00626 }
00627 
00628 // -*- 12 -*-
00629 SparseComplexMatrix
00630 xleftdiv (const ComplexDiagMatrix& d, const SparseComplexMatrix& a,  MatrixType&)
00631 {
00632   return do_leftdiv_dm_sm<SparseComplexMatrix> (d, a);
00633 }
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines