Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

idep_binrel.cxx

Go to the documentation of this file.
00001 // idep_binrel.c
00002 #include "idep_binrel.h"
00003 
00004 #include <memory.h>     // memcpy() memset() memcmp()
00005 #include <iostream>
00006 #include <cassert>
00007 
00008 // IMPLEMENTATION NOTE: MEMORY LAYOUT
00009 // +---------+          +---------+             +---+---+---+---+
00010 // |         |--------->|         |------------>|   |   |   |   |
00011 // +---------+          +---------+             +---+---+---+---+
00012 //    char**            |         |------------>|   |   |   |   |
00013 //                      +---------+             +---+---+---+---+
00014 //                      |         |------------>|   |   |   |   |
00015 //                      +---------+             +---+---+---+---+
00016 //                      |         |------------>|   |   |   |   |
00017 //                      +---------+             +---+---+---+---+
00018 //                      char*[size]             contiguous memory
00019 //                                              char[size * size]
00020 
00021                 // -*-*-*- static functions -*-*-*-
00022 
00023 enum { START_SIZE = 1, GROW_FACTOR = 2 };
00024 
00025 static void clean(char **p) 
00026 {
00027     delete [] *p;               // only one 2-d block is allocated
00028     delete [] p;                // delete single block  
00029 }
00030 
00031 static char **alloc(int size) 
00032 {
00033     register int s = size;
00034     char **rel = new char *[s];
00035     register char *p = new char[s * s];
00036     for (register int i = 0; i < s; ++i, p += s) {
00037         rel[i] = p;
00038     }
00039     return rel;
00040 }
00041 
00042 static void clear(char *const *rel, int size) 
00043 {
00044     memset(*rel, 0, size * size);
00045 }
00046 
00047 static void copy(char **left, const char *const *right, int size)
00048 {
00049     memcpy(*left, *right, size * size);
00050 }
00051 
00052                 // -*-*-*- private functions -*-*-*-
00053 
00054 void idep_BinRel::grow()
00055 {
00056     int newSize = d_size * GROW_FACTOR;
00057     char **tmp = d_rel_p;
00058     d_rel_p = alloc(newSize);
00059     clear(d_rel_p, newSize);
00060 
00061     for (int i = 0; i < d_size; ++i) {
00062         memcpy(d_rel_p[i], tmp[i], d_size);
00063     }
00064 
00065     d_size = newSize;
00066     clean(tmp);
00067 }
00068 
00069 void idep_BinRel::compress()
00070 {
00071     if (d_size > d_length && d_length > 0) {
00072         d_size = d_length;
00073         char **tmp = d_rel_p;
00074         d_rel_p = alloc(d_size);
00075         clear(d_rel_p, d_size);
00076         for (int i = 0; i < d_size; ++i) {
00077             memcpy(d_rel_p[i], tmp[i], d_size);
00078         }
00079         clean(tmp);
00080     }
00081 }
00082 
00083                 // -*-*-*- public functions -*-*-*-
00084 
00085 idep_BinRel::idep_BinRel(int initialEntries, int maxEntriesHint) 
00086 : d_size(maxEntriesHint > 0 ? maxEntriesHint : START_SIZE) 
00087 , d_length(initialEntries > 0 ? initialEntries : 0)
00088 {
00089     if (d_size < d_length) {
00090         d_size = d_length;
00091     }
00092     d_rel_p = alloc(d_size);
00093     clear(d_rel_p, d_size);
00094 }
00095 
00096 idep_BinRel::idep_BinRel(const idep_BinRel& rel) 
00097 : d_rel_p(alloc(rel.d_size)) 
00098 , d_size(rel.d_size)
00099 , d_length(rel.d_length)
00100 { 
00101     copy(d_rel_p, rel.d_rel_p, d_size);
00102 }
00103 
00104 idep_BinRel& idep_BinRel::operator=(const idep_BinRel& rel) 
00105 {  
00106     if (&rel != this) {
00107         if (d_size != rel.d_size) { 
00108             clean(d_rel_p);
00109             d_size = rel.d_size;
00110             d_rel_p = alloc(d_size);
00111         }
00112         copy(d_rel_p, rel.d_rel_p, d_size);
00113         d_length = rel.d_length;
00114     }
00115     return *this;
00116 }
00117 
00118 idep_BinRel::~idep_BinRel() 
00119 {
00120     clean(d_rel_p);
00121 }
00122 
00123 int idep_BinRel::cmp(const idep_BinRel& rel) const
00124 {
00125     enum { SAME = 0, DIFFERENT = 1 };
00126 
00127     if (d_length != rel.d_length) {
00128         return DIFFERENT;
00129     }
00130 
00131     if (d_size == rel.d_size && 
00132                             memcmp(*d_rel_p, *rel.d_rel_p, d_size * d_size)) {
00133         return DIFFERENT;
00134     }
00135 
00136     for (int i = 0; i < d_length; ++i) {
00137         if (memcmp(d_rel_p[i], rel.d_rel_p[i], d_length)) {
00138             return DIFFERENT;
00139         }
00140     }
00141 
00142     return SAME;
00143 }
00144 
00145 void idep_BinRel::warshall(int bit) 
00146 {
00147     // DEFINITION: Transitive Closure
00148     //
00149     // Given: R is a relation (matrix) indicating transitions in 1 step.
00150     // TransitiveClosure(R) = R + R^2 + R^3 + ... + R^N 
00151     //      where N is the number of rows and columns in the square matrix R.
00152     //
00153     // Warshall's algorithm to construct the transitive closure:
00154     // foreach index k
00155     //     foreach row i
00156     //         foreach column j
00157     //             if (A[i][k] && A[k][j]) 
00158     //                 A[i][j] = 1;      
00159     // 
00160     // See Aho, Hopcroft, & Ullman, "Data Structures And Algorithms,"
00161     // Addison-Wesley, Reading MA, pp. 212-213.  Also see, Warshall, S. [1962].
00162     // "A theorem on Boolean matrices," Journal of the ACM, 9:1, pp. 11-12.
00163 
00164     compress();
00165     assert(d_size == d_length || 0 == d_length);
00166 
00167     register const int VALUE = !!bit;
00168     register int s = d_length;  // size and length are the same or length is 0
00169     register char *top_row = d_rel_p[0] + s * s;
00170 
00171     for (int k = 0; k < s; ++k) {
00172         register char *row_k = d_rel_p[k];
00173         for (register char *row_r = d_rel_p[0]; row_r < top_row; row_r += s) {
00174             if (!row_r[k]) { 
00175                 continue;                   // huge optimization
00176             }
00177             if (d_rel_p[k] == row_r) {  
00178                 continue;                   // note: ignore self dependency
00179             }
00180             for (register int c = 0; c < s; ++c) {
00181                 if (row_k[c] && row_r[k]) { // note: both conditions are needed
00182                                             // in reverse (consider k == c).
00183                     if (c != k) {           // note: ignore self dependency
00184                         row_r[c] = VALUE;   
00185                     }
00186                 }
00187             }
00188         }
00189     }
00190 }
00191 
00192 void idep_BinRel::makeTransitive() 
00193 {
00194     warshall(1);
00195 }
00196 
00197 void idep_BinRel::makeNonTransitive() 
00198 {
00199     warshall(0);
00200     // make non-reflexive too -- i.e., subtract the identity matrix.
00201     for (int i = 0; i < length(); ++i) {
00202         d_rel_p[i][i] = 0;
00203     }
00204 }
00205 
00206                 // -*-*-*- free operators -*-*-*-
00207 
00208 std::ostream& operator<<(std::ostream& o, const idep_BinRel& rel) 
00209 {
00210     int r, c;
00211     const int GAP_GRID = 10;
00212     const char *SP = rel.length() < 30 ? " " : "";
00213     for (r = 0; r < rel.length(); ++r) {
00214         if (r && 0 == r % GAP_GRID) { 
00215             o << std::endl;
00216         }
00217         
00218         for (c = 0; c < rel.length(); ++c) {
00219             if (c && 0 == c % GAP_GRID) { 
00220                 o << ' ' << SP;
00221             }
00222             o << (rel.get(r,c) ? '1' : '_') << SP;
00223         }
00224         o << std::endl;
00225     }
00226     return o;
00227 }

Generated on Mon Feb 15 11:06:48 2010 for loon by  doxygen 1.3.9.1