///|
/// Balanced two-shaft plain weave, repeated in both dimensions.
pub fn plain(warp_repeats : Int, weft_repeats : Int) -> Result[Draft, String] {
if warp_repeats < 1 ||
weft_repeats < 1 ||
warp_repeats > 1024 ||
weft_repeats > 1024 ||
warp_repeats * weft_repeats > 65536 {
return Err("weave.size")
}
draft(
2,
Array::makei(warp_repeats * 2, fn(i) { i % 2 + 1 }),
Array::makei(weft_repeats * 2, fn(i) { [i % 2 + 1] }),
)
}
///|
/// Straight twill. up/down specify consecutive raised/lowered shafts.
pub fn twill(up : Int, down : Int) -> Result[Draft, String] {
if up < 1 || down < 1 || up > 63 || down > 63 || up + down > 64 {
return Err("weave.twill")
}
let n = up + down
draft(
n,
Array::makei(n, fn(i) { i + 1 }),
Array::makei(n, fn(p) { Array::makei(up, fn(k) { (p + k) % n + 1 }) }),
)
}
///|
fn gcd(a : Int, b : Int) -> Int {
if b == 0 {
a
} else {
gcd(b, a % b)
}
}
///|
/// Warp-faced regular satin: one lowered shaft per pick. Reject adjacent or non-coprime steps.
pub fn satin(shafts : Int, step : Int) -> Result[Draft, String] {
if shafts < 5 ||
shafts > 64 ||
step <= 1 ||
step >= shafts - 1 ||
gcd(shafts, step) != 1 {
return Err("weave.satin")
}
draft(
shafts,
Array::makei(shafts, fn(i) { i + 1 }),
Array::makei(shafts, fn(p) {
Array::makei(shafts, fn(i) { i + 1 }).filter(fn(s) {
s != p * step % shafts + 1
})
}),
)
}