nysol-zdd 3.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +7 -0
  2. data/ext/zdd_so/BDD.cc +495 -0
  3. data/ext/zdd_so/BDD.h +356 -0
  4. data/ext/zdd_so/BDDDG.cc +1818 -0
  5. data/ext/zdd_so/BDDDG.h +107 -0
  6. data/ext/zdd_so/BDDHASH.cc +91 -0
  7. data/ext/zdd_so/BtoI.cc +503 -0
  8. data/ext/zdd_so/BtoI.h +144 -0
  9. data/ext/zdd_so/CtoI.cc +1072 -0
  10. data/ext/zdd_so/CtoI.h +186 -0
  11. data/ext/zdd_so/MLZBDDV.cc +153 -0
  12. data/ext/zdd_so/MLZBDDV.h +42 -0
  13. data/ext/zdd_so/SOP.cc +608 -0
  14. data/ext/zdd_so/SOP.h +199 -0
  15. data/ext/zdd_so/ZBDD.cc +1035 -0
  16. data/ext/zdd_so/ZBDD.h +243 -0
  17. data/ext/zdd_so/ZBDDDG.cc +1834 -0
  18. data/ext/zdd_so/ZBDDDG.h +105 -0
  19. data/ext/zdd_so/ZBDDHASH.cc +91 -0
  20. data/ext/zdd_so/bddc.c +2816 -0
  21. data/ext/zdd_so/bddc.h +132 -0
  22. data/ext/zdd_so/extconf.rb +25 -0
  23. data/ext/zdd_so/include/aheap.c +211 -0
  24. data/ext/zdd_so/include/aheap.h +111 -0
  25. data/ext/zdd_so/include/base.c +93 -0
  26. data/ext/zdd_so/include/base.h +60 -0
  27. data/ext/zdd_so/include/itemset.c +473 -0
  28. data/ext/zdd_so/include/itemset.h +153 -0
  29. data/ext/zdd_so/include/problem.c +371 -0
  30. data/ext/zdd_so/include/problem.h +160 -0
  31. data/ext/zdd_so/include/queue.c +518 -0
  32. data/ext/zdd_so/include/queue.h +177 -0
  33. data/ext/zdd_so/include/sgraph.c +331 -0
  34. data/ext/zdd_so/include/sgraph.h +170 -0
  35. data/ext/zdd_so/include/stdlib2.c +832 -0
  36. data/ext/zdd_so/include/stdlib2.h +746 -0
  37. data/ext/zdd_so/include/trsact.c +723 -0
  38. data/ext/zdd_so/include/trsact.h +167 -0
  39. data/ext/zdd_so/include/vec.c +583 -0
  40. data/ext/zdd_so/include/vec.h +159 -0
  41. data/ext/zdd_so/lcm-vsop.cc +596 -0
  42. data/ext/zdd_so/print.cc +683 -0
  43. data/ext/zdd_so/table.cc +330 -0
  44. data/ext/zdd_so/vsop.h +88 -0
  45. data/ext/zdd_so/zdd_so.cpp +3277 -0
  46. data/lib/nysol/zdd.rb +31 -0
  47. metadata +131 -0
@@ -0,0 +1,105 @@
1
+ /*****************************************
2
+ * ZZBDDDG - Decomposition Graph *
3
+ * (SAPPORO-1.02) - Header *
4
+ * (C) Shin-ichi MINATO (Aug. 8, 2005) *
5
+ *****************************************/
6
+
7
+ #ifndef _ZBDDDG_
8
+ #define _ZBDDDG_
9
+
10
+ #include "ZBDD.h"
11
+
12
+ #define ZBDDDG_InitSize 4
13
+
14
+ #define ZBDDDG_NIL BDD_MaxNode
15
+
16
+ #define ZBDDDG_C0 1
17
+ #define ZBDDDG_P1 2
18
+ #define ZBDDDG_LIT 3
19
+ #define ZBDDDG_AND 4
20
+ #define ZBDDDG_OR 5
21
+ #define ZBDDDG_OTHER 6
22
+
23
+ class ZBDDDG
24
+ {
25
+ struct Node;
26
+ struct NodeLink
27
+ {
28
+ bddword _ndx;
29
+ bddword _nxt;
30
+ NodeLink(void){ _ndx = ZBDDDG_NIL; _nxt = ZBDDDG_NIL; }
31
+ };
32
+
33
+ bddword _nodeSize;
34
+ bddword _nodeUsed;
35
+ bddword _linkSize;
36
+ bddword _linkUsed;
37
+ bddword* _hashWheel;
38
+ Node* _nodeA;
39
+ NodeLink* _linkA;
40
+ bddword _c0;
41
+ bddword _c1;
42
+
43
+ bddword HashIndex(ZBDD);
44
+ bddword NewNdx(ZBDD, char);
45
+ int EnlargeNode(void);
46
+ bddword NewLkx(bddword);
47
+ int EnlargeLink(void);
48
+ int LinkNodes(bddword, bddword);
49
+ int Merge3(bddword, bddword, bddword);
50
+ ZBDD Func0(ZBDD, ZBDD);
51
+ ZBDD Func1(ZBDD, ZBDD);
52
+ int LinkNodesC3(bddword, bddword);
53
+ void Print0(bddword);
54
+ bddword Merge(ZBDD, bddword, bddword);
55
+ bddword ReferNdx(ZBDD);
56
+ int PhaseSweep(bddword);
57
+ void MarkSweep(bddword);
58
+ void MarkSweepR(bddword);
59
+ int Mark1(bddword);
60
+ void Mark2R(bddword);
61
+ int MarkChkR(bddword);
62
+ void Mark3R(bddword);
63
+ bddword Mark4R(bddword, bddword, bddword);
64
+ bddword Mark5R(bddword, bddword, bddword);
65
+ void Mark6R(bddword, bddword);
66
+ bddword AppendR(bddword, int, bddword, bddword);
67
+
68
+ struct Node
69
+ {
70
+ bddword _lkx;
71
+ ZBDD _f;
72
+ bddword _ndxP;
73
+ char _type; // NULL, C1, P1, LIT, OR, XOR, OTHER
74
+ char _mark;
75
+ Node(void);
76
+ Node(ZBDD, char);
77
+ };
78
+
79
+ public:
80
+ ZBDDDG(void);
81
+ ~ZBDDDG(void);
82
+ void Clear(void);
83
+ bddword NodeUsed(void);
84
+ int PrintDecomp(ZBDD);
85
+ bddword Decomp(ZBDD);
86
+
87
+ friend class ZBDDDG_Tag;
88
+ };
89
+
90
+ class ZBDDDG_Tag
91
+ {
92
+ ZBDDDG* _dg;
93
+ bddword _ndx;
94
+ bddword _lkx;
95
+ public:
96
+ ZBDDDG_Tag(void);
97
+ int Set(ZBDDDG *, bddword);
98
+ bddword TopNdx(void);
99
+ bddword NextNdx(void);
100
+ char Type(void);
101
+ ZBDD Func(void);
102
+ };
103
+
104
+ #endif // _ZBDDDG_
105
+
@@ -0,0 +1,91 @@
1
+ /****************************************
2
+ * ZBDD+ Manipulator (SAPPORO-1.59) *
3
+ * (Hash table methods) *
4
+ * (C) Shin-ichi MINATO (Dec. 10, 2013) *
5
+ ****************************************/
6
+
7
+ #include "ZBDD.h"
8
+
9
+ using std::cerr;
10
+
11
+ ZBDD_Hash::ZBDD_Hash()
12
+ {
13
+ _hashSize = 16;
14
+ _wheel = new ZBDD_Entry[_hashSize];
15
+ _amount = 0;
16
+ }
17
+
18
+ ZBDD_Hash::~ZBDD_Hash() { delete[] _wheel; }
19
+
20
+ void ZBDD_Hash::Clear()
21
+ {
22
+ if(_hashSize != 0) delete[] _wheel;
23
+ _hashSize = 16;
24
+ _wheel = new ZBDD_Entry[_hashSize];
25
+ _amount = 0;
26
+ }
27
+
28
+ ZBDD_Hash::ZBDD_Entry* ZBDD_Hash::GetEntry(ZBDD key)
29
+ {
30
+ bddword id = key.GetID();
31
+ bddword hash = (id+(id>>10)+(id>>20)) & (_hashSize - 1);
32
+ bddword i = hash;
33
+ while(_wheel[i]._key != -1)
34
+ {
35
+ if(key == _wheel[i]._key) return & _wheel[i];
36
+ i++;
37
+ i &= (_hashSize -1);
38
+ }
39
+ i = hash;
40
+ while(_wheel[i]._key != -1)
41
+ {
42
+ if(_wheel[i]._ptr == 0) break;
43
+ i++;
44
+ i &= (_hashSize -1);
45
+ }
46
+ return & _wheel[i];
47
+ }
48
+
49
+ void ZBDD_Hash::Enlarge()
50
+ {
51
+ bddword oldSize = _hashSize;
52
+ ZBDD_Entry* oldWheel = _wheel;
53
+
54
+ _hashSize <<= 2;
55
+ _wheel = new ZBDD_Entry[_hashSize];
56
+ if(_wheel == 0)
57
+ {
58
+ cerr << "<ERROR> ZBDD_Hash::Enlarge(): Memory overflow (";
59
+ cerr << _hashSize << ")\n";
60
+ exit(1);
61
+ }
62
+ _amount = 0;
63
+ for(bddword i=0; i<oldSize; i++)
64
+ if(oldWheel[i]._ptr != 0)
65
+ if(oldWheel[i]._key != -1)
66
+ Enter(oldWheel[i]._key, oldWheel[i]._ptr);
67
+ delete[] oldWheel;
68
+ }
69
+
70
+ void ZBDD_Hash::Enter(ZBDD key, void* ptr)
71
+ // ptr = 0 means deleting.
72
+ {
73
+ ZBDD_Entry* ent = GetEntry(key);
74
+ if(ent -> _key == -1) _amount++;
75
+ else if(ent -> _ptr == 0) _amount++;
76
+ if(ptr == 0) _amount--;
77
+ ent -> _key = key;
78
+ ent -> _ptr = ptr;
79
+ if(_amount >= (_hashSize>>1)) Enlarge();
80
+ }
81
+
82
+ void* ZBDD_Hash::Refer(ZBDD key)
83
+ // returns 0 if not found.
84
+ {
85
+ ZBDD_Entry* ent = GetEntry(key);
86
+ if(ent -> _key == -1) return 0;
87
+ return ent -> _ptr;
88
+ }
89
+
90
+ bddword ZBDD_Hash::Amount() { return _amount; }
91
+
@@ -0,0 +1,2816 @@
1
+ /*****************************************
2
+ * BDD Package (SAPPORO-1.70) - Body *
3
+ * (C) Shin-ichi MINATO (Sep. 16, 2015) *
4
+ ******************************************/
5
+
6
+ #include <stdio.h>
7
+ #include <stdlib.h>
8
+ #include "bddc.h"
9
+
10
+ /* ----------------- MACRO Definitions ---------------- */
11
+ /* Operation IDs in Cache */
12
+ #define BC_NULL 0
13
+ #define BC_AND 1
14
+ #define BC_XOR 2
15
+ #define BC_AT0 3
16
+ #define BC_AT1 4
17
+ #define BC_LSHIFT 5
18
+ #define BC_RSHIFT 6
19
+ #define BC_COFACTOR 7
20
+ #define BC_UNIV 8
21
+ #define BC_SUPPORT 9
22
+ #define BC_INTERSEC 10
23
+ #define BC_UNION 11
24
+ #define BC_SUBTRACT 12
25
+ #define BC_OFFSET 13
26
+ #define BC_ONSET 14
27
+ #define BC_CHANGE 15
28
+ #define BC_CARD 16
29
+ #define BC_LIT 17
30
+ #define BC_LEN 18
31
+
32
+ /* Macros for malloc, realloc */
33
+ #define B_MALLOC(type, size) \
34
+ (type *)malloc(sizeof(type) * size)
35
+ #define B_REALLOC(ptr, type, size) \
36
+ (type *)realloc(ptr, sizeof(type) * size)
37
+
38
+ /* Printf format of bddp */
39
+ #ifdef B_64
40
+ # define B_BDDP_FD "%lld"
41
+ # define B_BDDP_FX "0x%llX"
42
+ #else
43
+ # define B_BDDP_FD "%d"
44
+ # define B_BDDP_FX "0x%X"
45
+ #endif
46
+
47
+ /* strtol or strtoll */
48
+ #ifdef B_64
49
+ # define B_STRTOI strtoll
50
+ #else
51
+ # define B_STRTOI strtol
52
+ #endif
53
+
54
+ /* Table spaces */
55
+ #define B_NODE_MAX (B_VAL_MASK>>1U) /* Max number of BDD nodes */
56
+ #define B_NODE_SPC0 256 /* Default initial node size */
57
+ #define B_VAR_SPC0 16 /* Initial var table size */
58
+ #define B_HASH_SPC0 4 /* Initial hash size */
59
+ #define B_RFCT_SPC0 4 /* Initial RFCT size */
60
+
61
+ /* Negative edge manipulation */
62
+ #define B_NEG(f) ((f) & B_INV_MASK)
63
+ #define B_NOT(f) ((f) ^ B_INV_MASK)
64
+ #define B_ABS(f) ((f) & ~B_INV_MASK)
65
+
66
+ /* Constant node manipulation */
67
+ #define B_CST(f) ((f) & B_CST_MASK)
68
+ #define B_VAL(f) ((f) & B_VAL_MASK)
69
+
70
+ /* Conversion of bddp and node index/pointer */
71
+ #define B_NP(f) (Node+(B_ABS(f)>>1U))
72
+ #define B_NDX(f) (B_ABS(f)>>1U)
73
+ #define B_BDDP_NP(p) ((bddp)((p)-Node) << 1U)
74
+
75
+ /* Read & Write of bddp field in the tables */
76
+ #ifdef B_64
77
+ # define B_LOW32(f) ((bddp_32)((f)&((1ULL<<32U)-1U)))
78
+ # define B_HIGH8(f) ((bddp_h8)((f)>>32U))
79
+ # define B_SET_NXP(p, f, i) \
80
+ (p ## _h8 = f ## _h8 + i, p ## _32 = f ## _32 + i)
81
+ # define B_GET_BDDP(f) \
82
+ ((bddp) f ## _32 | ((bddp) f ## _h8 << 32U))
83
+ # define B_SET_BDDP(f, g) \
84
+ (f ## _h8 = B_HIGH8(g), f ## _32 = B_LOW32(g))
85
+ # define B_CPY_BDDP(f, g) \
86
+ (f ## _h8 = g ## _h8, f ## _32 = g ## _32)
87
+ #else
88
+ # define B_SET_NXP(p, f, i) (p ## _32 = f ## _32 + i)
89
+ # define B_GET_BDDP(f) (f ## _32)
90
+ # define B_SET_BDDP(f, g) (f ## _32 = g)
91
+ # define B_CPY_BDDP(f, g) (f ## _32 = g ## _32)
92
+ #endif /* B_64 */
93
+
94
+ /* var & rfc manipulation */
95
+ #define B_VAR_NP(p) ((p)->varrfc & B_VAR_MASK)
96
+ #define B_RFC_MASK (~B_VAR_MASK)
97
+ #define B_RFC_UNIT (1U << B_VAR_WIDTH)
98
+ #define B_RFC_NP(p) ((p)->varrfc >> B_VAR_WIDTH)
99
+ #define B_RFC_ZERO_NP(p) ((p)->varrfc < B_RFC_UNIT)
100
+ #define B_RFC_ONE_NP(p) (((p)->varrfc & B_RFC_MASK) == B_RFC_UNIT)
101
+ #define B_RFC_INC_NP(p) \
102
+ (((p)->varrfc < B_RFC_MASK - B_RFC_UNIT)? \
103
+ ((p)->varrfc += B_RFC_UNIT, 0) : rfc_inc_ovf(p))
104
+ #define B_RFC_DEC_NP(p) \
105
+ (((p)->varrfc >= B_RFC_MASK)? rfc_dec_ovf(p): \
106
+ (B_RFC_ZERO_NP(p))? \
107
+ err("B_RFC_DEC_NP: rfc under flow", p-Node): \
108
+ ((p)->varrfc -= B_RFC_UNIT, 0))
109
+
110
+ /* ----------- Stack overflow limitter ------------ */
111
+ const int BDD_RecurLimit = 8192;
112
+ int BDD_RecurCount = 0;
113
+ #define BDD_RECUR_INC \
114
+ {if(++BDD_RecurCount >= BDD_RecurLimit) \
115
+ err("BDD_RECUR_INC: Recursion Limit", BDD_RecurCount);}
116
+ #define BDD_RECUR_DEC BDD_RecurCount--
117
+
118
+ /* Conversion of ZBDD node flag */
119
+ #define B_Z_NP(p) ((p)->f0_32 & (bddp_32)B_INV_MASK)
120
+
121
+ /* Hash Functions */
122
+ #define B_HASHKEY(f0, f1, hashSpc) \
123
+ (((B_CST(f0)? (f0): (f0)+2U) \
124
+ ^(B_NEG(f0)? ~((f0)>>1U): ((f0)>>1U)) \
125
+ ^(B_CST(f1)? (f1)<<1U: ((f1)+2U)<<1U) \
126
+ ^(B_NEG(f1)? ~((f1)>>1U): ((f1)>>1U)) )\
127
+ & (hashSpc-1U))
128
+ /* (((f0)^((f0)>>10)^((f0)>>31)^(f1)^((f1)>>8)^((f1)>>31)) \*/
129
+ #define B_CACHEKEY(op, f, g) \
130
+ ((((bddp)(op)<<2U) \
131
+ ^(B_CST(f)? (f): (f)+2U) \
132
+ ^(B_NEG(f)? ~((f)>>1U): ((f)>>1U)) \
133
+ ^(B_CST(g)? (g)<<3U: ((g)+2U)<<3U) \
134
+ ^(B_NEG(g)? ~((g)>>1U): ((g)>>1U)) )\
135
+ & (CacheSpc-1U))
136
+
137
+ /* ------- Declaration of static (internal) data ------- */
138
+ /* typedef of bddp field in the tables */
139
+ typedef unsigned int bddp_32;
140
+ #ifdef B_64
141
+ typedef unsigned char bddp_h8;
142
+ #endif
143
+
144
+ /* Declaration of Node table */
145
+ struct B_NodeTable
146
+ {
147
+ bddp_32 f0_32; /* 0-edge */
148
+ bddp_32 f1_32; /* 1-edge */
149
+ bddp_32 nx_32; /* Node index */
150
+ unsigned int varrfc; /* VarID & Reference counter */
151
+ #ifdef B_64
152
+ bddp_h8 f0_h8; /* Extention of 0-edge */
153
+ bddp_h8 f1_h8; /* Extention of 1-edge */
154
+ bddp_h8 nx_h8; /* Extention of node index */
155
+ #endif /* B_64 */
156
+ };
157
+ static struct B_NodeTable *Node = 0; /* Node Table */
158
+ static bddp NodeLimit = 0; /* Final limit size */
159
+ static bddp NodeUsed = 0; /* Number of used node */
160
+ static bddp Avail = bddnull; /* Head of available node */
161
+ static bddp NodeSpc = 0; /* Current Node-Table size */
162
+
163
+ /* Declaration of Hash-table per Var */
164
+ struct B_VarTable
165
+ {
166
+ bddp hashSpc; /* Current hash-table size */
167
+ bddp hashUsed; /* Current used entries */
168
+ bddvar lev; /* Level of the variable */
169
+ bddp_32 *hash_32; /* Hash-table */
170
+ #ifdef B_64
171
+ bddp_h8 *hash_h8; /* Extension of hash-table */
172
+ #endif /* B_64 */
173
+ };
174
+ static struct B_VarTable *Var = 0; /* Var-tables */
175
+ static bddvar *VarID = 0; /* VarID reverse table */
176
+ static bddvar VarUsed = 0; /* Number of used Var */
177
+ static bddvar VarSpc = 0; /* Current Var-table size */
178
+
179
+ /* Declaration of Operation Cache */
180
+ struct B_CacheTable
181
+ {
182
+ bddp_32 f_32; /* an operand BDD */
183
+ bddp_32 g_32; /* an operand BDD */
184
+ bddp_32 h_32; /* Result BDD */
185
+ unsigned char op; /* Operation code */
186
+ #ifdef B_64
187
+ bddp_h8 f_h8; /* Extention of an operand BDD */
188
+ bddp_h8 g_h8; /* Extention of an operand BDD */
189
+ bddp_h8 h_h8; /* Extention of result BDD */
190
+ #endif /* B_64 */
191
+ };
192
+ static struct B_CacheTable *Cache = 0; /* Opeartion cache */
193
+ static bddp CacheSpc = 0; /* Current cache size */
194
+
195
+ /* Declaration of RFC-table */
196
+ struct B_RFC_Table
197
+ {
198
+ bddp_32 nx_32; /* Node index */
199
+ bddp_32 rfc_32; /* RFC */
200
+ #ifdef B_64
201
+ bddp_h8 nx_h8; /* Extension of Node index */
202
+ bddp_h8 rfc_h8; /* Extension of RFC */
203
+ #endif /* B_64 */
204
+ };
205
+ static struct B_RFC_Table *RFCT = 0; /* RFC-Table */
206
+ static bddp RFCT_Spc; /* Current RFC-table size */
207
+ static bddp RFCT_Used; /* Current RFC-table used entries */
208
+
209
+ /* ----- Declaration of static (internal) functions ------ */
210
+ /* Private procedure */
211
+ static int err B_ARG((char *msg, bddp num));
212
+ static int rfc_inc_ovf B_ARG((struct B_NodeTable *np));
213
+ static int rfc_dec_ovf B_ARG((struct B_NodeTable *np));
214
+ static void var_enlarge B_ARG((void));
215
+ static int node_enlarge B_ARG((void));
216
+ static int hash_enlarge B_ARG((bddvar v));
217
+ static bddp getnode B_ARG((bddvar v, bddp f0, bddp f1));
218
+ static bddp getbddp B_ARG((bddvar v, bddp f0, bddp f1));
219
+ static bddp getzbddp B_ARG((bddvar v, bddp f0, bddp f1));
220
+ static bddp apply B_ARG((bddp f, bddp g, unsigned char op, unsigned char skip));
221
+ static void gc1 B_ARG((struct B_NodeTable *np));
222
+ static bddp count B_ARG((bddp f));
223
+ static void dump B_ARG((bddp f));
224
+ static void reset B_ARG((bddp f));
225
+ static void export B_ARG((FILE *strm, bddp f));
226
+ static int import B_ARG((FILE *strm, bddp *p, int lim, int z));
227
+ static int andfalse B_ARG((bddp f, bddp g));
228
+
229
+
230
+ /* ------------------ Body of program -------------------- */
231
+ /* ----------------- External functions ------------------ */
232
+ int bddinit(initsize, limitsize)
233
+ bddp initsize;
234
+ bddp limitsize;
235
+ /* Returns 1 if not enough memory (usually 0) */
236
+ {
237
+ bddp ix;
238
+ bddvar i;
239
+
240
+ /* Check dupulicate initialization */
241
+ if(Node) free(Node);
242
+ if(Var)
243
+ {
244
+ for(i=0; i<VarSpc; i++)
245
+ {
246
+ if(Var[i].hash_32) free(Var[i].hash_32);
247
+ #ifdef B_64
248
+ if(Var[i].hash_h8) free(Var[i].hash_h8);
249
+ #endif
250
+ }
251
+ free(Var);
252
+ }
253
+ if(VarID) free(VarID);
254
+ if(Cache) free(Cache);
255
+ if(RFCT) free(RFCT);
256
+
257
+ /* Set NodeLimit */
258
+ if(limitsize < B_NODE_SPC0) NodeLimit = B_NODE_SPC0;
259
+ else if(limitsize > B_NODE_MAX) NodeLimit = B_NODE_MAX;
260
+ else NodeLimit = limitsize;
261
+
262
+ /* Set NodeSpc */
263
+ if(initsize < B_NODE_SPC0) NodeSpc = B_NODE_SPC0;
264
+ else if(initsize > NodeLimit) NodeSpc = NodeLimit;
265
+ else NodeSpc = initsize;
266
+
267
+ /* Set CacheSpc */
268
+ for(CacheSpc=B_NODE_SPC0; CacheSpc<NodeSpc>>1; CacheSpc<<=1U)
269
+ ; /* empty */
270
+
271
+ /* Set VarSpc */
272
+ VarSpc = B_VAR_SPC0;
273
+
274
+ /* Memory allocation */
275
+ Node = B_MALLOC(struct B_NodeTable, NodeSpc);
276
+ Var = B_MALLOC(struct B_VarTable, VarSpc);
277
+ VarID = B_MALLOC(bddvar, VarSpc);
278
+ Cache = B_MALLOC(struct B_CacheTable, CacheSpc);
279
+
280
+ /* Check overflow */
281
+ if(Node == 0 || Var == 0 || VarID == 0 || Cache == 0)
282
+ {
283
+ if(Cache){ free(Cache); Cache = 0; }
284
+ if(VarID){ free(VarID); VarID = 0; }
285
+ if(Var){ free(Var); Var = 0; }
286
+ if(Node){ free(Node); Node = 0; }
287
+ NodeLimit = 0;
288
+ return 1;
289
+ }
290
+
291
+ /* Initialize */
292
+ NodeUsed = 0;
293
+ Node[NodeSpc-1U].varrfc = 0;
294
+ B_SET_BDDP(Node[NodeSpc-1U].nx, bddnull);
295
+ for(ix=0; ix<NodeSpc-1U; ix++)
296
+ {
297
+ Node[ix].varrfc = 0;
298
+ B_SET_BDDP(Node[ix].nx, ix+1U);
299
+ }
300
+ Avail = 0;
301
+
302
+ VarUsed = 0;
303
+ for(i=0; i<VarSpc; i++)
304
+ {
305
+ Var[i].hashSpc = 0;
306
+ Var[i].hashUsed = 0;
307
+ Var[i].lev = i;
308
+ VarID[i] = i;
309
+ Var[i].hash_32 = 0;
310
+ #ifdef B_64
311
+ Var[i].hash_h8 = 0;
312
+ #endif
313
+ }
314
+
315
+ for(ix=0; ix<CacheSpc; ix++) Cache[ix].op = BC_NULL;
316
+
317
+ RFCT_Spc = 0;
318
+ RFCT_Used = 0;
319
+
320
+ return 0;
321
+ }
322
+
323
+ bddp bddcopy(f)
324
+ bddp f;
325
+ {
326
+ struct B_NodeTable *fp;
327
+
328
+ if(f == bddnull) return bddnull;
329
+ if(B_CST(f)) return f; /* Constant */
330
+ fp = B_NP(f);
331
+ if(fp >= Node+NodeSpc || fp->varrfc == 0)
332
+ err("bddcopy: Invalid bddp", f);
333
+ B_RFC_INC_NP(fp);
334
+ return f;
335
+ }
336
+
337
+ void bddfree(f)
338
+ bddp f;
339
+ {
340
+ struct B_NodeTable *fp;
341
+
342
+ if(f == bddnull) return;
343
+ if(B_CST(f)) return; /* Constant */
344
+ fp = B_NP(f);
345
+ if(fp >= Node+NodeSpc || fp->varrfc == 0)
346
+ err("bddfree: Invalid bddp", f);
347
+ B_RFC_DEC_NP(fp);
348
+ }
349
+
350
+ int bddgc()
351
+ /* Returns 1 if there are no free node (usually 0) */
352
+ {
353
+ bddp i, n, f;
354
+ struct B_NodeTable *fp;
355
+ struct B_CacheTable *cachep;
356
+ struct B_NodeTable *np;
357
+ struct B_VarTable *varp;
358
+ bddvar v;
359
+ bddp oldSpc, newSpc, nx, key, f0, f1;
360
+ bddp_32 *newhash_32, *p_32, *p2_32;
361
+ #ifdef B_64
362
+ bddp_h8 *newhash_h8, *p_h8, *p2_h8;
363
+ #endif
364
+
365
+ n = NodeUsed;
366
+ for(fp=Node; fp<Node+NodeSpc; fp++)
367
+ if(fp->varrfc != 0 && B_RFC_ZERO_NP(fp))
368
+ gc1(fp);
369
+ if(n == NodeUsed) return 1; /* No free node */
370
+
371
+ /* Cache clear */
372
+ for(cachep=Cache; cachep<Cache+CacheSpc; cachep++)
373
+ {
374
+ switch(cachep->op)
375
+ {
376
+ case BC_NULL:
377
+ break;
378
+ case BC_AND:
379
+ case BC_XOR:
380
+ case BC_INTERSEC:
381
+ case BC_UNION:
382
+ case BC_SUBTRACT:
383
+ case BC_CHANGE:
384
+ f = B_GET_BDDP(cachep->f);
385
+ if(!B_CST(f) && (fp=B_NP(f))<Node+NodeSpc && fp->varrfc == 0)
386
+ {
387
+ cachep->op = BC_NULL;
388
+ break;
389
+ }
390
+ f = B_GET_BDDP(cachep->g);
391
+ if(!B_CST(f) && (fp=B_NP(f))<Node+NodeSpc && fp->varrfc == 0)
392
+ {
393
+ cachep->op = BC_NULL;
394
+ break;
395
+ }
396
+ f = B_GET_BDDP(cachep->h);
397
+ if(!B_CST(f) && (fp=B_NP(f))<Node+NodeSpc && fp->varrfc == 0)
398
+ {
399
+ cachep->op = BC_NULL;
400
+ break;
401
+ }
402
+ break;
403
+ case BC_AT0:
404
+ case BC_AT1:
405
+ case BC_OFFSET:
406
+ case BC_ONSET:
407
+ f = B_GET_BDDP(cachep->f);
408
+ if(!B_CST(f) && (fp=B_NP(f))<Node+NodeSpc && fp->varrfc == 0)
409
+ {
410
+ cachep->op = BC_NULL;
411
+ break;
412
+ }
413
+ f = B_GET_BDDP(cachep->h);
414
+ if(!B_CST(f) && (fp=B_NP(f))<Node+NodeSpc && fp->varrfc == 0)
415
+ {
416
+ cachep->op = BC_NULL;
417
+ break;
418
+ }
419
+ break;
420
+ case BC_CARD:
421
+ case BC_LIT:
422
+ case BC_LEN:
423
+ f = B_GET_BDDP(cachep->f);
424
+ if(!B_CST(f) && (fp=B_NP(f))<Node+NodeSpc && fp->varrfc == 0)
425
+ {
426
+ cachep->op = BC_NULL;
427
+ break;
428
+ }
429
+ break;
430
+ default:
431
+ cachep->op = BC_NULL;
432
+ break;
433
+ }
434
+ }
435
+
436
+ /* Hash-table packing */
437
+ for(v=1; v<=VarUsed; v++)
438
+ {
439
+ varp = &Var[v];
440
+
441
+ /* Get new size */
442
+ oldSpc = varp->hashSpc;
443
+ newSpc = oldSpc;
444
+ while(newSpc > B_HASH_SPC0)
445
+ {
446
+ if(newSpc>>2 < varp->hashUsed) break;
447
+ newSpc >>= 1;
448
+ }
449
+ if(newSpc == oldSpc) continue;
450
+
451
+ /* Reduce space */
452
+ #ifdef B_64
453
+ newhash_32 = B_MALLOC(bddp_32, newSpc);
454
+ newhash_h8 = B_MALLOC(bddp_h8, newSpc);
455
+ if(!newhash_32 || !newhash_h8)
456
+ {
457
+ if(newhash_32) free(newhash_32);
458
+ if(newhash_h8) free(newhash_h8);
459
+ break; /* Not enough memory */
460
+ }
461
+ #else
462
+ newhash_32 = B_MALLOC(bddp_32, newSpc);
463
+ if(!newhash_32) break; /* Not enough memory */
464
+ #endif
465
+
466
+ /* Initialize new hash entry */
467
+ for(i=0; i<newSpc; i++)
468
+ {
469
+ B_SET_NXP(p, newhash, i);
470
+ B_SET_BDDP(*p, bddnull);
471
+ }
472
+
473
+ /* restore hash entry */
474
+ for(i=0; i<oldSpc; i++)
475
+ {
476
+ key = i & (newSpc-1U);
477
+ np = 0;
478
+ B_SET_NXP(p, newhash, key);
479
+ nx = B_GET_BDDP(*p);
480
+ while(nx != bddnull)
481
+ {
482
+ np = Node + nx;
483
+ nx = B_GET_BDDP(np->nx);
484
+ }
485
+ if(np) { B_SET_NXP(p2, varp->hash, i); B_CPY_BDDP(np->nx, *p2); }
486
+ else
487
+ {
488
+ B_SET_NXP(p, newhash, key);
489
+ B_SET_NXP(p2, varp->hash, i);
490
+ B_CPY_BDDP(*p, *p2);
491
+ }
492
+ }
493
+ varp->hashSpc = newSpc;
494
+ free(varp->hash_32);
495
+ varp->hash_32 = newhash_32;
496
+ #ifdef B_64
497
+ free(varp->hash_h8);
498
+ varp->hash_h8 = newhash_h8;
499
+ #endif
500
+ }
501
+ return 0;
502
+ }
503
+
504
+ bddp bddused() { return NodeUsed; }
505
+
506
+ bddp bddsize(f)
507
+ bddp f;
508
+ /* Returns 0 for bddnull */
509
+ {
510
+ bddp num;
511
+ struct B_NodeTable *fp;
512
+
513
+ if(f == bddnull) return 0;
514
+ if(B_CST(f)) return 0; /* Constant */
515
+ if((fp=B_NP(f))>=Node+NodeSpc || fp->varrfc == 0)
516
+ err("bddsize: Invalid bddp", f);
517
+
518
+ num = count(f);
519
+ reset(f);
520
+ return num;
521
+ }
522
+
523
+ bddp bddvsize(p, lim)
524
+ bddp *p;
525
+ int lim;
526
+ /* Returns 0 for bddnull */
527
+ {
528
+ bddp num;
529
+ struct B_NodeTable *fp;
530
+ int n, i;
531
+
532
+ /* Check operand */
533
+ n = lim;
534
+ for(i=0; i<n; i++)
535
+ {
536
+ if(p[i] == bddnull)
537
+ {
538
+ n = i;
539
+ break;
540
+ }
541
+ if(!B_CST(p[i])&&
542
+ ((fp=B_NP(p[i]))>=Node+NodeSpc || fp->varrfc==0))
543
+ err("bddvsize: Invalid bddp", p[i]);
544
+ }
545
+ num = 0;
546
+ for(i=0; i<n; i++) num += count(p[i]);
547
+ for(i=0; i<n; i++) reset(p[i]);
548
+ return num;
549
+ }
550
+
551
+ void bddexport(strm, p, lim)
552
+ FILE *strm;
553
+ bddp *p;
554
+ int lim;
555
+ {
556
+ struct B_NodeTable *fp;
557
+ int n, i, lev, lev0;
558
+
559
+ /* Check operands */
560
+ n = lim;
561
+ lev = 0;
562
+ for(i=0; i<n; i++)
563
+ {
564
+ if(p[i] == bddnull)
565
+ {
566
+ n = i;
567
+ break;
568
+ }
569
+ if(!B_CST(p[i])&&
570
+ ((fp=B_NP(p[i]))>=Node+NodeSpc || fp->varrfc==0))
571
+ err("bddvexport: Invalid bddp", p[i]);
572
+ lev0 = bddlevofvar(bddtop(p[i]));
573
+ if(lev0 > lev) lev = lev0;
574
+ }
575
+
576
+ fprintf(strm, "_i %d\n_o %d\n_n ", lev, n);
577
+ fprintf(strm, B_BDDP_FD, bddvsize(p, n));
578
+ fprintf(strm, "\n");
579
+
580
+ /* Put internal nodes */
581
+ for(i=0; i<n; i++) export(strm, p[i]);
582
+ for(i=0; i<n; i++) reset(p[i]);
583
+
584
+ /* Put external node */
585
+ for(i=0; i<n; i++)
586
+ {
587
+ if(p[i] == bddfalse) fprintf(strm, "F");
588
+ else if(p[i] == bddtrue) fprintf(strm, "T");
589
+ else fprintf(strm, B_BDDP_FD, p[i]);
590
+ fprintf(strm, "\n");
591
+ }
592
+ }
593
+
594
+ void bdddump(f)
595
+ bddp f;
596
+ {
597
+ struct B_NodeTable *fp;
598
+
599
+ /* Check indexes */
600
+ if(f == bddnull) { printf("RT = NULL\n\n"); return; }
601
+ if(!B_CST(f)&&
602
+ ((fp=B_NP(f))>=Node+NodeSpc || fp->varrfc==0))
603
+ err("bdddump: Invalid bddp", f);
604
+
605
+ /* Dump nodes */
606
+ dump(f);
607
+ reset(f);
608
+
609
+ /* Dump top node */
610
+ printf("RT = ");
611
+ if(B_NEG(f)) putchar('~');
612
+ if(B_CST(f)) printf(B_BDDP_FD, B_ABS(B_VAL(f)));
613
+ else { printf("N"); printf(B_BDDP_FD, B_NDX(f)); }
614
+ printf("\n\n");
615
+ }
616
+
617
+ void bddvdump(p, n)
618
+ bddp *p;
619
+ int n;
620
+ {
621
+ struct B_NodeTable *fp;
622
+ int i;
623
+
624
+ /* Check operands */
625
+ for(i=0; i<n; i++)
626
+ {
627
+ if(p[i] == bddnull) return;
628
+ if(!B_CST(p[i])&&
629
+ ((fp=B_NP(p[i]))>=Node+NodeSpc || fp->varrfc==0))
630
+ err("bddvdump: Invalid bddp", p[i]);
631
+ }
632
+
633
+ /* Dump nodes */
634
+ for(i=0; i<n; i++) if(p[i] != bddnull) dump(p[i]);
635
+ for(i=0; i<n; i++) if(p[i] != bddnull) reset(p[i]);
636
+
637
+ /* Dump top node */
638
+ for(i=0; i<n; i++)
639
+ {
640
+ printf("RT%d = ", i);
641
+ if(p[i] == bddnull) printf("NULL");
642
+ else
643
+ {
644
+ if(B_NEG(p[i])) putchar('~');
645
+ if(B_CST(p[i])) printf(B_BDDP_FD, B_ABS(B_VAL(p[i])));
646
+ else { printf("N"); printf(B_BDDP_FD, B_NDX(p[i])); }
647
+ }
648
+ putchar('\n');
649
+ }
650
+ printf("\n");
651
+ }
652
+
653
+ bddp bddrcache(op, f, g)
654
+ unsigned char op;
655
+ bddp f, g;
656
+ {
657
+ struct B_CacheTable *cachep;
658
+
659
+ cachep = Cache + B_CACHEKEY(op, f, g);
660
+ if(op == cachep->op &&
661
+ f == B_GET_BDDP(cachep->f) &&
662
+ g == B_GET_BDDP(cachep->g))
663
+ return B_GET_BDDP(cachep->h); /* Hit */
664
+ return bddnull;
665
+ }
666
+
667
+ void bddwcache(op, f, g, h)
668
+ unsigned char op;
669
+ bddp f, g, h;
670
+ {
671
+ struct B_CacheTable *cachep;
672
+
673
+ if(op < 20) err("bddwcache: op < 20", op);
674
+ if(h == bddnull) return;
675
+ cachep = Cache + B_CACHEKEY(op, f, g);
676
+ cachep->op = op;
677
+ B_SET_BDDP(cachep->f, f);
678
+ B_SET_BDDP(cachep->g, g);
679
+ B_SET_BDDP(cachep->h, h);
680
+ }
681
+
682
+ bddp bddnot(f)
683
+ bddp f;
684
+ {
685
+ if(f == bddnull) return bddnull;
686
+ return B_NOT(bddcopy(f));
687
+ }
688
+
689
+ bddvar bddlevofvar(v)
690
+ bddvar v;
691
+ {
692
+ if(v > VarUsed)
693
+ err("bddlevofvar: Invalid VarID", v);
694
+ return Var[v].lev;
695
+ }
696
+
697
+ bddvar bddvaroflev(lev)
698
+ bddvar lev;
699
+ {
700
+ if(lev > VarUsed)
701
+ err("bddvaroflev: Invalid level", lev);
702
+ return VarID[lev];
703
+ }
704
+
705
+ bddvar bddvarused()
706
+ {
707
+ return VarUsed;
708
+ }
709
+
710
+ bddvar bddnewvar()
711
+ {
712
+ if(++VarUsed == VarSpc) var_enlarge();
713
+ return VarUsed;
714
+ }
715
+
716
+ bddvar bddnewvaroflev(lev)
717
+ bddvar lev;
718
+ {
719
+ bddvar i, v;
720
+
721
+ if(lev == 0 || lev > ++VarUsed)
722
+ err("bddnewvaroflev: Invalid level", lev);
723
+ if(VarUsed == VarSpc) var_enlarge();
724
+ for(i=VarUsed; i>lev; i--) Var[ VarID[i] = VarID[i-1U] ].lev = i;
725
+ Var[ VarID[lev] = VarUsed ].lev = lev;
726
+ return VarUsed;
727
+ }
728
+
729
+ bddvar bddtop(f)
730
+ bddp f;
731
+ {
732
+ struct B_NodeTable *fp;
733
+
734
+ if(f == bddnull) return 0;
735
+ if(B_CST(f)) return 0; /* Constant */
736
+ fp = B_NP(f);
737
+ if(fp >= Node+NodeSpc || fp->varrfc == 0)
738
+ err("bddtop: Invalid bddp", f);
739
+ return B_VAR_NP(fp);
740
+ }
741
+
742
+ bddp bddprime(v)
743
+ bddvar v;
744
+ /* Returns bddnull if not enough memory */
745
+ {
746
+ if(v == 0 || v > VarUsed)
747
+ err("bddprime: Invalid VarID", v);
748
+ return getbddp(v, bddfalse, bddtrue);
749
+ }
750
+
751
+
752
+ bddp bddand(f, g)
753
+ bddp f, g;
754
+ /* Returns bddnull if not enough memory */
755
+ {
756
+ struct B_NodeTable *fp;
757
+
758
+ /* Check operands */
759
+ if(f == bddnull) return bddnull;
760
+ if(g == bddnull) return bddnull;
761
+ if(B_CST(f))
762
+ { if(B_ABS(f) != bddfalse) err("bddand: Invalid bddp", f); }
763
+ else
764
+ {
765
+ fp = B_NP(f);
766
+ if(fp>=Node+NodeSpc || !fp->varrfc)
767
+ err("bddand: Invalid bddp", f);
768
+ if(B_Z_NP(fp)) err("bddand: applying ZBDD node", f);
769
+ }
770
+ if(B_CST(g))
771
+ { if(B_ABS(g) != bddfalse) err("bddand: Invalid bddp", g); }
772
+ else
773
+ {
774
+ fp = B_NP(g);
775
+ if(fp>=Node+NodeSpc || !fp->varrfc)
776
+ err("bddand: Invalid bddp", g);
777
+ if(B_Z_NP(fp)) err("bddand: applying ZBDD node", g);
778
+ }
779
+
780
+ return apply(f, g, BC_AND, 0);
781
+ }
782
+
783
+ bddp bddor(f, g)
784
+ bddp f, g;
785
+ /* Returns bddnull if not enough memory */
786
+ {
787
+ bddp h;
788
+
789
+ if(f == bddnull) return bddnull;
790
+ if(g == bddnull) return bddnull;
791
+ h = bddand(B_NOT(f), B_NOT(g));
792
+ if(h == bddnull) return bddnull;
793
+ return B_NOT(h);
794
+ }
795
+
796
+ bddp bddxor(f, g)
797
+ bddp f, g;
798
+ /* Returns bddnull if not enough memory */
799
+ {
800
+ struct B_NodeTable *fp;
801
+
802
+ /* Check operands */
803
+ if(f == bddnull) return bddnull;
804
+ if(g == bddnull) return bddnull;
805
+ if(B_CST(f))
806
+ { if(B_ABS(f) != bddfalse) err("bddand: Invalid bddp", f); }
807
+ else
808
+ {
809
+ fp = B_NP(f);
810
+ if(fp>=Node+NodeSpc || !fp->varrfc)
811
+ err("bddxor: Invalid bddp", f);
812
+ if(B_Z_NP(fp)) err("bddand: applying ZBDD node", f);
813
+ }
814
+ if(B_CST(g))
815
+ { if(B_ABS(g) != bddfalse) err("bddand: Invalid bddp", g); }
816
+ else
817
+ {
818
+ fp = B_NP(g);
819
+ if(fp>=Node+NodeSpc || !fp->varrfc)
820
+ err("bddxor: Invalid bddp", g);
821
+ if(B_Z_NP(fp)) err("bddand: applying ZBDD node", g);
822
+ }
823
+
824
+ return apply(f, g, BC_XOR, 0);
825
+ }
826
+
827
+ bddp bddnand(f, g)
828
+ bddp f, g;
829
+ /* Returns bddnull if not enough memory */
830
+ {
831
+ bddp h;
832
+
833
+ h = bddand(f, g);
834
+ if(h == bddnull) return bddnull;
835
+ return B_NOT(h);
836
+ }
837
+
838
+ bddp bddnor(f, g)
839
+ bddp f, g;
840
+ /* Returns bddnull if not enough memory */
841
+ {
842
+ if(f == bddnull) return bddnull;
843
+ if(g == bddnull) return bddnull;
844
+ return bddand(B_NOT(f), B_NOT(g));
845
+ }
846
+
847
+ bddp bddxnor(f, g)
848
+ bddp f, g;
849
+ /* Returns bddnull if not enough memory */
850
+ {
851
+ if(g == bddnull) return bddnull;
852
+ return bddxor(f, B_NOT(g));
853
+ }
854
+
855
+ bddp bddcofactor(f, g)
856
+ bddp f, g;
857
+ /* Returns bddnull if not enough memory */
858
+ {
859
+ struct B_NodeTable *fp;
860
+
861
+ /* Check operands */
862
+ if(f == bddnull) return bddnull;
863
+ if(g == bddnull) return bddnull;
864
+ if(B_CST(f))
865
+ { if(B_ABS(f) != bddfalse) err("bddcofactor: Invalid bddp", f); }
866
+ else
867
+ {
868
+ fp = B_NP(f);
869
+ if(fp>=Node+NodeSpc || !fp->varrfc)
870
+ err("bddcofactor: Invalid bddp", f);
871
+ if(B_Z_NP(fp)) err("bddcofactor: applying ZBDD node", f);
872
+ }
873
+ if(B_CST(g))
874
+ { if(B_ABS(g) != bddfalse) err("bddcofactor: Invalid bddp", g); }
875
+ else
876
+ {
877
+ fp = B_NP(g);
878
+ if(fp>=Node+NodeSpc || !fp->varrfc)
879
+ err("bddcofactor: Invalid bddp", g);
880
+ if(B_Z_NP(fp)) err("bddcofactor: applying ZBDD node", g);
881
+ }
882
+
883
+ return apply(f, g, BC_COFACTOR, 0);
884
+ }
885
+
886
+ bddp bdduniv(f, g)
887
+ bddp f, g;
888
+ /* Returns bddnull if not enough memory */
889
+ {
890
+ struct B_NodeTable *fp;
891
+
892
+ /* Check operands */
893
+ if(f == bddnull) return bddnull;
894
+ if(g == bddnull) return bddnull;
895
+ if(B_CST(f))
896
+ { if(B_ABS(f) != bddfalse) err("bdduniv: Invalid bddp", f); }
897
+ else
898
+ {
899
+ fp = B_NP(f);
900
+ if(fp>=Node+NodeSpc || !fp->varrfc)
901
+ err("bdduniv: Invalid bddp", f);
902
+ if(B_Z_NP(fp)) err("bdduniv: applying ZBDD node", f);
903
+ }
904
+ if(B_CST(g))
905
+ { if(B_ABS(g) != bddfalse) err("bdduniv: Invalid bddp", g); }
906
+ else
907
+ {
908
+ fp = B_NP(g);
909
+ if(fp>=Node+NodeSpc || !fp->varrfc)
910
+ err("bdduniv: Invalid bddp", g);
911
+ if(B_Z_NP(fp)) err("bdduniv: applying ZBDD node", g);
912
+ }
913
+
914
+ return apply(f, g, BC_UNIV, 0);
915
+ }
916
+
917
+ bddp bddexist(f, g)
918
+ bddp f, g;
919
+ /* Returns bddnull if not enough memory */
920
+ {
921
+ bddp h;
922
+
923
+ if(f == bddnull) return bddnull;
924
+ if(g == bddnull) return bddnull;
925
+ h = bdduniv(B_NOT(f), g);
926
+ if(h == bddnull) return bddnull;
927
+ return B_NOT(h);
928
+ }
929
+
930
+ int bddimply(f, g)
931
+ bddp f, g;
932
+ {
933
+ struct B_NodeTable *fp;
934
+
935
+ /* Check operands */
936
+ if(f == bddnull) return 0;
937
+ if(g == bddnull) return 0;
938
+ if(B_CST(f))
939
+ { if(B_ABS(f) != bddfalse) err("bddimply: Invalid bddp", f); }
940
+ else
941
+ {
942
+ fp = B_NP(f);
943
+ if(fp>=Node+NodeSpc || !fp->varrfc)
944
+ err("bddimply: Invalid bddp", f);
945
+ if(B_Z_NP(fp)) err("bddimply: applying ZBDD node", f);
946
+ }
947
+ if(B_CST(g))
948
+ { if(B_ABS(g) != bddfalse) err("bddimply: Invalid bddp", g); }
949
+ else
950
+ {
951
+ fp = B_NP(g);
952
+ if(fp>=Node+NodeSpc || !fp->varrfc)
953
+ err("bddimply: Invalid bddp", g);
954
+ if(B_Z_NP(fp)) err("bddimply: applying ZBDD node", g);
955
+ }
956
+
957
+ return ! andfalse(f, B_NOT(g));
958
+ }
959
+
960
+ bddp bddsupport(f)
961
+ bddp f;
962
+ /* Returns bddnull if not enough memory */
963
+ {
964
+ struct B_NodeTable *fp;
965
+
966
+ /* Check operands */
967
+ if(f == bddnull) return bddnull;
968
+ if(B_CST(f)) return bddfalse;
969
+ fp = B_NP(f);
970
+ if(fp>=Node+NodeSpc || !fp->varrfc)
971
+ err("bddsupport: Invalid bddp", f);
972
+
973
+ return apply(f, bddfalse, BC_SUPPORT, 0);
974
+ }
975
+
976
+ bddp bddat0(f, v)
977
+ bddp f;
978
+ bddvar v;
979
+ /* Returns bddnull if not enough memory */
980
+ {
981
+ struct B_NodeTable *fp;
982
+
983
+ /* Check operands */
984
+ if(v > VarUsed || v == 0) err("bddat0: Invalid VarID", v);
985
+ if(f == bddnull) return bddnull;
986
+ if(B_CST(f)) return f;
987
+ fp = B_NP(f);
988
+ if(fp>=Node+NodeSpc || !fp->varrfc)
989
+ err("bddat0: Invalid bddp", f);
990
+
991
+ return apply(f, (bddp)v, BC_AT0, 0);
992
+ }
993
+
994
+ bddp bddat1(f, v)
995
+ bddp f;
996
+ bddvar v;
997
+ /* Returns bddnull if not enough memory */
998
+ {
999
+ struct B_NodeTable *fp;
1000
+
1001
+ /* Check operands */
1002
+ if(v > VarUsed || v == 0) err("bddat1: Invalid VarID", v);
1003
+ if(f == bddnull) return bddnull;
1004
+ if(B_CST(f)) return f;
1005
+ fp = B_NP(f);
1006
+ if(fp>=Node+NodeSpc || !fp->varrfc)
1007
+ err("bddat1: Invalid bddp", f);
1008
+
1009
+ return apply(f, (bddp)v, BC_AT1, 0);
1010
+ }
1011
+
1012
+ bddp bddlshift(f, shift)
1013
+ bddp f;
1014
+ bddvar shift;
1015
+ /* Returns bddnull if not enough memory */
1016
+ {
1017
+ struct B_NodeTable *fp;
1018
+ bddvar flev;
1019
+
1020
+ /* Check operands */
1021
+ if(shift >= VarUsed)
1022
+ err("bddlshift: Invalid shift", shift);
1023
+ if(f == bddnull) return bddnull;
1024
+ if(B_CST(f)) return f;
1025
+ if(shift == 0) return bddcopy(f);
1026
+ if((fp=B_NP(f))>=Node+NodeSpc || !fp->varrfc)
1027
+ err("bddlshift: Invalid bddp", f);
1028
+
1029
+ return apply(f, (bddp)shift, BC_LSHIFT, 0);
1030
+ }
1031
+
1032
+ bddp bddrshift(f, shift)
1033
+ bddp f;
1034
+ bddvar shift;
1035
+ /* Returns bddnull if not enough memory */
1036
+ {
1037
+ struct B_NodeTable *fp;
1038
+ bddvar flev;
1039
+
1040
+ /* Check operands */
1041
+ if(shift >= VarUsed)
1042
+ err("bddrshift: Invalid shift", shift);
1043
+ if(f == bddnull) return bddnull;
1044
+ if(B_CST(f)) return f;
1045
+ if(shift == 0) return bddcopy(f);
1046
+ if((fp=B_NP(f))>=Node+NodeSpc || !fp->varrfc)
1047
+ err("bddrshift: Invalid bddp", f);
1048
+
1049
+ return apply(f, (bddp)shift, BC_RSHIFT, 0);
1050
+ }
1051
+
1052
+ bddp bddoffset(f, v)
1053
+ bddp f;
1054
+ bddvar v;
1055
+ /* Returns bddnull if not enough memory */
1056
+ {
1057
+ struct B_NodeTable *fp;
1058
+
1059
+ /* Check operands */
1060
+ if(v > VarUsed || v == 0) err("bddoffset: Invalid VarID", v);
1061
+ if(f == bddnull) return bddnull;
1062
+ if(B_CST(f)) return f;
1063
+ fp = B_NP(f);
1064
+ if(fp>=Node+NodeSpc || !fp->varrfc)
1065
+ err("bddoffset: Invalid bddp", f);
1066
+ if(!B_Z_NP(fp)) err("bddoffset: applying non-ZBDD node", f);
1067
+
1068
+ return apply(f, (bddp)v, BC_OFFSET, 0);
1069
+ }
1070
+
1071
+ bddp bddonset0(f, v)
1072
+ bddp f;
1073
+ bddvar v;
1074
+ /* Returns bddnull if not enough memory */
1075
+ {
1076
+ struct B_NodeTable *fp;
1077
+
1078
+ /* Check operands */
1079
+ if(v > VarUsed || v == 0) err("bddonset0: Invalid VarID", v);
1080
+ if(f == bddnull) return bddnull;
1081
+ if(B_CST(f)) return bddfalse;
1082
+ fp = B_NP(f);
1083
+ if(fp>=Node+NodeSpc || !fp->varrfc)
1084
+ err("bddonset0: Invalid bddp", f);
1085
+ if(!B_Z_NP(fp)) err("bddonset0: applying non-ZBDD node", f);
1086
+
1087
+ return apply(f, (bddp)v, BC_ONSET, 0);
1088
+ }
1089
+
1090
+ bddp bddonset(f, v)
1091
+ bddp f;
1092
+ bddvar v;
1093
+ /* Returns bddnull if not enough memory */
1094
+ {
1095
+ bddp g, h;
1096
+
1097
+ g = bddonset0(f, v);
1098
+ h = bddchange(g, v);
1099
+ bddfree(g);
1100
+ return h;
1101
+ }
1102
+
1103
+ bddp bddchange(f, v)
1104
+ bddp f;
1105
+ bddvar v;
1106
+ /* Returns bddnull if not enough memory */
1107
+ {
1108
+ struct B_NodeTable *fp;
1109
+
1110
+ /* Check operands */
1111
+ if(v > VarUsed || v == 0) err("bddchange: Invalid VarID", v);
1112
+ if(f == bddnull) return bddnull;
1113
+ if(!B_CST(f))
1114
+ {
1115
+ fp = B_NP(f);
1116
+ if(fp>=Node+NodeSpc || !fp->varrfc)
1117
+ err("bddchange: Invalid bddp", f);
1118
+ if(!B_Z_NP(fp)) err("bddchange: applying non-ZBDD node", f);
1119
+ }
1120
+
1121
+ return apply(f, (bddp)v, BC_CHANGE, 0);
1122
+ }
1123
+
1124
+ bddp bddintersec(f, g)
1125
+ bddp f, g;
1126
+ /* Returns bddnull if not enough memory */
1127
+ {
1128
+ struct B_NodeTable *fp;
1129
+
1130
+ /* Check operands */
1131
+ if(f == bddnull) return bddnull;
1132
+ if(g == bddnull) return bddnull;
1133
+ if(B_CST(f))
1134
+ { if(B_ABS(f) != bddfalse) err("bddintersec: Invalid bddp", f); }
1135
+ else
1136
+ {
1137
+ fp = B_NP(f);
1138
+ if(fp>=Node+NodeSpc || !fp->varrfc)
1139
+ err("bddintersec: Invalid bddp", f);
1140
+ if(!B_Z_NP(fp)) err("bddintersec: applying non-ZBDD node", f);
1141
+ }
1142
+ if(B_CST(g))
1143
+ { if(B_ABS(g) != bddfalse) err("bddintersec: Invalid bddp", g); }
1144
+ else
1145
+ {
1146
+ fp = B_NP(g);
1147
+ if(fp>=Node+NodeSpc || !fp->varrfc)
1148
+ err("bddintersec: Invalid bddp", g);
1149
+ if(!B_Z_NP(fp)) err("bddintersec: applying non-ZBDD node", g);
1150
+ }
1151
+
1152
+ return apply(f, g, BC_INTERSEC, 0);
1153
+ }
1154
+
1155
+ bddp bddunion(f, g)
1156
+ bddp f, g;
1157
+ /* Returns bddnull if not enough memory */
1158
+ {
1159
+ struct B_NodeTable *fp;
1160
+
1161
+ /* Check operands */
1162
+ if(f == bddnull) return bddnull;
1163
+ if(g == bddnull) return bddnull;
1164
+ if(B_CST(f))
1165
+ { if(B_ABS(f) != bddfalse) err("bddunion: Invalid bddp", f); }
1166
+ else
1167
+ {
1168
+ fp = B_NP(f);
1169
+ if(fp>=Node+NodeSpc || !fp->varrfc)
1170
+ err("bddunion: Invalid bddp", f);
1171
+ if(!B_Z_NP(fp)) err("bddunion: applying non-ZBDD node", f);
1172
+ }
1173
+ if(B_CST(g))
1174
+ { if(B_ABS(g) != bddfalse) err("bddunion: Invalid bddp", g); }
1175
+ else
1176
+ {
1177
+ fp = B_NP(g);
1178
+ if(fp>=Node+NodeSpc || !fp->varrfc)
1179
+ err("bddunion: Invalid bddp", g);
1180
+ if(!B_Z_NP(fp)) err("bddunion: applying non-ZBDD node", g);
1181
+ }
1182
+
1183
+ return apply(f, g, BC_UNION, 0);
1184
+ }
1185
+
1186
+ bddp bddsubtract(f, g)
1187
+ bddp f, g;
1188
+ /* Returns bddnull if not enough memory */
1189
+ {
1190
+ struct B_NodeTable *fp;
1191
+
1192
+ /* Check operands */
1193
+ if(f == bddnull) return bddnull;
1194
+ if(g == bddnull) return bddnull;
1195
+ if(B_CST(f))
1196
+ { if(B_ABS(f) != bddfalse) err("bddsubtract: Invalid bddp", f); }
1197
+ else
1198
+ {
1199
+ fp = B_NP(f);
1200
+ if(fp>=Node+NodeSpc || !fp->varrfc)
1201
+ err("bddsubtarct: Invalid bddp", f);
1202
+ if(!B_Z_NP(fp)) err("bddsubtarct: applying non-ZBDD node", f);
1203
+ }
1204
+ if(B_CST(g))
1205
+ { if(B_ABS(g) != bddfalse) err("bddsubtarct: Invalid bddp", g); }
1206
+ else
1207
+ {
1208
+ fp = B_NP(g);
1209
+ if(fp>=Node+NodeSpc || !fp->varrfc)
1210
+ err("bddsubtarct: Invalid bddp", g);
1211
+ if(!B_Z_NP(fp)) err("bddsubtarct: applying non-ZBDD node", g);
1212
+ }
1213
+
1214
+ return apply(f, g, BC_SUBTRACT, 0);
1215
+ }
1216
+
1217
+ bddp bddcard(f)
1218
+ bddp f;
1219
+ {
1220
+ struct B_NodeTable *fp;
1221
+
1222
+ if(f == bddnull) return 0;
1223
+ if(B_CST(f)) return (f == bddempty)? 0: 1;
1224
+ fp = B_NP(f);
1225
+ if(fp>=Node+NodeSpc || !fp->varrfc)
1226
+ err("bddcard: Invalid bddp", f);
1227
+ if(!B_Z_NP(fp)) err("bddcard: applying non-ZBDD node", f);
1228
+
1229
+ return apply(f, bddempty, BC_CARD, 0);
1230
+ }
1231
+
1232
+ bddp bddlit(f)
1233
+ bddp f;
1234
+ {
1235
+ struct B_NodeTable *fp;
1236
+
1237
+ if(f == bddnull) return 0;
1238
+ if(B_CST(f)) return 0;
1239
+ fp = B_NP(f);
1240
+ if(fp>=Node+NodeSpc || !fp->varrfc)
1241
+ err("bddlit: Invalid bddp", f);
1242
+ if(!B_Z_NP(fp)) err("bddlit: applying non-ZBDD node", f);
1243
+
1244
+ return apply(f, bddempty, BC_LIT, 0);
1245
+ }
1246
+
1247
+ bddp bddlen(f)
1248
+ bddp f;
1249
+ {
1250
+ struct B_NodeTable *fp;
1251
+
1252
+ if(f == bddnull) return 0;
1253
+ if(B_CST(f)) return 0;
1254
+ fp = B_NP(f);
1255
+ if(fp>=Node+NodeSpc || !fp->varrfc)
1256
+ err("bddlen: Invalid bddp", f);
1257
+ if(!B_Z_NP(fp)) err("bddlen: applying non-ZBDD node", f);
1258
+
1259
+ return apply(f, bddempty, BC_LEN, 0);
1260
+ }
1261
+
1262
+
1263
+
1264
+ /* ----------------- Internal functions ------------------ */
1265
+ static void var_enlarge()
1266
+ {
1267
+ bddvar i, newSpc;
1268
+ struct B_VarTable *newVar;
1269
+ unsigned int *newVarID;
1270
+
1271
+ /* Get new size */
1272
+ if(VarSpc == bddvarmax+1U)
1273
+ err("var_enlarge: var index range full", VarSpc);
1274
+ newSpc = VarSpc << 2U;
1275
+ if(newSpc > bddvarmax+1) newSpc = bddvarmax+1U;
1276
+
1277
+ /* Enlarge space */
1278
+ newVar = B_MALLOC(struct B_VarTable, newSpc);
1279
+ newVarID = B_MALLOC(unsigned int, newSpc);
1280
+ if(newVar && newVarID)
1281
+ {
1282
+ for(i=0; i<VarSpc; i++)
1283
+ {
1284
+ newVar[i].hashSpc = Var[i].hashSpc;
1285
+ newVar[i].hashUsed = Var[i].hashUsed;
1286
+ newVar[i].lev = Var[i].lev;
1287
+ newVar[i].hash_32 = Var[i].hash_32;
1288
+ newVarID[i] = VarID[i];
1289
+ #ifdef B_64
1290
+ newVar[i].hash_h8 = Var[i].hash_h8;
1291
+ #endif
1292
+ }
1293
+ free(Var);
1294
+ free(VarID);
1295
+ Var = newVar;
1296
+ VarID = newVarID;
1297
+ }
1298
+ else
1299
+ {
1300
+ if(newVar) free(newVar);
1301
+ if(newVarID) free(newVarID);
1302
+ err("var_enlarge: memory allocation failed", VarSpc);
1303
+ }
1304
+
1305
+ /* Initialize new space */
1306
+ for(i=VarSpc; i<newSpc; i++)
1307
+ {
1308
+ Var[i].hashSpc = 0;
1309
+ Var[i].hashUsed = 0;
1310
+ Var[i].lev = i;
1311
+ Var[i].hash_32 = 0;
1312
+ VarID[i] = i;
1313
+ #ifdef B_64
1314
+ Var[i].hash_h8 = 0;
1315
+ #endif
1316
+ }
1317
+ VarSpc = newSpc;
1318
+ }
1319
+
1320
+ static int node_enlarge()
1321
+ /* Returns 1 if not enough memory */
1322
+ {
1323
+ bddp i, newSpc;
1324
+ struct B_NodeTable *newNode;
1325
+ struct B_CacheTable *newCache, *cp, *cp1;
1326
+
1327
+ /* Get new size */
1328
+ if(NodeSpc == NodeLimit) return 1; /* Cannot enlarge */
1329
+ newSpc = NodeSpc << 1U;
1330
+ if(newSpc > NodeLimit) newSpc = NodeLimit;
1331
+
1332
+ /* Enlarge space */
1333
+ newNode = B_MALLOC(struct B_NodeTable, newSpc);
1334
+ if(newNode)
1335
+ {
1336
+ for(i=0; i<NodeSpc; i++)
1337
+ {
1338
+ newNode[i].varrfc = Node[i].varrfc;
1339
+ newNode[i].f0_32 = Node[i].f0_32;
1340
+ newNode[i].f1_32 = Node[i].f1_32;
1341
+ newNode[i].nx_32 = Node[i].nx_32;
1342
+ #ifdef B_64
1343
+ newNode[i].f0_h8 = Node[i].f0_h8;
1344
+ newNode[i].f1_h8 = Node[i].f1_h8;
1345
+ newNode[i].nx_h8 = Node[i].nx_h8;
1346
+ #endif /* B_64 */
1347
+ }
1348
+ free(Node);
1349
+ Node = newNode;
1350
+ }
1351
+ else return 1; /* Not enough memory */
1352
+
1353
+ /* Initialize new space */
1354
+ Node[newSpc-1U].varrfc = 0;
1355
+ B_SET_BDDP(Node[newSpc-1U].nx, Avail);
1356
+ for(i=NodeSpc; i<newSpc-1U; i++)
1357
+ {
1358
+ Node[i].varrfc = 0;
1359
+ B_SET_BDDP(Node[i].nx, i+1U);
1360
+ }
1361
+ Avail = NodeSpc;
1362
+ NodeSpc = newSpc;
1363
+
1364
+ /* Realloc Cache */
1365
+ for(newSpc=CacheSpc; newSpc<NodeSpc>>1U; newSpc<<=1U)
1366
+ ; /* empty */
1367
+ newCache = B_MALLOC(struct B_CacheTable, newSpc);
1368
+ if(newCache)
1369
+ {
1370
+ for(i=0; i<CacheSpc; i++)
1371
+ {
1372
+ cp = newCache + i;
1373
+ cp1 = Cache + i;
1374
+ cp->op = cp1->op;
1375
+ B_CPY_BDDP(cp->f, cp1->f);
1376
+ B_CPY_BDDP(cp->g, cp1->g);
1377
+ B_CPY_BDDP(cp->h, cp1->h);
1378
+ }
1379
+ free(Cache);
1380
+ Cache = newCache;
1381
+ }
1382
+ else return 0; /* Only NodeTable enlarged */
1383
+
1384
+ /* Reconstruct Cache */
1385
+ for(i=CacheSpc; i<newSpc; i++)
1386
+ {
1387
+ cp = Cache + i;
1388
+ cp1 = Cache + (i & (CacheSpc - 1));
1389
+ cp->op = cp1->op;
1390
+ B_CPY_BDDP(cp->f, cp1->f);
1391
+ B_CPY_BDDP(cp->g, cp1->g);
1392
+ B_CPY_BDDP(cp->h, cp1->h);
1393
+ }
1394
+ CacheSpc = newSpc;
1395
+
1396
+ return 0;
1397
+ }
1398
+
1399
+ static int hash_enlarge(v)
1400
+ bddvar v;
1401
+ /* Returns 1 if not enough memory */
1402
+ {
1403
+ struct B_NodeTable *np, *np0;
1404
+ struct B_VarTable *varp;
1405
+ bddp i, oldSpc, newSpc, nx, key, f0, f1;
1406
+ bddp_32 *newhash_32, *p_32;
1407
+ #ifdef B_64
1408
+ bddp_h8 *newhash_h8, *p_h8;
1409
+ #endif
1410
+
1411
+ varp = &Var[v];
1412
+ /* Get new size */
1413
+ oldSpc = varp->hashSpc;
1414
+ if(oldSpc == B_NODE_MAX + 1U)
1415
+ return 0; /* Cancel enlarging */
1416
+ newSpc = oldSpc << 1U;
1417
+
1418
+ /* Enlarge space */
1419
+ #ifdef B_64
1420
+ newhash_32 = B_MALLOC(bddp_32, newSpc);
1421
+ newhash_h8 = B_MALLOC(bddp_h8, newSpc);
1422
+ if(newhash_32 && newhash_h8)
1423
+ {
1424
+ for(i=0; i<varp->hashSpc; i++)
1425
+ {
1426
+ newhash_32[i] = varp->hash_32[i];
1427
+ newhash_h8[i] = varp->hash_h8[i];
1428
+ }
1429
+ free(varp->hash_32);
1430
+ free(varp->hash_h8);
1431
+ varp->hash_32 = newhash_32;
1432
+ varp->hash_h8 = newhash_h8;
1433
+ }
1434
+ else
1435
+ {
1436
+ if(newhash_32) free(newhash_32);
1437
+ if(newhash_h8) free(newhash_h8);
1438
+ return 1;
1439
+ }
1440
+ #else
1441
+ newhash_32 = B_MALLOC(bddp_32, newSpc);
1442
+ if(newhash_32)
1443
+ {
1444
+ for(i=0; i<varp->hashSpc; i++) newhash_32[i] = varp->hash_32[i];
1445
+ free(varp->hash_32);
1446
+ varp->hash_32 = newhash_32;
1447
+ }
1448
+ else return 1; /* Not enough memory */
1449
+ #endif
1450
+ varp->hashSpc = newSpc;
1451
+
1452
+ /* Initialize new hash entry */
1453
+ for(i=oldSpc; i<newSpc; i++)
1454
+ {
1455
+ B_SET_NXP(p, varp->hash, i);
1456
+ B_SET_BDDP(*p, bddnull);
1457
+ }
1458
+
1459
+ /* restore hash entry */
1460
+ for(i=0; i<oldSpc; i++)
1461
+ {
1462
+ np0 = 0;
1463
+ B_SET_NXP(p, varp->hash, i);
1464
+ nx = B_GET_BDDP(*p);
1465
+ while(nx != bddnull)
1466
+ {
1467
+ np = Node + nx;
1468
+ f0 = B_GET_BDDP(np->f0);
1469
+ f1 = B_GET_BDDP(np->f1);
1470
+ key = B_HASHKEY(f0, f1, newSpc);
1471
+ if(key == i) np0 = np;
1472
+ else
1473
+ {
1474
+ if(np0) B_CPY_BDDP(np0->nx, np->nx);
1475
+ else { B_SET_NXP(p, varp->hash, i); B_CPY_BDDP(*p, np->nx); }
1476
+ B_SET_NXP(p, varp->hash, key);
1477
+ B_CPY_BDDP(np->nx, *p);
1478
+ B_SET_BDDP(*p, nx);
1479
+ }
1480
+ if(np0) nx = B_GET_BDDP(np0->nx);
1481
+ else { B_SET_NXP(p, varp->hash, i); nx = B_GET_BDDP(*p); }
1482
+ }
1483
+ }
1484
+ return 0;
1485
+ }
1486
+
1487
+ static bddp getnode(v, f0, f1)
1488
+ bddvar v;
1489
+ bddp f0, f1;
1490
+ /* Returns bddnull if not enough memory */
1491
+ {
1492
+ /* After checking elimination rule & negative edge rule */
1493
+ struct B_NodeTable *np, *fp;
1494
+ struct B_VarTable *varp;
1495
+ bddp ix, nx, key;
1496
+ bddp_32 *p_32;
1497
+ #ifdef B_64
1498
+ bddp_h8 *p_h8;
1499
+ #endif
1500
+
1501
+ varp = &Var[v];
1502
+ if(varp->hashSpc == 0)
1503
+ /* Create hash-table */
1504
+ {
1505
+ varp->hash_32 = B_MALLOC(bddp_32, B_HASH_SPC0);
1506
+ if(!varp->hash_32) return bddnull;
1507
+ #ifdef B_64
1508
+ varp->hash_h8 = B_MALLOC(bddp_h8, B_HASH_SPC0);
1509
+ if(!varp->hash_h8)
1510
+ {
1511
+ free(varp->hash_32);
1512
+ return bddnull;
1513
+ }
1514
+ #endif
1515
+ for(ix=0; ix<B_HASH_SPC0; ix++)
1516
+ {
1517
+ B_SET_NXP(p, varp->hash, ix);
1518
+ B_SET_BDDP(*p, bddnull);
1519
+ }
1520
+ varp->hashSpc = B_HASH_SPC0;
1521
+ key = B_HASHKEY(f0, f1, varp->hashSpc);
1522
+ }
1523
+ else
1524
+ /* Looking for equivalent existing node */
1525
+ {
1526
+ key = B_HASHKEY(f0, f1, varp->hashSpc);
1527
+ B_SET_NXP(p, varp->hash, key);
1528
+ nx = B_GET_BDDP(*p);
1529
+ while(nx != bddnull)
1530
+ {
1531
+ np = Node + nx;
1532
+ if(f0 == B_GET_BDDP(np->f0) &&
1533
+ f1 == B_GET_BDDP(np->f1) )
1534
+ {
1535
+ /* Sharing equivalent node */
1536
+ if(!B_CST(f0)) { fp = B_NP(f0); B_RFC_DEC_NP(fp); }
1537
+ if(!B_CST(f1)) { fp = B_NP(f1); B_RFC_DEC_NP(fp); }
1538
+ B_RFC_INC_NP(np);
1539
+ return B_BDDP_NP(np);
1540
+ }
1541
+ nx = B_GET_BDDP(np->nx);
1542
+ }
1543
+ }
1544
+
1545
+ /* Check hash-table overflow */
1546
+ if(++ varp->hashUsed >= varp->hashSpc)
1547
+ {
1548
+ if(hash_enlarge(v)) return bddnull; /* Hash-table overflow */
1549
+ key = B_HASHKEY(f0, f1, varp->hashSpc); /* Enlarge success */
1550
+ }
1551
+
1552
+ /* Check node-table overflow */
1553
+ if(NodeUsed >= NodeSpc-1U)
1554
+ {
1555
+ if(node_enlarge())
1556
+ {
1557
+ if(bddgc()) return bddnull; /* Node-table overflow */
1558
+ key = B_HASHKEY(f0, f1, varp->hashSpc);
1559
+ }
1560
+ /* Node-table enlarged or GC succeeded */
1561
+ }
1562
+ NodeUsed++;
1563
+
1564
+ /* Creating a new node */
1565
+ nx = Avail;
1566
+ np = Node + nx;
1567
+ Avail = B_GET_BDDP(np->nx);
1568
+ B_SET_NXP(p, varp->hash, key);
1569
+ B_CPY_BDDP(np->nx, *p);
1570
+ B_SET_BDDP(*p, nx);
1571
+ B_SET_BDDP(np->f0, f0);
1572
+ B_SET_BDDP(np->f1, f1);
1573
+ np->varrfc = v;
1574
+ B_RFC_INC_NP(np);
1575
+ return B_BDDP_NP(np);
1576
+ }
1577
+
1578
+ static bddp getbddp(v, f0, f1)
1579
+ bddvar v;
1580
+ bddp f0, f1;
1581
+ /* Returns bddnull if not enough memory */
1582
+ {
1583
+ struct B_NodeTable *fp;
1584
+
1585
+ /* Check elimination rule */
1586
+ if(f0 == f1)
1587
+ {
1588
+ if(!B_CST(f0)) { fp = B_NP(f0); B_RFC_DEC_NP(fp); }
1589
+ return f0;
1590
+ }
1591
+
1592
+ /* Negative edge constraint */
1593
+ if(B_NEG(f0))
1594
+ {
1595
+ bddp h;
1596
+
1597
+ h = getnode(v, B_NOT(f0), B_NOT(f1));
1598
+ if(h == bddnull) return bddnull;
1599
+ return B_NOT(h);
1600
+ }
1601
+ return getnode(v, f0, f1);
1602
+ }
1603
+
1604
+ static bddp apply(f, g, op, skip)
1605
+ bddp f, g;
1606
+ unsigned char op, skip;
1607
+ /* Returns bddnull if not enough memory */
1608
+ {
1609
+ struct B_NodeTable *fp, *gp;
1610
+ struct B_CacheTable *cachep;
1611
+ bddp key, f0, f1, g0, g1, h0, h1, h;
1612
+ bddvar v, flev, glev;
1613
+ char z; /* flag to check ZBDD node */
1614
+
1615
+ /* Check terminal case */
1616
+ if(!skip) switch(op)
1617
+ {
1618
+ case BC_AND:
1619
+ /* Check trivial cases */
1620
+ if(f == bddfalse || g == bddfalse || f == B_NOT(g))
1621
+ return bddfalse;
1622
+ if(f == g)
1623
+ {
1624
+ if(f != bddtrue) { fp = B_NP(f); B_RFC_INC_NP(fp); }
1625
+ return f;
1626
+ }
1627
+ if(f == bddtrue) { fp = B_NP(g); B_RFC_INC_NP(fp); return g; }
1628
+ if(g == bddtrue) { fp = B_NP(f); B_RFC_INC_NP(fp); return f; }
1629
+ /* Check operand swap */
1630
+ if(f < g) { h = f; f = g; g = h; } /* swap (f, g) */
1631
+ break;
1632
+
1633
+ case BC_XOR:
1634
+ /* Check trivial cases */
1635
+ if(f == g) return bddfalse;
1636
+ if(f == B_NOT(g)) return bddtrue;
1637
+ if(f == bddfalse) { fp = B_NP(g); B_RFC_INC_NP(fp); return g; }
1638
+ if(g == bddfalse) { fp = B_NP(f); B_RFC_INC_NP(fp); return f; }
1639
+ if(f == bddtrue) {fp=B_NP(g); B_RFC_INC_NP(fp); return B_NOT(g);}
1640
+ if(g == bddtrue) {fp=B_NP(f); B_RFC_INC_NP(fp); return B_NOT(f);}
1641
+ /* Check negation */
1642
+ if(B_NEG(f) && B_NEG(g)) { f = B_NOT(f); g = B_NOT(g); }
1643
+ else if(B_NEG(f) || B_NEG(g))
1644
+ {
1645
+ f = B_ABS(f); g = B_ABS(g);
1646
+ /* Check operand swap */
1647
+ h = (f < g)? apply(g, f, op, 1): apply(f, g, op, 1);
1648
+ if(h == bddnull) return bddnull;
1649
+ return B_NOT(h);
1650
+ }
1651
+ /* Check operand swap */
1652
+ if(f < g) { h = f; f = g; g = h; } /* swap (f, g) */
1653
+ break;
1654
+
1655
+ case BC_COFACTOR:
1656
+ /* Check trivial cases */
1657
+ if(B_CST(f)) return f;
1658
+ if(g == bddfalse || f == B_NOT(g)) return bddfalse;
1659
+ if(f == g) return bddtrue;
1660
+ if(g == bddtrue) { fp = B_NP(f); B_RFC_INC_NP(fp); return f; }
1661
+ break;
1662
+
1663
+ case BC_UNIV:
1664
+ /* Check trivial cases */
1665
+ if(B_CST(f)) return f;
1666
+ if(B_CST(g)) { fp = B_NP(f); B_RFC_INC_NP(fp); return f; }
1667
+ if(B_NEG(g)) g = B_NOT(g);
1668
+ break;
1669
+
1670
+ case BC_SUPPORT:
1671
+ if(B_CST(f)) return bddfalse;
1672
+ if(B_NEG(f)) f = B_NOT(f);
1673
+ break;
1674
+
1675
+ case BC_INTERSEC:
1676
+ /* Check trivial cases */
1677
+ if(f == bddfalse || g == bddfalse) return bddfalse;
1678
+ if(f == bddtrue) return B_NEG(g)? bddtrue: bddfalse;
1679
+ if(g == bddtrue) return B_NEG(f)? bddtrue: bddfalse;
1680
+ if(f == g) { fp = B_NP(f); B_RFC_INC_NP(fp); return f; }
1681
+ if(f == B_NOT(g)) {fp=B_NP(f); B_RFC_INC_NP(fp); return B_ABS(f); }
1682
+ /* Check operand swap */
1683
+ if(f < g) { h = f; f = g; g = h; } /* swap (f, g) */
1684
+ break;
1685
+
1686
+ case BC_UNION:
1687
+ /* Check trivial cases */
1688
+ if(f == bddfalse)
1689
+ {
1690
+ if(!B_CST(g)) {fp=B_NP(g); B_RFC_INC_NP(fp); }
1691
+ return g;
1692
+ }
1693
+ if(f == bddtrue)
1694
+ {
1695
+ if(!B_CST(g)) {fp=B_NP(g); B_RFC_INC_NP(fp); }
1696
+ return B_NEG(g)? g: B_NOT(g);
1697
+ }
1698
+ if(g == bddfalse || f == g)
1699
+ { fp=B_NP(f); B_RFC_INC_NP(fp); return f; }
1700
+ if(g == bddtrue || f == B_NOT(g))
1701
+ {
1702
+ fp=B_NP(f); B_RFC_INC_NP(fp);
1703
+ return B_NEG(f)? f: B_NOT(f);
1704
+ }
1705
+ /* Check operand swap */
1706
+ if(f < g) { h = f; f = g; g = h; } /* swap (f, g) */
1707
+ break;
1708
+
1709
+ case BC_SUBTRACT:
1710
+ /* Check trivial cases */
1711
+ if(f == bddfalse || f == g) return bddfalse;
1712
+ if(f == bddtrue || f == B_NOT(g))
1713
+ return B_NEG(g)? bddfalse: bddtrue;
1714
+ if(g == bddfalse) { fp=B_NP(f); B_RFC_INC_NP(fp); return f; }
1715
+ if(g == bddtrue) { fp=B_NP(f); B_RFC_INC_NP(fp); return B_ABS(f); }
1716
+ break;
1717
+
1718
+ case BC_AT0:
1719
+ case BC_AT1:
1720
+ case BC_OFFSET:
1721
+ /* Check trivial cases */
1722
+ if(B_CST(f)) return f;
1723
+ /* special cases */
1724
+ fp = B_NP(f); flev = Var[B_VAR_NP(fp)].lev;
1725
+ glev = Var[(bddvar)g].lev;
1726
+ if(flev < glev) { B_RFC_INC_NP(fp); return f; }
1727
+ if(flev == glev)
1728
+ {
1729
+ if(op != BC_AT1)
1730
+ {
1731
+ h = B_GET_BDDP(fp->f0);
1732
+ if(B_NEG(f)^B_NEG(h)) h = B_NOT(h);
1733
+ }
1734
+ else
1735
+ {
1736
+ h = B_GET_BDDP(fp->f1);
1737
+ if(B_NEG(f)) h = B_NOT(h);
1738
+ }
1739
+ if(!B_CST(h)) { fp = B_NP(h); B_RFC_INC_NP(fp); }
1740
+ return h;
1741
+ }
1742
+ /* Check negation */
1743
+ if(B_NEG(f))
1744
+ {
1745
+ h = apply(B_NOT(f), g, op, 1);
1746
+ if(h == bddnull) return bddnull;
1747
+ return B_NOT(h);
1748
+ }
1749
+ break;
1750
+
1751
+ case BC_ONSET:
1752
+ /* Check trivial cases */
1753
+ if(B_CST(f)) return bddfalse;
1754
+ /* special cases */
1755
+ fp = B_NP(f); flev = Var[B_VAR_NP(fp)].lev;
1756
+ glev = Var[(bddvar)g].lev;
1757
+ if(flev < glev) return bddfalse;
1758
+ if(flev == glev)
1759
+ {
1760
+ h = B_GET_BDDP(fp->f1);
1761
+ if(!B_CST(h)) { fp = B_NP(h); B_RFC_INC_NP(fp); }
1762
+ return h;
1763
+ }
1764
+ /* Check negation */
1765
+ if(B_NEG(f)) f = B_NOT(f);
1766
+ break;
1767
+
1768
+ case BC_CHANGE:
1769
+ /* Check trivial cases */
1770
+ if(f == bddfalse) return f;
1771
+ if(B_CST(f)) return getzbddp((bddvar)g, bddfalse, f);
1772
+ /* special cases */
1773
+ fp = B_NP(f); flev = Var[B_VAR_NP(fp)].lev;
1774
+ glev = Var[(bddvar)g].lev;
1775
+ if(flev < glev)
1776
+ {
1777
+ B_RFC_INC_NP(fp);
1778
+ h = getzbddp((bddvar)g, bddfalse, f);
1779
+ if(h == bddnull) bddfree(f);
1780
+ return h;
1781
+ }
1782
+ if(flev == glev)
1783
+ {
1784
+ h0 = B_GET_BDDP(fp->f1);
1785
+ h1 = B_GET_BDDP(fp->f0);
1786
+ if(B_NEG(f)^B_NEG(h1)) h1 = B_NOT(h1);
1787
+ if(!B_CST(h0)) { fp = B_NP(h0); B_RFC_INC_NP(fp); }
1788
+ if(!B_CST(h1)) { fp = B_NP(h1); B_RFC_INC_NP(fp); }
1789
+ h = getzbddp((bddvar)g, h0, h1);
1790
+ if(h == bddnull) { bddfree(h0); bddfree(h1); }
1791
+ return h;
1792
+ }
1793
+ break;
1794
+
1795
+ case BC_LSHIFT:
1796
+ case BC_RSHIFT:
1797
+ /* Check trivial cases */
1798
+ if(B_CST(f)) return f;
1799
+
1800
+ /* Check negation */
1801
+ if(B_NEG(f))
1802
+ {
1803
+ h = apply(B_NOT(f), g, op, 1);
1804
+ if(h == bddnull) return bddnull;
1805
+ return B_NOT(h);
1806
+ }
1807
+ break;
1808
+
1809
+ case BC_CARD:
1810
+ if(B_CST(f)) return (f == bddempty)? 0: 1;
1811
+ if(B_NEG(f)) return apply(B_NOT(f), bddempty, op, 1) + 1;
1812
+ break;
1813
+
1814
+ case BC_LIT:
1815
+ if(B_CST(f)) return 0;
1816
+ if(B_NEG(f)) f = B_NOT(f);
1817
+ break;
1818
+
1819
+ case BC_LEN:
1820
+ if(B_CST(f)) return 0;
1821
+ if(B_NEG(f)) f = B_NOT(f);
1822
+ break;
1823
+
1824
+ default:
1825
+ err("apply: unknown opcode", op);
1826
+ break;
1827
+ }
1828
+
1829
+ /* Non-trivial operations */
1830
+ switch(op)
1831
+ {
1832
+ /* binary operation */
1833
+ case BC_AND:
1834
+ case BC_XOR:
1835
+ case BC_COFACTOR:
1836
+ case BC_UNIV:
1837
+ case BC_INTERSEC:
1838
+ case BC_UNION:
1839
+ case BC_SUBTRACT:
1840
+ /* Try cache? */
1841
+ if((B_CST(f) || B_RFC_ONE_NP(B_NP(f))) &&
1842
+ (B_CST(g) || B_RFC_ONE_NP(B_NP(g)))) key = bddnull;
1843
+ else
1844
+ {
1845
+ /* Checking Cache */
1846
+ key = B_CACHEKEY(op, f, g);
1847
+ cachep = Cache + key;
1848
+ if(cachep->op == op &&
1849
+ f == B_GET_BDDP(cachep->f) &&
1850
+ g == B_GET_BDDP(cachep->g))
1851
+ {
1852
+ /* Hit */
1853
+ h = B_GET_BDDP(cachep->h);
1854
+ if(!B_CST(h) && h != bddnull) { fp = B_NP(h); B_RFC_INC_NP(fp); }
1855
+ return h;
1856
+ }
1857
+ }
1858
+ /* Get (f0, f1) and (g0, g1)*/
1859
+ z = 0;
1860
+ fp = B_NP(f);
1861
+ flev = B_CST(f)? 0: Var[B_VAR_NP(fp)].lev;
1862
+ gp = B_NP(g);
1863
+ glev = B_CST(g)? 0: Var[B_VAR_NP(gp)].lev;
1864
+ f0 = f; f1 = f;
1865
+ g0 = g; g1 = g;
1866
+
1867
+ if(flev <= glev)
1868
+ {
1869
+ v = B_VAR_NP(gp);
1870
+ if(B_Z_NP(gp))
1871
+ {
1872
+ z = 1;
1873
+ if(flev < glev) f1 = bddfalse;
1874
+ }
1875
+ g0 = B_GET_BDDP(gp->f0);
1876
+ g1 = B_GET_BDDP(gp->f1);
1877
+ if(B_NEG(g)^B_NEG(g0)) g0 = B_NOT(g0);
1878
+ if(B_NEG(g) && !z) g1 = B_NOT(g1);
1879
+ }
1880
+
1881
+ if(flev >= glev)
1882
+ {
1883
+ v = B_VAR_NP(fp);
1884
+ if(B_Z_NP(fp))
1885
+ {
1886
+ z = 1;
1887
+ if(flev > glev) g1 = bddfalse;
1888
+ }
1889
+ f0 = B_GET_BDDP(fp->f0);
1890
+ f1 = B_GET_BDDP(fp->f1);
1891
+ if(B_NEG(f)^B_NEG(f0)) f0 = B_NOT(f0);
1892
+ if(B_NEG(f) && !z) f1 = B_NOT(f1);
1893
+ }
1894
+ break;
1895
+
1896
+ /* unary operation */
1897
+ case BC_AT0:
1898
+ case BC_AT1:
1899
+ case BC_LSHIFT:
1900
+ case BC_RSHIFT:
1901
+ case BC_SUPPORT:
1902
+ case BC_OFFSET:
1903
+ case BC_ONSET:
1904
+ case BC_CHANGE:
1905
+ fp = B_NP(f);
1906
+ if(B_RFC_ONE_NP(fp)) key = bddnull;
1907
+ else
1908
+ {
1909
+ /* Checking Cache */
1910
+ key = B_CACHEKEY(op, f, g);
1911
+ cachep = Cache + key;
1912
+ if(cachep->op == op &&
1913
+ f == B_GET_BDDP(cachep->f) &&
1914
+ g == B_GET_BDDP(cachep->g))
1915
+ {
1916
+ /* Hit */
1917
+ h = B_GET_BDDP(cachep->h);
1918
+ if(!B_CST(h) && h != bddnull) { fp = B_NP(h); B_RFC_INC_NP(fp); }
1919
+ return h;
1920
+ }
1921
+ }
1922
+ /* Get (f0, f1)*/
1923
+ v = B_VAR_NP(fp);
1924
+ z = B_Z_NP(fp)? 1: 0;
1925
+ f0 = B_GET_BDDP(fp->f0);
1926
+ f1 = B_GET_BDDP(fp->f1);
1927
+ if(B_NEG(f)^B_NEG(f0)) f0 = B_NOT(f0);
1928
+ if(B_NEG(f) && !z) f1 = B_NOT(f1);
1929
+ break;
1930
+
1931
+ case BC_CARD:
1932
+ case BC_LIT:
1933
+ case BC_LEN:
1934
+ fp = B_NP(f);
1935
+ if(B_RFC_ONE_NP(fp)) key = bddnull;
1936
+ else
1937
+ {
1938
+ /* Checking Cache */
1939
+ key = B_CACHEKEY(op, f, bddempty);
1940
+ cachep = Cache + key;
1941
+ if(cachep->op == op &&
1942
+ f == B_GET_BDDP(cachep->f) &&
1943
+ bddempty == B_GET_BDDP(cachep->g))
1944
+ {
1945
+ /* Hit */
1946
+ return B_GET_BDDP(cachep->h);
1947
+ }
1948
+ }
1949
+ /* Get (f0, f1)*/
1950
+ f0 = B_GET_BDDP(fp->f0);
1951
+ f1 = B_GET_BDDP(fp->f1);
1952
+ if(B_NEG(f)^B_NEG(f0)) f0 = B_NOT(f0);
1953
+ break;
1954
+
1955
+ default:
1956
+ err("apply: unknown opcode", op);
1957
+ }
1958
+
1959
+ /* Stack overflow limitter */
1960
+ BDD_RECUR_INC;
1961
+
1962
+ /* Get result node */
1963
+ switch(op)
1964
+ {
1965
+ case BC_AND:
1966
+ case BC_XOR:
1967
+ case BC_INTERSEC:
1968
+ case BC_UNION:
1969
+ case BC_SUBTRACT:
1970
+ h0 = apply(f0, g0, op, 0);
1971
+ if(h0 == bddnull) { h = h0; break; } /* Overflow */
1972
+ h1 = apply(f1, g1, op, 0);
1973
+ if(h1 == bddnull) { bddfree(h0); h = h1; break; } /* Overflow */
1974
+ h = z? getzbddp(v, h0, h1): getbddp(v, h0, h1);
1975
+ if(h == bddnull) { bddfree(h0); bddfree(h1); } /* Overflow */
1976
+ break;
1977
+
1978
+ case BC_COFACTOR:
1979
+ if(g0 == bddfalse && g1 != bddfalse)
1980
+ {
1981
+ h = apply(f1, g1, op, 0);
1982
+ }
1983
+ else if(g1 == bddfalse && g0 != bddfalse)
1984
+ {
1985
+ h = apply(f0, g0, op, 0);
1986
+ }
1987
+ else
1988
+ {
1989
+ h0 = apply(f0, g0, op, 0);
1990
+ if(h0 == bddnull) { h = h0; break; } /* Overflow */
1991
+ h1 = apply(f1, g1, op, 0);
1992
+ if(h1 == bddnull) { bddfree(h0); h = h1; break; } /* Overflow */
1993
+ h = getbddp(v, h0, h1);
1994
+ if(h == bddnull) { bddfree(h0); bddfree(h1); } /* Overflow */
1995
+ }
1996
+ break;
1997
+
1998
+ case BC_UNIV:
1999
+ if(g0 != g1)
2000
+ {
2001
+ h0 = apply(f0, g0, op, 0);
2002
+ if(h0 == bddnull) { h = h0; break; } /* Overflow */
2003
+ h1 = apply(f1, g0, op, 0);
2004
+ if(h1 == bddnull) { bddfree(h0); h = h1; break; } /* Overflow */
2005
+ h = apply(h0, h1, BC_AND, 0);
2006
+ bddfree(h0); bddfree(h1);
2007
+ }
2008
+ else
2009
+ {
2010
+ h0 = apply(f0, g0, op, 0);
2011
+ if(h0 == bddnull) { h = h0; break; } /* Overflow */
2012
+ h1 = apply(f1, g0, op, 0);
2013
+ if(h1 == bddnull) { bddfree(h0); h = h1; break; } /* Overflow */
2014
+ h = getbddp(v, h0, h1);
2015
+ if(h == bddnull) { bddfree(h0); bddfree(h1); } /* Overflow */
2016
+ }
2017
+ break;
2018
+
2019
+ case BC_AT0:
2020
+ case BC_AT1:
2021
+ case BC_OFFSET:
2022
+ case BC_ONSET:
2023
+ case BC_CHANGE:
2024
+ h0 = apply(f0, g, op, 0);
2025
+ if(h0 == bddnull) { h = h0; break; } /* Overflow */
2026
+ h1 = apply(f1, g, op, 0);
2027
+ if(h1 == bddnull) { bddfree(h0); h = h1; break; } /* Overflow */
2028
+ h = z? getzbddp(v, h0, h1): getbddp(v, h0, h1);
2029
+ if(h == bddnull) { bddfree(h0); bddfree(h1); } /* Overflow */
2030
+ break;
2031
+
2032
+ case BC_SUPPORT:
2033
+ h0 = apply(f0, bddfalse, op, 0);
2034
+ if(h0 == bddnull) { h = h0; break; } /* Overflow */
2035
+ h1 = apply(f1, bddfalse, op, 0);
2036
+ if(h1 == bddnull) { bddfree(h0); h = h1; break; } /* Overflow */
2037
+ h = z? apply(h0, h1, BC_UNION, 0):
2038
+ apply(B_NOT(h0), B_NOT(h1), BC_AND, 0);
2039
+ bddfree(h0); bddfree(h1);
2040
+ if(h == bddnull) break; /* Overflow */
2041
+ h0 = h;
2042
+ h = z? getzbddp(v, h0, bddtrue):
2043
+ getbddp(v, B_NOT(h0), bddtrue);
2044
+ if(h == bddnull) bddfree(h0); /* Overflow */
2045
+ break;
2046
+
2047
+ case BC_LSHIFT:
2048
+ case BC_RSHIFT:
2049
+ /* Get VarID of new level */
2050
+ {
2051
+ bddvar flev, newlev;
2052
+
2053
+ flev = bddlevofvar(v);
2054
+ if(op == BC_LSHIFT)
2055
+ {
2056
+ newlev = flev + (bddvar)g;
2057
+ if(newlev > VarUsed || newlev < flev)
2058
+ err("apply: Invald shift", newlev);
2059
+ }
2060
+ else
2061
+ {
2062
+ newlev = flev - (bddvar)g;
2063
+ if(newlev == 0 || newlev > flev)
2064
+ err("apply: Invald shift", newlev);
2065
+ }
2066
+ v = bddvaroflev(newlev);
2067
+ }
2068
+ h0 = apply(f0, g, op, 0);
2069
+ if(h0 == bddnull) { h = h0; break; } /* Overflow */
2070
+ h1 = apply(f1, g, op, 0);
2071
+ if(h1 == bddnull) { bddfree(h0); h = h1; break; } /* Overflow */
2072
+ h = z? getzbddp(v, h0, h1): getbddp(v, h0, h1);
2073
+ if(h == bddnull) { bddfree(h0); bddfree(h1); } /* Overflow */
2074
+ break;
2075
+
2076
+ case BC_CARD:
2077
+ h = apply(f0, bddempty, op, 0)
2078
+ + apply(f1, bddempty, op, 0);
2079
+ if(h >= bddnull) h = bddnull - 1;
2080
+ break;
2081
+
2082
+ case BC_LIT:
2083
+ h = apply(f0, bddempty, op, 0)
2084
+ + apply(f1, bddempty, op, 0);
2085
+ if(h >= bddnull) h = bddnull - 1;
2086
+ h += apply(f1, bddempty, BC_CARD, 0);
2087
+ if(h >= bddnull) h = bddnull - 1;
2088
+ break;
2089
+
2090
+ case BC_LEN:
2091
+ h0 = apply(f0, bddempty, op, 0);
2092
+ h1 = apply(f1, bddempty, op, 0) + 1;
2093
+ h = (h0 < h1)? h1: h0;
2094
+ break;
2095
+
2096
+ default:
2097
+ err("apply: unknown opcode", op);
2098
+ break;
2099
+ }
2100
+
2101
+ /* Stack overflow limitter */
2102
+ BDD_RECUR_DEC;
2103
+
2104
+ /* Saving to Cache */
2105
+ if(key != bddnull && h != bddnull)
2106
+ {
2107
+ cachep = Cache + key;
2108
+ cachep->op = op;
2109
+ B_SET_BDDP(cachep->f, f);
2110
+ B_SET_BDDP(cachep->g, g);
2111
+ B_SET_BDDP(cachep->h, h);
2112
+ if(h == f) switch(op)
2113
+ {
2114
+ case BC_AT0:
2115
+ key = B_CACHEKEY(BC_AT1, f, g);
2116
+ cachep = Cache + key;
2117
+ cachep->op = BC_AT1;
2118
+ B_SET_BDDP(cachep->f, f);
2119
+ B_SET_BDDP(cachep->g, g);
2120
+ B_SET_BDDP(cachep->h, h);
2121
+ break;
2122
+ case BC_AT1:
2123
+ key = B_CACHEKEY(BC_AT0, f, g);
2124
+ cachep = Cache + key;
2125
+ cachep->op = BC_AT0;
2126
+ B_SET_BDDP(cachep->f, f);
2127
+ B_SET_BDDP(cachep->g, g);
2128
+ B_SET_BDDP(cachep->h, h);
2129
+ break;
2130
+ case BC_OFFSET:
2131
+ key = B_CACHEKEY(BC_ONSET, f, g);
2132
+ cachep = Cache + key;
2133
+ cachep->op = BC_ONSET;
2134
+ B_SET_BDDP(cachep->f, f);
2135
+ B_SET_BDDP(cachep->g, g);
2136
+ B_SET_BDDP(cachep->h, bddfalse);
2137
+ break;
2138
+ default:
2139
+ break;
2140
+ }
2141
+ if(h == bddfalse && op == BC_ONSET)
2142
+ {
2143
+ key = B_CACHEKEY(BC_OFFSET, f, g);
2144
+ cachep = Cache + key;
2145
+ cachep->op = BC_OFFSET;
2146
+ B_SET_BDDP(cachep->f, f);
2147
+ B_SET_BDDP(cachep->g, g);
2148
+ B_SET_BDDP(cachep->h, f);
2149
+ }
2150
+ }
2151
+ return h;
2152
+ }
2153
+
2154
+ static void gc1(np)
2155
+ struct B_NodeTable *np;
2156
+ {
2157
+ /* np is a node ptr to be collected. (refc == 0) */
2158
+ bddp key, nx1, f0, f1;
2159
+ struct B_VarTable *varp;
2160
+ struct B_NodeTable *np1, *np2;
2161
+ bddp_32 *p_32;
2162
+ #ifdef B_64
2163
+ bddp_h8 *p_h8;
2164
+ #endif
2165
+
2166
+ /* remove the node from hash list */
2167
+ varp = Var + B_VAR_NP(np);
2168
+ f0 = B_GET_BDDP(np->f0);
2169
+ f1 = B_GET_BDDP(np->f1);
2170
+ key = B_HASHKEY(f0, f1, varp->hashSpc);
2171
+ B_SET_NXP(p, varp->hash, key);
2172
+ nx1 = B_GET_BDDP(*p);
2173
+ np1 = Node + nx1;
2174
+
2175
+ if(np1 == np) B_CPY_BDDP(*p, np->nx);
2176
+ else
2177
+ {
2178
+ while(np1 != np)
2179
+ {
2180
+ if(nx1 == bddnull)
2181
+ err("gc1: Fail to find the node to be deleted", np-Node);
2182
+ np2 = np1;
2183
+ nx1 = B_GET_BDDP(np2->nx);
2184
+ np1 = Node + nx1;
2185
+ }
2186
+ B_CPY_BDDP(np2->nx, np->nx);
2187
+ }
2188
+ varp->hashUsed--;
2189
+
2190
+ /* append the node to avail list */
2191
+ B_SET_BDDP(np->nx, Avail);
2192
+ Avail = np - Node;
2193
+
2194
+ NodeUsed--;
2195
+ np->varrfc = 0;
2196
+
2197
+ /* Check sub-graphs recursively */
2198
+ if(!B_CST(f0))
2199
+ {
2200
+ np1 = B_NP(f0);
2201
+ B_RFC_DEC_NP(np1);
2202
+ if(B_RFC_ZERO_NP(np1))
2203
+ { BDD_RECUR_INC; gc1(np1); BDD_RECUR_DEC; }
2204
+ }
2205
+ if(!B_CST(f1))
2206
+ {
2207
+ np1 = B_NP(f1);
2208
+ B_RFC_DEC_NP(np1);
2209
+ if(B_RFC_ZERO_NP(np1))
2210
+ { BDD_RECUR_INC; gc1(np1); BDD_RECUR_DEC; }
2211
+ }
2212
+ }
2213
+
2214
+ static bddp count(f)
2215
+ bddp f;
2216
+ {
2217
+ bddp nx;
2218
+ bddp c, g;
2219
+ bddvar flev, glev;
2220
+ struct B_NodeTable *fp;
2221
+ struct B_NodeTable *gp;
2222
+
2223
+ /* Check consistensy
2224
+ if(f == bddnull)
2225
+ err("count: bddnull found", bddnull);
2226
+ */
2227
+
2228
+ if(B_CST(f)) return 0; /* Constant */
2229
+ fp = B_NP(f);
2230
+
2231
+ /* Check visit flag */
2232
+ nx = B_GET_BDDP(fp->nx);
2233
+ if(nx & B_CST_MASK) return 0;
2234
+
2235
+ /* Check consistensy
2236
+ flev = Var[B_VAR_NP(fp)].lev;
2237
+ g = B_GET_BDDP(fp->f0);
2238
+ if(!B_CST(g))
2239
+ {
2240
+ gp = B_NP(g); glev = Var[B_VAR_NP(gp)].lev;
2241
+ if(flev <= glev)
2242
+ err("count: inconsistensy found at f0", fp-Node);
2243
+ }
2244
+ g = B_GET_BDDP(fp->f1);
2245
+ if(!B_CST(g))
2246
+ {
2247
+ gp = B_NP(g); glev = Var[B_VAR_NP(gp)].lev;
2248
+ if(flev <= glev)
2249
+ err("count: inconsistensy found at f1", fp-Node);
2250
+ }
2251
+ */
2252
+
2253
+ BDD_RECUR_INC;
2254
+ c = count(B_GET_BDDP(fp->f0)) + count(B_GET_BDDP(fp->f1)) + 1U ;
2255
+ BDD_RECUR_DEC;
2256
+
2257
+ /* Set visit flag */
2258
+ B_SET_BDDP(fp->nx, nx | B_CST_MASK);
2259
+
2260
+ return c;
2261
+ }
2262
+
2263
+ static void export(strm, f)
2264
+ FILE *strm;
2265
+ bddp f;
2266
+ {
2267
+ bddp nx, f0, f1;
2268
+ bddvar v;
2269
+ struct B_NodeTable *fp;
2270
+
2271
+ if(B_CST(f)) return; /* Constant */
2272
+ fp = B_NP(f);
2273
+
2274
+ /* Check visit flag */
2275
+ nx = B_GET_BDDP(fp->nx);
2276
+ if(nx & B_CST_MASK) return;
2277
+
2278
+ /* Set visit flag */
2279
+ B_SET_BDDP(fp->nx, nx | B_CST_MASK);
2280
+
2281
+ /* Dump its subgraphs recursively */
2282
+ v = B_VAR_NP(fp);
2283
+ f0 = B_GET_BDDP(fp->f0);
2284
+ f0 = B_ABS(f0);
2285
+ f1 = B_GET_BDDP(fp->f1);
2286
+ BDD_RECUR_INC;
2287
+ export(strm, f0);
2288
+ export(strm, f1);
2289
+ BDD_RECUR_DEC;
2290
+
2291
+ /* Dump this node */
2292
+ fprintf(strm, B_BDDP_FD, B_ABS(f));
2293
+ fprintf(strm, " %d ", Var[v].lev);
2294
+ if(f0 == bddfalse) fprintf(strm, "F");
2295
+ else if(f0 == bddtrue) fprintf(strm, "T");
2296
+ else fprintf(strm, B_BDDP_FD, f0);
2297
+ fprintf(strm, " ");
2298
+ if(f1 == bddfalse) fprintf(strm, "F");
2299
+ else if(f1 == bddtrue) fprintf(strm, "T");
2300
+ else fprintf(strm, B_BDDP_FD, f1);
2301
+ fprintf(strm, "\n");
2302
+ }
2303
+
2304
+ static void dump(f)
2305
+ bddp f;
2306
+ {
2307
+ bddp nx, f0, f1;
2308
+ bddvar v;
2309
+ struct B_NodeTable *fp;
2310
+
2311
+ if(B_CST(f)) return; /* Constant */
2312
+ fp = B_NP(f);
2313
+
2314
+ /* Check visit flag */
2315
+ nx = B_GET_BDDP(fp->nx);
2316
+ if(nx & B_CST_MASK) return;
2317
+
2318
+ /* Set visit flag */
2319
+ B_SET_BDDP(fp->nx, nx | B_CST_MASK);
2320
+
2321
+ /* Dump its subgraphs recursively */
2322
+ v = B_VAR_NP(fp);
2323
+ f0 = B_GET_BDDP(fp->f0);
2324
+ f0 = B_ABS(f0);
2325
+ f1 = B_GET_BDDP(fp->f1);
2326
+ BDD_RECUR_INC;
2327
+ dump(f0);
2328
+ dump(f1);
2329
+ BDD_RECUR_DEC;
2330
+
2331
+ /* Dump this node */
2332
+ printf("N");
2333
+ printf(B_BDDP_FD, B_NDX(f));
2334
+ printf(" = [V%d(%d), ", v, Var[v].lev);
2335
+ if(B_CST(f0)) printf(B_BDDP_FD, B_VAL(f0));
2336
+ else { printf("N"); printf(B_BDDP_FD, B_NDX(f0)); }
2337
+ printf(", ");
2338
+ if(B_NEG(f1)) putchar('~');
2339
+ if(B_CST(f1)) printf(B_BDDP_FD, B_ABS(B_VAL(f1)));
2340
+ else { printf("N"); printf(B_BDDP_FD, B_NDX(f1)); }
2341
+ printf("]");
2342
+ if(B_Z_NP(fp)) printf(" #Z");
2343
+ printf("\n");
2344
+ }
2345
+
2346
+ static void reset(f)
2347
+ bddp f;
2348
+ {
2349
+ bddp nx;
2350
+ struct B_NodeTable *fp;
2351
+
2352
+ if(B_CST(f)) return; /* Constant */
2353
+ fp = B_NP(f);
2354
+
2355
+ /* Check visit flag */
2356
+ nx = B_GET_BDDP(fp->nx);
2357
+ if(nx & B_CST_MASK)
2358
+ {
2359
+ /* Reset visit flag */
2360
+ B_SET_BDDP(fp->nx, nx & ~B_CST_MASK);
2361
+ BDD_RECUR_INC;
2362
+ reset(B_GET_BDDP(fp->f0));
2363
+ reset(B_GET_BDDP(fp->f1));
2364
+ BDD_RECUR_DEC;
2365
+ }
2366
+ }
2367
+
2368
+ static bddp getzbddp(v, f0, f1)
2369
+ bddvar v;
2370
+ bddp f0, f1;
2371
+ /* Returns bddnull if not enough memory */
2372
+ {
2373
+ struct B_NodeTable *fp;
2374
+
2375
+ /* Check elimination rule */
2376
+ if(f1 == bddfalse) return f0;
2377
+
2378
+ /* Negative edge constraint */
2379
+ if(B_NEG(f0))
2380
+ {
2381
+ bddp h;
2382
+
2383
+ h = getnode(v, f0, f1);
2384
+ if(h == bddnull) return bddnull;
2385
+ return B_NOT(h);
2386
+ }
2387
+ return getnode(v, B_NOT(f0), f1);
2388
+ }
2389
+
2390
+ static int andfalse(f, g)
2391
+ bddp f, g;
2392
+ {
2393
+ struct B_NodeTable *fp, *gp;
2394
+ struct B_CacheTable *cachep;
2395
+ bddp key, f0, f1, g0, g1, h0, h1, h;
2396
+ bddvar v, flev, glev;
2397
+
2398
+ /* Check trivial cases */
2399
+ if(f == bddfalse || g == bddfalse || f == B_NOT(g)) return 0;
2400
+ if(f == bddtrue || g == bddtrue || f == g) return 1;
2401
+ /* Check operand swap */
2402
+ if(f > g) { h = f; f = g; g = h; } /* swap (f, g) */
2403
+
2404
+ /* Non-trivial operations */
2405
+ /* Try cache? */
2406
+ if((B_CST(f) || B_RFC_ONE_NP(B_NP(f))) &&
2407
+ (B_CST(g) || B_RFC_ONE_NP(B_NP(g)))) key = bddnull;
2408
+ else
2409
+ {
2410
+ /* Checking Cache */
2411
+ key = B_CACHEKEY(BC_AND, f, g);
2412
+ cachep = Cache + key;
2413
+ if(cachep->op == BC_AND &&
2414
+ f == B_GET_BDDP(cachep->f) &&
2415
+ g == B_GET_BDDP(cachep->g))
2416
+ {
2417
+ /* Hit */
2418
+ h = B_GET_BDDP(cachep->h);
2419
+ return (h==bddfalse)? 0: 1;
2420
+ }
2421
+ }
2422
+ /* Get (f0, f1) and (g0, g1)*/
2423
+ fp = B_NP(f);
2424
+ flev = B_CST(f)? 0: Var[B_VAR_NP(fp)].lev;
2425
+ gp = B_NP(g);
2426
+ glev = B_CST(g)? 0: Var[B_VAR_NP(gp)].lev;
2427
+ f0 = f; f1 = f;
2428
+ g0 = g; g1 = g;
2429
+
2430
+ if(flev <= glev)
2431
+ {
2432
+ v = B_VAR_NP(gp);
2433
+ g0 = B_GET_BDDP(gp->f0);
2434
+ g1 = B_GET_BDDP(gp->f1);
2435
+ if(B_NEG(g)) { g0 = B_NOT(g0); g1 = B_NOT(g1); }
2436
+ }
2437
+
2438
+ if(flev >= glev)
2439
+ {
2440
+ v = B_VAR_NP(fp);
2441
+ f0 = B_GET_BDDP(fp->f0);
2442
+ f1 = B_GET_BDDP(fp->f1);
2443
+ if(B_NEG(f)) { f0 = B_NOT(f0); f1 = B_NOT(f1); }
2444
+ }
2445
+
2446
+ /* Get result */
2447
+ if(andfalse(f0, g0) == 1) return 1;
2448
+ if(andfalse(f1, g1) == 1) return 1;
2449
+
2450
+ /* Saving to Cache */
2451
+ if(key != bddnull)
2452
+ {
2453
+ cachep = Cache + key;
2454
+ cachep->op = BC_AND;
2455
+ B_SET_BDDP(cachep->f, f);
2456
+ B_SET_BDDP(cachep->g, g);
2457
+ B_SET_BDDP(cachep->h, bddfalse);
2458
+ }
2459
+ return 0;
2460
+ }
2461
+
2462
+ static int err(msg, num)
2463
+ char *msg;
2464
+ bddp num;
2465
+ {
2466
+ fprintf(stderr,"***** ERROR %s ( ", msg);
2467
+ fprintf(stderr, B_BDDP_FX, num);
2468
+ fprintf(stderr," ) *****\n");
2469
+ fprintf(stderr," NodeLimit : ");
2470
+ fprintf(stderr, B_BDDP_FD, NodeLimit);
2471
+ fprintf(stderr,"\t NodeSpc : ");
2472
+ fprintf(stderr, B_BDDP_FD, NodeSpc);
2473
+ fprintf(stderr,"\t VarSpc : %d",VarSpc);
2474
+ fprintf(stderr,"\n CacheSpc : ");
2475
+ fprintf(stderr, B_BDDP_FD, CacheSpc);
2476
+ fprintf(stderr,"\t NodeUsed : ");
2477
+ fprintf(stderr, B_BDDP_FD, NodeUsed);
2478
+ fprintf(stderr,"\t VarUsed : %d\n",VarUsed);
2479
+ exit(1);
2480
+ return 1;
2481
+ }
2482
+
2483
+ static int rfc_inc_ovf(np)
2484
+ struct B_NodeTable *np;
2485
+ {
2486
+ bddp ix, nx, nx2, key, rfc, oldSpc;
2487
+ bddp *p, *p2;
2488
+ struct B_RFC_Table *oldRFCT;
2489
+
2490
+ /* printf("rfc_inc %d (u:%d)\n", np-Node, RFCT_Used); */
2491
+ if(RFCT_Spc == 0)
2492
+ {
2493
+ /* Create RFC-table */
2494
+ RFCT = B_MALLOC(struct B_RFC_Table, B_RFCT_SPC0);
2495
+ if(!RFCT)
2496
+ {
2497
+ err("B_RFC_INC_NP: rfc memory over flow", np-Node);
2498
+ return 1;
2499
+ }
2500
+ for(ix=0; ix<B_RFCT_SPC0; ix++)
2501
+ {
2502
+ B_SET_BDDP((RFCT+ix)->nx, bddnull);
2503
+ B_SET_BDDP((RFCT+ix)->rfc, (bddp)0);
2504
+ }
2505
+ RFCT_Spc = B_RFCT_SPC0;
2506
+ }
2507
+
2508
+ nx = np - Node;
2509
+ key = nx & (RFCT_Spc-1);
2510
+ nx2 = B_GET_BDDP((RFCT+key)->nx);
2511
+ while(nx2 != bddnull)
2512
+ {
2513
+ if(nx == nx2)
2514
+ {
2515
+ if(np->varrfc < B_RFC_MASK)
2516
+ {
2517
+ rfc = 0;
2518
+ np->varrfc += B_RFC_UNIT;
2519
+ }
2520
+ else rfc = B_GET_BDDP((RFCT+key)->rfc) + 1;
2521
+ B_SET_BDDP((RFCT+key)->rfc, rfc);
2522
+ return 0;
2523
+ }
2524
+ key = (key+1) & (RFCT_Spc-1);
2525
+ nx2 = B_GET_BDDP((RFCT+key)->nx);
2526
+ }
2527
+
2528
+ /* new rfc entry */
2529
+ B_SET_BDDP((RFCT+key)->nx, nx);
2530
+ B_SET_BDDP((RFCT+key)->rfc, (bddp)0);
2531
+ np->varrfc += B_RFC_UNIT;
2532
+ RFCT_Used++;
2533
+
2534
+ if((RFCT_Used << 1) >= RFCT_Spc)
2535
+ {
2536
+ /* Enlarge RFC-table */
2537
+ oldSpc = RFCT_Spc;
2538
+ RFCT_Spc <<= 2;
2539
+
2540
+ oldRFCT = RFCT;
2541
+ RFCT = B_MALLOC(struct B_RFC_Table, RFCT_Spc);
2542
+ if(!RFCT)
2543
+ {
2544
+ err("B_RFC_INC_NP: rfc memory over flow", np-Node);
2545
+ return 1;
2546
+ }
2547
+ for(ix=0; ix<RFCT_Spc; ix++)
2548
+ {
2549
+ B_SET_BDDP((RFCT+ix)->nx, bddnull);
2550
+ B_SET_BDDP((RFCT+ix)->rfc, (bddp)0);
2551
+ }
2552
+ for(ix=0; ix<oldSpc; ix++)
2553
+ {
2554
+ nx = B_GET_BDDP((oldRFCT+ix)->nx);
2555
+ if(nx == bddnull) continue;
2556
+ key = nx & (RFCT_Spc-1);
2557
+ nx2 = B_GET_BDDP((RFCT+key)->nx);
2558
+ while(nx2 != bddnull)
2559
+ {
2560
+ key = (key+1) & (RFCT_Spc-1);
2561
+ nx2 = B_GET_BDDP((RFCT+key)->nx);
2562
+ }
2563
+ B_SET_BDDP((RFCT+key)->nx, nx);
2564
+ rfc = B_GET_BDDP((oldRFCT+ix)->rfc);
2565
+ B_SET_BDDP((RFCT+key)->rfc, rfc);
2566
+ }
2567
+ free(oldRFCT);
2568
+ }
2569
+
2570
+ return 0;
2571
+ }
2572
+
2573
+ static int rfc_dec_ovf(np)
2574
+ struct B_NodeTable *np;
2575
+ {
2576
+ bddp nx, key, nx2, rfc;
2577
+
2578
+ /* printf("rfc_dec %d (u:%d)\n", np-Node, RFCT_Used); */
2579
+ nx = np - Node;
2580
+ key = nx & (RFCT_Spc-1);
2581
+ nx2 = B_GET_BDDP((RFCT+key)->nx);
2582
+ while(nx2 != bddnull)
2583
+ {
2584
+ if(nx == nx2)
2585
+ {
2586
+ rfc = B_GET_BDDP((RFCT+key)->rfc);
2587
+ if(rfc == 0)
2588
+ {
2589
+ np->varrfc -= B_RFC_UNIT;
2590
+ return 0;
2591
+ }
2592
+ B_SET_BDDP((RFCT+key)->rfc, rfc-1);
2593
+ return 0;
2594
+ }
2595
+ key = (key+1) & (RFCT_Spc-1);
2596
+ nx2 = B_GET_BDDP((RFCT+key)->nx);
2597
+ }
2598
+ return 0;
2599
+ }
2600
+
2601
+ #define IMPORTHASH(x) ((((x)>>1)^((x)<<8)^((x)<<16)) & (hashsize-1))
2602
+
2603
+ int import(strm, p, lim, z)
2604
+ FILE *strm;
2605
+ bddp *p;
2606
+ int lim;
2607
+ int z;
2608
+ {
2609
+ int n, m, v, i, lev, var, inv, e;
2610
+ bddp n_nd, ix, f, f0, f1, nd, nd0, nd1, hashsize, ixx;
2611
+ char s[256];
2612
+ bddp *hash1;
2613
+ bddp *hash2;
2614
+
2615
+ v = fscanf(strm, "%s", s);
2616
+ if(v == EOF) return 1;
2617
+ if(strcmp(s, "_i") != 0) return 1;
2618
+ v = fscanf(strm, "%s", s);
2619
+ if(v == EOF) return 1;
2620
+ n = strtol(s, NULL, 10);
2621
+ while(n > bddvarused()) bddnewvar();
2622
+
2623
+ v = fscanf(strm, "%s", s);
2624
+ if(v == EOF) return 1;
2625
+ if(strcmp(s, "_o") != 0) return 1;
2626
+ v = fscanf(strm, "%s", s);
2627
+ if(v == EOF) return 1;
2628
+ m = strtol(s, NULL, 10);
2629
+
2630
+ v = fscanf(strm, "%s", s);
2631
+ if(v == EOF) return 1;
2632
+ if(strcmp(s, "_n") != 0) return 1;
2633
+ v = fscanf(strm, "%s", s);
2634
+ if(v == EOF) return 1;
2635
+ n_nd = B_STRTOI(s, NULL, 10);
2636
+
2637
+ for(hashsize = 1; hashsize < (n_nd<<1); hashsize <<= 1)
2638
+ ; /* empty */
2639
+ hash1 = B_MALLOC(bddp, hashsize);
2640
+ if(hash1 == 0) return 1;
2641
+ hash2 = B_MALLOC(bddp, hashsize);
2642
+ if(hash2 == 0)
2643
+ {
2644
+ free(hash1);
2645
+ return 1;
2646
+ }
2647
+ for(ix=0; ix<hashsize; ix++) hash1[ix] = bddnull;
2648
+
2649
+ e = 0;
2650
+ for(ix=0; ix<n_nd; ix++)
2651
+ {
2652
+ v = fscanf(strm, "%s", s);
2653
+ if(v == EOF) { e = 1; break; }
2654
+ nd = B_STRTOI(s, NULL, 10);
2655
+
2656
+ v = fscanf(strm, "%s", s);
2657
+ if(v == EOF) { e = 1; break; }
2658
+ lev = strtol(s, NULL, 10);
2659
+ var = bddvaroflev(lev);
2660
+
2661
+ v = fscanf(strm, "%s", s);
2662
+ if(v == EOF) { e = 1; break; }
2663
+ if(strcmp(s, "F") == 0) f0 = bddfalse;
2664
+ else if(strcmp(s, "T") == 0) f0 = bddtrue;
2665
+ else
2666
+ {
2667
+ nd0 = B_STRTOI(s, NULL, 10);
2668
+
2669
+ ixx = IMPORTHASH(nd0);
2670
+ while(hash1[ixx] != nd0)
2671
+ {
2672
+ if(hash1[ixx] == bddnull)
2673
+ {
2674
+ err("bddimport: internal error", ixx);
2675
+ return 1;
2676
+ }
2677
+ ixx++;
2678
+ ixx &= (hashsize-1);
2679
+ }
2680
+ f0 = bddcopy(hash2[ixx]);
2681
+ }
2682
+
2683
+ v = fscanf(strm, "%s", s);
2684
+ if(v == EOF) { e = 1; bddfree(f0); break; }
2685
+ if(strcmp(s, "F") == 0) f1 = bddfalse;
2686
+ else if(strcmp(s, "T") == 0) f1 = bddtrue;
2687
+ else
2688
+ {
2689
+ nd1 = B_STRTOI(s, NULL, 10);
2690
+ if(nd1 & 1) { inv = 1; nd1 ^= 1; }
2691
+ else inv = 0;
2692
+
2693
+ ixx = IMPORTHASH(nd1);
2694
+ while(hash1[ixx] != nd1)
2695
+ {
2696
+ if(hash1[ixx] == bddnull)
2697
+ {
2698
+ err("bddimport: internal error", ixx);
2699
+ return 1;
2700
+ }
2701
+ ixx++;
2702
+ ixx &= (hashsize-1);
2703
+ }
2704
+ f1 = (inv)? bddnot(hash2[ixx]): bddcopy(hash2[ixx]);
2705
+ }
2706
+
2707
+ f = (z)? getzbddp(var, f0, f1): getbddp(var, f0, f1);
2708
+ if(f == bddnull)
2709
+ {
2710
+ e = 1;
2711
+ bddfree(f1);
2712
+ bddfree(f0);
2713
+ break;
2714
+ }
2715
+
2716
+ ixx = IMPORTHASH(nd);
2717
+ while(hash1[ixx] != bddnull)
2718
+ {
2719
+ if(hash1[ixx] == nd)
2720
+ {
2721
+ err("bddimport: internal error", ixx);
2722
+ return 1;
2723
+ }
2724
+ ixx++;
2725
+ ixx &= (hashsize-1);
2726
+ }
2727
+ hash1[ixx] = nd;
2728
+ hash2[ixx] = f;
2729
+ }
2730
+
2731
+ if(e)
2732
+ {
2733
+ for(ix=0; ix<hashsize; ix++)
2734
+ if(hash1[ix] != bddnull) bddfree(hash2[ix]);
2735
+ free(hash2);
2736
+ free(hash1);
2737
+ return 1;
2738
+ }
2739
+
2740
+ for(i=0; i<m; i++)
2741
+ {
2742
+ if(i >= lim) break;
2743
+ v = fscanf(strm, "%s", s);
2744
+ if(v == EOF)
2745
+ {
2746
+ for(i--; i>=0; i--) bddfree(p[i]);
2747
+ for(ix=0; ix<hashsize; ix++)
2748
+ if(hash1[ix] != bddnull) bddfree(hash2[ix]);
2749
+ free(hash2);
2750
+ free(hash1);
2751
+ return 1;
2752
+ }
2753
+ nd = B_STRTOI(s, NULL, 10);
2754
+ if(strcmp(s, "F") == 0) p[i] = bddfalse;
2755
+ else if(strcmp(s, "T") == 0) p[i] = bddtrue;
2756
+ else
2757
+ {
2758
+ if(nd & 1) { inv = 1; nd ^= 1; }
2759
+ else inv = 0;
2760
+
2761
+ ixx = IMPORTHASH(nd);
2762
+ while(hash1[ixx] != nd)
2763
+ {
2764
+ if(hash1[ixx] == bddnull)
2765
+ {
2766
+ err("bddimport: internal error", ixx);
2767
+ return 1;
2768
+ }
2769
+ ixx++;
2770
+ ixx &= (hashsize-1);
2771
+ }
2772
+ p[i] = (inv)? bddnot(hash2[ixx]): bddcopy(hash2[ixx]);
2773
+ }
2774
+ }
2775
+ if(i < lim) p[i] = bddnull;
2776
+
2777
+ /* clear hash table */
2778
+ for(ix=0; ix<hashsize; ix++)
2779
+ if(hash1[ix] != bddnull) bddfree(hash2[ix]);
2780
+ free(hash2);
2781
+ free(hash1);
2782
+
2783
+ return 0;
2784
+ }
2785
+
2786
+ int bddimport(strm, p, lim)
2787
+ FILE *strm;
2788
+ bddp *p;
2789
+ int lim;
2790
+ {
2791
+ return import(strm, p, lim, 0);
2792
+ }
2793
+
2794
+ int bddimportz(strm, p, lim)
2795
+ FILE *strm;
2796
+ bddp *p;
2797
+ int lim;
2798
+ {
2799
+ return import(strm, p, lim, 1);
2800
+ }
2801
+
2802
+ bddp bddpush(f, v)
2803
+ bddp f;
2804
+ bddvar v;
2805
+ /* Returns bddnull if not enough memory */
2806
+ {
2807
+ struct B_NodeTable *fp;
2808
+
2809
+ /* Check operands */
2810
+ if(v > VarUsed || v == 0) err("bddpush: Invalid VarID", v);
2811
+ if(f == bddnull) return bddnull;
2812
+
2813
+ if(!B_CST(f)) { fp = B_NP(f); B_RFC_INC_NP(fp); }
2814
+ return getzbddp(v, bddfalse, f);
2815
+ }
2816
+