use std::f32::consts::PI;
pub fn generate(r: 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 = r * (PI * x).sin();
if x < 0.0 {
x = 0.0;
} else if x > 1.0 && r <= PI {
x = x.min(1.0);
}
}
result
}
pub fn sine_smooth(n: usize) -> Vec<f32> {
generate(2.7, 0.4, n)
}
pub fn sine_chaotic(n: usize) -> Vec<f32> {
generate(PI, 0.5, n)
}
pub fn sine_gentle(n: usize) -> Vec<f32> {
generate(2.5, 0.3, n)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_sine_map_basic() {
let sequence = generate(2.9, 0.5, 10);
assert_eq!(sequence.len(), 10);
assert_eq!(sequence[0], 0.5);
}
#[test]
fn test_sine_map_stays_in_range() {
let sequence = generate(2.9, 0.5, 200);
for &val in &sequence {
assert!(val >= 0.0, "Value {} is negative", val);
assert!(val <= 3.5, "Value {} is too large", val);
}
}
#[test]
fn test_sine_map_deterministic() {
let seq1 = generate(2.9, 0.5, 50);
let seq2 = generate(2.9, 0.5, 50);
assert_eq!(seq1, seq2);
}
#[test]
fn test_sine_map_different_initial_conditions() {
let seq1 = generate(2.9, 0.5, 50);
let seq2 = generate(2.9, 0.6, 50);
assert_ne!(seq1, seq2);
}
#[test]
fn test_sine_map_first_iteration() {
let sequence = generate(2.9, 0.5, 2);
assert!((sequence[1] - 1.0).abs() < 0.001);
}
#[test]
fn test_sine_map_at_pi() {
let sequence = generate(PI, 0.5, 100);
for &val in &sequence {
assert!(val >= 0.0 && val <= 1.0);
}
}
#[test]
fn test_sine_map_chaotic_behavior() {
let sequence = generate(2.7, 0.3, 200);
let has_low = sequence.iter().any(|&x| x < 0.5);
let has_high = sequence.iter().any(|&x| x >= 0.5);
assert!(has_low || has_high, "Should show variation");
}
#[test]
fn test_sine_map_clamps_input() {
let sequence = generate(2.9, 1.5, 1);
assert_eq!(sequence[0], 1.0); }
#[test]
fn test_sine_map_single_iteration() {
let sequence = generate(2.9, 0.5, 1);
assert_eq!(sequence.len(), 1);
assert_eq!(sequence[0], 0.5);
}
#[test]
fn test_sine_map_at_zero() {
let sequence = generate(2.9, 0.0, 5);
for &val in &sequence {
assert_eq!(val, 0.0);
}
}
#[test]
fn test_sine_map_at_one() {
let sequence = generate(2.9, 1.0, 3);
assert_eq!(sequence[0], 1.0);
assert!((sequence[1] - 0.0).abs() < 0.001);
}
#[test]
fn test_sine_map_smoothness() {
let sequence = generate(2.7, 0.3, 100);
let mut total_diff = 0.0;
for i in 1..sequence.len() {
total_diff += (sequence[i] - sequence[i-1]).abs();
}
let avg_diff = total_diff / (sequence.len() - 1) as f32;
assert!(avg_diff > 0.0 && avg_diff < 2.0, "avg_diff = {}", avg_diff);
}
#[test]
fn test_sine_map_sensitive_to_initial_conditions() {
let seq1 = generate(2.7, 0.3, 50);
let seq2 = generate(2.7, 0.31, 50);
assert_ne!(seq1, seq2);
}
#[test]
fn test_sine_map_periodic_window() {
let sequence = generate(2.0, 0.5, 100);
for &val in &sequence {
assert!(val >= 0.0 && val <= 1.0);
}
}
#[test]
fn test_sine_map_coverage() {
let sequence = generate(2.7, 0.3, 1000);
let min_val = sequence.iter().cloned().fold(f32::INFINITY, f32::min);
let max_val = sequence.iter().cloned().fold(f32::NEG_INFINITY, f32::max);
let range = max_val - min_val;
assert!(range > 0.1, "Should show variation, range = {}", range);
}
#[test]
fn test_sine_map_musical_sweet_spot() {
for r in [2.5, 2.6, 2.7, 2.8, 2.9] {
let sequence = generate(r, 0.4, 100);
for &val in &sequence {
assert!(val >= 0.0, "r={}, val={} is negative", r, val);
}
let has_nonzero = sequence.iter().any(|&val| val > 0.1);
assert!(has_nonzero, "r={} should produce non-zero values", r);
}
}
}