<commit_before>use std::env;
use std::ffi::{OsStr, OsString};
use std::io::{self, Write};
use std::path::PathBuf;
use std::process::{self, Command};

#[cfg(unix)]
use std::process::{Child, Stdio};

extern crate isatty;
use isatty::{stdout_isatty, stderr_isatty};

#[cfg(unix)]
extern crate tempdir;
#[cfg(unix)]
use tempdir::TempDir;

fn main() {
    let result = cargo_expand();
    process::exit(match result {
        Ok(code) => code,
        Err(err) => {
            let _ = writeln!(&mut io::stderr(), "{}", err);
            1
        }
    });
}

#[cfg(windows)]
fn cargo_expand() -> io::Result<i32> {
    // Build cargo command
    let mut cmd = Command::new("cargo");
    cmd.args(&wrap_args(env::args_os(), None));
    run(cmd)
}

#[cfg(unix)]
fn cargo_expand() -> io::Result<i32> {
    let args: Vec<_> = env::args_os().collect();
    match args.last().unwrap().to_str().unwrap_or("") {
        "--filter-cargo" => filter_err(ignore_cargo_err),
        "--filter-rustfmt" => filter_err(ignore_rustfmt_err),
        _ => {}
    }

    macro_rules! shell {
        ($($arg:expr)*) => {
            &[$(OsStr::new(&$arg)),*]
        };
    }

    let which_rustfmt = which(&["rustfmt"]);
    let which_pygmentize = if stdout_isatty() {
        which(&["pygmentize", "-l", "rust"])
    } else {
        None
    };

    let outdir = if which_rustfmt.is_some() || which_pygmentize.is_some() {
        Some(TempDir::new("cargo-expand").expect("failed to create tmp file"))
    } else {
        None
    };
    let outfile = outdir.as_ref().map(|dir| dir.path().join("expanded"));

    // Build cargo command
    let mut cmd = Command::new("cargo");
    cmd.args(&wrap_args(args.clone(), outfile.as_ref()));

    // Pipe to a tmp file to separate out any println output from build scripts
    if let Some(outfile) = outfile {
        let mut filter_cargo = Vec::new();
        filter_cargo.extend(args.iter().map(OsString::as_os_str));
        filter_cargo.push(OsStr::new("--filter-cargo"));

        let _wait = try!(cmd.pipe_to(shell!("cat"), Some(&filter_cargo)));
        try!(run(cmd));
        drop(_wait);

        cmd = Command::new("cat");
        cmd.arg(outfile);
    }

    // Pipe to rustfmt
    let _wait = match which_rustfmt {
        Some(ref fmt) => {
            let args: Vec<_> = env::args_os().collect();
            let mut filter_rustfmt = Vec::new();
            filter_rustfmt.extend(args.iter().map(OsString::as_os_str));
            filter_rustfmt.push(OsStr::new("--filter-rustfmt"));

            Some((
                // Work around $crate issue https://github.com/rust-lang/rust/issues/38016
                try!(cmd.pipe_to(shell!("sed" "s/$crate/XCRATE/g"), None)),
                try!(cmd.pipe_to(shell!(fmt), None)),
                try!(cmd.pipe_to(shell!("sed" "s/XCRATE/$crate/g"), Some(&filter_rustfmt))),
            ))
        }
        None => None,
    };

    // Pipe to pygmentize
    let _wait = match which_pygmentize {
        Some(pyg) => Some(try!(cmd.pipe_to(shell!(pyg "-l" "rust"), None))),
        None => None,
    };

    run(cmd)
}

fn run(mut cmd: Command) -> io::Result<i32> {
    cmd.status().map(|status| status.code().unwrap_or(1))
}

#[cfg(unix)]
struct Wait(Vec<Child>);

#[cfg(unix)]
impl Drop for Wait {
    fn drop(&mut self) {
        for child in &mut self.0 {
            if let Err(err) = child.wait() {
                let _ = writeln!(&mut io::stderr(), "{}", err);
            }
        }
    }
}

#[cfg(unix)]
trait PipeTo {
    fn pipe_to(&mut self, out: &[&OsStr], err: Option<&[&OsStr]>) -> io::Result<Wait>;
}

#[cfg(unix)]
impl PipeTo for Command {
    fn pipe_to(&mut self, out: &[&OsStr], err: Option<&[&OsStr]>) -> io::Result<Wait> {
        use std::os::unix::io::{AsRawFd, FromRawFd};

        self.stdout(Stdio::piped());
        if err.is_some() {
            self.stderr(Stdio::piped());
        }

        let child = try!(self.spawn());

        *self = Command::new(out[0]);
        self.args(&out[1..]);
        self.stdin(unsafe {
            Stdio::from_raw_fd(child.stdout.as_ref().map(AsRawFd::as_raw_fd).unwrap())
        });

        match err {
            None => {
                Ok(Wait(vec![child]))
            }
            Some(err) => {
                let mut errcmd = Command::new(err[0]);
                errcmd.args(&err[1..]);
                errcmd.stdin(unsafe {
                    Stdio::from_raw_fd(child.stderr.as_ref().map(AsRawFd::as_raw_fd).unwrap())
                });
                errcmd.stdout(Stdio::null());
                errcmd.stderr(Stdio::inherit());
                let spawn = try!(errcmd.spawn());
                Ok(Wait(vec![spawn, child]))
            }
        }
    }
}

// Based on https://github.com/rsolomo/cargo-check
fn wrap_args<I>(it: I, outfile: Option<&PathBuf>) -> Vec<OsString>
    where I: IntoIterator<Item=OsString>
{
    let mut args = vec!["rustc".into()];
    let mut ends_with_test = false;
    let mut ends_with_example = false;
    let mut has_color = false;

    let mut it = it.into_iter().skip(2);
    for arg in &mut it {
        if arg == *"--" {
            break;
        }
        ends_with_test = arg == *"--test";
        ends_with_example = arg == *"--example";
        has_color |= arg.to_str().unwrap_or("").starts_with("--color");
        args.push(arg.into());
    }

    if ends_with_test {
        // Expand the `test.rs` test by default.
        args.push("test".into());
    }

    if ends_with_example {
        // Expand the `example.rs` example by default.
        args.push("example".into());
    }

    if !has_color {
        let color = stderr_isatty();
        let setting = if color { "always" } else { "never" };
        args.push(format!("--color={}", setting).into());
    }

    args.push("--".into());
    if let Some(path) = outfile {
        args.push("-o".into());
        args.push(path.into());
    }
    args.push("-Zunstable-options".into());
    args.push("--pretty=expanded".into());
    args.extend(it);
    args
}

#[cfg(unix)]
fn which(cmd: &[&str]) -> Option<OsString> {
    if env::args_os().find(|arg| arg == "--help").is_some() {
        None
    } else {
        match env::var_os(&cmd[0].to_uppercase()) {
            Some(which) => {
                if which.is_empty() {
                    None
                } else {
                    Some(which)
                }
            }
            None => {
                let in_path = Command::new(cmd[0])
                    .args(&cmd[1..])
                    .stdin(Stdio::null())
                    .stdout(Stdio::null())
                    .stderr(Stdio::null())
                    .spawn()
                    .is_ok();
                if in_path {
                    Some(cmd[0].into())
                } else {
                    None
                }
            }
        }
    }
}

#[cfg(unix)]
fn filter_err(ignore: fn(&str) -> bool) -> ! {
    let mut line = String::new();
    while let Ok(n) = io::stdin().read_line(&mut line) {
        if n == 0 {
            break;
        }
        if !ignore(&line) {
            let _ = write!(&mut io::stderr(), "{}", line);
        }
        line.clear();
    }
    process::exit(0);
}

#[cfg(unix)]
fn ignore_rustfmt_err(line: &str) -> bool {
    line.trim().is_empty()
        || line.trim_right().ends_with("line exceeded maximum length (sorry)")
        || line.trim_right().ends_with("left behind trailing whitespace (sorry)")
}

#[cfg(unix)]
fn ignore_cargo_err(line: &str) -> bool {
    line.trim().is_empty()
        || line.contains("ignoring specified output filename because multiple outputs were requested")
        || line.contains("ignoring --out-dir flag due to -o flag.")
}
<commit_msg>Update error filters<commit_after>use std::env;
use std::ffi::{OsStr, OsString};
use std::io::{self, Write};
use std::path::PathBuf;
use std::process::{self, Command};

#[cfg(unix)]
use std::process::{Child, Stdio};

extern crate isatty;
use isatty::{stdout_isatty, stderr_isatty};

#[cfg(unix)]
extern crate tempdir;
#[cfg(unix)]
use tempdir::TempDir;

fn main() {
    let result = cargo_expand();
    process::exit(match result {
        Ok(code) => code,
        Err(err) => {
            let _ = writeln!(&mut io::stderr(), "{}", err);
            1
        }
    });
}

#[cfg(windows)]
fn cargo_expand() -> io::Result<i32> {
    // Build cargo command
    let mut cmd = Command::new("cargo");
    cmd.args(&wrap_args(env::args_os(), None));
    run(cmd)
}

#[cfg(unix)]
fn cargo_expand() -> io::Result<i32> {
    let args: Vec<_> = env::args_os().collect();
    match args.last().unwrap().to_str().unwrap_or("") {
        "--filter-cargo" => filter_err(ignore_cargo_err),
        "--filter-rustfmt" => filter_err(ignore_rustfmt_err),
        _ => {}
    }

    macro_rules! shell {
        ($($arg:expr)*) => {
            &[$(OsStr::new(&$arg)),*]
        };
    }

    let which_rustfmt = which(&["rustfmt"]);
    let which_pygmentize = if stdout_isatty() {
        which(&["pygmentize", "-l", "rust"])
    } else {
        None
    };

    let outdir = if which_rustfmt.is_some() || which_pygmentize.is_some() {
        Some(TempDir::new("cargo-expand").expect("failed to create tmp file"))
    } else {
        None
    };
    let outfile = outdir.as_ref().map(|dir| dir.path().join("expanded"));

    // Build cargo command
    let mut cmd = Command::new("cargo");
    cmd.args(&wrap_args(args.clone(), outfile.as_ref()));

    // Pipe to a tmp file to separate out any println output from build scripts
    if let Some(outfile) = outfile {
        let mut filter_cargo = Vec::new();
        filter_cargo.extend(args.iter().map(OsString::as_os_str));
        filter_cargo.push(OsStr::new("--filter-cargo"));

        let _wait = try!(cmd.pipe_to(shell!("cat"), Some(&filter_cargo)));
        try!(run(cmd));
        drop(_wait);

        cmd = Command::new("cat");
        cmd.arg(outfile);
    }

    // Pipe to rustfmt
    let _wait = match which_rustfmt {
        Some(ref fmt) => {
            let args: Vec<_> = env::args_os().collect();
            let mut filter_rustfmt = Vec::new();
            filter_rustfmt.extend(args.iter().map(OsString::as_os_str));
            filter_rustfmt.push(OsStr::new("--filter-rustfmt"));

            Some((
                // Work around $crate issue https://github.com/rust-lang/rust/issues/38016
                try!(cmd.pipe_to(shell!("sed" "s/$crate/XCRATE/g"), None)),
                try!(cmd.pipe_to(shell!(fmt), None)),
                try!(cmd.pipe_to(shell!("sed" "s/XCRATE/$crate/g"), Some(&filter_rustfmt))),
            ))
        }
        None => None,
    };

    // Pipe to pygmentize
    let _wait = match which_pygmentize {
        Some(pyg) => Some(try!(cmd.pipe_to(shell!(pyg "-l" "rust"), None))),
        None => None,
    };

    run(cmd)
}

fn run(mut cmd: Command) -> io::Result<i32> {
    cmd.status().map(|status| status.code().unwrap_or(1))
}

#[cfg(unix)]
struct Wait(Vec<Child>);

#[cfg(unix)]
impl Drop for Wait {
    fn drop(&mut self) {
        for child in &mut self.0 {
            if let Err(err) = child.wait() {
                let _ = writeln!(&mut io::stderr(), "{}", err);
            }
        }
    }
}

#[cfg(unix)]
trait PipeTo {
    fn pipe_to(&mut self, out: &[&OsStr], err: Option<&[&OsStr]>) -> io::Result<Wait>;
}

#[cfg(unix)]
impl PipeTo for Command {
    fn pipe_to(&mut self, out: &[&OsStr], err: Option<&[&OsStr]>) -> io::Result<Wait> {
        use std::os::unix::io::{AsRawFd, FromRawFd};

        self.stdout(Stdio::piped());
        if err.is_some() {
            self.stderr(Stdio::piped());
        }

        let child = try!(self.spawn());

        *self = Command::new(out[0]);
        self.args(&out[1..]);
        self.stdin(unsafe {
            Stdio::from_raw_fd(child.stdout.as_ref().map(AsRawFd::as_raw_fd).unwrap())
        });

        match err {
            None => {
                Ok(Wait(vec![child]))
            }
            Some(err) => {
                let mut errcmd = Command::new(err[0]);
                errcmd.args(&err[1..]);
                errcmd.stdin(unsafe {
                    Stdio::from_raw_fd(child.stderr.as_ref().map(AsRawFd::as_raw_fd).unwrap())
                });
                errcmd.stdout(Stdio::null());
                errcmd.stderr(Stdio::inherit());
                let spawn = try!(errcmd.spawn());
                Ok(Wait(vec![spawn, child]))
            }
        }
    }
}

// Based on https://github.com/rsolomo/cargo-check
fn wrap_args<I>(it: I, outfile: Option<&PathBuf>) -> Vec<OsString>
    where I: IntoIterator<Item=OsString>
{
    let mut args = vec!["rustc".into()];
    let mut ends_with_test = false;
    let mut ends_with_example = false;
    let mut has_color = false;

    let mut it = it.into_iter().skip(2);
    for arg in &mut it {
        if arg == *"--" {
            break;
        }
        ends_with_test = arg == *"--test";
        ends_with_example = arg == *"--example";
        has_color |= arg.to_str().unwrap_or("").starts_with("--color");
        args.push(arg.into());
    }

    if ends_with_test {
        // Expand the `test.rs` test by default.
        args.push("test".into());
    }

    if ends_with_example {
        // Expand the `example.rs` example by default.
        args.push("example".into());
    }

    if !has_color {
        let color = stderr_isatty();
        let setting = if color { "always" } else { "never" };
        args.push(format!("--color={}", setting).into());
    }

    args.push("--".into());
    if let Some(path) = outfile {
        args.push("-o".into());
        args.push(path.into());
    }
    args.push("-Zunstable-options".into());
    args.push("--pretty=expanded".into());
    args.extend(it);
    args
}

#[cfg(unix)]
fn which(cmd: &[&str]) -> Option<OsString> {
    if env::args_os().find(|arg| arg == "--help").is_some() {
        None
    } else {
        match env::var_os(&cmd[0].to_uppercase()) {
            Some(which) => {
                if which.is_empty() {
                    None
                } else {
                    Some(which)
                }
            }
            None => {
                let in_path = Command::new(cmd[0])
                    .args(&cmd[1..])
                    .stdin(Stdio::null())
                    .stdout(Stdio::null())
                    .stderr(Stdio::null())
                    .spawn()
                    .is_ok();
                if in_path {
                    Some(cmd[0].into())
                } else {
                    None
                }
            }
        }
    }
}

#[cfg(unix)]
fn filter_err(ignore: fn(&str) -> bool) -> ! {
    let mut line = String::new();
    while let Ok(n) = io::stdin().read_line(&mut line) {
        if n == 0 {
            break;
        }
        if !ignore(&line) {
            let _ = write!(&mut io::stderr(), "{}", line);
        }
        line.clear();
    }
    process::exit(0);
}

#[cfg(unix)]
fn ignore_rustfmt_err(line: &str) -> bool {
    line.trim().is_empty()
        || line.contains(": line exceeded maximum length (")
        || line.trim_right().ends_with("left behind trailing whitespace (sorry)")
}

#[cfg(unix)]
fn ignore_cargo_err(line: &str) -> bool {
    line.trim().is_empty()
        || line.contains("ignoring specified output filename because multiple outputs were requested")
        || line.contains("ignoring specified output filename for 'link' output because multiple outputs were requested")
        || line.contains("ignoring --out-dir flag due to -o flag.")
}
<|endoftext|>


<commit_before>use std::f64::consts;
use std::vec::Vec;

const LENGTH: f64 = 2.0*consts::PI; //length of PIC box
const NG: i32 = 64; //number of zones for mesh
const MASS: i32 = 1; //mass of each particle
const CHARGE: i32 = -1; //charge of each particle
const V_STREAM: f64 = 4.0; //initial velocity of each stream, this number will turned into positive and negative!

fn main() {
	let particle_loading: i32 = 4; //particle loading
	let np: i32 = particle_loading*NG; //number of particles
	let k: i32 = 1; //used for the peturbation of the sin wave
	let dt: f64 = LENGTH/(NG as f64)/(4.0); //timestep
	let delta_x: f64 = LENGTH/(np as f64); //L/np, or the delta x of the lattice
	let t_max: f64 = 16 as f64*consts::PI/((2 as f64*(np as f64)/LENGTH).sqrt()); //maximum time
	let mut velocity: Vec<f64> = Vec::new(); //velocities of each particle, index is
	let mut x_position: Vec<f64> = Vec::new(); //x-position of each particle

	//seed the initial positions and velocities
	for i in 0..(np*2) {
		if i < np {
			x_position.push(i as f64*LENGTH/np as f64);
			velocity.push(-V_STREAM);
		}
		else {
			x_position.push((i-np) as f64*LENGTH/np as f64);
			velocity.push(V_STREAM);
		}
		//rust only accepts usize for indexes
		println!("x: {}, v: {}", x_position[i as usize], velocity[i as usize]);
	}

	//peturb the x positions
	perturb(&mut x_position, k);
	let mut rho: Vec<f64> = vec![0.0; np as usize]; //mesh densities!
	let mut phi: Vec<f64> = vec![0.0; NG as usize]; //vector of phi's to solve for the poisson
	let mut electric_mesh: Vec<f64> = vec![0.0; NG as usize]; //vector of electric field from potential

}

//evaluates the electron number density using CIC weight.
//Each mesh loops through all the particles to add in their contribution, calculates the electron density for that mesh block alone.
fn density(rho: &mut Vec<f64>, x_position: & Vec<f64>, np: i32) {
	for rho_i in 0..rho.len() {
		let mut sum: f64 = 0.0;
		for x_p in 0..np*2 {
			sum += (MASS as f64)*cic_weight(rho_i as f64 - x_position[x_p as usize], np);
		}
		rho[rho_i as usize] = 1.0/(LENGTH/NG as f64)*sum;
	}
}

//Cloud in Cell weighting
fn cic_weight(x: f64, np: i32) -> f64{
	let delta_x: f64 = LENGTH/(np as f64);
	if x > -delta_x {
		return 1.0 + x/delta_x;
	}
	else if x < delta_x {
		return 1.0 - x/delta_x;
	}
	else {
		return 0.0;
	}
}

//solves the 1D poisson equation
fn poisson1d(phi: &mut Vec<f64>, rho: &Vec<f64>) {
	for i in 0..NG {
		phi.push(0.0);
	}
	let dx_g: f64 = LENGTH as f64/NG as f64;
	let error_tolerance: f64 = 0.000001; //10^-6
	let source = source_l2_norm(&rho, dx_g);
	let residual = residual_l2_norm(&rho, &phi, dx_g);
}

//calculates the L2Norm for the source
//probably don't want to call this outside of the poisson solver?
fn source_l2_norm(rho: &Vec<f64>, dx_g: f64) -> f64 {
	let mut source: f64 = 0.0;
	//sum the entire array
	for i in 0..rho.len() {
		source += rho[i as usize].powi(2);
	}
	//divide it by 1/Ng
	source /= dx_g;
	//then square root it
	source = source.sqrt();
	return source;
}

//calculates the L2Norm for the residual
fn residual_l2_norm(rho: &Vec<f64>, phi: &Vec<f64>, dx_g: f64) -> f64 {
	let mut residual: f64 = 0.0;

	for i in 0..rho.len() {
		residual += rho[i as usize];
		if i == 0 {
			residual += phi[i+1 as usize] - 2.0*phi[i as usize] + phi[(rho.len()-1) as usize];
		}
		else if i+1 == LENGTH as usize {
			residual += phi[0] - 2.0*phi[i as usize] + phi[(i-1) as usize];
		}
		else {
			residual += phi[(i+1 as usize)] - 2.0*phi[i as usize] + phi[(i-1) as usize];
			residual /= (LENGTH as f64/NG as f64).powi(2);
			residual = residual.sqrt();
		}

	}
	residual /= dx_g;
	residual = residual.sqrt();
	return residual;
}

//calculates the electric field from potential, where
//E is the potential
//uses the second order finite difference
fn electric_field (phi: &mut Vec<f64>, electric_mesh: & mut Vec<f64>) {
	//get dx_g
	let dx: f64 = LENGTH/(NG as f64);
	//set the iteration length for easier reference
	let iter_length = phi.len();
	for i in 1..iter_length-1 {
		//finite difference
		let phi_next = phi[i+1 as usize];
		let phi_prev = phi[i-1 as usize];
		electric_mesh[i] = (phi_next - 2.0*phi[i as usize] + phi_prev)/(dx.powi(2));
	}
	//particles at the edge need to wrap around, so wrap them around
	electric_mesh[0] = (phi[1] - 2.0*phi[0] + phi[iter_length-1])/(dx.powi(2));
	electric_mesh[iter_length-1] = (phi[0] - 2.0*phi[iter_length-1] + phi[iter_length-2])/(dx.powi(2));
}

//gets called whenever a timestep is taken, extrapolates x and v for a particle for a single timestep
fn leapfrog(electric_mesh: &Vec<f64>, x_position: &mut Vec<f64>, velocity: &mut Vec<f64>, dt: f64, delta_x: f64) {
	for i in 0..x_position.len() {
		let (x_new, v_new) = leap(x_position[i as usize], delta_x, velocity[i as usize], dt, electric_mesh);
		x_position[i as usize] = x_new;
		velocity[i as usize] = v_new;
	}
}

//calculates the drift/kick/drift for a specific value
//returns the new X and new V
//THIS SHOULD *ONLY* BE CALLED FROM THE LEAPFROG METHOD
fn leap(x: f64, delta_x: f64, v: f64, dt: f64, electric_mesh: &Vec<f64>) -> (f64, f64) {
	let j: i32 = (x/delta_x).floor() as i32;
	let y: f64 = x/delta_x - j as f64;
	//drift
	let x_half: f64 = x + 0.5*v*dt;
	//kick
	let v_new: f64 = v + accel(j, y, x_half, electric_mesh)*dt;
	//drift
	let x_new: f64 = x_half + 0.5*v_new*dt;
	return (x_new, v_new)
}

//calculates the accleration
fn accel(j: i32, y: f64, x_value: f64, electric_mesh: &Vec<f64>) -> f64{
	let mut dphi_dx: f64 = 0.0;
	if j+1 == NG {
		dphi_dx = electric_mesh[j as usize]*(1.0-y) + electric_mesh[0]*y;
	}
	else {
		dphi_dx = electric_mesh[j as usize]*(1.0-y) + electric_mesh[(j+1) as usize]*y;
	}
	let a: f64 = -CHARGE as f64/MASS as f64*dphi_dx;
	return a;
}

//petrubs the function by a sine wave with waveLENGTH = L/k and amplitude of .01K
fn perturb(x_position: &mut Vec<f64>, k: i32) {
	let wavelength: f64 = LENGTH/(k as f64);
	let amplitude: f64 = 0.01 * LENGTH;
	for i in 0..x_position.len() {
		x_position[i as usize] = x_position[i as usize] + amplitude*(wavelength*x_position[i as usize]*2.0*consts::PI).sin();
	}
}

//prints the list of X positions. THIS IS A COPY, NOT A DIRECT REFERENCE
fn print_vec(vector: &Vec<f64>) {
	for i in 0..vector.len() {
		println!("{}", vector[i as usize])
	}
}<commit_msg>Finish poisson solver, need to finish evolution<commit_after>use std::f64::consts;
use std::vec::Vec;

const LENGTH: f64 = 2.0*consts::PI; //length of PIC box
const NG: i32 = 64; //number of zones for mesh
const MASS: i32 = 1; //mass of each particle
const CHARGE: i32 = -1; //charge of each particle
const V_STREAM: f64 = 4.0; //initial velocity of each stream, this number will turned into positive and negative!

fn main() {
	let particle_loading: i32 = 4; //particle loading
	let np: i32 = particle_loading*NG; //number of particles
	let k: i32 = 1; //used for the peturbation of the sin wave
	let dt: f64 = LENGTH/(NG as f64)/(4.0); //timestep
	let delta_x: f64 = LENGTH/(np as f64); //L/np, or the delta x of the lattice
	let t_max: f64 = 16 as f64*consts::PI/((2 as f64*(np as f64)/LENGTH).sqrt()); //maximum time
	let mut velocity: Vec<f64> = Vec::new(); //velocities of each particle, index is
	let mut x_position: Vec<f64> = Vec::new(); //x-position of each particle

	//seed the initial positions and velocities
	for i in 0..(np*2) {
		if i < np {
			x_position.push(i as f64*LENGTH/np as f64);
			velocity.push(-V_STREAM);
		}
		else {
			x_position.push((i-np) as f64*LENGTH/np as f64);
			velocity.push(V_STREAM);
		}
		//rust only accepts usize for indexes
		println!("x: {}, v: {}", x_position[i as usize], velocity[i as usize]);
	}

	//peturb the x positions
	perturb(&mut x_position, k);
	let mut rho: Vec<f64> = vec![0.0; NG as usize]; //mesh densities
	let mut phi: Vec<f64> = vec![0.0; NG as usize]; //vector of phi's to solve for the poisson
	let mut electric_mesh: Vec<f64> = vec![0.0; NG as usize]; //vector of electric field from potential
}

//evaluates the electron number density using CIC weight.
//Each mesh loops through all the particles to add in their contribution, calculates the electron density for that mesh block alone.
fn density(rho: &mut Vec<f64>, x_position: & Vec<f64>, np: i32) {
	for rho_i in 0..rho.len() {
		let mut sum: f64 = 0.0;
		for x_p in 0..np*2 {
			sum += (MASS as f64)*cic_weight(rho_i as f64 - x_position[x_p as usize], np);
		}
		rho[rho_i as usize] = 1.0/(LENGTH/NG as f64)*sum;
	}
}

//Cloud in Cell weighting
fn cic_weight(x: f64, np: i32) -> f64{
	let delta_x: f64 = LENGTH/(np as f64);
	if x > -delta_x {
		return 1.0 + x/delta_x;
	}
	else if x < delta_x {
		return 1.0 - x/delta_x;
	}
	else {
		return 0.0;
	}
}

//solves the 1D poisson equation using the Gauss-Seidel relaxation
fn poisson1d(phi: &mut Vec<f64>, rho: &Vec<f64>) {
	for i in 0..NG {
		phi.push(0.0);
	}
	let dx_g: f64 = LENGTH as f64/NG as f64;
	let error_tolerance: f64 = 0.000001; //10^-6
	let source = source_l2_norm(&rho, dx_g);
	let mut residual = residual_l2_norm(&rho, &phi, dx_g);
	while residual > error_tolerance*source {
		for i in 0..NG-1 {
			// rust uses C-like functions, so % isn't mod, but rather remainder
			let im: i32 = ((i - 1 + NG) % NG) + NG;
			let ip: i32 = ((i + 1) % NG) + NG;
			phi[i as usize] = 0.5*(phi[im as usize] + phi[ip as usize]) + dx_g.powi(2)/2.0*rho[i as usize];
		}
		residual = residual_l2_norm(&rho, &phi, dx_g);
	}
}

//calculates the L2Norm for the source
//probably don't want to call this outside of the poisson solver?
fn source_l2_norm(rho: &Vec<f64>, dx_g: f64) -> f64 {
	let mut source: f64 = 0.0;
	//sum the entire array
	for i in 0..rho.len() {
		source += rho[i as usize].powi(2);
	}
	//divide it by 1/Ng
	source /= dx_g;
	//then square root it
	source = source.sqrt();
	return source;
}

//calculates the L2Norm for the residual
fn residual_l2_norm(rho: &Vec<f64>, phi: &Vec<f64>, dx_g: f64) -> f64 {
	let mut residual: f64 = 0.0;

	for i in 0..rho.len() {
		residual += rho[i as usize];
		if i == 0 {
			residual += phi[i+1 as usize] - 2.0*phi[i as usize] + phi[(rho.len()-1) as usize];
		}
		else if i+1 == LENGTH as usize {
			residual += phi[0] - 2.0*phi[i as usize] + phi[(i-1) as usize];
		}
		else {
			residual += phi[(i+1 as usize)] - 2.0*phi[i as usize] + phi[(i-1) as usize];
			residual /= (LENGTH as f64/NG as f64).powi(2);
			residual = residual.sqrt();
		}

	}
	residual /= dx_g;
	residual = residual.sqrt();
	return residual;
}

//calculates the electric field from potential, where
//E is the potential
//uses the second order finite difference
fn electric_field (phi: &mut Vec<f64>, electric_mesh: & mut Vec<f64>) {
	//get dx_g
	let dx: f64 = LENGTH/(NG as f64);
	//set the iteration length for easier reference
	let iter_length = phi.len();
	for i in 1..iter_length-1 {
		//finite difference
		let phi_next = phi[i+1 as usize];
		let phi_prev = phi[i-1 as usize];
		electric_mesh[i] = (phi_next - 2.0*phi[i as usize] + phi_prev)/(dx.powi(2));
	}
	//particles at the edge need to wrap around, so wrap them around
	electric_mesh[0] = (phi[1] - 2.0*phi[0] + phi[iter_length-1])/(dx.powi(2));
	electric_mesh[iter_length-1] = (phi[0] - 2.0*phi[iter_length-1] + phi[iter_length-2])/(dx.powi(2));
}

//gets called whenever a timestep is taken, extrapolates x and v for a particle for a single timestep
fn leapfrog(electric_mesh: &Vec<f64>, x_position: &mut Vec<f64>, velocity: &mut Vec<f64>, dt: f64, delta_x: f64) {
	for i in 0..x_position.len() {
		let (x_new, v_new) = leap(x_position[i as usize], delta_x, velocity[i as usize], dt, electric_mesh);
		x_position[i as usize] = x_new;
		velocity[i as usize] = v_new;
	}
}

//calculates the drift/kick/drift for a specific value
//returns the new X and new V
//THIS SHOULD *ONLY* BE CALLED FROM THE LEAPFROG METHOD
fn leap(x: f64, delta_x: f64, v: f64, dt: f64, electric_mesh: &Vec<f64>) -> (f64, f64) {
	let j: i32 = (x/delta_x).floor() as i32;
	let y: f64 = x/delta_x - j as f64;
	//drift
	let x_half: f64 = x + 0.5*v*dt;
	//kick
	let v_new: f64 = v + accel(j, y, x_half, electric_mesh)*dt;
	//drift
	let x_new: f64 = x_half + 0.5*v_new*dt;
	return (x_new, v_new)
}

//calculates the accleration
fn accel(j: i32, y: f64, x_value: f64, electric_mesh: &Vec<f64>) -> f64{
	let mut dphi_dx: f64 = 0.0;
	if j+1 == NG {
		dphi_dx = electric_mesh[j as usize]*(1.0-y) + electric_mesh[0]*y;
	}
	else {
		dphi_dx = electric_mesh[j as usize]*(1.0-y) + electric_mesh[(j+1) as usize]*y;
	}
	let a: f64 = -CHARGE as f64/MASS as f64*dphi_dx;
	return a;
}

//petrubs the function by a sine wave with waveLENGTH = L/k and amplitude of .01K
fn perturb(x_position: &mut Vec<f64>, k: i32) {
	let wavelength: f64 = LENGTH/(k as f64);
	let amplitude: f64 = 0.01 * LENGTH;
	for i in 0..x_position.len() {
		x_position[i as usize] = x_position[i as usize] + amplitude*(wavelength*x_position[i as usize]*2.0*consts::PI).sin();
	}
}

//prints the list of X positions. THIS IS A COPY, NOT A DIRECT REFERENCE
fn print_vec(vector: &Vec<f64>) {
	for i in 0..vector.len() {
		println!("{}", vector[i as usize])
	}
}<|endoftext|>


<commit_before>#![deny(
    unused_allocation,
    unused_attributes,
    unused_import_braces,
    unused_imports,
    unused_must_use,
    unused_mut,
    unused_parens,
    unused_results,
    unused_unsafe,
    unused_variables,

    dead_code,
)]

extern crate term;
extern crate git2;
extern crate prompt_buffer;

use prompt_buffer::thread::PromptThread;
use prompt_buffer::buffer::PromptBuffer;

use std::collections::HashMap;
use std::io::{
    self,
    Acceptor,
    Command,
    File,
    fs,
    IoError,
    Listener,
    process,
    stdio,
    timer,
    IoErrorKind
};
use std::io::fs::PathExtensions;
use std::io::net::pipe::{
    UnixListener,
    UnixStream,
};
use std::os;
use std::time::Duration;

mod git;
mod due_date;

fn get_prompt() -> PromptBuffer {
    let mut buf = PromptBuffer::new();
    buf.add_plugin(due_date::DueDatePlugin::new());
    buf.add_plugin(git::GitPlugin::new());

    buf
}

fn exe_changed() -> u64 {
    match os::self_exe_name() {
        Some(exe_path) => {
            match exe_path.stat() {
                Ok(s) => s.modified,
                _ => 0u64
            }
        },
        None => 0u64
    }
}

fn current_pid(pid_path: &Path) -> Result<i32, IoError> {
    let mut file = try!(File::open(pid_path));
    let contents = try!(file.read_to_string());

    match contents.parse() {
        Some(value) => Ok(value),
        None => Err(io::standard_error(IoErrorKind::InvalidInput))
    }
}

macro_rules! sock_try {
    ($x:expr) => {
        match $x {
            Ok(v) => v,
            Err(_) => continue
        }
    };
}

fn main() {
    let stdout_path = Path::new("/var/log/megaprompt/current.out");
    let stderr_path = Path::new("/var/log/megaprompt/current.err");
    let pid_path = Path::new("/var/log/megaprompt/current.pid");
    let socket_path = Path::new("/tmp/megaprompt-socket");

    let args = os::args();
    if args.len() > 1 { // Daemon process
        let _ = stdio::set_stdout(Box::new(File::create(&stdout_path)));
        let _ = stdio::set_stderr(Box::new(File::create(&stderr_path)));

        let last_modified = exe_changed();
        let mut threads: HashMap<Path, PromptThread> = HashMap::new();

        if socket_path.exists() {
            fs::unlink(&socket_path).unwrap();
        }

        let stream = match UnixListener::bind(&socket_path) {
            Err(_) => panic!("Failed to bind to socket"),
            Ok(stream) => stream
        };

        for mut connection in stream.listen().incoming() {
            let c = &mut connection;

            let output = Path::new(sock_try!(c.read_to_string()));
            println!("Preparing to respond to for {}", output.display());

            let keys: Vec<Path> = threads.keys().map(|x| { x.clone() }).collect();
            for path in keys.iter() {
                if !threads.get_mut(path).unwrap().is_alive() {
                    println!("- Remove thread {}", path.display());
                    let _ = threads.remove(path);
                }
            }

            if !threads.contains_key(&output) {
                println!("+ Add thread {}", output.display());
                let _ = threads.insert(output.clone(), PromptThread::new(output.clone(), &get_prompt));
            }

            for path in threads.keys() {
                println!("* Active thread {}", path.display());
            }

            let mut thr = threads.get_mut(&output).unwrap();

            sock_try!(write!(c, "{}", thr.get(&get_prompt)));

            println!("");

            if last_modified != exe_changed() {
                sock_try!(write!(c, "♻  "));
                return;
            }
        }
    } else {
        let current_pid = current_pid(&pid_path).ok().unwrap_or(-1);

        match process::Process::kill(current_pid, 0) {
            Err(_) => {
                // We need to start up the daemon again
                let child = Command::new(args.get(0).as_slice()[0])
                    .arg("daemon")
                    .detached().spawn().unwrap();

                let mut f = match File::create(&pid_path) {
                    Ok(f) => f,
                    Err(_) => panic!("Unable to open pid file")
                };

                write!(&mut f, "{}", child.id()).unwrap();

                println!("Spawned child {}", child.id());

                child.forget();

                timer::sleep(Duration::milliseconds(10));
            }
            _ => {}
        }

        let mut stream = match UnixStream::connect(&socket_path) {
            Err(_) => {
                println!("Can't connect");
                get_prompt().print();
                return;
            },
            Ok(stream) => stream
        };

        write!(&mut stream, "{}", os::make_absolute(&Path::new(".")).unwrap().display()).unwrap();
        stream.close_write().unwrap();
        stream.set_read_timeout(Some(200));
        match stream.read_to_string() {
            Ok(s) => println!("{}", s),
            Err(_) => {
                println!("Response too slow");
                get_prompt().print_fast();
                return;
            }
        }
    }
}
<commit_msg>Add minimal smoke test<commit_after>#![deny(
    unused_allocation,
    unused_attributes,
    unused_import_braces,
    unused_imports,
    unused_must_use,
    unused_mut,
    unused_parens,
    unused_results,
    unused_unsafe,
    unused_variables,

    dead_code,
)]

extern crate term;
extern crate git2;
extern crate prompt_buffer;

use prompt_buffer::thread::PromptThread;
use prompt_buffer::buffer::PromptBuffer;

use std::collections::HashMap;
use std::io::{
    self,
    Acceptor,
    Command,
    File,
    fs,
    IoError,
    Listener,
    process,
    stdio,
    timer,
    IoErrorKind
};
use std::io::fs::PathExtensions;
use std::io::net::pipe::{
    UnixListener,
    UnixStream,
};
use std::os;
use std::time::Duration;

mod git;
mod due_date;

fn get_prompt() -> PromptBuffer {
    let mut buf = PromptBuffer::new();
    buf.add_plugin(due_date::DueDatePlugin::new());
    buf.add_plugin(git::GitPlugin::new());

    buf
}

fn exe_changed() -> u64 {
    match os::self_exe_name() {
        Some(exe_path) => {
            match exe_path.stat() {
                Ok(s) => s.modified,
                _ => 0u64
            }
        },
        None => 0u64
    }
}

fn current_pid(pid_path: &Path) -> Result<i32, IoError> {
    let mut file = try!(File::open(pid_path));
    let contents = try!(file.read_to_string());

    match contents.parse() {
        Some(value) => Ok(value),
        None => Err(io::standard_error(IoErrorKind::InvalidInput))
    }
}

macro_rules! sock_try {
    ($x:expr) => {
        match $x {
            Ok(v) => v,
            Err(_) => continue
        }
    };
}

fn main() {
    let stdout_path = Path::new("/var/log/megaprompt/current.out");
    let stderr_path = Path::new("/var/log/megaprompt/current.err");
    let pid_path = Path::new("/var/log/megaprompt/current.pid");
    let socket_path = Path::new("/tmp/megaprompt-socket");

    let args = os::args();
    if args.len() > 1 { // Daemon process
        let _ = stdio::set_stdout(Box::new(File::create(&stdout_path)));
        let _ = stdio::set_stderr(Box::new(File::create(&stderr_path)));

        let last_modified = exe_changed();
        let mut threads: HashMap<Path, PromptThread> = HashMap::new();

        if socket_path.exists() {
            fs::unlink(&socket_path).unwrap();
        }

        let stream = match UnixListener::bind(&socket_path) {
            Err(_) => panic!("Failed to bind to socket"),
            Ok(stream) => stream
        };

        for mut connection in stream.listen().incoming() {
            let c = &mut connection;

            let output = Path::new(sock_try!(c.read_to_string()));
            println!("Preparing to respond to for {}", output.display());

            let keys: Vec<Path> = threads.keys().map(|x| { x.clone() }).collect();
            for path in keys.iter() {
                if !threads.get_mut(path).unwrap().is_alive() {
                    println!("- Remove thread {}", path.display());
                    let _ = threads.remove(path);
                }
            }

            if !threads.contains_key(&output) {
                println!("+ Add thread {}", output.display());
                let _ = threads.insert(output.clone(), PromptThread::new(output.clone(), &get_prompt));
            }

            for path in threads.keys() {
                println!("* Active thread {}", path.display());
            }

            let mut thr = threads.get_mut(&output).unwrap();

            sock_try!(write!(c, "{}", thr.get(&get_prompt)));

            println!("");

            if last_modified != exe_changed() {
                sock_try!(write!(c, "♻  "));
                return;
            }
        }
    } else {
        let current_pid = current_pid(&pid_path).ok().unwrap_or(-1);

        match process::Process::kill(current_pid, 0) {
            Err(_) => {
                // We need to start up the daemon again
                let child = Command::new(args.get(0).as_slice()[0])
                    .arg("daemon")
                    .detached().spawn().unwrap();

                let mut f = match File::create(&pid_path) {
                    Ok(f) => f,
                    Err(_) => panic!("Unable to open pid file")
                };

                write!(&mut f, "{}", child.id()).unwrap();

                println!("Spawned child {}", child.id());

                child.forget();

                timer::sleep(Duration::milliseconds(10));
            }
            _ => {}
        }

        let mut stream = match UnixStream::connect(&socket_path) {
            Err(_) => {
                println!("Can't connect");
                get_prompt().print();
                return;
            },
            Ok(stream) => stream
        };

        write!(&mut stream, "{}", os::make_absolute(&Path::new(".")).unwrap().display()).unwrap();
        stream.close_write().unwrap();
        stream.set_read_timeout(Some(200));
        match stream.read_to_string() {
            Ok(s) => println!("{}", s),
            Err(_) => {
                println!("Response too slow");
                get_prompt().print_fast();
                return;
            }
        }
    }
}

#[test]
fn test_main_does_not_error() {
    main();
}
<|endoftext|>


<commit_before>#![crate_id = "rboy"]
#![license = "MIT"]

#![feature(phase)]
#[phase(syntax, link)] extern crate log;

extern crate native;
extern crate getopts;
extern crate sync;
extern crate time;
extern crate sdl;
#[cfg(test)]
extern crate test;

use cpu::CPU;
use sync::DuplexStream;
use sync::{Arc,RWLock};
use std::comm::{Disconnected,Empty};

mod register;
mod mbc;
mod mmu;
mod cpu;
mod serial;
mod timer;
mod keypad;
mod gpu;
mod sound;
mod gbmode;
mod util;

static SCALE: uint = 2;

#[cfg(not(test))]
#[start]
fn start(argc: int, argv: **u8) -> int { native::start(argc, argv, main) }

fn main() {
	let mut args = Vec::new();
	for a in std::os::args().iter()
	{
		args.push(a.to_strbuf());
	}

	let opts = [ getopts::optflag("s", "serial", "Output serial to stdout"), getopts::optflag("c", "classic", "Force Classic mode") ];
	let matches = match getopts::getopts(args.tail(), opts) {
		Ok(m) => { m }
		Err(f) => { println!("{}", f.to_err_msg()); return }
	};

	let filename = if !matches.free.is_empty() {
		matches.free.get(0).clone()
	} else {
		println!("{}", getopts::usage(args.get(0).clone().append(" <filename>").to_str(), opts));
		return;
	};

	sdl::init([sdl::InitVideo]);
	sdl::wm::set_caption("RBoy - A gameboy in Rust", "rboy");
	let screen = match sdl::video::set_video_mode(160*SCALE as int, 144*SCALE as int, 32, [sdl::video::HWSurface], [sdl::video::DoubleBuf]) {
		Ok(screen) => screen,
		Err(err) => fail!("failed to open screen: {}", err),
	};

	let (sdlstream, cpustream) = sync::duplex();
	let rawscreen = [0x00u8,.. 160*144*3];
	let arc = Arc::new(RWLock::new(rawscreen));
	let arc2 = arc.clone();
	native::task::spawn(proc() cpuloop(&cpustream, arc2, filename.to_str(), &matches));

	let mut timer = std::io::timer::Timer::new().unwrap();
	let periodic = timer.periodic(8);

	'main : loop {
		periodic.recv();
		match sdlstream.try_recv() {
			Err(Disconnected) => { break 'main },
			Ok(_) => recalculate_screen(&screen, &arc),
			Err(Empty) => {},
		}
		'event : loop {
			match sdl::event::poll_event() {
				sdl::event::QuitEvent => break 'main,
				sdl::event::NoEvent => break 'event,
				sdl::event::KeyEvent(sdl::event::EscapeKey, _, _, _)
					=> break 'main,
				sdl::event::KeyEvent(sdl::event::LShiftKey, true, _, _)
					=> sdlstream.send(SpeedUp),
				sdl::event::KeyEvent(sdl::event::LShiftKey, false, _, _)
					=> sdlstream.send(SlowDown),
				sdl::event::KeyEvent(sdlkey, true, _, _) => {
					match sdl_to_keypad(sdlkey) {
						Some(key) => sdlstream.send(KeyDown(key)),
						None => {},
					}
				},
				sdl::event::KeyEvent(sdlkey, false, _, _) => {
					match sdl_to_keypad(sdlkey) {
						Some(key) => sdlstream.send(KeyUp(key)),
						None => {},
					}
				},
				_ => {}
			}
		}
	}
}

fn sdl_to_keypad(key: sdl::event::Key) -> Option<keypad::KeypadKey> {
	match key {
		sdl::event::ZKey => Some(keypad::A),
		sdl::event::XKey => Some(keypad::B),
		sdl::event::UpKey => Some(keypad::Up),
		sdl::event::DownKey => Some(keypad::Down),
		sdl::event::LeftKey => Some(keypad::Left),
		sdl::event::RightKey => Some(keypad::Right),
		sdl::event::SpaceKey => Some(keypad::Select),
		sdl::event::ReturnKey => Some(keypad::Start),
		_ => None,
	}
}

fn recalculate_screen(screen: &sdl::video::Surface, arc: &Arc<RWLock<[u8,.. 160*144*3]>>) {
	let data = arc.read();
	for y in range(0u, 144) {
		for x in range(0u, 160) {
			screen.fill_rect(
				Some(sdl::Rect { x: (x*SCALE) as i16, y: (y*SCALE) as i16, w: SCALE as u16, h: SCALE as u16 }),
				sdl::video::RGB(data[y*160*3 + x*3 + 0],
				                data[y*160*3 + x*3 + 1],
				                data[y*160*3 + x*3 + 2])
			);
		}
	}
	screen.flip();
}

enum GBEvent {
	KeyUp(keypad::KeypadKey),
	KeyDown(keypad::KeypadKey),
	SpeedUp,
	SlowDown,
}

fn cpuloop(channel: &DuplexStream<uint, GBEvent>, arc: Arc<RWLock<[u8,.. 160*144*3]>>, filename: &str, matches: &getopts::Matches) {
	let opt_c = match matches.opt_present("classic") {
		true => CPU::new(filename),
		false => CPU::new_cgb(filename),
	};
	let mut c = match opt_c
	{
		Some(cpu) => { cpu },
		None => { error!("Could not get a valid gameboy"); return; },
	};
	c.mmu.serial.tostdout = matches.opt_present("serial");

	let mut timer = std::io::timer::Timer::new().unwrap();
	let mut periodic = timer.periodic(8);

	let waitticks = (4194.304 * 4.0) as uint;

	let mut ticks = 0;
	'cpuloop: loop {
		while ticks < waitticks {
			ticks += c.cycle();
			if c.mmu.gpu.updated {
				c.mmu.gpu.updated = false;
				let mut data = arc.write();
				for i in range(0, data.len()) { data[i] = c.mmu.gpu.data[i]; }
				if channel.send_opt(0).is_err() { break 'cpuloop };
			}
		}
		ticks -= waitticks;
		periodic.recv();

		match channel.try_recv() {
			Ok(event) => match event {
				KeyUp(key) => c.mmu.keypad.keyup(key),
				KeyDown(key) => c.mmu.keypad.keydown(key),
				SpeedUp => periodic = timer.periodic(1),
				SlowDown => periodic = timer.periodic(8),
			},
			Err(Empty) => {},
			Err(Disconnected) => { break },
		};
	}
}
<commit_msg>Replace loop by .map.collect<commit_after>#![crate_id = "rboy"]
#![license = "MIT"]

#![feature(phase)]
#[phase(syntax, link)] extern crate log;

extern crate native;
extern crate getopts;
extern crate sync;
extern crate time;
extern crate sdl;
#[cfg(test)]
extern crate test;

use cpu::CPU;
use sync::DuplexStream;
use sync::{Arc,RWLock};
use std::comm::{Disconnected,Empty};

mod register;
mod mbc;
mod mmu;
mod cpu;
mod serial;
mod timer;
mod keypad;
mod gpu;
mod sound;
mod gbmode;
mod util;

static SCALE: uint = 2;

#[cfg(not(test))]
#[start]
fn start(argc: int, argv: **u8) -> int { native::start(argc, argv, main) }

fn main() {
	let args = std::os::args().move_iter().map(|s| s.into_strbuf()).collect::<Vec<StrBuf>>();
	let opts = [ getopts::optflag("s", "serial", "Output serial to stdout"), getopts::optflag("c", "classic", "Force Classic mode") ];
	let matches = match getopts::getopts(args.tail(), opts) {
		Ok(m) => { m }
		Err(f) => { println!("{}", f.to_err_msg()); return }
	};

	let filename = if !matches.free.is_empty() {
		matches.free.get(0).clone()
	} else {
		println!("{}", getopts::usage(args.get(0).clone().append(" <filename>").to_str(), opts));
		return;
	};

	sdl::init([sdl::InitVideo]);
	sdl::wm::set_caption("RBoy - A gameboy in Rust", "rboy");
	let screen = match sdl::video::set_video_mode(160*SCALE as int, 144*SCALE as int, 32, [sdl::video::HWSurface], [sdl::video::DoubleBuf]) {
		Ok(screen) => screen,
		Err(err) => fail!("failed to open screen: {}", err),
	};

	let (sdlstream, cpustream) = sync::duplex();
	let rawscreen = [0x00u8,.. 160*144*3];
	let arc = Arc::new(RWLock::new(rawscreen));
	let arc2 = arc.clone();
	native::task::spawn(proc() cpuloop(&cpustream, arc2, filename.to_str(), &matches));

	let mut timer = std::io::timer::Timer::new().unwrap();
	let periodic = timer.periodic(8);

	'main : loop {
		periodic.recv();
		match sdlstream.try_recv() {
			Err(Disconnected) => { break 'main },
			Ok(_) => recalculate_screen(&screen, &arc),
			Err(Empty) => {},
		}
		'event : loop {
			match sdl::event::poll_event() {
				sdl::event::QuitEvent => break 'main,
				sdl::event::NoEvent => break 'event,
				sdl::event::KeyEvent(sdl::event::EscapeKey, _, _, _)
					=> break 'main,
				sdl::event::KeyEvent(sdl::event::LShiftKey, true, _, _)
					=> sdlstream.send(SpeedUp),
				sdl::event::KeyEvent(sdl::event::LShiftKey, false, _, _)
					=> sdlstream.send(SlowDown),
				sdl::event::KeyEvent(sdlkey, true, _, _) => {
					match sdl_to_keypad(sdlkey) {
						Some(key) => sdlstream.send(KeyDown(key)),
						None => {},
					}
				},
				sdl::event::KeyEvent(sdlkey, false, _, _) => {
					match sdl_to_keypad(sdlkey) {
						Some(key) => sdlstream.send(KeyUp(key)),
						None => {},
					}
				},
				_ => {}
			}
		}
	}
}

fn sdl_to_keypad(key: sdl::event::Key) -> Option<keypad::KeypadKey> {
	match key {
		sdl::event::ZKey => Some(keypad::A),
		sdl::event::XKey => Some(keypad::B),
		sdl::event::UpKey => Some(keypad::Up),
		sdl::event::DownKey => Some(keypad::Down),
		sdl::event::LeftKey => Some(keypad::Left),
		sdl::event::RightKey => Some(keypad::Right),
		sdl::event::SpaceKey => Some(keypad::Select),
		sdl::event::ReturnKey => Some(keypad::Start),
		_ => None,
	}
}

fn recalculate_screen(screen: &sdl::video::Surface, arc: &Arc<RWLock<[u8,.. 160*144*3]>>) {
	let data = arc.read();
	for y in range(0u, 144) {
		for x in range(0u, 160) {
			screen.fill_rect(
				Some(sdl::Rect { x: (x*SCALE) as i16, y: (y*SCALE) as i16, w: SCALE as u16, h: SCALE as u16 }),
				sdl::video::RGB(data[y*160*3 + x*3 + 0],
				                data[y*160*3 + x*3 + 1],
				                data[y*160*3 + x*3 + 2])
			);
		}
	}
	screen.flip();
}

enum GBEvent {
	KeyUp(keypad::KeypadKey),
	KeyDown(keypad::KeypadKey),
	SpeedUp,
	SlowDown,
}

fn cpuloop(channel: &DuplexStream<uint, GBEvent>, arc: Arc<RWLock<[u8,.. 160*144*3]>>, filename: &str, matches: &getopts::Matches) {
	let opt_c = match matches.opt_present("classic") {
		true => CPU::new(filename),
		false => CPU::new_cgb(filename),
	};
	let mut c = match opt_c
	{
		Some(cpu) => { cpu },
		None => { error!("Could not get a valid gameboy"); return; },
	};
	c.mmu.serial.tostdout = matches.opt_present("serial");

	let mut timer = std::io::timer::Timer::new().unwrap();
	let mut periodic = timer.periodic(8);

	let waitticks = (4194.304 * 4.0) as uint;

	let mut ticks = 0;
	'cpuloop: loop {
		while ticks < waitticks {
			ticks += c.cycle();
			if c.mmu.gpu.updated {
				c.mmu.gpu.updated = false;
				let mut data = arc.write();
				for i in range(0, data.len()) { data[i] = c.mmu.gpu.data[i]; }
				if channel.send_opt(0).is_err() { break 'cpuloop };
			}
		}
		ticks -= waitticks;
		periodic.recv();

		match channel.try_recv() {
			Ok(event) => match event {
				KeyUp(key) => c.mmu.keypad.keyup(key),
				KeyDown(key) => c.mmu.keypad.keydown(key),
				SpeedUp => periodic = timer.periodic(1),
				SlowDown => periodic = timer.periodic(8),
			},
			Err(Empty) => {},
			Err(Disconnected) => { break },
		};
	}
}
<|endoftext|>


<commit_before>use config::Config;
use error::Result;
use error::Error;
use ip::IpAddr;
use hyper::Client;
use hyper::header::Connection;
use std::io;
use std::io::prelude::*;
use std::result::Result as StdResult;
use std::str::FromStr;
use regex::Regex;

// All HTTP IP providers URL
static URL_SFR_LABOX_FIBRE: &'static str = "http://192.168.0.1/";

#[derive(Debug)]
pub enum IpProvider {
    Stdin,
    SfrLaBoxFibre,
}

impl FromStr for IpProvider {
    type Err = String;

    fn from_str(s: &str) -> StdResult<IpProvider, String> {
        match s {
            "-" => Ok(IpProvider::Stdin),
            "sfrlaboxfibre" => Ok(IpProvider::SfrLaBoxFibre),
            value => Err(format!("Unknown value for IP provider: {}", value).to_owned()),
        }
    }
}

pub trait IpAddressProvider {
    fn get_my_ip_addr(&self) -> Result<IpAddr>;
}

impl IpAddressProvider {
    pub fn from_config(config: &Config) -> Box<IpAddressProvider + 'static>  {
        match config.ip_provider {
            IpProvider::Stdin => Box::new(StdinIpProvider),
            IpProvider::SfrLaBoxFibre => Box::new(HttpIpProvider::new(URL_SFR_LABOX_FIBRE)),
        }
    }
}

pub struct StdinIpProvider;

impl IpAddressProvider for StdinIpProvider {
    fn get_my_ip_addr(&self) -> Result<IpAddr> {
        let mut input = String::new();

        try!(io::stdin().read_line(&mut input));

        trace!("Read stdin: {}", input);

        let ip_addr = try!(IpAddr::from_str(input.trim()));
        Ok(ip_addr)
    }
}

pub struct HttpIpProvider<'a> {
    url: &'a str,
}

impl<'a> HttpIpProvider<'a> {
    fn new(url: &'a str) -> HttpIpProvider {
        HttpIpProvider {
            url: url,
        }
    }
}

impl<'a> IpAddressProvider for HttpIpProvider<'a> {
    fn get_my_ip_addr(&self) -> Result<IpAddr> {
        let client = Client::new();

        let mut res = try!(client.get(self.url)
            .header(Connection::close())
            .send());

        let mut body = String::new();
        try!(res.read_to_string(&mut body));

        trace!("HTTP Response: {}", body);

        let regex = try!(Regex::new(r"((?:(?:0|1[\d]{0,2}|2(?:[0-4]\d?|5[0-5]?|[6-9])?|[3-9]\d?)\.){3}(?:0|1[\d]{0,2}|2(?:[0-4]\d?|5[0-5]?|[6-9])?|[3-9]\d?))"));

        regex.captures(&*body)
            .and_then(|caps| caps.at(1))
            // Convert Option to Result
            .ok_or(Error::IpNotFound)
            .and_then(|val| IpAddr::from_str(val).map_err(|e| {
                error!("IP parse error: {}", e);
                Error::IpNotFound
            }))
    }
}
<commit_msg>Add OpenDNS HTTP provider<commit_after>use config::Config;
use error::Result;
use error::Error;
use ip::IpAddr;
use hyper::Client;
use hyper::header::Connection;
use std::io;
use std::io::prelude::*;
use std::result::Result as StdResult;
use std::str::FromStr;
use regex::Regex;

// All HTTP IP providers URL
static URL_SFR_LABOX_FIBRE: &'static str = "http://192.168.0.1/";
static URL_OPENDNS: &'static str = "https://diagnostic.opendns.com/myip";

#[derive(Debug)]
pub enum IpProvider {
    Stdin,
    SfrLaBoxFibre,
    OpenDNS,
}

impl FromStr for IpProvider {
    type Err = String;

    fn from_str(s: &str) -> StdResult<IpProvider, String> {
        match s {
            "-" => Ok(IpProvider::Stdin),
            "sfrlaboxfibre" => Ok(IpProvider::SfrLaBoxFibre),
            "opendns" => Ok(IpProvider::OpenDNS),
            value => Err(format!("Unknown value for IP provider: {}", value).to_owned()),
        }
    }
}

pub trait IpAddressProvider {
    fn get_my_ip_addr(&self) -> Result<IpAddr>;
}

impl IpAddressProvider {
    pub fn from_config(config: &Config) -> Box<IpAddressProvider + 'static>  {
        match config.ip_provider {
            IpProvider::Stdin => Box::new(StdinIpProvider),
            IpProvider::SfrLaBoxFibre => Box::new(HttpIpProvider::new(URL_SFR_LABOX_FIBRE)),
            IpProvider::OpenDNS => Box::new(HttpIpProvider::new(URL_OPENDNS)),
        }
    }
}

pub struct StdinIpProvider;

impl IpAddressProvider for StdinIpProvider {
    fn get_my_ip_addr(&self) -> Result<IpAddr> {
        let mut input = String::new();

        try!(io::stdin().read_line(&mut input));

        trace!("Read stdin: {}", input);

        let ip_addr = try!(IpAddr::from_str(input.trim()));
        Ok(ip_addr)
    }
}

pub struct HttpIpProvider<'a> {
    url: &'a str,
}

impl<'a> HttpIpProvider<'a> {
    fn new(url: &'a str) -> HttpIpProvider {
        HttpIpProvider {
            url: url,
        }
    }
}

impl<'a> IpAddressProvider for HttpIpProvider<'a> {
    fn get_my_ip_addr(&self) -> Result<IpAddr> {
        let client = Client::new();

        let mut res = try!(client.get(self.url)
            .header(Connection::close())
            .send());

        let mut body = String::new();
        try!(res.read_to_string(&mut body));

        trace!("HTTP Response: {}", body);

        let regex = try!(Regex::new(r"((?:(?:0|1[\d]{0,2}|2(?:[0-4]\d?|5[0-5]?|[6-9])?|[3-9]\d?)\.){3}(?:0|1[\d]{0,2}|2(?:[0-4]\d?|5[0-5]?|[6-9])?|[3-9]\d?))"));

        regex.captures(&*body)
            .and_then(|caps| caps.at(1))
            // Convert Option to Result
            .ok_or(Error::IpNotFound)
            .and_then(|val| IpAddr::from_str(val).map_err(|e| {
                error!("IP parse error: {}", e);
                Error::IpNotFound
            }))
    }
}
<|endoftext|>


<commit_before>enum Interest {
    Interested,
    Uninterested,
}

enum Choke {
    Choked,
    Unchoked,
}

struct PeerData {
    // Only maintain remote choke/interest, state machine should track our state
    choke: Choke,
    interest: Interest,
}

pub enum PeerEvent {
    // Got a handshake
    Handshake,
    // We got the piece bitfield
    Bitfield,
    // We received a piece from somewhere else
    HavePiece,
    // We were unchoked
    Unchoked,
    // We received a piece from this peer
    ReceivedPiece,
    // The peer is interested
    Interested,
    // The peer is uninterested
    UnInterested,
    // We were chocked
    Choked,
    // The peer wants a piece
    RequestPiece,

    // Something timed out
    Timeout,
    // We received a piece from somewhere else
    ReceivedExternalPiece,
    // The manager(TBD) deems this a good peer, or optimistically unchoked, and should be allowed
    // to DL
    AllowReciprocation,
    // The manager doesn't want to reciprocate to this peer anymore
    RevokeReciprocation,
    // The torrent was completed
    CompletedTorrent,
    // This connection should be terminated
    Terminate,
}

pub enum PeerReaction {
    StartHandshake,
    GetBF,
    SendInterest,
    SendRequest,
    SendUnchoke,
    SendChoke,
    SendHave,
    SendCancel,
    SendPing,
    BroadcastPiece,
    Terminate,
}

enum State {
    // Starting state for an incomplete torrent, waiting for events
    Initial,
    // The handshake went through, the peer is valid
    Valid,
    // The peer has nothing to offer us, waiting for HAVE messages
    Uninteresting,
    // The peer has stuff we want, we're waiting for them to unchoke us
    WaitingUnchoke,
    // We've been unchoked and can now download
    Unchoked,
    // We sent a request and are waiting for a piece back
    AwaitingPiece,
}

pub struct Peer {
    data: PeerData,
    state: State,
}
<commit_msg>Flesh out peer design more<commit_after>use std::mem;
use std::time::Instant;

enum Interest {
    Interested,
    Uninterested,
}

struct PeerData {
    // Only maintain remote interest, state machine should track our state otherwise
    pub interest: Interest,
    pub received: usize,
    pub last_action: Instant
}

impl PeerData {
    fn new() -> PeerData {
        PeerData {
            interest: Interest::Uninterested,
            received: 0,
            last_action: Instant::now(),
        }
    }
}

pub enum PeerEvent {
    // Initialization
    Init,
    // Got a handshake
    Handshake,
    // We got the piece bitfield
    Bitfield(bool),
    // We received a piece from somewhere else
    HavePiece,
    // We were unchoked
    Unchoked,
    // We received a piece from this peer
    ReceivedPiece,
    // The peer is interested
    Interested,
    // The peer is uninterested
    Uninterested,
    // We were chocked
    Choked,
    // The peer wants a piece
    RequestPiece,

    // We received a piece from somewhere else
    ReceivedExternalPiece,
    // The manager(TBD) deems this a good peer, or optimistically unchoked, and should be allowed
    // to DL
    AllowReciprocation,
    // The manager doesn't want to reciprocate to this peer anymore
    RevokeReciprocation,
    // The torrent was completed
    CompletedTorrent,
    // No pieces can be requested from this peer
    NotRequestable,
    // This connection should be terminated
    Terminate,
}

pub enum PeerReaction {
    SendBF,
    SendInterested,
    SendUninterested,
    SendRequest,
    SendUnchoke,
    SendChoke,
    SendHave,
    SendPiece,
    SendCancel,
    // used in endgame mode, cancel last piece, request a new one
    CancelAndReq,
    Terminate,
    // Instructs the manager to release the piece this was attempting to retrieve, and let another
    // peer handle its retrieval
    ReleasePiece,
    Nothing,
}

enum State {
    Null,
    // Starting state for an incomplete torrent, waiting for events
    Initial,
    // The handshake went through, the peer is valid
    Valid,
    // The peer has nothing to offer us, waiting for HAVE messages
    Uninteresting,
    // The peer has stuff we want, we're waiting for them to unchoke us
    AwaitingUnchoke,
    // We've been unchoked and can now download
    Unchoked,
    // We sent a request and are waiting for a piece back
    AwaitingPiece,
    // We have everything
    Seeding,
}

pub struct Peer {
    can_recip: bool,
    data: PeerData,
    state: State,
}

impl Peer {
    fn new() -> Peer {
        Peer {
            can_recip: false,
            data: PeerData::new(),
            state: State::Initial,
        }
    }

    fn data<'a>(&'a self) -> &'a PeerData {
        &self.data
    }

    // Drive the state machine
    fn handle(&mut self, event: PeerEvent) -> PeerReaction {
        self.data.last_action = Instant::now();
        let old_state = mem::replace(&mut self.state, State::Null);
        let (new_state, resp) = match (old_state, event) {
            (State::Initial, PeerEvent::Handshake) => {
                (State::Valid, PeerReaction::SendBF)
            }
            (State::Valid, PeerEvent::Bitfield(bf)) => {
                // Check if bitfield is interesting - use bool as placeholder
                if bf {
                    // Try to get the peer to unchoke us, manager should priotiize seeding to this
                    // peer
                    (State::AwaitingUnchoke, PeerReaction::SendInterested)
                } else {
                    // Just wait, no need to transition state here
                    (State::Valid, PeerReaction::Nothing)
                }
            }
            (State::AwaitingUnchoke, PeerEvent::Unchoked) => {
                (State::AwaitingPiece, PeerReaction::SendRequest)
            }
            (State::AwaitingPiece, PeerEvent::ReceivedPiece) => {
                self.data.received += 1;
                // If we still have pieces retrievable from this peer, send another request,
                // otherwise send uninterested
                if true {
                    (State::AwaitingPiece, PeerReaction::SendRequest)
                } else {
                    (State::Unchoked, PeerReaction::SendUninterested)
                }
            }
            (State::Unchoked, PeerEvent::Choked) => {
                // If we're choked by an idle peer, just revert to valid
                (State::Valid, PeerReaction::Nothing)
            }
            (State::AwaitingPiece, PeerEvent::Choked) => {
                // If we're choked while waiting for a piece, just wait
                (State::AwaitingUnchoke, PeerReaction::ReleasePiece)
            }
            (State::Unchoked, PeerEvent::HavePiece) => {
                // If the peer got a piece we want and isn't choking us request it
                if true {
                    (State::AwaitingPiece, PeerReaction::SendRequest)
                } else {
                    (State::Unchoked, PeerReaction::Nothing)
                }
            }
            (State::Valid, PeerEvent::HavePiece) => {
                // If the peer got a piece we want and isn't choking us request it
                if true {
                    (State::AwaitingUnchoke, PeerReaction::SendInterested)
                } else {
                    (State::Valid, PeerReaction::Nothing)
                }
            }
            (s, PeerEvent::HavePiece) => {
                // Just modify state so we know we got the piece
                (s, PeerReaction::Nothing)
            }
            (State::AwaitingPiece, PeerEvent::ReceivedExternalPiece) => {
                // If this is a piece we want rn cancel and req, otherwise announce have
                let s = State::AwaitingPiece;
                if true {
                    (s, PeerReaction::CancelAndReq)
                } else {
                    // If the peer doens't have this piece inform them
                    if true {
                        (s, PeerReaction::SendHave)
                    } else {
                        (s, PeerReaction::Nothing)
                    }
                }
            }
            (s, PeerEvent::AllowReciprocation) => {
                self.can_recip = true;
                if let Interest::Interested = self.data.interest {
                    (s, PeerReaction::SendUnchoke)
                } else {
                    (s, PeerReaction::Nothing)
                }
            }
            (s, PeerEvent::RevokeReciprocation) => {
                self.can_recip = false;
                if let Interest::Interested = self.data.interest {
                    (s, PeerReaction::SendChoke)
                } else {
                    (s, PeerReaction::Nothing)
                }
            }
            (State::Seeding, PeerEvent::RequestPiece) => {
                (State::Seeding, PeerReaction::SendPiece)
            }
            (s, PeerEvent::RequestPiece) => {
                if self.can_recip {
                    (s, PeerReaction::SendPiece)
                } else {
                    // Peers should not be requesting when we have choked them, kill conn
                    (s, PeerReaction::Terminate)
                }
            }
            (s, PeerEvent::Interested) => {
                self.data.interest = Interest::Interested;
                (s, PeerReaction::Nothing)
            }
            (State::Seeding, PeerEvent::Uninterested) => {
                // If we're seeding and for some reason the peer is uninterested, terminate
                // connection
                self.data.interest = Interest::Uninterested;
                (State::Seeding, PeerReaction::Terminate)
            }
            (s, PeerEvent::Uninterested) => {
                self.data.interest = Interest::Uninterested;
                (s, PeerReaction::Nothing)
            }
            (s, PeerEvent::ReceivedExternalPiece) => {
                // If we got a piece from somewhere else, and they don't have it inform this peer
                if true {
                    (s, PeerReaction::SendHave)
                } else {
                    (s, PeerReaction::Nothing)
                }
            }
            (State::AwaitingPiece, PeerEvent::CompletedTorrent) => {
                (State::Seeding, PeerReaction::SendCancel)
            }
            (_, PeerEvent::CompletedTorrent) => {
                (State::Seeding, PeerReaction::Nothing)
            }
            (state, _event) => {
                (state, PeerReaction::Nothing)
            }
        };
        self.state = new_state;
        resp
    }
}
<|endoftext|>


<commit_before>use value::{Value};
use std::str::FromStr;
use std::f64;

#[derive(Clone, Debug, Copy)]
pub enum Primitive {
    LT,
    LTE,
    NEQ,
    Add,
    Subtract,
    Multiply,
    Round,
    Split,
    Concat,
    ParseFloat,
    Count,
    Contains,
    Sum,
    Mean,
    StandardDeviation,
    Empty,
}

pub fn resolve_as_scalar<'a>(mut ix: usize, constants: &'a [Value], outer: &'a [Value]) -> &'a Value {
    if ix < constants.len() {
        return &constants[ix];
    } else {
        ix = ix - constants.len()
    }
    return &outer[ix];
}

pub fn resolve_as_vector<'a>(mut ix: usize, constants: &'a [Value], outer: &'a [Value], inner: &'a [Vec<Value>]) -> Vec<&'a Value> {
    if ix < constants.len() {
        return vec![&constants[ix]; inner.len()];
    } else {
        ix = ix - constants.len()
    }
    if ix < outer.len() {
        return vec![&outer[ix]; inner.len()];
    } else {
        ix = ix - outer.len()
    }
    return inner.iter().map(|values| &values[ix]).collect();
}

impl Primitive {
    pub fn eval_from_join<'a>(&self, input_bindings: &[(usize, usize)], inputs: &[Value]) -> Vec<Vec<Value>> {
        use primitive::Primitive::*;
        use value::Value::*;
        let values = input_bindings.iter().enumerate().map(|(ix, &(field_ix, variable_ix))| {
            assert_eq!(ix, field_ix);
            &inputs[variable_ix]
        }).collect::<Vec<_>>();
        match (*self, &values[..]) {
            // NOTE be aware that arguments will be in alphabetical order by field id
            (LT, [ref a, ref b]) => if a < b {vec![vec![]]} else {vec![]},
            (LTE, [ref a, ref b]) => if a <= b {vec![vec![]]} else {vec![]},
            (NEQ, [ref a, ref b]) => if a != b {vec![vec![]]} else {vec![]},
            (Add, [&Float(a), &Float(b)]) => vec![vec![Float(a+b)]],
            (Subtract, [&Float(a), &Float(b)]) => vec![vec![Float(a-b)]],
            (Multiply, [&Float(a), &Float(b)]) => vec![vec![Float(a*b)]],
            (Round, [&Float(a), &Float(b)]) => vec![vec![Float((a*10f64.powf(b)).round()/10f64.powf(b))]],
            (Contains, [&String(ref inner), &String(ref outer)]) => {
              let inner_lower = &inner.to_lowercase();
              let outer_lower = &outer.to_lowercase();
              vec![vec![Bool(outer_lower.contains(inner_lower))]]
            },
            (Split, [&String(ref split), &String(ref string)]) => {
                string.split(split).enumerate().map(|(ix, segment)| vec![Float(ix as f64), String(segment.to_owned())]).collect()
            },
            (Concat, [&String(ref a), &String(ref b)]) => vec![vec![String(a.to_owned() + b)]],
            (ParseFloat, [&String(ref a)]) => {
                match f64::from_str(&a) {
                    Ok(v) => vec![vec![Float(v), Bool(true)]],
                    _ => vec![vec![Float(f64::MAX), Bool(false)]]
                }
            },
            (Count, _) => panic!("Cannot use {:?} in a join", self),
            (Sum, _) => panic!("Cannot use {:?} in a join", self),
            (Mean, _) => panic!("Cannot use {:?} in a join", self),
            (StandardDeviation, _) => panic!("Cannot use {:?} in a join", self),
            (Empty, _) => panic!("Cannot use {:?} in a join", self),
            _ => panic!("Type error while calling: {:?} {:?}", self, values)
        }
    }

    pub fn eval_from_aggregate<'a>(&self, arguments: &[usize], constants: &[Value], outer: &[Value], inner: &[Vec<Value>]) -> Vec<Vec<Value>> {
        use primitive::Primitive::*;
        use value::Value::*;
        match (*self, arguments) {
            // NOTE be aware that arguments will be in alphabetical order by field id
            (LT, _) => panic!("Cannot use {:?} in an aggregate", self),
            (LTE, _) => panic!("Cannot use {:?} in an aggregate", self),
            (NEQ, _) => panic!("Cannot use {:?} in an aggregate", self),
            (Add, _) => panic!("Cannot use {:?} in an aggregate", self),
            (Subtract, _) => panic!("Cannot use {:?} in an aggregate", self),
            (Multiply, _) => panic!("Cannot use {:?} in an aggregate", self),
            (Round, _) => panic!("Cannot use {:?} in an aggregate", self),
            (Contains, _) => panic!("Cannot use {:?} in an aggregate", self),
            (Split, _) => panic!("Cannot use {:?} in an aggregate", self),
            (Concat, _) => panic!("Cannot use {:?} in an aggregate", self),
            (ParseFloat, _) => panic!("Cannot use {:?} in an aggregate", self),
            (Count, [_]) => {
                vec![vec![Float(inner.len() as f64)]]
            },
            (Sum, [in_ix]) => {
                let in_values = resolve_as_vector(in_ix, constants, outer, inner);
                let sum = in_values.iter().fold(0f64, |sum, value|
                    match **value {
                        Float(float) => sum + float,
                        _ => panic!("Type error while calling: {:?} {:?}", self, in_values),
                    });
                vec![vec![Float(sum)]]
            },
            (Mean, [in_ix]) => {
                let in_values = resolve_as_vector(in_ix, constants, outer, inner);
                let sum = in_values.iter().fold(0f64, |sum, value|
                    match **value {
                        Float(float) => sum + float,
                        _ => panic!("Type error while calling: {:?} {:?}", self, in_values),
                    });
                let mean = sum / (in_values.len() as f64);
                vec![vec![Float(mean)]]
            },
            (StandardDeviation, [in_ix]) => {
                let in_values = resolve_as_vector(in_ix, constants, outer, inner);
                let sum = in_values.iter().fold(0f64, |sum, value|
                    match **value {
                        Float(float) => sum + float,
                        _ => panic!("Type error while calling: {:?} {:?}", self, in_values),
                    });
                let sum_squares = in_values.iter().fold(0f64, |sum, value|
                    match **value {
                        Float(float) => sum + float.powi(2),
                        _ => panic!("Type error while calling: {:?} {:?}", self, in_values),
                    });
                let standard_deviation = ((sum_squares - sum.powi(2)) / (in_values.len() as f64)).sqrt();
                vec![vec![Float(standard_deviation)]]
            },
            (Empty, [in_ix]) => {
                let in_values = resolve_as_vector(in_ix, constants, outer, inner);
                vec![vec![Bool(in_values.len() == 0)]]
            },
            _ => panic!("Wrong number of arguments while calling: {:?} {:?}", self, arguments),
        }
    }

    pub fn from_str(string: &str) -> Self {
        match string {
            "<" => Primitive::LT,
            "<=" => Primitive::LTE,
            "!=" => Primitive::NEQ,
            "add" => Primitive::Add,
            "subtract" => Primitive::Subtract,
            "multiply" => Primitive::Multiply,
            "round" => Primitive::Round,
            "contains" => Primitive::Contains,
            "split" => Primitive::Split,
            "concat" => Primitive::Concat,
            "parse float" => Primitive::ParseFloat,
            "count" => Primitive::Count,
            "sum" => Primitive::Sum,
            "mean" => Primitive::Mean,
            "standard deviation" => Primitive::StandardDeviation,
            "empty" => Primitive::Empty,
            _ => panic!("Unknown primitive: {:?}", string),
        }
    }
}

pub fn primitives() -> Vec<(&'static str, Vec<&'static str>, Vec<&'static str>, Vec<&'static str>)> {
    vec![
        ("<", vec!["in A", "in B"], vec![], vec![]),
        ("<=", vec!["in A", "in B"], vec![], vec![]),
        ("!=", vec!["in A", "in B"], vec![], vec![]),
        ("add", vec!["in A", "in B"], vec![], vec!["out"]),
        ("subtract", vec!["in A", "in B"], vec![], vec!["out"]),
        ("multiply", vec!["in A", "in B"], vec![], vec!["out"]),
        ("round", vec!["in A", "in B"], vec![], vec!["out"]),
        ("contains", vec!["inner", "outer"], vec![], vec!["out"]),
        ("split", vec!["split", "string"], vec![], vec!["ix", "segment"]),
        ("concat", vec!["a", "b"], vec![], vec!["out"]),
        ("parse float", vec!["a"], vec![], vec!["out", "valid"]),
        ("count", vec![], vec!["in"], vec!["out"]),
        ("sum", vec![], vec!["in"], vec!["out"]),
        ("mean", vec![], vec!["in"], vec!["out"]),
        ("standard deviation", vec![], vec!["in"], vec!["out"]),
        ("empty", vec![], vec!["in"], vec!["out"]),
    ]
}
<commit_msg>Port aggregates to use columns<commit_after>use value::{Value};
use std::str::FromStr;
use std::f64;

#[derive(Clone, Debug, Copy)]
pub enum Primitive {
    LT,
    LTE,
    NEQ,
    Add,
    Subtract,
    Multiply,
    Round,
    Split,
    Concat,
    ParseFloat,
    Count,
    Contains,
    Sum,
    Mean,
    StandardDeviation,
    Empty,
}

pub fn resolve_as_scalar<'a>(mut ix: usize, constants: &'a [Value], outer: &'a [Value]) -> &'a Value {
    if ix < constants.len() {
        return &constants[ix];
    } else {
        ix = ix - constants.len()
    }
    return &outer[ix];
}

pub fn resolve_as_vector<'a>(mut ix: usize, constants: &'a [Value], outer: &'a [Value], inner: &'a [Vec<Value>]) -> Vec<&'a Value> {
    if ix < constants.len() {
        return vec![&constants[ix]; inner.len()];
    } else {
        ix = ix - constants.len()
    }
    if ix < outer.len() {
        return vec![&outer[ix]; inner.len()];
    } else {
        ix = ix - outer.len()
    }
    return inner.iter().map(|values| &values[ix]).collect();
}

impl Primitive {
    pub fn eval_from_join<'a>(&self, input_bindings: &[(usize, usize)], inputs: &[Value]) -> Vec<Vec<Value>> {
        use primitive::Primitive::*;
        use value::Value::*;
        let values = input_bindings.iter().enumerate().map(|(ix, &(field_ix, variable_ix))| {
            assert_eq!(ix, field_ix);
            &inputs[variable_ix]
        }).collect::<Vec<_>>();
        match (*self, &values[..]) {
            // NOTE be aware that arguments will be in alphabetical order by field id
            (LT, [ref a, ref b]) => if a < b {vec![vec![]]} else {vec![]},
            (LTE, [ref a, ref b]) => if a <= b {vec![vec![]]} else {vec![]},
            (NEQ, [ref a, ref b]) => if a != b {vec![vec![]]} else {vec![]},
            (Add, [&Float(a), &Float(b)]) => vec![vec![Float(a+b)]],
            (Subtract, [&Float(a), &Float(b)]) => vec![vec![Float(a-b)]],
            (Multiply, [&Float(a), &Float(b)]) => vec![vec![Float(a*b)]],
            (Round, [&Float(a), &Float(b)]) => vec![vec![Float((a*10f64.powf(b)).round()/10f64.powf(b))]],
            (Contains, [&String(ref inner), &String(ref outer)]) => {
              let inner_lower = &inner.to_lowercase();
              let outer_lower = &outer.to_lowercase();
              vec![vec![Bool(outer_lower.contains(inner_lower))]]
            },
            (Split, [&String(ref split), &String(ref string)]) => {
                string.split(split).enumerate().map(|(ix, segment)| vec![Float(ix as f64), String(segment.to_owned())]).collect()
            },
            (Concat, [&String(ref a), &String(ref b)]) => vec![vec![String(a.to_owned() + b)]],
            (ParseFloat, [&String(ref a)]) => {
                match f64::from_str(&a) {
                    Ok(v) => vec![vec![Float(v), Bool(true)]],
                    _ => vec![vec![Float(f64::MAX), Bool(false)]]
                }
            },
            (Count, [&Column(ref column)]) => vec![vec![Float(column.len() as f64)]],
            (Sum, [&Column(ref column)]) => {
                let sum = column.iter().fold(0f64, |sum, value|
                    match *value {
                        Float(float) => sum + float,
                        _ => panic!("Type error while calling: {:?} {:?}", self, column),
                    });
                vec![vec![Float(sum)]]
            }
            (Mean, [&Column(ref column)]) => {
                let sum = column.iter().fold(0f64, |sum, value|
                    match *value {
                        Float(float) => sum + float,
                        _ => panic!("Type error while calling: {:?} {:?}", self, column),
                    });
                let mean = sum / (column.len() as f64);
                vec![vec![Float(mean)]]
            },
            (StandardDeviation, [&Column(ref column)]) => {
                let sum = column.iter().fold(0f64, |sum, value|
                    match *value {
                        Float(float) => sum + float,
                        _ => panic!("Type error while calling: {:?} {:?}", self, column),
                    });
                let sum_squares = column.iter().fold(0f64, |sum, value|
                    match *value {
                        Float(float) => sum + float.powi(2),
                        _ => panic!("Type error while calling: {:?} {:?}", self, column),
                    });
                let standard_deviation = ((sum_squares - sum.powi(2)) / (column.len() as f64)).sqrt();
                vec![vec![Float(standard_deviation)]]
            }
            (Empty, [&Column(ref column)]) => vec![vec![Bool(column.len() == 0)]],
            _ => panic!("Type error while calling: {:?} {:?}", self, values)
        }
    }

    pub fn eval_from_aggregate<'a>(&self, arguments: &[usize], constants: &[Value], outer: &[Value], inner: &[Vec<Value>]) -> Vec<Vec<Value>> {
        use primitive::Primitive::*;
        use value::Value::*;
        match (*self, arguments) {
            // NOTE be aware that arguments will be in alphabetical order by field id
            (LT, _) => panic!("Cannot use {:?} in an aggregate", self),
            (LTE, _) => panic!("Cannot use {:?} in an aggregate", self),
            (NEQ, _) => panic!("Cannot use {:?} in an aggregate", self),
            (Add, _) => panic!("Cannot use {:?} in an aggregate", self),
            (Subtract, _) => panic!("Cannot use {:?} in an aggregate", self),
            (Multiply, _) => panic!("Cannot use {:?} in an aggregate", self),
            (Round, _) => panic!("Cannot use {:?} in an aggregate", self),
            (Contains, _) => panic!("Cannot use {:?} in an aggregate", self),
            (Split, _) => panic!("Cannot use {:?} in an aggregate", self),
            (Concat, _) => panic!("Cannot use {:?} in an aggregate", self),
            (ParseFloat, _) => panic!("Cannot use {:?} in an aggregate", self),
            (Count, [_]) => {
                vec![vec![Float(inner.len() as f64)]]
            },
            (Sum, [in_ix]) => {
                let in_values = resolve_as_vector(in_ix, constants, outer, inner);
                let sum = in_values.iter().fold(0f64, |sum, value|
                    match **value {
                        Float(float) => sum + float,
                        _ => panic!("Type error while calling: {:?} {:?}", self, in_values),
                    });
                vec![vec![Float(sum)]]
            },
            (Mean, [in_ix]) => {
                let in_values = resolve_as_vector(in_ix, constants, outer, inner);
                let sum = in_values.iter().fold(0f64, |sum, value|
                    match **value {
                        Float(float) => sum + float,
                        _ => panic!("Type error while calling: {:?} {:?}", self, in_values),
                    });
                let mean = sum / (in_values.len() as f64);
                vec![vec![Float(mean)]]
            },
            (StandardDeviation, [in_ix]) => {
                let in_values = resolve_as_vector(in_ix, constants, outer, inner);
                let sum = in_values.iter().fold(0f64, |sum, value|
                    match **value {
                        Float(float) => sum + float,
                        _ => panic!("Type error while calling: {:?} {:?}", self, in_values),
                    });
                let sum_squares = in_values.iter().fold(0f64, |sum, value|
                    match **value {
                        Float(float) => sum + float.powi(2),
                        _ => panic!("Type error while calling: {:?} {:?}", self, in_values),
                    });
                let standard_deviation = ((sum_squares - sum.powi(2)) / (in_values.len() as f64)).sqrt();
                vec![vec![Float(standard_deviation)]]
            },
            (Empty, [in_ix]) => {
                let in_values = resolve_as_vector(in_ix, constants, outer, inner);
                vec![vec![Bool(in_values.len() == 0)]]
            },
            _ => panic!("Wrong number of arguments while calling: {:?} {:?}", self, arguments),
        }
    }

    pub fn from_str(string: &str) -> Self {
        match string {
            "<" => Primitive::LT,
            "<=" => Primitive::LTE,
            "!=" => Primitive::NEQ,
            "add" => Primitive::Add,
            "subtract" => Primitive::Subtract,
            "multiply" => Primitive::Multiply,
            "round" => Primitive::Round,
            "contains" => Primitive::Contains,
            "split" => Primitive::Split,
            "concat" => Primitive::Concat,
            "parse float" => Primitive::ParseFloat,
            "count" => Primitive::Count,
            "sum" => Primitive::Sum,
            "mean" => Primitive::Mean,
            "standard deviation" => Primitive::StandardDeviation,
            "empty" => Primitive::Empty,
            _ => panic!("Unknown primitive: {:?}", string),
        }
    }
}

pub fn primitives() -> Vec<(&'static str, Vec<&'static str>, Vec<&'static str>, Vec<&'static str>)> {
    vec![
        ("<", vec!["in A", "in B"], vec![], vec![]),
        ("<=", vec!["in A", "in B"], vec![], vec![]),
        ("!=", vec!["in A", "in B"], vec![], vec![]),
        ("add", vec!["in A", "in B"], vec![], vec!["out"]),
        ("subtract", vec!["in A", "in B"], vec![], vec!["out"]),
        ("multiply", vec!["in A", "in B"], vec![], vec!["out"]),
        ("round", vec!["in A", "in B"], vec![], vec!["out"]),
        ("contains", vec!["inner", "outer"], vec![], vec!["out"]),
        ("split", vec!["split", "string"], vec![], vec!["ix", "segment"]),
        ("concat", vec!["a", "b"], vec![], vec!["out"]),
        ("parse float", vec!["a"], vec![], vec!["out", "valid"]),
        ("count", vec![], vec!["in"], vec!["out"]),
        ("sum", vec![], vec!["in"], vec!["out"]),
        ("mean", vec![], vec!["in"], vec!["out"]),
        ("standard deviation", vec![], vec!["in"], vec!["out"]),
        ("empty", vec![], vec!["in"], vec!["out"]),
    ]
}
<|endoftext|>


<commit_before>mod changelog;

use xshell::{cmd, cp, pushd, read_dir, write_file};

use crate::{codegen, date_iso, flags, is_release_tag, project_root, Result};

impl flags::Release {
    pub(crate) fn run(self) -> Result<()> {
        if !self.dry_run {
            cmd!("git switch release").run()?;
            cmd!("git fetch upstream --tags --force").run()?;
            cmd!("git reset --hard tags/nightly").run()?;
            // The `release` branch sometimes have a couple of cherry-picked
            // commits for patch releases. If that's the case, just overwrite
            // it. As we are setting `release` branch to an up-to-date `nightly`
            // tag, this shouldn't be problematic in general.
            //
            // Note that, as we tag releases, we don't worry about "loosing"
            // commits -- they'll be kept alive by the tag. More generally, we
            // don't care about historic releases all that much, it's fine even
            // to delete old tags.
            cmd!("git push --force").run()?;
        }
        codegen::docs()?;

        let website_root = project_root().join("../rust-analyzer.github.io");
        let changelog_dir = website_root.join("./thisweek/_posts");

        let today = date_iso()?;
        let commit = cmd!("git rev-parse HEAD").read()?;
        let changelog_n = read_dir(changelog_dir.as_path())?.len();

        for &adoc in [
            "manual.adoc",
            "generated_assists.adoc",
            "generated_config.adoc",
            "generated_diagnostic.adoc",
            "generated_features.adoc",
        ]
        .iter()
        {
            let src = project_root().join("./docs/user/").join(adoc);
            let dst = website_root.join(adoc);
            cp(src, dst)?;
        }

        let tags = cmd!("git tag --list").read()?;
        let prev_tag = tags.lines().filter(|line| is_release_tag(line)).last().unwrap();

        let contents = changelog::get_changelog(changelog_n, &commit, prev_tag, &today)?;
        let path = changelog_dir.join(format!("{}-changelog-{}.adoc", today, changelog_n));
        write_file(&path, &contents)?;

        Ok(())
    }
}

impl flags::Promote {
    pub(crate) fn run(self) -> Result<()> {
        let _dir = pushd("../rust-rust-analyzer")?;
        cmd!("git switch master").run()?;
        cmd!("git fetch upstream").run()?;
        cmd!("git reset --hard upstream/master").run()?;
        cmd!("git submodule update --recursive").run()?;

        let branch = format!("rust-analyzer-{}", date_iso()?);
        cmd!("git switch -c {branch}").run()?;
        {
            let _dir = pushd("src/tools/rust-analyzer")?;
            cmd!("git fetch origin").run()?;
            cmd!("git reset --hard origin/release").run()?;
        }
        cmd!("git add src/tools/rust-analyzer").run()?;
        cmd!("git commit -m':arrow_up: rust-analyzer'").run()?;
        if !self.dry_run {
            cmd!("git push -u").run()?;
            cmd!("xdg-open https://github.com/matklad/rust/pull/new/{branch}?body=r%3F%20%40ghost")
                .run()?;
        }
        Ok(())
    }
}
<commit_msg>Update xtask/src/release.rs<commit_after>mod changelog;

use xshell::{cmd, cp, pushd, read_dir, write_file};

use crate::{codegen, date_iso, flags, is_release_tag, project_root, Result};

impl flags::Release {
    pub(crate) fn run(self) -> Result<()> {
        if !self.dry_run {
            cmd!("git switch release").run()?;
            cmd!("git fetch upstream --tags --force").run()?;
            cmd!("git reset --hard tags/nightly").run()?;
            // The `release` branch sometimes has a couple of cherry-picked
            // commits for patch releases. If that's the case, just overwrite
            // it. As we are setting `release` branch to an up-to-date `nightly`
            // tag, this shouldn't be problematic in general.
            //
            // Note that, as we tag releases, we don't worry about "loosing"
            // commits -- they'll be kept alive by the tag. More generally, we
            // don't care about historic releases all that much, it's fine even
            // to delete old tags.
            cmd!("git push --force").run()?;
        }
        codegen::docs()?;

        let website_root = project_root().join("../rust-analyzer.github.io");
        let changelog_dir = website_root.join("./thisweek/_posts");

        let today = date_iso()?;
        let commit = cmd!("git rev-parse HEAD").read()?;
        let changelog_n = read_dir(changelog_dir.as_path())?.len();

        for &adoc in [
            "manual.adoc",
            "generated_assists.adoc",
            "generated_config.adoc",
            "generated_diagnostic.adoc",
            "generated_features.adoc",
        ]
        .iter()
        {
            let src = project_root().join("./docs/user/").join(adoc);
            let dst = website_root.join(adoc);
            cp(src, dst)?;
        }

        let tags = cmd!("git tag --list").read()?;
        let prev_tag = tags.lines().filter(|line| is_release_tag(line)).last().unwrap();

        let contents = changelog::get_changelog(changelog_n, &commit, prev_tag, &today)?;
        let path = changelog_dir.join(format!("{}-changelog-{}.adoc", today, changelog_n));
        write_file(&path, &contents)?;

        Ok(())
    }
}

impl flags::Promote {
    pub(crate) fn run(self) -> Result<()> {
        let _dir = pushd("../rust-rust-analyzer")?;
        cmd!("git switch master").run()?;
        cmd!("git fetch upstream").run()?;
        cmd!("git reset --hard upstream/master").run()?;
        cmd!("git submodule update --recursive").run()?;

        let branch = format!("rust-analyzer-{}", date_iso()?);
        cmd!("git switch -c {branch}").run()?;
        {
            let _dir = pushd("src/tools/rust-analyzer")?;
            cmd!("git fetch origin").run()?;
            cmd!("git reset --hard origin/release").run()?;
        }
        cmd!("git add src/tools/rust-analyzer").run()?;
        cmd!("git commit -m':arrow_up: rust-analyzer'").run()?;
        if !self.dry_run {
            cmd!("git push -u").run()?;
            cmd!("xdg-open https://github.com/matklad/rust/pull/new/{branch}?body=r%3F%20%40ghost")
                .run()?;
        }
        Ok(())
    }
}
<|endoftext|>