///|
/// Apposition aligns objects by identity and concatenates disjoint attribute vocabularies.
pub fn Context::apposition(
self : Context,
other : Context,
) -> Context raise FcaError {
if self.object_count() != other.object_count() {
raise Invalid("apposition requires the same object identities")
}
let alignment : Array[Int32] = []
for name in self.object_names {
match other.object_index(name) {
Some(index) => alignment.push(index)
None => raise Invalid("apposition object identity is missing")
}
}
let names = self.attributes()
for name in other.attribute_names {
if names.contains(name) {
raise Invalid("apposition attribute identities must be disjoint")
}
names.push(name)
}
let rows : Array[Array[Bool]] = []
for o = 0; o < self.object_count(); o = o + 1 {
let row = self.incidence[o].copy()
for value in other.incidence[alignment[o]] {
row.push(value)
}
rows.push(row)
}
context(self.objects(), names, rows)
}
///|
/// Subposition aligns attributes by identity and concatenates disjoint object populations.
pub fn Context::subposition(
self : Context,
other : Context,
) -> Context raise FcaError {
if self.attribute_count() != other.attribute_count() {
raise Invalid("subposition requires the same attribute identities")
}
let alignment : Array[Int32] = []
for name in self.attribute_names {
match other.attribute_index(name) {
Some(index) => alignment.push(index)
None => raise Invalid("subposition attribute identity is missing")
}
}
let names = self.objects()
let rows = self.rows()
for o = 0; o < other.object_count(); o = o + 1 {
let name = other.object_names[o]
if names.contains(name) {
raise Invalid("subposition object identities must be disjoint")
}
names.push(name)
rows.push(alignment.map(fn(a) { other.incidence[o][a] }))
}
context(names, self.attributes(), rows)
}