()
| 214 | } |
| 215 | |
| 216 | fn main() -> eyre::Result<()> { |
| 217 | color_eyre::install()?; |
| 218 | let mut args = CmdlineOptions::parse(); |
| 219 | |
| 220 | let filter = tracing_subscriber::EnvFilter::builder() |
| 221 | .with_default_directive(args.log_level.into()) |
| 222 | .from_env_lossy(); |
| 223 | tracing_subscriber::fmt() |
| 224 | .with_env_filter(filter) |
| 225 | .with_ansi(true) |
| 226 | .with_writer(std::io::stderr) |
| 227 | .init(); |
| 228 | |
| 229 | let seed = generate_random_seed_if_not_specified(args.seed); |
| 230 | tracing::info!("Seeding RNG with: {seed}"); |
| 231 | let mut rng = StdRng::seed_from_u64(seed); |
| 232 | |
| 233 | let dynamical_system = build_dynamical_system_function(&args)?; |
| 234 | |
| 235 | let dist = Uniform::new(-1.0, 1.0).unwrap(); |
| 236 | if args.num_points > 1 { |
| 237 | args.initial_x = None; |
| 238 | args.initial_y = None; |
| 239 | } |
| 240 | |
| 241 | let mut initial_values = Vec::with_capacity(args.num_points as usize); |
| 242 | for _ in 0..args.num_points { |
| 243 | let initial_x = args.initial_x.unwrap_or_else(|| dist.sample(&mut rng)); |
| 244 | let initial_y = args.initial_y.unwrap_or_else(|| dist.sample(&mut rng)); |
| 245 | initial_values.push((initial_x, initial_y)); |
| 246 | } |
| 247 | |
| 248 | let expected_coords = (args.iterations * args.num_points) as usize; |
| 249 | let mut formatter = AttractorFormatter::new( |
| 250 | args.output_format, |
| 251 | args.output, |
| 252 | expected_coords, |
| 253 | args.width, |
| 254 | args.height, |
| 255 | )?; |
| 256 | |
| 257 | let start = std::time::Instant::now(); |
| 258 | for (i, (mut x, mut y)) in initial_values.into_iter().enumerate() { |
| 259 | tracing::trace!("i={i}: Starting at: ({x}, {y})"); |
| 260 | for j in 0..args.iterations { |
| 261 | let (x_new, y_new) = dynamical_system(x, y); |
| 262 | if !x_new.is_finite() || !y_new.is_finite() || x_new.abs() > 1e6 || y_new.abs() > 1e6 { |
| 263 | tracing::warn!( |
| 264 | "Dynamical system produced non-finite value at iteration {j} for point {i}: ({x}, {y})" |
| 265 | ); |
| 266 | break; |
| 267 | } |
| 268 | (x, y) = (x_new, y_new); |
| 269 | formatter.handle_point(x, y)?; |
| 270 | } |
| 271 | } |
| 272 | formatter.flush()?; |
| 273 | let elapsed = start.elapsed(); |
nothing calls this directly
no test coverage detected