///|
/// Joint recurrence intersects masks as well as recurrence indicators.
pub fn joint_recurrence(
matrices : Array[Recurrence],
) -> Result[Recurrence, RqaError] {
if matrices.length() == 0 || matrices.length() > 64 {
return Err(Invalid("joint matrix count"))
}
let first = matrices[0]
let bits = first.bits.copy()
let mask = first.mask.copy()
for r in matrices {
if r.shape() != first.shape() {
return Err(Invalid("joint shape mismatch"))
}
for p in 0.. Result[Recurrence, RqaError] {
if rows.length() == 0 {
return Err(Invalid("empty recurrence rows"))
}
let n = rows.length()
let m = rows[0].length()
if n > 4096 || m > 4096 || !cell_budget(n, m, 1048576) {
return Err(Limit("import matrix cell budget"))
}
let bits : Array[Bool] = []
let mask : Array[Bool] = []
for row in rows {
if row.length() != m {
return Err(Invalid("ragged recurrence matrix"))
}
for x in row {
if x < -1 || x > 1 {
return Err(Invalid("ternary cell"))
}
bits.push(x == 1)
mask.push(x != -1)
}
}
Ok({ height: n, width: m, bits, mask, })
}
///|
pub fn Recurrence::rows(self : Recurrence) -> Array[Array[Int32]] {
Array::makei(self.height, fn(i) {
Array::makei(self.width, fn(j) {
let p = i * self.width + j
if !self.mask[p] {
-1
} else if self.bits[p] {
1
} else {
0
}
})
})
}