pub fn generate(mu: f32, x0: f32, n: usize) -> Vec<f32> {
let mut result = Vec::with_capacity(n);
let mut x = x0.clamp(0.0, 1.0);
for _ in 0..n {
result.push(x);
x = if x < 0.5 {
mu * x
} else {
mu * (1.0 - x)
};
x = x.clamp(0.0, 1.0);
}
result
}
pub fn tent_chaotic(n: usize) -> Vec<f32> {
generate(2.0, 0.3, n)
}
pub fn tent_moderate(n: usize) -> Vec<f32> {
generate(1.8, 0.4, n)
}
pub fn tent_mild(n: usize) -> Vec<f32> {
generate(1.5, 0.5, n)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_tent_map_basic() {
let sequence = generate(2.0, 0.3, 10);
assert_eq!(sequence.len(), 10);
assert_eq!(sequence[0], 0.3);
}
#[test]
fn test_tent_map_stays_in_range() {
let sequence = generate(2.0, 0.5, 200);
for &val in &sequence {
assert!(val >= 0.0 && val <= 1.0, "Value {} out of range", val);
}
}
#[test]
fn test_tent_map_deterministic() {
let seq1 = generate(2.0, 0.3, 50);
let seq2 = generate(2.0, 0.3, 50);
assert_eq!(seq1, seq2);
}
#[test]
fn test_tent_map_different_initial_conditions() {
let seq1 = generate(2.0, 0.3, 50);
let seq2 = generate(2.0, 0.4, 50);
assert_ne!(seq1, seq2);
}
#[test]
fn test_tent_map_left_side() {
let sequence = generate(2.0, 0.25, 2);
assert!((sequence[1] - 0.5).abs() < 0.001);
}
#[test]
fn test_tent_map_right_side() {
let sequence = generate(2.0, 0.75, 2);
assert!((sequence[1] - 0.5).abs() < 0.001);
}
#[test]
fn test_tent_map_at_boundary() {
let sequence = generate(2.0, 0.5, 2);
assert!((sequence[1] - 1.0).abs() < 0.001);
}
#[test]
fn test_tent_map_mu_equals_2_is_chaotic() {
let sequence = generate(2.0, 0.123456, 100);
let has_low = sequence.iter().any(|&x| x < 0.3);
let has_mid = sequence.iter().any(|&x| x >= 0.3 && x < 0.7);
let has_high = sequence.iter().any(|&x| x >= 0.7);
assert!(has_low, "Should have values in low range");
assert!(has_mid, "Should have values in mid range");
assert!(has_high, "Should have values in high range");
}
#[test]
fn test_tent_map_mu_less_than_2() {
let sequence = generate(1.5, 0.5, 100);
for &val in &sequence {
assert!(val >= 0.0 && val <= 1.0);
}
}
#[test]
fn test_tent_map_symmetry() {
let seq1 = generate(2.0, 0.3, 10);
let seq2 = generate(2.0, 0.7, 10);
assert!((seq1[1] - seq2[1]).abs() < 0.001);
}
#[test]
fn test_tent_map_clamps_input() {
let sequence = generate(2.0, 1.5, 1);
assert_eq!(sequence[0], 1.0); }
#[test]
fn test_tent_map_single_iteration() {
let sequence = generate(2.0, 0.5, 1);
assert_eq!(sequence.len(), 1);
assert_eq!(sequence[0], 0.5);
}
#[test]
fn test_tent_map_different_mu_values() {
let seq1 = generate(1.5, 0.5, 50);
let seq2 = generate(2.0, 0.5, 50);
assert_ne!(seq1, seq2);
}
#[test]
fn test_tent_map_period_2_orbit() {
let sequence = generate(2.0, 2.0/3.0, 5);
assert!((sequence[0] - 2.0/3.0).abs() < 0.01);
assert!((sequence[1] - 2.0/3.0).abs() < 0.01);
}
#[test]
fn test_tent_map_coverage() {
let sequence = generate(2.0, 0.123456, 1000);
let mut bins = vec![0; 10];
for &val in &sequence {
let bin = (val * 10.0).floor() as usize;
bins[bin.min(9)] += 1;
}
for &count in &bins {
assert!(count > 0, "Should have coverage in all bins");
}
}
}