#include "espresso.h"
ABC_NAMESPACE_IMPL_START
static bool toggle = TRUE;
pcover reduce(F, D)
INOUT pcover F;
IN pcover D;
{
register pcube last, p, cunder, *FD;
if (use_random_order)
F = random_order(F);
else {
F = toggle ? sort_reduce(F) : mini_sort(F, descend);
toggle = ! toggle;
}
FD = cube2list(F, D);
foreach_set(F, last, p) {
cunder = reduce_cube(FD, p);
if (setp_equal(cunder, p)) {
SET(p, ACTIVE);
SET(p, PRIME);
} else {
if (debug & REDUCE) {
printf("REDUCE: %s to %s %s\n",
pc1(p), pc2(cunder), print_time(ptime()));
}
set_copy(p, cunder);
RESET(p, PRIME);
if (setp_empty(cunder))
RESET(p, ACTIVE);
else
SET(p, ACTIVE);
}
free_cube(cunder);
}
free_cubelist(FD);
return sf_inactive(F);
}
pcube reduce_cube(FD, p)
IN pcube *FD, p;
{
pcube cunder;
cunder = sccc(cofactor(FD, p));
return set_and(cunder, cunder, p);
}
pcube sccc(T)
INOUT pcube *T;
{
pcube r;
register pcube cl, cr;
register int best;
static int sccc_level = 0;
if (debug & REDUCE1) {
debug_print(T, "SCCC", sccc_level++);
}
if (sccc_special_cases(T, &r) == MAYBE) {
cl = new_cube();
cr = new_cube();
best = binate_split_select(T, cl, cr, REDUCE1);
r = sccc_merge(sccc(scofactor(T, cl, best)),
sccc(scofactor(T, cr, best)), cl, cr);
free_cubelist(T);
}
if (debug & REDUCE1)
printf("SCCC[%d]: result is %s\n", --sccc_level, pc1(r));
return r;
}
pcube sccc_merge(left, right, cl, cr)
INOUT register pcube left, right;
INOUT register pcube cl, cr;
{
INLINEset_and(left, left, cl);
INLINEset_and(right, right, cr);
INLINEset_or(left, left, right);
free_cube(right);
free_cube(cl);
free_cube(cr);
return left;
}
pcube sccc_cube(result, p)
register pcube result, p;
{
register pcube temp=cube.temp[0], mask;
int var;
if ((var = cactive(p)) >= 0) {
mask = cube.var_mask[var];
INLINEset_xor(temp, p, mask);
INLINEset_and(result, result, temp);
}
return result;
}
bool sccc_special_cases(T, result)
INOUT pcube *T;
OUT pcube *result;
{
register pcube *T1, p, temp = cube.temp[1], ceil, cof = T[0];
pcube *A, *B;
if (T[2] == NULL) {
*result = set_save(cube.fullset);
free_cubelist(T);
return TRUE;
}
for(T1 = T+2; (p = *T1++) != NULL; ) {
if (full_row(p, cof)) {
*result = new_cube();
free_cubelist(T);
return TRUE;
}
}
massive_count(T);
if (cdata.vars_unate == cdata.vars_active || T[3] == NULL) {
*result = set_save(cube.fullset);
for(T1 = T+2; (p = *T1++) != NULL; ) {
(void) sccc_cube(*result, set_or(temp, p, cof));
}
free_cubelist(T);
return TRUE;
}
ceil = set_save(cof);
for(T1 = T+2; (p = *T1++) != NULL; ) {
INLINEset_or(ceil, ceil, p);
}
if (! setp_equal(ceil, cube.fullset)) {
*result = sccc_cube(set_save(cube.fullset), ceil);
if (setp_equal(*result, cube.fullset)) {
free_cube(ceil);
} else {
*result = sccc_merge(sccc(cofactor(T,ceil)),
set_save(cube.fullset), ceil, *result);
}
free_cubelist(T);
return TRUE;
}
free_cube(ceil);
if (cdata.vars_active == 1) {
*result = new_cube();
free_cubelist(T);
return TRUE;
}
if (cdata.var_zeros[cdata.best] < CUBELISTSIZE(T)/2) {
if (cubelist_partition(T, &A, &B, debug & REDUCE1) == 0) {
return MAYBE;
} else {
free_cubelist(T);
*result = sccc(A);
ceil = sccc(B);
(void) set_and(*result, *result, ceil);
set_free(ceil);
return TRUE;
}
}
return MAYBE;
}
ABC_NAMESPACE_IMPL_END