///|
pub(all) struct RepeatSize {
warp : Int
pick : Int
} derive(Eq, Debug, ToJson, FromJson)
///|
/// Smallest axis-aligned period dividing the finite drawdown. O(cells*(width+height)) worst case.
pub fn Draft::repeat_size(self : Draft) -> RepeatSize {
let a = self.drawdown()
let mut wx = self.width()
for n = 1; n <= self.width(); n = n + 1 {
if self.width() % n != 0 {
continue
}
let mut good = true
for row in a {
for x, v in row {
if v != row[x % n] {
good = false
break
}
}
if !good {
break
}
}
if good {
wx = n
break
}
}
let mut py = self.height()
for n = 1; n <= self.height(); n = n + 1 {
if self.height() % n != 0 {
continue
}
let mut good = true
for y, row in a {
if row != a[y % n] {
good = false
break
}
}
if good {
py = n
break
}
}
{ warp: wx, pick: py, }
}
///|
/// Preserve draft shafts and crop to the smallest drawdown repeat.
pub fn Draft::reduce_repeat(self : Draft) -> Draft {
let r = self.repeat_size()
{
shafts: self.shafts,
threading: Array::makei(r.warp, fn(i) { self.threading[i] }),
lifts: Array::makei(r.pick, fn(i) { self.lifts[i].copy() }),
}
}