You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
542 lines
19 KiB
542 lines
19 KiB
/**
|
|
* Binary operation Times (for MTBDDs of same type)
|
|
* Only for MTBDDs where either all leaves are Integer or Double.
|
|
* If either operand is mtbdd_false (not defined),
|
|
* then the result is mtbdd_false (i.e. not defined).
|
|
*/
|
|
TASK_IMPL_2(MTBDD, mtbdd_op_divide, MTBDD*, pa, MTBDD*, pb)
|
|
{
|
|
MTBDD a = *pa, b = *pb;
|
|
if (a == mtbdd_false || b == mtbdd_false) return mtbdd_false;
|
|
|
|
// Do not handle Boolean MTBDDs...
|
|
|
|
mtbddnode_t na = GETNODE(a);
|
|
mtbddnode_t nb = GETNODE(b);
|
|
|
|
if (mtbddnode_isleaf(na) && mtbddnode_isleaf(nb)) {
|
|
uint64_t val_a = mtbddnode_getvalue(na);
|
|
uint64_t val_b = mtbddnode_getvalue(nb);
|
|
if (mtbddnode_gettype(na) == 0 && mtbddnode_gettype(nb) == 0) {
|
|
// both uint64_t
|
|
if (val_a == 0) return a;
|
|
else if (val_b == 0) return b;
|
|
else {
|
|
MTBDD result;
|
|
if (val_a == 1) result = b;
|
|
else if (val_b == 1) result = a;
|
|
else result = mtbdd_uint64(val_a*val_b);
|
|
int nega = mtbdd_isnegated(a);
|
|
int negb = mtbdd_isnegated(b);
|
|
if (nega ^ negb) return mtbdd_negate(result);
|
|
else return result;
|
|
}
|
|
} else if (mtbddnode_gettype(na) == 1 && mtbddnode_gettype(nb) == 1) {
|
|
// both double
|
|
double vval_a = *(double*)&val_a;
|
|
double vval_b = *(double*)&val_b;
|
|
if (vval_a == 0.0) return a;
|
|
else if (vval_b == 0.0) return b;
|
|
else {
|
|
MTBDD result;
|
|
if (vval_a == 0.0 || vval_b == 1.0) result = a;
|
|
|
|
int nega = mtbdd_isnegated(a);
|
|
int negb = mtbdd_isnegated(b);
|
|
result = mtbdd_double(vval_a / vval_b);
|
|
if (nega ^ negb) return mtbdd_negate(result);
|
|
else return result;
|
|
}
|
|
}
|
|
else if (mtbddnode_gettype(na) == 2 && mtbddnode_gettype(nb) == 2) {
|
|
// both fraction
|
|
uint64_t nom_a = val_a>>32;
|
|
uint64_t nom_b = val_b>>32;
|
|
uint64_t denom_a = val_a&0xffffffff;
|
|
uint64_t denom_b = val_b&0xffffffff;
|
|
// multiply!
|
|
uint32_t c = gcd(denom_b, denom_a);
|
|
uint32_t d = gcd(nom_a, nom_b);
|
|
nom_a /= d;
|
|
denom_a /= c;
|
|
nom_a *= (denom_b/c);
|
|
denom_a *= (nom_b/d);
|
|
// compute result
|
|
int nega = mtbdd_isnegated(a);
|
|
int negb = mtbdd_isnegated(b);
|
|
MTBDD result = mtbdd_fraction(nom_a, denom_a);
|
|
if (nega ^ negb) return mtbdd_negate(result);
|
|
else return result;
|
|
}
|
|
}
|
|
|
|
return mtbdd_invalid;
|
|
}
|
|
|
|
/**
|
|
* Binary operation Equals (for MTBDDs of same type)
|
|
* Only for MTBDDs where either all leaves are Boolean, or Integer, or Double.
|
|
* For Integer/Double MTBDD, if either operand is mtbdd_false (not defined),
|
|
* then the result is mtbdd_false (i.e. not defined).
|
|
*/
|
|
TASK_IMPL_2(MTBDD, mtbdd_op_equals, MTBDD*, pa, MTBDD*, pb)
|
|
{
|
|
MTBDD a = *pa, b = *pb;
|
|
if (a == mtbdd_false && b == mtbdd_false) return mtbdd_true;
|
|
if (a == mtbdd_true && b == mtbdd_true) return mtbdd_true;
|
|
|
|
mtbddnode_t na = GETNODE(a);
|
|
mtbddnode_t nb = GETNODE(b);
|
|
|
|
if (mtbddnode_isleaf(na) && mtbddnode_isleaf(nb)) {
|
|
uint64_t val_a = mtbddnode_getvalue(na);
|
|
uint64_t val_b = mtbddnode_getvalue(nb);
|
|
if (mtbddnode_gettype(na) == 0 && mtbddnode_gettype(nb) == 0) {
|
|
// both uint64_t
|
|
int nega = mtbdd_isnegated(a);
|
|
int negb = mtbdd_isnegated(b);
|
|
if (val_a == val_b && !(nega ^ negb)) return mtbdd_true;
|
|
return mtbdd_false;
|
|
} else if (mtbddnode_gettype(na) == 1 && mtbddnode_gettype(nb) == 1) {
|
|
// both double
|
|
double vval_a = *(double*)&val_a;
|
|
double vval_b = *(double*)&val_b;
|
|
int nega = mtbdd_isnegated(a);
|
|
int negb = mtbdd_isnegated(b);
|
|
if (vval_a == vval_b && !(nega ^ negb)) return mtbdd_true;
|
|
return mtbdd_false;
|
|
} else if (mtbddnode_gettype(na) == 2 && mtbddnode_gettype(nb) == 2) {
|
|
// both fraction
|
|
uint64_t nom_a = val_a>>32;
|
|
uint64_t nom_b = val_b>>32;
|
|
uint64_t denom_a = val_a&0xffffffff;
|
|
uint64_t denom_b = val_b&0xffffffff;
|
|
int nega = mtbdd_isnegated(a);
|
|
int negb = mtbdd_isnegated(b);
|
|
if (nom_a == nom_b && denom_a == denom_b && !(nega ^ negb)) return mtbdd_true;
|
|
return mtbdd_false;
|
|
}
|
|
}
|
|
|
|
if (a < b) {
|
|
*pa = b;
|
|
*pb = a;
|
|
}
|
|
|
|
return mtbdd_invalid;
|
|
}
|
|
|
|
/**
|
|
* Binary operation Equals (for MTBDDs of same type)
|
|
* Only for MTBDDs where either all leaves are Boolean, or Integer, or Double.
|
|
* For Integer/Double MTBDD, if either operand is mtbdd_false (not defined),
|
|
* then the result is mtbdd_false (i.e. not defined).
|
|
*/
|
|
TASK_IMPL_2(MTBDD, mtbdd_op_less, MTBDD*, pa, MTBDD*, pb)
|
|
{
|
|
MTBDD a = *pa, b = *pb;
|
|
if (a == mtbdd_false && b == mtbdd_false) return mtbdd_true;
|
|
if (a == mtbdd_true && b == mtbdd_true) return mtbdd_true;
|
|
|
|
mtbddnode_t na = GETNODE(a);
|
|
mtbddnode_t nb = GETNODE(b);
|
|
|
|
if (mtbddnode_isleaf(na) && mtbddnode_isleaf(nb)) {
|
|
uint64_t val_a = mtbddnode_getvalue(na);
|
|
uint64_t val_b = mtbddnode_getvalue(nb);
|
|
if (mtbddnode_gettype(na) == 0 && mtbddnode_gettype(nb) == 0) {
|
|
// both uint64_t
|
|
int nega = mtbdd_isnegated(a);
|
|
int negb = mtbdd_isnegated(b);
|
|
if (nega && !negb) return mtbdd_true;
|
|
if (!nega && negb) return mtbdd_false;
|
|
if (nega && negb && val_a < val_b) return mtbdd_false;
|
|
return mtbdd_true;
|
|
} else if (mtbddnode_gettype(na) == 1 && mtbddnode_gettype(nb) == 1) {
|
|
// both double
|
|
double vval_a = *(double*)&val_a;
|
|
double vval_b = *(double*)&val_b;
|
|
int nega = mtbdd_isnegated(a);
|
|
if (nega) vval_a = -vval_a;
|
|
int negb = mtbdd_isnegated(b);
|
|
if (negb) vval_b = -vval_b;
|
|
if (vval_a < vval_b) return mtbdd_true;
|
|
return mtbdd_false;
|
|
} else if (mtbddnode_gettype(na) == 2 && mtbddnode_gettype(nb) == 2) {
|
|
// both fraction
|
|
uint64_t nom_a = val_a>>32;
|
|
uint64_t nom_b = val_b>>32;
|
|
uint64_t denom_a = val_a&0xffffffff;
|
|
uint64_t denom_b = val_b&0xffffffff;
|
|
int nega = mtbdd_isnegated(a);
|
|
int negb = mtbdd_isnegated(b);
|
|
if (nega && !negb) return mtbdd_true;
|
|
if (!nega && negb) return mtbdd_false;
|
|
return nom_a * denom_b < nom_b * denom_a ? mtbdd_true : mtbdd_false;
|
|
}
|
|
}
|
|
|
|
return mtbdd_invalid;
|
|
}
|
|
|
|
/**
|
|
* Binary operation Equals (for MTBDDs of same type)
|
|
* Only for MTBDDs where either all leaves are Boolean, or Integer, or Double.
|
|
* For Integer/Double MTBDD, if either operand is mtbdd_false (not defined),
|
|
* then the result is mtbdd_false (i.e. not defined).
|
|
*/
|
|
TASK_IMPL_2(MTBDD, mtbdd_op_less_or_equal, MTBDD*, pa, MTBDD*, pb)
|
|
{
|
|
MTBDD a = *pa, b = *pb;
|
|
if (a == mtbdd_false && b == mtbdd_false) return mtbdd_true;
|
|
if (a == mtbdd_true && b == mtbdd_true) return mtbdd_true;
|
|
|
|
mtbddnode_t na = GETNODE(a);
|
|
mtbddnode_t nb = GETNODE(b);
|
|
|
|
if (mtbddnode_isleaf(na) && mtbddnode_isleaf(nb)) {
|
|
uint64_t val_a = mtbddnode_getvalue(na);
|
|
uint64_t val_b = mtbddnode_getvalue(nb);
|
|
if (mtbddnode_gettype(na) == 0 && mtbddnode_gettype(nb) == 0) {
|
|
// both uint64_t
|
|
int nega = mtbdd_isnegated(a);
|
|
int negb = mtbdd_isnegated(b);
|
|
if (nega && !negb) {
|
|
if (val_a != 0) return mtbdd_true;
|
|
if (val_b != 0) return mtbdd_true;
|
|
return mtbdd_false;
|
|
}
|
|
if (!nega && negb) {
|
|
if (val_b != 0) return mtbdd_false;
|
|
if (val_a != 0) return mtbdd_false;
|
|
return mtbdd_true;
|
|
}
|
|
if (nega && negb) {
|
|
return val_a >= val_b ? mtbdd_true : mtbdd_false;
|
|
}
|
|
return val_a <= val_b ? mtbdd_true : mtbdd_false;
|
|
} else if (mtbddnode_gettype(na) == 1 && mtbddnode_gettype(nb) == 1) {
|
|
// both double
|
|
double vval_a = *(double*)&val_a;
|
|
double vval_b = *(double*)&val_b;
|
|
int nega = mtbdd_isnegated(a);
|
|
if (nega) vval_a = -vval_a;
|
|
int negb = mtbdd_isnegated(b);
|
|
if (negb) vval_b = -vval_b;
|
|
if (vval_a <= vval_b) return mtbdd_true;
|
|
return mtbdd_false;
|
|
} else if (mtbddnode_gettype(na) == 2 && mtbddnode_gettype(nb) == 2) {
|
|
// both fraction
|
|
uint64_t nom_a = val_a>>32;
|
|
uint64_t nom_b = val_b>>32;
|
|
uint64_t denom_a = val_a&0xffffffff;
|
|
uint64_t denom_b = val_b&0xffffffff;
|
|
int nega = mtbdd_isnegated(a);
|
|
int negb = mtbdd_isnegated(b);
|
|
nom_a *= denom_b;
|
|
nom_b *= denom_a;
|
|
if (nega && !negb) {
|
|
if (nom_a != 0) return mtbdd_true;
|
|
if (nom_b != 0) return mtbdd_true;
|
|
return mtbdd_false;
|
|
}
|
|
if (!nega && negb) {
|
|
if (nom_a != 0) return mtbdd_false;
|
|
if (nom_b != 0) return mtbdd_false;
|
|
return mtbdd_true;
|
|
}
|
|
if (nega && negb) {
|
|
return nom_a >= nom_b ? mtbdd_true : mtbdd_false;
|
|
}
|
|
return val_a <= val_b ? mtbdd_true : mtbdd_false;
|
|
}
|
|
}
|
|
|
|
return mtbdd_invalid;
|
|
}
|
|
|
|
/**
|
|
* Binary operation Pow (for MTBDDs of same type)
|
|
* Only for MTBDDs where either all leaves are Double.
|
|
* For Integer/Double MTBDD, if either operand is mtbdd_false (not defined),
|
|
* then the result is mtbdd_false (i.e. not defined).
|
|
*/
|
|
TASK_IMPL_2(MTBDD, mtbdd_op_pow, MTBDD*, pa, MTBDD*, pb)
|
|
{
|
|
MTBDD a = *pa, b = *pb;
|
|
|
|
mtbddnode_t na = GETNODE(a);
|
|
mtbddnode_t nb = GETNODE(b);
|
|
|
|
if (mtbddnode_isleaf(na) && mtbddnode_isleaf(nb)) {
|
|
uint64_t val_a = mtbddnode_getvalue(na);
|
|
uint64_t val_b = mtbddnode_getvalue(nb);
|
|
if (mtbddnode_gettype(na) == 0 && mtbddnode_gettype(nb) == 0) {
|
|
assert(0);
|
|
} else if (mtbddnode_gettype(na) == 1 && mtbddnode_gettype(nb) == 1) {
|
|
// both double
|
|
double vval_a = *(double*)&val_a;
|
|
double vval_b = *(double*)&val_b;
|
|
int nega = mtbdd_isnegated(a);
|
|
if (nega) vval_a = -vval_a;
|
|
int negb = mtbdd_isnegated(b);
|
|
if (negb) vval_b = -vval_b;
|
|
return mtbdd_double(pow(vval_a, vval_b));
|
|
} else if (mtbddnode_gettype(na) == 2 && mtbddnode_gettype(nb) == 2) {
|
|
assert(0);
|
|
}
|
|
}
|
|
|
|
return mtbdd_invalid;
|
|
}
|
|
|
|
/**
|
|
* Binary operation Mod (for MTBDDs of same type)
|
|
* Only for MTBDDs where either all leaves are Double.
|
|
* For Integer/Double MTBDD, if either operand is mtbdd_false (not defined),
|
|
* then the result is mtbdd_false (i.e. not defined).
|
|
*/
|
|
TASK_IMPL_2(MTBDD, mtbdd_op_mod, MTBDD*, pa, MTBDD*, pb)
|
|
{
|
|
MTBDD a = *pa, b = *pb;
|
|
|
|
mtbddnode_t na = GETNODE(a);
|
|
mtbddnode_t nb = GETNODE(b);
|
|
|
|
if (mtbddnode_isleaf(na) && mtbddnode_isleaf(nb)) {
|
|
uint64_t val_a = mtbddnode_getvalue(na);
|
|
uint64_t val_b = mtbddnode_getvalue(nb);
|
|
if (mtbddnode_gettype(na) == 0 && mtbddnode_gettype(nb) == 0) {
|
|
assert(0);
|
|
} else if (mtbddnode_gettype(na) == 1 && mtbddnode_gettype(nb) == 1) {
|
|
// both double
|
|
double vval_a = *(double*)&val_a;
|
|
double vval_b = *(double*)&val_b;
|
|
int nega = mtbdd_isnegated(a);
|
|
if (nega) vval_a = -vval_a;
|
|
int negb = mtbdd_isnegated(b);
|
|
if (negb) vval_b = -vval_b;
|
|
return mtbdd_double(fmod(vval_a, vval_b));
|
|
} else if (mtbddnode_gettype(na) == 2 && mtbddnode_gettype(nb) == 2) {
|
|
assert(0);
|
|
}
|
|
}
|
|
|
|
return mtbdd_invalid;
|
|
}
|
|
|
|
/**
|
|
* Binary operation Log (for MTBDDs of same type)
|
|
* Only for MTBDDs where either all leaves are Double.
|
|
* For Integer/Double MTBDD, if either operand is mtbdd_false (not defined),
|
|
* then the result is mtbdd_false (i.e. not defined).
|
|
*/
|
|
TASK_IMPL_2(MTBDD, mtbdd_op_logxy, MTBDD*, pa, MTBDD*, pb)
|
|
{
|
|
MTBDD a = *pa, b = *pb;
|
|
|
|
mtbddnode_t na = GETNODE(a);
|
|
mtbddnode_t nb = GETNODE(b);
|
|
|
|
if (mtbddnode_isleaf(na) && mtbddnode_isleaf(nb)) {
|
|
uint64_t val_a = mtbddnode_getvalue(na);
|
|
uint64_t val_b = mtbddnode_getvalue(nb);
|
|
if (mtbddnode_gettype(na) == 0 && mtbddnode_gettype(nb) == 0) {
|
|
assert(0);
|
|
} else if (mtbddnode_gettype(na) == 1 && mtbddnode_gettype(nb) == 1) {
|
|
// both double
|
|
double vval_a = *(double*)&val_a;
|
|
double vval_b = *(double*)&val_b;
|
|
int nega = mtbdd_isnegated(a);
|
|
if (nega) vval_a = -vval_a;
|
|
int negb = mtbdd_isnegated(b);
|
|
if (negb) vval_b = -vval_b;
|
|
return mtbdd_double(log(vval_a) / log(vval_b));
|
|
} else if (mtbddnode_gettype(na) == 2 && mtbddnode_gettype(nb) == 2) {
|
|
assert(0);
|
|
}
|
|
}
|
|
|
|
return mtbdd_invalid;
|
|
}
|
|
|
|
TASK_IMPL_2(MTBDD, mtbdd_op_not_zero, MTBDD, a, size_t, v)
|
|
{
|
|
/* We only expect "double" terminals, or false */
|
|
if (a == mtbdd_false) return mtbdd_false;
|
|
if (a == mtbdd_true) return mtbdd_true;
|
|
|
|
// a != constant
|
|
mtbddnode_t na = GETNODE(a);
|
|
|
|
if (mtbddnode_isleaf(na)) {
|
|
if (mtbddnode_gettype(na) == 0) {
|
|
return mtbdd_getuint64(a) != 0 ? mtbdd_true : mtbdd_false;
|
|
} else if (mtbddnode_gettype(na) == 1) {
|
|
return mtbdd_getdouble(a) != 0.0 ? mtbdd_true : mtbdd_false;
|
|
} else if (mtbddnode_gettype(na) == 2) {
|
|
return mtbdd_getnumer(a) != 0 ? mtbdd_true : mtbdd_false;
|
|
}
|
|
}
|
|
|
|
// Ugly hack to get rid of the error "unused variable v" (because there is no version of uapply without a parameter).
|
|
(void)v;
|
|
|
|
return mtbdd_invalid;
|
|
}
|
|
|
|
TASK_IMPL_1(MTBDD, mtbdd_not_zero, MTBDD, dd)
|
|
{
|
|
return mtbdd_uapply(dd, TASK(mtbdd_op_not_zero), 0);
|
|
}
|
|
|
|
TASK_IMPL_2(MTBDD, mtbdd_op_floor, MTBDD, a, size_t, v)
|
|
{
|
|
/* We only expect "double" terminals, or false */
|
|
if (a == mtbdd_false) return mtbdd_false;
|
|
if (a == mtbdd_true) return mtbdd_true;
|
|
|
|
// a != constant
|
|
mtbddnode_t na = GETNODE(a);
|
|
|
|
if (mtbddnode_isleaf(na)) {
|
|
if (mtbddnode_gettype(na) == 0) {
|
|
return a;
|
|
} else if (mtbddnode_gettype(na) == 1) {
|
|
MTBDD result = mtbdd_double(floor(mtbdd_getdouble(a)));
|
|
return mtbdd_isnegated(a) ? mtbdd_negate(result) : result;
|
|
} else if (mtbddnode_gettype(na) == 2) {
|
|
MTBDD result = mtbdd_fraction(mtbdd_getnumer(a) / mtbdd_getdenom(a), 1);
|
|
return mtbdd_isnegated(a) ? mtbdd_negate(result) : result;
|
|
}
|
|
}
|
|
|
|
// Ugly hack to get rid of the error "unused variable v" (because there is no version of uapply without a parameter).
|
|
(void)v;
|
|
|
|
return mtbdd_invalid;
|
|
}
|
|
|
|
TASK_IMPL_1(MTBDD, mtbdd_floor, MTBDD, dd)
|
|
{
|
|
return mtbdd_uapply(dd, TASK(mtbdd_op_floor), 0);
|
|
}
|
|
|
|
TASK_IMPL_2(MTBDD, mtbdd_op_ceil, MTBDD, a, size_t, v)
|
|
{
|
|
/* We only expect "double" terminals, or false */
|
|
if (a == mtbdd_false) return mtbdd_false;
|
|
if (a == mtbdd_true) return mtbdd_true;
|
|
|
|
// a != constant
|
|
mtbddnode_t na = GETNODE(a);
|
|
|
|
if (mtbddnode_isleaf(na)) {
|
|
if (mtbddnode_gettype(na) == 0) {
|
|
return a;
|
|
} else if (mtbddnode_gettype(na) == 1) {
|
|
MTBDD result = mtbdd_double(ceil(mtbdd_getdouble(a)));
|
|
return mtbdd_isnegated(a) ? mtbdd_negate(result) : result;
|
|
} else if (mtbddnode_gettype(na) == 2) {
|
|
MTBDD result = mtbdd_fraction(mtbdd_getnumer(a) / mtbdd_getdenom(a) + 1, 1);
|
|
return mtbdd_isnegated(a) ? mtbdd_negate(result) : result;
|
|
}
|
|
}
|
|
|
|
// Ugly hack to get rid of the error "unused variable v" (because there is no version of uapply without a parameter).
|
|
(void)v;
|
|
|
|
return mtbdd_invalid;
|
|
}
|
|
|
|
TASK_IMPL_1(MTBDD, mtbdd_ceil, MTBDD, dd)
|
|
{
|
|
return mtbdd_uapply(dd, TASK(mtbdd_op_ceil), 0);
|
|
}
|
|
|
|
TASK_IMPL_2(MTBDD, mtbdd_op_bool_to_double, MTBDD, a, size_t, v)
|
|
{
|
|
/* We only expect "double" terminals, or false */
|
|
if (a == mtbdd_false) return mtbdd_double(0);
|
|
if (a == mtbdd_true) return mtbdd_double(1.0);
|
|
|
|
// Ugly hack to get rid of the error "unused variable v" (because there is no version of uapply without a parameter).
|
|
(void)v;
|
|
|
|
return mtbdd_invalid;
|
|
}
|
|
|
|
TASK_IMPL_1(MTBDD, mtbdd_bool_to_double, MTBDD, dd)
|
|
{
|
|
return mtbdd_uapply(dd, TASK(mtbdd_op_bool_to_double), 0);
|
|
}
|
|
|
|
TASK_IMPL_2(MTBDD, mtbdd_op_bool_to_uint64, MTBDD, a, size_t, v)
|
|
{
|
|
/* We only expect "double" terminals, or false */
|
|
if (a == mtbdd_false) return mtbdd_uint64(0);
|
|
if (a == mtbdd_true) return mtbdd_uint64(1);
|
|
|
|
// Ugly hack to get rid of the error "unused variable v" (because there is no version of uapply without a parameter).
|
|
(void)v;
|
|
|
|
return mtbdd_invalid;
|
|
}
|
|
|
|
TASK_IMPL_1(MTBDD, mtbdd_bool_to_uint64, MTBDD, dd)
|
|
{
|
|
return mtbdd_uapply(dd, TASK(mtbdd_op_bool_to_uint64), 0);
|
|
}
|
|
|
|
/**
|
|
* Calculate the number of satisfying variable assignments according to <variables>.
|
|
*/
|
|
TASK_IMPL_2(double, mtbdd_non_zero_count, MTBDD, dd, size_t, nvars)
|
|
{
|
|
/* Trivial cases */
|
|
if (dd == mtbdd_false) return 0.0;
|
|
|
|
mtbddnode_t na = GETNODE(dd);
|
|
|
|
if (mtbdd_isleaf(dd)) {
|
|
if (mtbddnode_gettype(na) == 0) {
|
|
return mtbdd_getuint64(dd) != 0 ? powl(2.0L, nvars) : 0.0;
|
|
} else if (mtbddnode_gettype(na) == 1) {
|
|
return mtbdd_getdouble(dd) != 0 ? powl(2.0L, nvars) : 0.0;
|
|
} else if (mtbddnode_gettype(na) == 2) {
|
|
return mtbdd_getnumer(dd) != 0 ? powl(2.0L, nvars) : 0.0;
|
|
}
|
|
}
|
|
|
|
/* Perhaps execute garbage collection */
|
|
sylvan_gc_test();
|
|
|
|
union {
|
|
double d;
|
|
uint64_t s;
|
|
} hack;
|
|
|
|
/* Consult cache */
|
|
if (cache_get3(CACHE_MTBDD_NONZERO_COUNT, dd, 0, nvars, &hack.s)) {
|
|
sylvan_stats_count(CACHE_MTBDD_NONZERO_COUNT);
|
|
return hack.d;
|
|
}
|
|
|
|
SPAWN(mtbdd_non_zero_count, mtbdd_gethigh(dd), nvars-1);
|
|
double low = CALL(mtbdd_non_zero_count, mtbdd_getlow(dd), nvars-1);
|
|
hack.d = low + SYNC(mtbdd_non_zero_count);
|
|
|
|
cache_put3(CACHE_MTBDD_NONZERO_COUNT, dd, 0, nvars, hack.s);
|
|
return hack.d;
|
|
}
|
|
|
|
int mtbdd_iszero(MTBDD dd) {
|
|
if (mtbdd_gettype(dd) == 0) {
|
|
return mtbdd_getuint64(dd) == 0;
|
|
} else if (mtbdd_gettype(dd) == 1) {
|
|
return mtbdd_getdouble(dd) == 0;
|
|
} else if (mtbdd_gettype(dd) == 2) {
|
|
return mtbdd_getnumer(dd) == 0;
|
|
}
|
|
return 0;
|
|
}
|