gravatar
alpar (Alpar Juttner)
alpar@cs.elte.hu
Avoid bit operator precedence warning with gcc-4.3 Some of these warnings are actually revealed real bugs
0 2 0
default
2 files changed with 24 insertions and 23 deletions:
↑ Collapse diff ↑
Ignore white space 6 line context
1 1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
2 2
 *
3 3
 * This file is a part of LEMON, a generic C++ optimization library.
4 4
 *
5 5
 * Copyright (C) 2003-2008
6 6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
8 8
 *
9 9
 * Permission to use, modify and distribute this software is granted
10 10
 * provided that this copyright notice appears in all copies. For
11 11
 * precise terms see the accompanying LICENSE file.
12 12
 *
13 13
 * This software is provided "AS IS" with no warranty of any kind,
14 14
 * express or implied, and with no claim as to its suitability for any
15 15
 * purpose.
16 16
 *
17 17
 */
18 18

	
19 19
#ifndef HYPERCUBE_GRAPH_H
20 20
#define HYPERCUBE_GRAPH_H
21 21

	
22 22
#include <vector>
23 23
#include <lemon/core.h>
24 24
#include <lemon/assert.h>
25 25
#include <lemon/bits/graph_extender.h>
26 26

	
27 27
///\ingroup graphs
28 28
///\file
29 29
///\brief HypercubeGraph class.
30 30

	
31 31
namespace lemon {
32 32

	
33 33
  class HypercubeGraphBase {
34 34

	
35 35
  public:
36 36

	
37 37
    typedef HypercubeGraphBase Graph;
38 38

	
39 39
    class Node;
40 40
    class Edge;
41 41
    class Arc;
42 42

	
43 43
  public:
44 44

	
45 45
    HypercubeGraphBase() {}
46 46

	
47 47
  protected:
48 48

	
49 49
    void construct(int dim) {
50 50
      LEMON_ASSERT(dim >= 1, "The number of dimensions must be at least 1.");
51 51
      _dim = dim;
52 52
      _node_num = 1 << dim;
53
      _edge_num = dim * (1 << dim-1);
53
      _edge_num = dim * (1 << (dim-1));
54 54
    }
55 55

	
56 56
  public:
57 57

	
58 58
    typedef True NodeNumTag;
59 59
    typedef True EdgeNumTag;
60 60
    typedef True ArcNumTag;
61 61

	
62 62
    int nodeNum() const { return _node_num; }
63 63
    int edgeNum() const { return _edge_num; }
64 64
    int arcNum() const { return 2 * _edge_num; }
65 65

	
66 66
    int maxNodeId() const { return _node_num - 1; }
67 67
    int maxEdgeId() const { return _edge_num - 1; }
68 68
    int maxArcId() const { return 2 * _edge_num - 1; }
69 69

	
70 70
    static Node nodeFromId(int id) { return Node(id); }
71 71
    static Edge edgeFromId(int id) { return Edge(id); }
72 72
    static Arc arcFromId(int id) { return Arc(id); }
73 73

	
74 74
    static int id(Node node) { return node._id; }
75 75
    static int id(Edge edge) { return edge._id; }
76 76
    static int id(Arc arc) { return arc._id; }
77 77

	
78 78
    Node u(Edge edge) const {
79
      int base = edge._id & ((1 << _dim-1) - 1);
80
      int k = edge._id >> _dim-1;
81
      return ((base >> k) << k+1) | (base & ((1 << k) - 1));
79
      int base = edge._id & ((1 << (_dim-1)) - 1);
80
      int k = edge._id >> (_dim-1);
81
      return ((base >> k) << (k+1)) | (base & ((1 << k) - 1));
82 82
    }
83 83

	
84 84
    Node v(Edge edge) const {
85
      int base = edge._id & ((1 << _dim-1) - 1);
86
      int k = edge._id >> _dim-1;
87
      return ((base >> k) << k+1) | (base & ((1 << k) - 1)) | (1 << k);
85
      int base = edge._id & ((1 << (_dim-1)) - 1);
86
      int k = edge._id >> (_dim-1);
87
      return ((base >> k) << (k+1)) | (base & ((1 << k) - 1)) | (1 << k);
88 88
    }
89 89

	
90 90
    Node source(Arc arc) const {
91 91
      return (arc._id & 1) == 1 ? u(arc) : v(arc);
92 92
    }
93 93

	
94 94
    Node target(Arc arc) const {
95 95
      return (arc._id & 1) == 1 ? v(arc) : u(arc);
96 96
    }
97 97

	
98 98
    typedef True FindEdgeTag;
99 99
    typedef True FindArcTag;
100 100

	
101 101
    Edge findEdge(Node u, Node v, Edge prev = INVALID) const {
102 102
      if (prev != INVALID) return INVALID;
103 103
      int d = u._id ^ v._id;
104 104
      int k = 0;
105 105
      if (d == 0) return INVALID;
106 106
      for ( ; (d & 1) == 0; d >>= 1) ++k;
107 107
      if (d >> 1 != 0) return INVALID;
108
      return (k << _dim-1) | ((u._id >> k+1) << k) | (u._id & ((1 << k) - 1));
108
      return (k << (_dim-1)) | ((u._id >> (k+1)) << k) |
109
        (u._id & ((1 << k) - 1));
109 110
    }
110 111

	
111 112
    Arc findArc(Node u, Node v, Arc prev = INVALID) const {
112 113
      Edge edge = findEdge(u, v, prev);
113 114
      if (edge == INVALID) return INVALID;
114
      int k = edge._id >> _dim-1;
115
      int k = edge._id >> (_dim-1);
115 116
      return ((u._id >> k) & 1) == 1 ? edge._id << 1 : (edge._id << 1) | 1;
116 117
    }
117 118

	
118 119
    class Node {
119 120
      friend class HypercubeGraphBase;
120 121

	
121 122
    protected:
122 123
      int _id;
123 124
      Node(int id) : _id(id) {}
124 125
    public:
125 126
      Node() {}
126 127
      Node (Invalid) : _id(-1) {}
127 128
      bool operator==(const Node node) const {return _id == node._id;}
128 129
      bool operator!=(const Node node) const {return _id != node._id;}
129 130
      bool operator<(const Node node) const {return _id < node._id;}
130 131
    };
131 132

	
132 133
    class Edge {
133 134
      friend class HypercubeGraphBase;
134 135
      friend class Arc;
135 136

	
136 137
    protected:
137 138
      int _id;
138 139

	
139 140
      Edge(int id) : _id(id) {}
140 141

	
141 142
    public:
142 143
      Edge() {}
143 144
      Edge (Invalid) : _id(-1) {}
144 145
      bool operator==(const Edge edge) const {return _id == edge._id;}
145 146
      bool operator!=(const Edge edge) const {return _id != edge._id;}
146 147
      bool operator<(const Edge edge) const {return _id < edge._id;}
147 148
    };
148 149

	
149 150
    class Arc {
150 151
      friend class HypercubeGraphBase;
151 152

	
152 153
    protected:
153 154
      int _id;
154 155

	
155 156
      Arc(int id) : _id(id) {}
156 157

	
157 158
    public:
158 159
      Arc() {}
159 160
      Arc (Invalid) : _id(-1) {}
160 161
      operator Edge() const { return _id != -1 ? Edge(_id >> 1) : INVALID; }
161 162
      bool operator==(const Arc arc) const {return _id == arc._id;}
162 163
      bool operator!=(const Arc arc) const {return _id != arc._id;}
163 164
      bool operator<(const Arc arc) const {return _id < arc._id;}
164 165
    };
165 166

	
166 167
    void first(Node& node) const {
167 168
      node._id = _node_num - 1;
168 169
    }
169 170

	
170 171
    static void next(Node& node) {
171 172
      --node._id;
172 173
    }
173 174

	
174 175
    void first(Edge& edge) const {
175 176
      edge._id = _edge_num - 1;
176 177
    }
177 178

	
178 179
    static void next(Edge& edge) {
179 180
      --edge._id;
180 181
    }
181 182

	
182 183
    void first(Arc& arc) const {
183 184
      arc._id = 2 * _edge_num - 1;
184 185
    }
185 186

	
186 187
    static void next(Arc& arc) {
187 188
      --arc._id;
188 189
    }
189 190

	
190 191
    void firstInc(Edge& edge, bool& dir, const Node& node) const {
191 192
      edge._id = node._id >> 1;
192 193
      dir = (node._id & 1) == 0;
193 194
    }
194 195

	
195 196
    void nextInc(Edge& edge, bool& dir) const {
196 197
      Node n = dir ? u(edge) : v(edge);
197
      int k = (edge._id >> _dim-1) + 1;
198
      int k = (edge._id >> (_dim-1)) + 1;
198 199
      if (k < _dim) {
199
        edge._id = (k << _dim-1) |
200
                   ((n._id >> k+1) << k) | (n._id & ((1 << k) - 1));
200
        edge._id = (k << (_dim-1)) |
201
          ((n._id >> (k+1)) << k) | (n._id & ((1 << k) - 1));
201 202
        dir = ((n._id >> k) & 1) == 0;
202 203
      } else {
203 204
        edge._id = -1;
204 205
        dir = true;
205 206
      }
206 207
    }
207 208

	
208 209
    void firstOut(Arc& arc, const Node& node) const {
209 210
      arc._id = ((node._id >> 1) << 1) | (~node._id & 1);
210 211
    }
211 212

	
212 213
    void nextOut(Arc& arc) const {
213 214
      Node n = (arc._id & 1) == 1 ? u(arc) : v(arc);
214 215
      int k = (arc._id >> _dim) + 1;
215 216
      if (k < _dim) {
216
        arc._id = (k << _dim-1) |
217
                  ((n._id >> k+1) << k) | (n._id & ((1 << k) - 1));
217
        arc._id = (k << (_dim-1)) |
218
          ((n._id >> (k+1)) << k) | (n._id & ((1 << k) - 1));
218 219
        arc._id = (arc._id << 1) | (~(n._id >> k) & 1);
219 220
      } else {
220 221
        arc._id = -1;
221 222
      }
222 223
    }
223 224

	
224 225
    void firstIn(Arc& arc, const Node& node) const {
225 226
      arc._id = ((node._id >> 1) << 1) | (node._id & 1);
226 227
    }
227 228

	
228 229
    void nextIn(Arc& arc) const {
229 230
      Node n = (arc._id & 1) == 1 ? v(arc) : u(arc);
230 231
      int k = (arc._id >> _dim) + 1;
231 232
      if (k < _dim) {
232
        arc._id = (k << _dim-1) |
233
                  ((n._id >> k+1) << k) | (n._id & ((1 << k) - 1));
233
        arc._id = (k << (_dim-1)) |
234
          ((n._id >> (k+1)) << k) | (n._id & ((1 << k) - 1));
234 235
        arc._id = (arc._id << 1) | ((n._id >> k) & 1);
235 236
      } else {
236 237
        arc._id = -1;
237 238
      }
238 239
    }
239 240

	
240 241
    static bool direction(Arc arc) {
241 242
      return (arc._id & 1) == 1;
242 243
    }
243 244

	
244 245
    static Arc direct(Edge edge, bool dir) {
245 246
      return Arc((edge._id << 1) | (dir ? 1 : 0));
246 247
    }
247 248

	
248 249
    int dimension() const {
249 250
      return _dim;
250 251
    }
251 252

	
252 253
    bool projection(Node node, int n) const {
253 254
      return static_cast<bool>(node._id & (1 << n));
254 255
    }
255 256

	
256 257
    int dimension(Edge edge) const {
257
      return edge._id >> _dim-1;
258
      return edge._id >> (_dim-1);
258 259
    }
259 260

	
260 261
    int dimension(Arc arc) const {
261 262
      return arc._id >> _dim;
262 263
    }
263 264

	
264 265
    int index(Node node) const {
265 266
      return node._id;
266 267
    }
267 268

	
268 269
    Node operator()(int ix) const {
269 270
      return Node(ix);
270 271
    }
271 272

	
272 273
  private:
273 274
    int _dim;
274 275
    int _node_num, _edge_num;
275 276
  };
276 277

	
277 278

	
278 279
  typedef GraphExtender<HypercubeGraphBase> ExtendedHypercubeGraphBase;
279 280

	
280 281
  /// \ingroup graphs
281 282
  ///
282 283
  /// \brief Hypercube graph class
283 284
  ///
284 285
  /// This class implements a special graph type. The nodes of the graph
285 286
  /// are indiced with integers with at most \c dim binary digits.
286 287
  /// Two nodes are connected in the graph if and only if their indices
287 288
  /// differ only on one position in the binary form.
288 289
  ///
289 290
  /// \note The type of the indices is chosen to \c int for efficiency
290 291
  /// reasons. Thus the maximum dimension of this implementation is 26
291 292
  /// (assuming that the size of \c int is 32 bit).
292 293
  ///
293 294
  /// This graph type is fully conform to the \ref concepts::Graph
294 295
  /// "Graph" concept, and it also has an important extra feature
295 296
  /// that its maps are real \ref concepts::ReferenceMap
296 297
  /// "reference map"s.
297 298
  class HypercubeGraph : public ExtendedHypercubeGraphBase {
298 299
  public:
299 300

	
300 301
    typedef ExtendedHypercubeGraphBase Parent;
301 302

	
302 303
    /// \brief Constructs a hypercube graph with \c dim dimensions.
303 304
    ///
304 305
    /// Constructs a hypercube graph with \c dim dimensions.
305 306
    HypercubeGraph(int dim) { construct(dim); }
306 307

	
307 308
    /// \brief The number of dimensions.
308 309
    ///
309 310
    /// Gives back the number of dimensions.
310 311
    int dimension() const {
311 312
      return Parent::dimension();
312 313
    }
313 314

	
314 315
    /// \brief Returns \c true if the n'th bit of the node is one.
315 316
    ///
316 317
    /// Returns \c true if the n'th bit of the node is one.
317 318
    bool projection(Node node, int n) const {
318 319
      return Parent::projection(node, n);
319 320
    }
320 321

	
321 322
    /// \brief The dimension id of an edge.
322 323
    ///
323 324
    /// Gives back the dimension id of the given edge.
324 325
    /// It is in the [0..dim-1] range.
325 326
    int dimension(Edge edge) const {
326 327
      return Parent::dimension(edge);
327 328
    }
328 329

	
329 330
    /// \brief The dimension id of an arc.
330 331
    ///
331 332
    /// Gives back the dimension id of the given arc.
332 333
    /// It is in the [0..dim-1] range.
333 334
    int dimension(Arc arc) const {
334 335
      return Parent::dimension(arc);
335 336
    }
336 337

	
337 338
    /// \brief The index of a node.
338 339
    ///
339 340
    /// Gives back the index of the given node.
340 341
    /// The lower bits of the integer describes the node.
341 342
    int index(Node node) const {
342 343
      return Parent::index(node);
343 344
    }
344 345

	
345 346
    /// \brief Gives back a node by its index.
346 347
    ///
347 348
    /// Gives back a node by its index.
348 349
    Node operator()(int ix) const {
349 350
      return Parent::operator()(ix);
350 351
    }
351 352

	
352 353
    /// \brief Number of nodes.
353 354
    int nodeNum() const { return Parent::nodeNum(); }
Ignore white space 192 line context
... ...
@@ -228,172 +228,172 @@
228 228

	
229 229
  check(!g.valid(n1), "Wrong validity check");
230 230
  check(g.valid(n2), "Wrong validity check");
231 231
  check(g.valid(n3), "Wrong validity check");
232 232
  check(!g.valid(e1), "Wrong validity check");
233 233
  check(g.valid(e2), "Wrong validity check");
234 234

	
235 235
  check(!g.valid(g.nodeFromId(-1)), "Wrong validity check");
236 236
  check(!g.valid(g.edgeFromId(-1)), "Wrong validity check");
237 237
  check(!g.valid(g.arcFromId(-1)), "Wrong validity check");
238 238
}
239 239

	
240 240
void checkGridGraph(int width, int height) {
241 241
  typedef GridGraph Graph;
242 242
  GRAPH_TYPEDEFS(Graph);
243 243
  Graph G(width, height);
244 244

	
245 245
  check(G.width() == width, "Wrong column number");
246 246
  check(G.height() == height, "Wrong row number");
247 247

	
248 248
  for (int i = 0; i < width; ++i) {
249 249
    for (int j = 0; j < height; ++j) {
250 250
      check(G.col(G(i, j)) == i, "Wrong column");
251 251
      check(G.row(G(i, j)) == j, "Wrong row");
252 252
      check(G.pos(G(i, j)).x == i, "Wrong column");
253 253
      check(G.pos(G(i, j)).y == j, "Wrong row");
254 254
    }
255 255
  }
256 256

	
257 257
  for (int j = 0; j < height; ++j) {
258 258
    for (int i = 0; i < width - 1; ++i) {
259 259
      check(G.source(G.right(G(i, j))) == G(i, j), "Wrong right");
260 260
      check(G.target(G.right(G(i, j))) == G(i + 1, j), "Wrong right");
261 261
    }
262 262
    check(G.right(G(width - 1, j)) == INVALID, "Wrong right");
263 263
  }
264 264

	
265 265
  for (int j = 0; j < height; ++j) {
266 266
    for (int i = 1; i < width; ++i) {
267 267
      check(G.source(G.left(G(i, j))) == G(i, j), "Wrong left");
268 268
      check(G.target(G.left(G(i, j))) == G(i - 1, j), "Wrong left");
269 269
    }
270 270
    check(G.left(G(0, j)) == INVALID, "Wrong left");
271 271
  }
272 272

	
273 273
  for (int i = 0; i < width; ++i) {
274 274
    for (int j = 0; j < height - 1; ++j) {
275 275
      check(G.source(G.up(G(i, j))) == G(i, j), "Wrong up");
276 276
      check(G.target(G.up(G(i, j))) == G(i, j + 1), "Wrong up");
277 277
    }
278 278
    check(G.up(G(i, height - 1)) == INVALID, "Wrong up");
279 279
  }
280 280

	
281 281
  for (int i = 0; i < width; ++i) {
282 282
    for (int j = 1; j < height; ++j) {
283 283
      check(G.source(G.down(G(i, j))) == G(i, j), "Wrong down");
284 284
      check(G.target(G.down(G(i, j))) == G(i, j - 1), "Wrong down");
285 285
    }
286 286
    check(G.down(G(i, 0)) == INVALID, "Wrong down");
287 287
  }
288 288

	
289 289
  checkGraphNodeList(G, width * height);
290 290
  checkGraphEdgeList(G, width * (height - 1) + (width - 1) * height);
291 291
  checkGraphArcList(G, 2 * (width * (height - 1) + (width - 1) * height));
292 292

	
293 293
  for (NodeIt n(G); n != INVALID; ++n) {
294 294
    int nb = 4;
295 295
    if (G.col(n) == 0) --nb;
296 296
    if (G.col(n) == width - 1) --nb;
297 297
    if (G.row(n) == 0) --nb;
298 298
    if (G.row(n) == height - 1) --nb;
299 299

	
300 300
    checkGraphOutArcList(G, n, nb);
301 301
    checkGraphInArcList(G, n, nb);
302 302
    checkGraphIncEdgeList(G, n, nb);
303 303
  }
304 304

	
305 305
  checkArcDirections(G);
306 306

	
307 307
  checkGraphConArcList(G, 2 * (width * (height - 1) + (width - 1) * height));
308 308
  checkGraphConEdgeList(G, width * (height - 1) + (width - 1) * height);
309 309

	
310 310
  checkNodeIds(G);
311 311
  checkArcIds(G);
312 312
  checkEdgeIds(G);
313 313
  checkGraphNodeMap(G);
314 314
  checkGraphArcMap(G);
315 315
  checkGraphEdgeMap(G);
316 316

	
317 317
}
318 318

	
319 319
void checkHypercubeGraph(int dim) {
320 320
  GRAPH_TYPEDEFS(HypercubeGraph);
321 321

	
322 322
  HypercubeGraph G(dim);
323 323
  checkGraphNodeList(G, 1 << dim);
324
  checkGraphEdgeList(G, dim * (1 << dim-1));
324
  checkGraphEdgeList(G, dim * (1 << (dim-1)));
325 325
  checkGraphArcList(G, dim * (1 << dim));
326 326

	
327 327
  Node n = G.nodeFromId(dim);
328 328

	
329 329
  for (NodeIt n(G); n != INVALID; ++n) {
330 330
    checkGraphIncEdgeList(G, n, dim);
331 331
    for (IncEdgeIt e(G, n); e != INVALID; ++e) {
332 332
      check( (G.u(e) == n &&
333
              G.id(G.v(e)) == G.id(n) ^ (1 << G.dimension(e))) ||
333
              G.id(G.v(e)) == (G.id(n) ^ (1 << G.dimension(e)))) ||
334 334
             (G.v(e) == n &&
335
              G.id(G.u(e)) == G.id(n) ^ (1 << G.dimension(e))),
335
              G.id(G.u(e)) == (G.id(n) ^ (1 << G.dimension(e)))),
336 336
             "Wrong edge or wrong dimension");
337 337
    }
338 338

	
339 339
    checkGraphOutArcList(G, n, dim);
340 340
    for (OutArcIt a(G, n); a != INVALID; ++a) {
341 341
      check(G.source(a) == n &&
342
            G.id(G.target(a)) == G.id(n) ^ (1 << G.dimension(a)),
342
            G.id(G.target(a)) == (G.id(n) ^ (1 << G.dimension(a))),
343 343
            "Wrong arc or wrong dimension");
344 344
    }
345 345

	
346 346
    checkGraphInArcList(G, n, dim);
347 347
    for (InArcIt a(G, n); a != INVALID; ++a) {
348 348
      check(G.target(a) == n &&
349
            G.id(G.source(a)) == G.id(n) ^ (1 << G.dimension(a)),
349
            G.id(G.source(a)) == (G.id(n) ^ (1 << G.dimension(a))),
350 350
            "Wrong arc or wrong dimension");
351 351
    }
352 352
  }
353 353

	
354 354
  checkGraphConArcList(G, (1 << dim) * dim);
355
  checkGraphConEdgeList(G, dim * (1 << dim-1));
355
  checkGraphConEdgeList(G, dim * (1 << (dim-1)));
356 356

	
357 357
  checkArcDirections(G);
358 358

	
359 359
  checkNodeIds(G);
360 360
  checkArcIds(G);
361 361
  checkEdgeIds(G);
362 362
  checkGraphNodeMap(G);
363 363
  checkGraphArcMap(G);
364 364
  checkGraphEdgeMap(G);
365 365
}
366 366

	
367 367
void checkGraphs() {
368 368
  { // Checking ListGraph
369 369
    checkGraph<ListGraph>();
370 370
    checkGraphValidityErase<ListGraph>();
371 371
  }
372 372
  { // Checking SmartGraph
373 373
    checkGraph<SmartGraph>();
374 374
    checkGraphValidity<SmartGraph>();
375 375
  }
376 376
  { // Checking FullGraph
377 377
    checkFullGraph(7);
378 378
    checkFullGraph(8);
379 379
  }
380 380
  { // Checking GridGraph
381 381
    checkGridGraph(5, 8);
382 382
    checkGridGraph(8, 5);
383 383
    checkGridGraph(5, 5);
384 384
    checkGridGraph(0, 0);
385 385
    checkGridGraph(1, 1);
386 386
  }
387 387
  { // Checking HypercubeGraph
388 388
    checkHypercubeGraph(1);
389 389
    checkHypercubeGraph(2);
390 390
    checkHypercubeGraph(3);
391 391
    checkHypercubeGraph(4);
392 392
  }
393 393
}
394 394

	
395 395
int main() {
396 396
  checkConcepts();
397 397
  checkGraphs();
398 398
  return 0;
399 399
}
0 comments (0 inline)