00001
00002 #include "idep_binrel.h"
00003
00004 #include <memory.h>
00005 #include <iostream>
00006 #include <cassert>
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 enum { START_SIZE = 1, GROW_FACTOR = 2 };
00024
00025 static void clean(char **p)
00026 {
00027 delete [] *p;
00028 delete [] p;
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
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
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
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
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;
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;
00176 }
00177 if (d_rel_p[k] == row_r) {
00178 continue;
00179 }
00180 for (register int c = 0; c < s; ++c) {
00181 if (row_k[c] && row_r[k]) {
00182
00183 if (c != k) {
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
00201 for (int i = 0; i < length(); ++i) {
00202 d_rel_p[i][i] = 0;
00203 }
00204 }
00205
00206
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 }