|
|
@ -1263,11 +1263,6 @@ TASK_IMPL_2(MTBDD, mtbdd_op_divide, MTBDD*, pa, MTBDD*, pb) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (a < b) { |
|
|
|
*pa = b; |
|
|
|
*pb = a; |
|
|
|
} |
|
|
|
|
|
|
|
return mtbdd_invalid; |
|
|
|
} |
|
|
|
|
|
|
@ -1480,6 +1475,135 @@ TASK_IMPL_2(MTBDD, mtbdd_op_equals, MTBDD*, pa, MTBDD*, pb) |
|
|
|
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; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Compute IF <f> THEN <g> ELSE <h>. |
|
|
|
* <f> must be a Boolean MTBDD (or standard BDD). |
|
|
@ -1588,7 +1712,7 @@ TASK_IMPL_2(MTBDD, mtbdd_op_strict_threshold_double, MTBDD, a, size_t, svalue) |
|
|
|
return mtbdd_invalid; |
|
|
|
} |
|
|
|
|
|
|
|
TASK_IMPL_1(MTBDD, mtbdd_not_zero, MTBDD, a) |
|
|
|
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; |
|
|
@ -1607,7 +1731,18 @@ TASK_IMPL_1(MTBDD, mtbdd_not_zero, MTBDD, a) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return mtbdd_invalid; |
|
|
|
// Ugly hack to get rid of the error "unused variable v" (because there is no version of uapply without a parameter). |
|
|
|
return v > 0 ? mtbdd_invalid : mtbdd_invalid; |
|
|
|
} |
|
|
|
|
|
|
|
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). |
|
|
|
return v > 0 ? mtbdd_invalid : mtbdd_invalid; |
|
|
|
} |
|
|
|
|
|
|
|
TASK_IMPL_2(MTBDD, mtbdd_threshold_double, MTBDD, dd, double, d) |
|
|
@ -1620,6 +1755,16 @@ TASK_IMPL_2(MTBDD, mtbdd_strict_threshold_double, MTBDD, dd, double, d) |
|
|
|
return mtbdd_uapply(dd, TASK(mtbdd_op_strict_threshold_double), *(size_t*)&d); |
|
|
|
} |
|
|
|
|
|
|
|
TASK_IMPL_1(MTBDD, mtbdd_not_zero, MTBDD, dd) |
|
|
|
{ |
|
|
|
return mtbdd_uapply(dd, TASK(mtbdd_op_not_zero), 0); |
|
|
|
} |
|
|
|
|
|
|
|
TASK_IMPL_1(MTBDD, mtbdd_bool_to_double, MTBDD, dd) |
|
|
|
{ |
|
|
|
return mtbdd_uapply(dd, TASK(mtbdd_op_bool_to_double), 0); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Compare two Double MTBDDs, returns Boolean True if they are equal within some value epsilon |
|
|
|
*/ |
|
|
|