///|
pub(all) struct Generator {
mask : Int32
sign : Int32
} derive(Debug, Eq)
///|
pub extend Generator with @debug.Debug::{to_repr}
///|
pub extend Generator with Eq::{equal, not_equal}
///|
pub fn fraction(
factors : Array[Factor],
base : Int32,
generators : Array[Generator],
) -> Plan raise DesignError {
validate_factors(factors)
if base < 1 || base > 12 || base + generators.length() != factors.length() {
raise Budget("fraction base must be 1..12 and match factor/generator count")
}
for g in generators {
if g.mask <= 0 || g.mask >= 1 << base || (g.sign != -1 && g.sign != 1) {
raise Invalid(
"generator requires nonempty base-factor mask and sign +/-1",
)
}
}
let points = []
for row in 0..<(1 << base) {
let point : Array[Double] = [
for j in 0.. if (row & (1 << j)) == 0 { -1.0 } else { 1.0 }
]
for g in generators {
let mut x = g.sign.to_double()
for j in 0..