MFEM v2.0
table.cpp
Go to the documentation of this file.
00001 // Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
00002 // the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
00003 // reserved. See file COPYRIGHT for details.
00004 //
00005 // This file is part of the MFEM library. For more information and source code
00006 // availability see http://mfem.googlecode.com.
00007 //
00008 // MFEM is free software; you can redistribute it and/or modify it under the
00009 // terms of the GNU Lesser General Public License (as published by the Free
00010 // Software Foundation) version 2.1 dated February 1999.
00011 
00012 // Implementation of data types Table.
00013 
00014 #include <iostream>
00015 #include <iomanip>
00016 
00017 #include "array.hpp"
00018 #include "table.hpp"
00019 
00020 
00021 Table::Table (int dim, int connections_per_row)
00022 {
00023    int i, j, sum = dim * connections_per_row;
00024 
00025    size = dim;
00026    I = new int[size+1];
00027    J = new int[sum];
00028 
00029    I[0] = 0;
00030    for (i = 1; i <= size; i++)
00031    {
00032       I[i] = I[i-1] + connections_per_row;
00033       for (j = I[i-1]; j < I[i]; j++) { J[j] = -1; }
00034    }
00035 }
00036 
00037 Table::Table (int nrows, int *partitioning)
00038 {
00039    size = nrows;
00040 
00041    I = new int[size+1];
00042    J = new int[size];
00043 
00044    for (int i = 0; i < size; i++)
00045    {
00046       I[i] = i;
00047       J[i] = partitioning[i];
00048    }
00049    I[size] = size;
00050 }
00051 
00052 void Table::MakeI (int nrows)
00053 {
00054    SetDims (nrows, 0);
00055 
00056    for (int i = 0; i <= nrows; i++)
00057       I[i] = 0;
00058 }
00059 
00060 void Table::MakeJ()
00061 {
00062    int i, j, k;
00063 
00064    for (k = i = 0; i < size; i++)
00065       j = I[i], I[i] = k, k += j;
00066 
00067    J = new int[I[size]=k];
00068 }
00069 
00070 void Table::AddConnections (int r, int *c, int nc)
00071 {
00072    int *jp = J+I[r];
00073 
00074    for (int i = 0; i < nc; i++)
00075       jp[i] = c[i];
00076    I[r] += nc;
00077 }
00078 
00079 void Table::ShiftUpI()
00080 {
00081    for (int i = size; i > 0; i--)
00082       I[i] = I[i-1];
00083    I[0] = 0;
00084 }
00085 
00086 void Table::SetSize(int dim, int connections_per_row)
00087 {
00088    SetDims (dim, dim * connections_per_row);
00089 
00090    if (size > 0)
00091    {
00092       I[0] = 0;
00093       for (int i = 0, j = 0; i < size; i++)
00094       {
00095          int end = I[i] + connections_per_row;
00096          I[i+1] = end;
00097          for ( ; j < end; j++) J[j] = -1;
00098       }
00099    }
00100 }
00101 
00102 void Table::SetDims(int rows, int nnz)
00103 {
00104    int j;
00105 
00106    j = (I) ? (I[size]) : (0);
00107    if (size != rows)
00108    {
00109       size = rows;
00110       if (I) delete [] I;
00111       I = (rows >= 0) ? (new int[rows+1]) : (NULL);
00112    }
00113 
00114    if (j != nnz)
00115    {
00116       if (J) delete [] J;
00117       J = (nnz > 0) ? (new int[nnz]) : (NULL);
00118    }
00119 
00120    if (size >= 0)
00121    {
00122       I[0] = 0;
00123       I[size] = nnz;
00124    }
00125 }
00126 
00127 int Table::operator() (int i, int j) const
00128 {
00129    if ( i>=size || i<0 )
00130       return -1;
00131 
00132    int k, end = I[i+1];
00133 
00134    for(k=I[i]; k<end; k++)
00135       if (J[k]==j)
00136          return k;
00137       else if (J[k]==-1)
00138          return -1;
00139 
00140    return -1;
00141 }
00142 
00143 void Table::GetRow(int i, Array<int> &row) const
00144 {
00145    const int *jp = GetRow(i), n = RowSize(i);
00146 
00147    row.SetSize(n);
00148    for(int i = 0; i < n; i++)
00149       row[i] = jp[i];
00150 }
00151 
00152 void Table::SetIJ(int *newI, int *newJ, int newsize)
00153 {
00154    delete [] I;
00155    delete [] J;
00156    I = newI;
00157    J = newJ;
00158    if (newsize >= 0)
00159       size = newsize;
00160 }
00161 
00162 int Table::Push(int i, int j)
00163 {
00164 #ifdef MFEM_DEBUG
00165    if (i >= size || i < 0)
00166    {
00167       cerr << "Table::Push() i = " << i << endl;
00168       mfem_error();
00169    }
00170 #endif
00171 
00172    for(int k = I[i], end = I[i+1]; k < end; k++)
00173       if (J[k] == j)
00174          return k;
00175       else if (J[k] == -1)
00176       {
00177          J[k] = j;
00178          return k;
00179       }
00180    cerr << "Table::Push() : (i,j) = (" << i << ", " << j << ")" << endl;
00181    mfem_error();
00182 
00183    return -1;
00184 }
00185 
00186 void Table::Finalize()
00187 {
00188    int i, j, end, sum = 0, n = 0, newI = 0;
00189 
00190    for(i=0; i<I[size]; i++)
00191       if (J[i] != -1)
00192          sum++;
00193 
00194    if (sum != I[size]){
00195       int *NewJ = new int[sum];
00196 
00197       for(i=0; i<size; i++){
00198          end = I[i+1];
00199          for(j=I[i]; j<end; j++){
00200             if (J[j] == -1) break;
00201             NewJ[ n++ ] = J[j];
00202          }
00203          I[i] = newI;
00204          newI = n;
00205       }
00206       I[size] = sum;
00207 
00208       delete [] J;
00209 
00210       J = NewJ;
00211 
00212 #ifdef MFEM_DEBUG
00213       if (sum != n)
00214          mfem_error ("Table::Finalize");
00215 #endif
00216    }
00217 }
00218 
00219 int Table::Width() const
00220 {
00221    int width = -1, nnz = I[size];
00222    for (int k = 0; k < nnz; k++)
00223       if (J[k] > width) width = J[k];
00224    return width + 1;
00225 }
00226 
00227 void Table::Print(ostream & out, int width) const
00228 {
00229    int i, j;
00230 
00231    for (i = 0; i < size; i++)
00232    {
00233       out << "[row " << i << "]\n";
00234       for (j = I[i]; j < I[i+1]; j++)
00235       {
00236          out << setw(5) << J[j];
00237          if ( !((j+1-I[i]) % width) )
00238             out << '\n';
00239       }
00240       if ((j-I[i]) % width)
00241          out << '\n';
00242    }
00243 }
00244 
00245 void Table::Save(ostream & out) const
00246 {
00247    int i;
00248 
00249    out << size << '\n';
00250 
00251    for (i = 0; i <= size; i++)
00252       out << I[i] << '\n';
00253    for (i = 0; i < I[size]; i++)
00254       out << J[i] << '\n';
00255 }
00256 
00257 Table::~Table ()
00258 {
00259    if (I) delete [] I;
00260    if (J) delete [] J;
00261 }
00262 
00263 void Transpose (const Table &A, Table &At, int _ncols_A)
00264 {
00265    const int *i_A     = A.GetI();
00266    const int *j_A     = A.GetJ();
00267    const int  nrows_A = A.Size();
00268    const int  ncols_A = (_ncols_A < 0) ? A.Width() : _ncols_A;
00269    const int  nnz_A   = i_A[nrows_A];
00270 
00271    At.SetDims (ncols_A, nnz_A);
00272 
00273    int *i_At = At.GetI();
00274    int *j_At = At.GetJ();
00275 
00276    for (int i = 0; i <= ncols_A; i++)
00277       i_At[i] = 0;
00278    for (int i = 0; i < nnz_A; i++)
00279       i_At[j_A[i]+1]++;
00280    for (int i = 1; i < ncols_A; i++)
00281       i_At[i+1] += i_At[i];
00282 
00283    for (int i = 0; i < nrows_A; i++)
00284       for (int j = i_A[i]; j < i_A[i+1]; j++)
00285          j_At[i_At[j_A[j]]++] = i;
00286    for (int i = ncols_A; i > 0; i--)
00287       i_At[i] = i_At[i-1];
00288    i_At[0] = 0;
00289 }
00290 
00291 void Transpose(const Array<int> &A, Table &At, int _ncols_A)
00292 {
00293    At.MakeI((_ncols_A < 0) ? (A.Max() + 1) : _ncols_A);
00294    for (int i = 0; i < A.Size(); i++)
00295       At.AddAColumnInRow(A[i]);
00296    At.MakeJ();
00297    for (int i = 0; i < A.Size(); i++)
00298       At.AddConnection(A[i], i);
00299    At.ShiftUpI();
00300 }
00301 
00302 void Mult (const Table &A, const Table &B, Table &C)
00303 {
00304    int  i, j, k, l, m;
00305    const int *i_A     = A.GetI();
00306    const int *j_A     = A.GetJ();
00307    const int *i_B     = B.GetI();
00308    const int *j_B     = B.GetJ();
00309    const int  nrows_A = A.Size();
00310    const int  nrows_B = B.Size();
00311    const int  ncols_A = A.Width();
00312    const int  ncols_B = B.Width();
00313 
00314    if (ncols_A > nrows_B)
00315       mfem_error ("Mult (Table &A, Table &B, Table &C)");
00316 
00317    Array<int> B_marker (ncols_B);
00318 
00319    for (i = 0; i < ncols_B; i++)
00320       B_marker[i] = -1;
00321 
00322    int counter = 0;
00323    for (i = 0; i < nrows_A; i++)
00324    {
00325       for (j = i_A[i]; j < i_A[i+1]; j++)
00326       {
00327          k = j_A[j];
00328          for (l = i_B[k]; l < i_B[k+1]; l++)
00329          {
00330             m = j_B[l];
00331             if (B_marker[m] != i)
00332             {
00333                B_marker[m] = i;
00334                counter++;
00335             }
00336          }
00337       }
00338    }
00339 
00340    C.SetDims (nrows_A, counter);
00341 
00342    for (i = 0; i < ncols_B; i++)
00343       B_marker[i] = -1;
00344 
00345    int *i_C = C.GetI();
00346    int *j_C = C.GetJ();
00347    counter = 0;
00348    for (i = 0; i < nrows_A; i++)
00349    {
00350       i_C[i] = counter;
00351       for (j = i_A[i]; j < i_A[i+1]; j++)
00352       {
00353          k = j_A[j];
00354          for (l = i_B[k]; l < i_B[k+1]; l++)
00355          {
00356             m = j_B[l];
00357             if (B_marker[m] != i)
00358             {
00359                B_marker[m] = i;
00360                j_C[counter] = m;
00361                counter++;
00362             }
00363          }
00364       }
00365    }
00366 }
00367 
00368 
00369 STable::STable (int dim, int connections_per_row) :
00370    Table(dim, connections_per_row)
00371 {}
00372 
00373 int STable::operator() (int i, int j) const
00374 {
00375    if (i < j)
00376       return Table::operator()(i,j);
00377    else
00378       return Table::operator()(j,i);
00379 }
00380 
00381 int STable::Push( int i, int j ){
00382    if (i < j)
00383       return Table::Push(i, j);
00384    else
00385       return Table::Push(j, i);
00386 }
00387 
00388 
00389 DSTable::DSTable(int nrows)
00390 {
00391    Rows = new Node*[nrows];
00392    for (int i = 0; i < nrows; i++)
00393    {
00394       Rows[i] = NULL;
00395    }
00396    NumRows = nrows;
00397    NumEntries = 0;
00398 }
00399 
00400 int DSTable::Push_(int r, int c)
00401 {
00402 #ifdef MFEM_DEBUG
00403    if (r < 0 || r >= NumRows)
00404       mfem_error("DSTable::Push_()");
00405 #endif
00406    Node *n;
00407    for (n = Rows[r]; n != NULL; n = n->Prev)
00408    {
00409       if (n->Column == c)
00410       {
00411          return(n->Index);
00412       }
00413    }
00414 #ifdef MFEM_USE_MEMALLOC
00415    n = NodesMem.Alloc ();
00416 #else
00417    n = new Node;
00418 #endif
00419    n->Column = c;
00420    n->Index  = NumEntries;
00421    n->Prev   = Rows[r];
00422    Rows[r]   = n;
00423    return(NumEntries++);
00424 }
00425 
00426 int DSTable::Index(int r, int c) const
00427 {
00428 #ifdef MFEM_DEBUG
00429    if (r < 0)
00430       mfem_error("DSTable::Index()");
00431 #endif
00432    if (r >= NumRows)
00433       return(-1);
00434    for (Node *n = Rows[r]; n != NULL; n = n->Prev)
00435    {
00436       if (n->Column == c)
00437       {
00438          return(n->Index);
00439       }
00440    }
00441    return(-1);
00442 }
00443 
00444 DSTable::~DSTable()
00445 {
00446 #ifdef MFEM_USE_MEMALLOC
00447    // NodesMem.Clear();  // this is done implicitly
00448 #else
00449    for (int i = 0; i < NumRows; i++)
00450    {
00451       Node *na, *nb = Rows[i];
00452       while (nb != NULL)
00453       {
00454          na = nb;
00455          nb = nb->Prev;
00456          delete na;
00457       }
00458    }
00459 #endif
00460    delete [] Rows;
00461 }
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines