summaryrefslogtreecommitdiffstats
path: root/src/misc/espresso/cofactor.c
blob: 04b211dddb9af07cd297efbdffd42d03f5372088 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
/*
 * Revision Control Information
 *
 * $Source$
 * $Author$
 * $Revision$
 * $Date$
 *
 */
#include "espresso.h"

ABC_NAMESPACE_IMPL_START


/*
    The cofactor of a cover against a cube "c" is a cover formed by the
    cofactor of each cube in the cover against c.  The cofactor of two
    cubes is null if they are distance 1 or more apart.  If they are
    distance zero apart, the cofactor is the restriction of the cube
    to the minterms of c.

    The cube list contains the following information:

    T[0] = pointer to a cube identifying the variables that have
        been cofactored against
    T[1] = pointer to just beyond the sentinel (i.e., T[n] in this case)
    T[2]
      .
      .  = pointers to cubes
      .
    T[n-2]
    T[n-1] = NULL pointer (sentinel)


    Cofactoring involves repeated application of "cdist0" to check if a
    cube of the cover intersects the cofactored cube.  This can be
    slow, especially for the recursive descent of the espresso
    routines.  Therefore, a special cofactor routine "scofactor" is
    provided which assumes the cofactor is only in a single variable.
*/


/* cofactor -- compute the cofactor of a cover with respect to a cube */
pcube *cofactor(T, c)
IN pcube *T;
IN register pcube c;
{
    pcube temp = cube.temp[0], *Tc_save, *Tc, *T1;
    register pcube p;
    int listlen;

    listlen = CUBELISTSIZE(T) + 5;

    /* Allocate a new list of cube pointers (max size is previous size) */
    Tc_save = Tc = ALLOC(pcube, listlen);

    /* pass on which variables have been cofactored against */
    *Tc++ = set_or(new_cube(), T[0], set_diff(temp, cube.fullset, c));
    Tc++;

    /* Loop for each cube in the list, determine suitability, and save */
    for(T1 = T+2; (p = *T1++) != NULL; ) {
    if (p != c) {

#ifdef NO_INLINE
    if (! cdist0(p, c)) goto false;
#else
    {register int w,last;register unsigned int x;if((last=cube.inword)!=-1)
    {x=p[last]&c[last];if(~(x|x>>1)&cube.inmask)goto false;for(w=1;w<last;w++)
    {x=p[w]&c[w];if(~(x|x>>1)&DISJOINT)goto false;}}}{register int w,var,last;
    register pcube mask;for(var=cube.num_binary_vars;var<cube.num_vars;var++){
    mask=cube.var_mask[var];last=cube.last_word[var];for(w=cube.first_word[var
    ];w<=last;w++)if(p[w]&c[w]&mask[w])goto nextvar;goto false;nextvar:;}}
#endif

        *Tc++ = p;
    false: ;
    }
    }

    *Tc++ = (pcube) NULL;                       /* sentinel */
    Tc_save[1] = (pcube) Tc;                    /* save pointer to last */
    return Tc_save;
}

/*
    scofactor -- compute the cofactor of a cover with respect to a cube,
    where the cube is "active" in only a single variable.

    This routine has been optimized for speed.
*/

pcube *scofactor(T, c, var)
IN pcube *T, c;
IN int var;
{
    pcube *Tc, *Tc_save;
    register pcube p, mask = cube.temp[1], *T1;
    register int first = cube.first_word[var], last = cube.last_word[var];
    int listlen;

    listlen = CUBELISTSIZE(T) + 5;

    /* Allocate a new list of cube pointers (max size is previous size) */
    Tc_save = Tc = ALLOC(pcube, listlen);

    /* pass on which variables have been cofactored against */
    *Tc++ = set_or(new_cube(), T[0], set_diff(mask, cube.fullset, c));
    Tc++;

    /* Setup for the quick distance check */
    (void) set_and(mask, cube.var_mask[var], c);

    /* Loop for each cube in the list, determine suitability, and save */
    for(T1 = T+2; (p = *T1++) != NULL; )
    if (p != c) {
        register int i = first;
        do
        if (p[i] & mask[i]) {
            *Tc++ = p;
            break;
        }
        while (++i <= last);
    }

    *Tc++ = (pcube) NULL;                       /* sentinel */
    Tc_save[1] = (pcube) Tc;                    /* save pointer to last */
    return Tc_save;
}

void massive_count(T)
IN pcube *T;
{
    int *count = cdata.part_zeros;
    pcube *T1;

    /* Clear the column counts (count of # zeros in each column) */
 {  register int i;
    for(i = cube.size - 1; i >= 0; i--)
    count[i] = 0;
 }

    /* Count the number of zeros in each column */
 {  register int i, *cnt;
    register unsigned int val;
    register pcube p, cof = T[0], full = cube.fullset;
    for(T1 = T+2; (p = *T1++) != NULL; )
    for(i = LOOP(p); i > 0; i--)
        if ((val = full[i] & ~ (p[i] | cof[i]))) {
        cnt = count + ((i-1) << LOGBPI);
#if BPI == 32
        if (val & 0xFF000000) {
        if (val & 0x80000000) cnt[31]++;
        if (val & 0x40000000) cnt[30]++;
        if (val & 0x20000000) cnt[29]++;
        if (val & 0x10000000) cnt[28]++;
        if (val & 0x08000000) cnt[27]++;
        if (val & 0x04000000) cnt[26]++;
        if (val & 0x02000000) cnt[25]++;
        if (val & 0x01000000) cnt[24]++;
        }
        if (val & 0x00FF0000) {
        if (val & 0x00800000) cnt[23]++;
        if (val & 0x00400000) cnt[22]++;
        if (val & 0x00200000) cnt[21]++;
        if (val & 0x00100000) cnt[20]++;
        if (val & 0x00080000) cnt[19]++;
        if (val & 0x00040000) cnt[18]++;
        if (val & 0x00020000) cnt[17]++;
        if (val & 0x00010000) cnt[16]++;
        }
#endif
        if (val & 0xFF00) {
        if (val & 0x8000) cnt[15]++;
        if (val & 0x4000) cnt[14]++;
        if (val & 0x2000) cnt[13]++;
        if (val & 0x1000) cnt[12]++;
        if (val & 0x0800) cnt[11]++;
        if (val & 0x0400) cnt[10]++;
        if (val & 0x0200) cnt[ 9]++;
        if (val & 0x0100) cnt[ 8]++;
        }
        if (val & 0x00FF) {
        if (val & 0x0080) cnt[ 7]++;
        if (val & 0x0040) cnt[ 6]++;
        if (val & 0x0020) cnt[ 5]++;
        if (val & 0x0010) cnt[ 4]++;
        if (val & 0x0008) cnt[ 3]++;
        if (val & 0x0004) cnt[ 2]++;
        if (val & 0x0002) cnt[ 1]++;
        if (val & 0x0001) cnt[ 0]++;
        }
    }
 }

    /*
     * Perform counts for each variable:
     *    cdata.var_zeros[var] = number of zeros in the variable
     *    cdata.parts_active[var] = number of active parts for each variable
     *    cdata.vars_active = number of variables which are active
     *    cdata.vars_unate = number of variables which are active and unate
     *
     *    best -- the variable which is best for splitting based on:
     *    mostactive -- most # active parts in any variable
     *    mostzero -- most # zeros in any variable
     *    mostbalanced -- minimum over the maximum # zeros / part / variable
     */

 {  register int var, i, lastbit, active, maxactive;
    int best = -1, mostactive = 0, mostzero = 0, mostbalanced = 32000;
    cdata.vars_unate = cdata.vars_active = 0;

    for(var = 0; var < cube.num_vars; var++) {
    if (var < cube.num_binary_vars) { /* special hack for binary vars */
        i = count[var*2];
        lastbit = count[var*2 + 1];
        active = (i > 0) + (lastbit > 0);
        cdata.var_zeros[var] = i + lastbit;
        maxactive = MAX(i, lastbit);
    } else {
        maxactive = active = cdata.var_zeros[var] = 0;
        lastbit = cube.last_part[var];
        for(i = cube.first_part[var]; i <= lastbit; i++) {
        cdata.var_zeros[var] += count[i];
        active += (count[i] > 0);
        if (active > maxactive) maxactive = active;
        }
    }

    /* first priority is to maximize the number of active parts */
    /* for binary case, this will usually select the output first */
    if (active > mostactive)
        best = var, mostactive = active, mostzero = cdata.var_zeros[best],
        mostbalanced = maxactive;
    else if (active == mostactive)
    {
        /* secondary condition is to maximize the number zeros */
        /* for binary variables, this is the same as minimum # of 2's */
        if (cdata.var_zeros[var] > mostzero)
        best = var, mostzero = cdata.var_zeros[best],
        mostbalanced = maxactive;
        else if (cdata.var_zeros[var] == mostzero)
        /* third condition is to pick a balanced variable */
        /* for binary vars, this means roughly equal # 0's and 1's */
        if (maxactive < mostbalanced)
            best = var, mostbalanced = maxactive;
    }

    cdata.parts_active[var] = active;
    cdata.is_unate[var] = (active == 1);
    cdata.vars_active += (active > 0);
    cdata.vars_unate += (active == 1);
    }
    cdata.best = best;
 }
}

int binate_split_select(T, cleft, cright, debug_flag)
IN pcube *T;
IN register pcube cleft, cright;
IN int debug_flag;
{
    int best = cdata.best;
    register int i, lastbit = cube.last_part[best], halfbit = 0;
    register pcube cof=T[0];

    /* Create the cubes to cofactor against */
    (void) set_diff(cleft, cube.fullset, cube.var_mask[best]);
    (void) set_diff(cright, cube.fullset, cube.var_mask[best]);
    for(i = cube.first_part[best]; i <= lastbit; i++)
    if (! is_in_set(cof,i))
        halfbit++;
    for(i = cube.first_part[best], halfbit = halfbit/2; halfbit > 0; i++)
    if (! is_in_set(cof,i))
        halfbit--, set_insert(cleft, i);
    for(; i <= lastbit; i++)
    if (! is_in_set(cof,i))
        set_insert(cright, i);

    if (debug & debug_flag) {
    (void) printf("BINATE_SPLIT_SELECT: split against %d\n", best);
    if (verbose_debug)
        (void) printf("cl=%s\ncr=%s\n", pc1(cleft), pc2(cright));
    }
    return best;
}


pcube *cube1list(A)
pcover A;
{
    register pcube last, p, *plist, *list;

    list = plist = ALLOC(pcube, A->count + 3);
    *plist++ = new_cube();
    plist++;
    foreach_set(A, last, p) {
    *plist++ = p;
    }
    *plist++ = NULL;                    /* sentinel */
    list[1] = (pcube) plist;
    return list;
}


pcube *cube2list(A, B)
pcover A, B;
{
    register pcube last, p, *plist, *list;

    list = plist = ALLOC(pcube, A->count + B->count + 3);
    *plist++ = new_cube();
    plist++;
    foreach_set(A, last, p) {
    *plist++ = p;
    }
    foreach_set(B, last, p) {
    *plist++ = p;
    }
    *plist++ = NULL;
    list[1] = (pcube) plist;
    return list;
}


pcube *cube3list(A, B, C)
pcover A, B, C;
{
    register pcube last, p, *plist, *list;

    plist = ALLOC(pcube, A->count + B->count + C->count + 3);
    list = plist;
    *plist++ = new_cube();
    plist++;
    foreach_set(A, last, p) {
    *plist++ = p;
    }
    foreach_set(B, last, p) {
    *plist++ = p;
    }
    foreach_set(C, last, p) {
    *plist++ = p;
    }
    *plist++ = NULL;
    list[1] = (pcube) plist;
    return list;
}


pcover cubeunlist(A1)
pcube *A1;
{
    register int i;
    register pcube p, pdest, cof = A1[0];
    register pcover A;

    A = new_cover(CUBELISTSIZE(A1));
    for(i = 2; (p = A1[i]) != NULL; i++) {
    pdest = GETSET(A, i-2);
    INLINEset_or(pdest, p, cof);
    }
    A->count = CUBELISTSIZE(A1);
    return A;
}

void simplify_cubelist(T)
pcube *T;
{
    register pcube *Tdest;
    register int i, ncubes;

    (void) set_copy(cube.temp[0], T[0]);        /* retrieve cofactor */

    ncubes = CUBELISTSIZE(T);
    qsort((char *) (T+2), (size_t)ncubes, sizeof(pset), (int (*)()) d1_order);

    Tdest = T+2;
    /*   *Tdest++ = T[2];   */
    for(i = 3; i < ncubes; i++) {
    if (d1_order(&T[i-1], &T[i]) != 0) {
        *Tdest++ = T[i];
    }
    }

    *Tdest++ = NULL;                /* sentinel */
    Tdest[1] = (pcube) Tdest;            /* save pointer to last */
}
ABC_NAMESPACE_IMPL_END