ABC: A System for Sequential Synthesis and Verification
 
Loading...
Searching...
No Matches
range.hpp
Go to the documentation of this file.
1#ifndef _range_hpp_INCLUDED
2#define _range_hpp_INCLUDED
3
4#include "global.h"
5
6#include <cassert>
7
9
10namespace CaDiCaL {
11
12struct Clause;
13
14/*----------------------------------------------------------------------*/
15
16// Used for compact and safe iteration over positive ranges of integers,
17// particularly for iterating over all variable indices.
18//
19// Range vars (max_var);
20// for (auto idx : vars) ...
21//
22// This iterates over '1, ..., max_var' and is safe for non-negative
23// numbers, thus also for 'max_var == 0' or 'max_var == INT_MAX'.
24//
25// Note that
26//
27// for (int idx = 1; idx <= max_var; idx++) ...
28//
29// leads to an overflow if 'max_var == INT_MAX' and thus depending on what
30// the compiler does ('int' overflow is undefined) might lead to any
31// behaviour (infinite loop or worse array access way out of bounds).
32//
33// If we make 'idx' in this last 'for' loop an 'unsigned' then it is safe to
34// use this idiom, but we would need to cast 'max_var' explicitly to 'int'
35// in order to avoid a warning in the loop condition and actually everywhere
36// where 'idx' is compared to a 'signed' expression. Worse for instance
37// 'vals[-idx]' will lead to out of bounds access too. This is awkward and
38// using the range iterator provided here is safer in general.
39//
40// Another issue is that the dereferencing operator '*' below is required to
41// return a reference to the internal index of the iterator. Thus the 'idx'
42// in the auto loop is actually of the same type as the internal state of
43// the iterator. To keep it 'signed' and still avoid overflow issues we
44// just have to make sure to use the proper increment (with two implicit
45// casts, i.e., from 'int' to 'unsigned', then 'unsigned' addition and the
46// result is cast back from 'unsigned' to 'int').
47//
48// For simplicity we keep a reference to the actual maximum integer, e.g.,
49// 'max_var', which makes the idiom 'for (auto idx : vars) ...' possible.
50// Further note that the referenced integer has to be non-negative before
51// starting to iterate (it can be zero though), otherwise it breaks.
52
53class Range {
54 static unsigned inc (unsigned u) { return u + 1u; }
55 class iterator {
56 int idx;
57
58 public:
59 iterator (int i) : idx (i) {}
60 void operator++ () { idx = inc (idx); }
61 const int &operator* () const { return idx; }
62 friend bool operator!= (const iterator &a, const iterator &b) {
63 return a.idx != b.idx;
64 }
65 };
66 int &n;
67
68public:
69 iterator begin () const { return CADICAL_assert (n >= 0), iterator (inc (0)); }
70 iterator end () const { return CADICAL_assert (n >= 0), iterator (inc (n)); }
71 Range (int &m) : n (m) { CADICAL_assert (m >= 0); }
72};
73
74// Same, but iterating over literals '-1,1,-2,2,....,-max_var,max_var'.
75//
76// The only difference to 'Range' is the 'inc' function, but I am too lazy
77// to figure out how to properly factor the code into a generic range
78// template with 'inc' as only parameter. This gives at least clean code.
79
80class Sange {
81 static unsigned inc (unsigned u) { return ~u + (u >> 31); }
82 class iterator {
83 int lit;
84
85 public:
86 iterator (int i) : lit (i) {}
87 void operator++ () { lit = inc (lit); }
88 const int &operator* () const { return lit; }
89 friend bool operator!= (const iterator &a, const iterator &b) {
90 return a.lit != b.lit;
91 }
92 };
93 int &n;
94
95public:
96 iterator begin () const { return CADICAL_assert (n >= 0), iterator (inc (0)); }
97 iterator end () const { return CADICAL_assert (n >= 0), iterator (inc (n)); }
98 Sange (int &m) : n (m) { CADICAL_assert (m >= 0); }
99};
100
101} // namespace CaDiCaL
102
104
105#endif
#define ABC_NAMESPACE_CXX_HEADER_START
#define ABC_NAMESPACE_CXX_HEADER_END
#define CADICAL_assert(ignore)
Definition global.h:14
iterator end() const
Definition range.hpp:70
iterator begin() const
Definition range.hpp:69
Range(int &m)
Definition range.hpp:71
iterator end() const
Definition range.hpp:97
Sange(int &m)
Definition range.hpp:98
iterator begin() const
Definition range.hpp:96
int lit
Definition satVec.h:130