mirror of
				https://github.com/rust-lang/rust.git
				synced 2025-10-30 20:44:34 +00:00 
			
		
		
		
	 2d857e1c21
			
		
	
	
		2d857e1c21
		
	
	
	
	
		
			
			This also allows reusing the same generator logic between logspace tests and extensive tests, so comes with a nice bit of cleanup. Changes: * Make the generator part of `CheckCtx` since a `Generator` and `CheckCtx` are almost always passed together. * Rename `domain_logspace` to `spaced` since this no longer only operates within a domain and we may want to handle integer spacing. * Domain is now calculated at runtime rather than using traits, which is much easier to work with. * With the above, domains for multidimensional functions are added. * The extensive test generator code tests has been combined with the domain_logspace generator code. With this, the domain tests have just become a subset of extensive tests. These were renamed to "quickspace" since, technically, the extensive tests are also "domain" or "domain logspace" tests. * Edge case generators now handle functions with multiple inputs. * The test runners can be significantly cleaned up and deduplicated.
		
			
				
	
	
		
			98 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
			
		
		
	
	
			98 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
| //! Program to write all inputs from a generator to a file, then invoke a Julia script to plot
 | |
| //! them. Output is in `target/plots`.
 | |
| //!
 | |
| //! Requires Julia with the `CairoMakie` dependency.
 | |
| //!
 | |
| //! Note that running in release mode by default generates a _lot_ more datapoints, which
 | |
| //! causes plotting to be extremely slow (some simplification to be done in the script).
 | |
| 
 | |
| use std::fmt::Write as _;
 | |
| use std::io::{BufWriter, Write};
 | |
| use std::path::Path;
 | |
| use std::process::Command;
 | |
| use std::{env, fs};
 | |
| 
 | |
| use libm_test::gen::spaced::SpacedInput;
 | |
| use libm_test::gen::{edge_cases, spaced};
 | |
| use libm_test::{CheckBasis, CheckCtx, GeneratorKind, MathOp, op};
 | |
| 
 | |
| const JL_PLOT: &str = "examples/plot_file.jl";
 | |
| 
 | |
| fn main() {
 | |
|     let manifest_env = env::var("CARGO_MANIFEST_DIR").unwrap();
 | |
|     let manifest_dir = Path::new(&manifest_env);
 | |
|     let out_dir = manifest_dir.join("../../target/plots");
 | |
|     if !out_dir.exists() {
 | |
|         fs::create_dir(&out_dir).unwrap();
 | |
|     }
 | |
| 
 | |
|     let jl_script = manifest_dir.join(JL_PLOT);
 | |
|     let mut config = format!(r#"out_dir = "{}""#, out_dir.display());
 | |
|     config.write_str("\n\n").unwrap();
 | |
| 
 | |
|     // Plot a few domains with some functions that use them.
 | |
|     plot_one_operator::<op::sqrtf::Routine>(&out_dir, &mut config);
 | |
|     plot_one_operator::<op::cosf::Routine>(&out_dir, &mut config);
 | |
|     plot_one_operator::<op::cbrtf::Routine>(&out_dir, &mut config);
 | |
| 
 | |
|     let config_path = out_dir.join("config.toml");
 | |
|     fs::write(&config_path, config).unwrap();
 | |
| 
 | |
|     // The script expects a path to `config.toml` to be passed as its only argument
 | |
|     let mut cmd = Command::new("julia");
 | |
|     if cfg!(optimizations_enabled) {
 | |
|         cmd.arg("-O3");
 | |
|     }
 | |
|     cmd.arg(jl_script).arg(config_path);
 | |
| 
 | |
|     println!("launching script... {cmd:?}");
 | |
|     cmd.status().unwrap();
 | |
| }
 | |
| 
 | |
| /// Run multiple generators for a single operator.
 | |
| fn plot_one_operator<Op>(out_dir: &Path, config: &mut String)
 | |
| where
 | |
|     Op: MathOp<FTy = f32, RustArgs = (f32,)>,
 | |
|     Op::RustArgs: SpacedInput<Op>,
 | |
| {
 | |
|     let mut ctx = CheckCtx::new(Op::IDENTIFIER, CheckBasis::Mpfr, GeneratorKind::QuickSpaced);
 | |
|     plot_one_generator(out_dir, &ctx, "logspace", config, spaced::get_test_cases::<Op>(&ctx).0);
 | |
|     ctx.gen_kind = GeneratorKind::EdgeCases;
 | |
|     plot_one_generator(out_dir, &ctx, "edge_cases", config, edge_cases::get_test_cases::<Op>(&ctx));
 | |
| }
 | |
| 
 | |
| /// Plot the output of a single generator.
 | |
| fn plot_one_generator(
 | |
|     out_dir: &Path,
 | |
|     ctx: &CheckCtx,
 | |
|     gen_name: &str,
 | |
|     config: &mut String,
 | |
|     gen: impl Iterator<Item = (f32,)>,
 | |
| ) {
 | |
|     let fn_name = ctx.base_name_str;
 | |
|     let text_file = out_dir.join(format!("input-{fn_name}-{gen_name}.txt"));
 | |
| 
 | |
|     let f = fs::File::create(&text_file).unwrap();
 | |
|     let mut w = BufWriter::new(f);
 | |
|     let mut count = 0u64;
 | |
| 
 | |
|     for input in gen {
 | |
|         writeln!(w, "{:e}", input.0).unwrap();
 | |
|         count += 1;
 | |
|     }
 | |
| 
 | |
|     w.flush().unwrap();
 | |
|     println!("generated {count} inputs for {fn_name}-{gen_name}");
 | |
| 
 | |
|     writeln!(
 | |
|         config,
 | |
|         r#"[[input]]
 | |
| function = "{fn_name}"
 | |
| generator = "{gen_name}"
 | |
| input_file = "{}"
 | |
| "#,
 | |
|         text_file.to_str().unwrap()
 | |
|     )
 | |
|     .unwrap()
 | |
| }
 |