pub fn generate(x0: f32, y0: f32, n: usize) -> (Vec<f32>, Vec<f32>) {
let mut x_vals = Vec::with_capacity(n);
let mut y_vals = Vec::with_capacity(n);
let mut x = x0.clamp(0.0, 1.0);
let mut y = y0.clamp(0.0, 1.0);
for _ in 0..n {
x_vals.push(x);
y_vals.push(y);
let (x_next, y_next) = if x < 0.5 {
(2.0 * x, y / 2.0)
} else {
(2.0 * x - 1.0, (y + 1.0) / 2.0)
};
x = x_next;
y = y_next;
}
(x_vals, y_vals)
}
pub fn bakers_x(x0: f32, y0: f32, n: usize) -> Vec<f32> {
generate(x0, y0, n).0
}
pub fn bakers_y(x0: f32, y0: f32, n: usize) -> Vec<f32> {
generate(x0, y0, n).1
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_bakers_map_basic() {
let (x_vals, y_vals) = generate(0.3, 0.7, 10);
assert_eq!(x_vals.len(), 10);
assert_eq!(y_vals.len(), 10);
assert_eq!(x_vals[0], 0.3);
assert_eq!(y_vals[0], 0.7);
}
#[test]
fn test_bakers_map_stays_in_unit_square() {
let (x_vals, y_vals) = generate(0.5, 0.5, 200);
for &x in &x_vals {
assert!(x >= 0.0 && x <= 1.0, "x = {} out of range", x);
}
for &y in &y_vals {
assert!(y >= 0.0 && y <= 1.0, "y = {} out of range", y);
}
}
#[test]
fn test_bakers_map_deterministic() {
let (x1, y1) = generate(0.3, 0.7, 50);
let (x2, y2) = generate(0.3, 0.7, 50);
assert_eq!(x1, x2);
assert_eq!(y1, y2);
}
#[test]
fn test_bakers_map_different_initial_conditions() {
let (x1, _) = generate(0.3, 0.7, 50);
let (x2, _) = generate(0.4, 0.6, 50);
assert_ne!(x1, x2);
}
#[test]
fn test_bakers_map_left_half() {
let (x_vals, y_vals) = generate(0.25, 0.8, 2);
assert!((x_vals[1] - 0.5).abs() < 0.001);
assert!((y_vals[1] - 0.4).abs() < 0.001);
}
#[test]
fn test_bakers_map_right_half() {
let (x_vals, y_vals) = generate(0.75, 0.6, 2);
assert!((x_vals[1] - 0.5).abs() < 0.001);
assert!((y_vals[1] - 0.8).abs() < 0.001);
}
#[test]
fn test_bakers_map_clamps_input() {
let (x_vals, y_vals) = generate(1.5, -0.5, 1);
assert_eq!(x_vals[0], 1.0); assert_eq!(y_vals[0], 0.0); }
#[test]
fn test_bakers_map_single_point() {
let (x_vals, y_vals) = generate(0.5, 0.5, 1);
assert_eq!(x_vals.len(), 1);
assert_eq!(y_vals.len(), 1);
}
#[test]
fn test_bakers_map_mixing() {
let (x_vals, y_vals) = generate(0.123456, 0.789012, 100);
let has_low_x = x_vals.iter().any(|&x| x < 0.5);
let has_high_x = x_vals.iter().any(|&x| x >= 0.5);
let has_low_y = y_vals.iter().any(|&y| y < 0.5);
let has_high_y = y_vals.iter().any(|&y| y >= 0.5);
assert!(has_low_x && has_high_x, "Should mix x values");
assert!(has_low_y && has_high_y, "Should mix y values");
}
#[test]
fn test_bakers_x_convenience() {
let x_only = bakers_x(0.3, 0.7, 32);
let (x_full, _) = generate(0.3, 0.7, 32);
assert_eq!(x_only, x_full);
}
#[test]
fn test_bakers_y_convenience() {
let y_only = bakers_y(0.3, 0.7, 32);
let (_, y_full) = generate(0.3, 0.7, 32);
assert_eq!(y_only, y_full);
}
#[test]
fn test_bakers_map_boundary_behavior() {
let (x_vals, y_vals) = generate(0.5, 0.5, 2);
assert!((x_vals[1] - 0.0).abs() < 0.001);
assert!((y_vals[1] - 0.75).abs() < 0.001);
}
#[test]
fn test_bakers_map_distribution() {
let (x_vals, _) = generate(0.123456, 0.789012, 1000);
let count_0_to_0_5 = x_vals.iter().filter(|&&x| x < 0.5).count();
let count_0_5_to_1 = x_vals.iter().filter(|&&x| x >= 0.5).count();
assert!(count_0_to_0_5 > 10 || count_0_5_to_1 > 10);
assert!(count_0_to_0_5 + count_0_5_to_1 == 1000);
}
}
pub fn classic() -> (Vec<f32>, Vec<f32>) {
generate(0.5, 0.5, 50)
}
pub fn extended() -> (Vec<f32>, Vec<f32>) {
generate(0.5, 0.5, 100)
}