///|
fn checked_count_add(a : UInt64, b : UInt64) -> UInt64 raise ZddError {
let out = a + b
if out < a {
raise CountOverflow
}
out
}
///|
fn Family::counts(self : Family) -> Array[UInt64] raise ZddError {
let counts : Array[UInt64] = [0, 1]
for id in 2..2^64-1 members raise CountOverflow.
pub fn Family::count(self : Family) -> UInt64 raise ZddError {
self.counts()[self.root]
}
///|
pub(all) struct Enumeration {
sets : Array[Array[Int32]]
complete : Bool
}
///|
/// Low edges precede high edges; earlier variables are the most significant bits.
/// complete is false only if at least one actual member was omitted.
pub fn Family::enumerate(
self : Family,
limit : Int32,
limits~ : Limits = Limits::default(),
) -> Enumeration raise ZddError {
let work = engine(self.universe, limits)
if limit < 0 || limit > 10000 {
raise Invalid("enumeration limit must be 0..10000")
}
let sets : Array[Array[Int32]] = []
let path : Array[Int32] = []
fn visit(id : Int32) -> Bool raise ZddError {
work.tick()
if id == 0 {
return true
}
if id == 1 {
if sets.length() >= limit {
return false
}
sets.push(path.copy())
return true
}
let node = self.nodes[id]
if !visit(node.low) {
return false
}
path.push(node.variable)
let complete = visit(node.high)
ignore(path.pop())
complete
}
let complete = visit(self.root)
{ sets, complete, }
}