<commit_before>use clap::{App, AppSettings, Arg};
use std::path::{Path, PathBuf};
use utils::EmulationSpeed;
use zx::constants::{SCREEN_HEIGHT, SCREEN_WIDTH};
use zx::machine::ZXMachine;
use zx::sound::ay::ZXAYMode;
// TODO: move comand line parsing here

/// Structure to handle all emulator runtime settings
pub struct RustzxSettings {
    pub machine: ZXMachine,
    pub speed: EmulationSpeed,
    pub fastload: bool,
    pub scale: usize,
    pub screen_size: (usize, usize),
    pub kempston: bool,
    pub ay_mode: ZXAYMode,
    pub ay_enabled: bool,
    pub beeper_enabled: bool,
    pub sound_enabled: bool,
    pub volume: usize,
    pub latency: usize,
    pub rom: Option<PathBuf>,
    pub tap: Option<PathBuf>,
    pub sna: Option<PathBuf>,
}

impl RustzxSettings {
    /// constructs new Settings
    pub fn new() -> RustzxSettings {
        RustzxSettings {
            machine: ZXMachine::Sinclair48K,
            speed: EmulationSpeed::Definite(1),
            fastload: false,
            scale: 2,
            screen_size: (SCREEN_WIDTH * 2, SCREEN_HEIGHT * 2),
            kempston: false,
            ay_mode: ZXAYMode::Mono,
            ay_enabled: false,
            beeper_enabled: true,
            sound_enabled: true,
            volume: 100,
            latency: 1024,
            rom: None,
            tap: None,
            sna: None,
        }
    }
    pub fn from_clap() -> RustzxSettings {
        // get defaults
        let mut out = Self::new();
        // parse cli
        let cmd = App::new("rustzx")
            .setting(AppSettings::ColoredHelp)
            .version(env!("CARGO_PKG_VERSION"))
            .author("Vladislav Nikonov <pacmancoder@gmail.com>")
            .about("ZX Spectrum emulator written in pure Rust")
            // machine settings
            .arg(
                Arg::with_name("128K")
                    .long("128k")
                    .help("Enables ZX Spectrum 128K mode"),
            )
            .arg(
                Arg::with_name("FASTLOAD")
                    .short("f")
                    .long("fastload")
                    .help("Accelerates standard tape loaders"),
            )
            // media files
            .arg(
                Arg::with_name("ROM")
                    .long("rom")
                    .value_name("ROM_PATH")
                    .help("Selects path to rom, otherwise default will be used"),
            )
            .arg(
                Arg::with_name("TAP")
                    .long("tap")
                    .value_name("TAP_PATH")
                    .help("Selects path to *.tap file"),
            )
            .arg(
                Arg::with_name("SNA")
                    .long("sna")
                    .value_name("SNA_PATH")
                    .help("Selects path to *.sna snapshot file"),
            )
            // devices
            .arg(Arg::with_name("KEMPSTON").short("k").long("kempston").help(
                "Enables Kempston joystick. Controlls via arrow keys and \
                 Alt buttons",
            ))
            // emulator settings
            .arg(
                Arg::with_name("SPEED")
                    .long("speed")
                    .value_name("SPEED_VALUE")
                    .help("Selects speed for emulator in integer multiplier form"),
            )
            .arg(
                Arg::with_name("SCALE")
                    .long("scale")
                    .value_name("SCALE_VALUE")
                    .help(
                        "Selects default screen size. possible values are positive \
                         integers. Default value is 2",
                    ),
            )
            // sound
            .arg(Arg::with_name("NOSOUND").long("nosound").help(
                "Disables sound. Use it when you have problems with audio \
                 playback",
            ))
            .arg(
                Arg::with_name("NOBEEPER")
                    .long("nobeeper")
                    .help("Disables beeper"),
            )
            .arg(
                Arg::with_name("AY")
                    .long("ay")
                    .value_name("AY_TYPE")
                    .possible_values(&["none", "mono", "abc", "acb"])
                    .help(
                        "Selects AY mode. Use none to disable. \
                         For stereo features use abc or acb, default is mono for \
                         128k and none for 48k.",
                    ),
            )
            .arg(
                Arg::with_name("VOLUME")
                    .long("volume")
                    .value_name("VOLUME_VALUE")
                    .help(
                        "Selects volume - value in range 0..200. Volume over 100 \
                         can cause sound artifacts",
                    ),
            )
            .arg(
                Arg::with_name("LATENCY")
                    .long("latency")
                    .short("l")
                    .value_name("SAMPLES")
                    .help(
                        "Selects audio latency. Default is 1024 samples. Set higher \
                         latency if emulator have sound glitches. Or if your \
                         machine can handle this - try to set it lower. Must be \
                         power of two.",
                    ),
            )
            .get_matches();
        // machine type
        if cmd.is_present("128K") {
            out.machine(ZXMachine::Sinclair128K);
        }
        if let Some(speed_str) = cmd.value_of("SPEED") {
            if let Ok(speed) = speed_str.parse::<usize>() {
                out.speed(EmulationSpeed::Definite(speed));
            }
        };
        if let Some(scale_str) = cmd.value_of("SCALE") {
            if let Ok(scale) = scale_str.parse::<usize>() {
                out.scale(scale);
            } else {
                println!("[Warning] Invalid scale factor");
            };
        }
        out.fastload(cmd.is_present("FASTLOAD"))
            .beeper(!cmd.is_present("NOBEEPER"))
            .sound(!cmd.is_present("NOSOUND"))
            .kempston(cmd.is_present("KEMPSTON"));
        if let Some(path) = cmd.value_of_os("ROM") {
            if Path::new(path).is_file() {
                out.rom(path);
            } else {
                println!(
                    "[Warning] ROM file \"{}\" not found",
                    path.to_string_lossy()
                );
            }
        }
        if let Some(path) = cmd.value_of_os("TAP") {
            if Path::new(path).is_file() {
                out.tap(path);
            } else {
                println!(
                    "[Warning] Tape file \"{}\" not found",
                    path.to_string_lossy()
                );
            }
        }
        if let Some(path) = cmd.value_of_os("SNA") {
            if out.machine == ZXMachine::Sinclair48K {
                if Path::new(path).is_file() {
                    out.sna(path);
                } else {
                    println!(
                        "[Warning] Snapshot file \"{}\" not found",
                        path.to_string_lossy()
                    );
                }
            } else {
                println!("[Warning] 128K SNA is not supported!");
            }
        }
        if let Some(value) = cmd.value_of("AY") {
            match value {
                "none" => out.ay(false),
                "mono" => out.ay_mode(ZXAYMode::Mono),
                "abc" => out.ay_mode(ZXAYMode::ABC),
                "acb" => out.ay_mode(ZXAYMode::ACB),
                _ => unreachable!(),
            };
        };
        if let Some(value) = cmd.value_of("VOLUME") {
            if let Ok(value) = value.parse::<usize>() {
                out.volume(value);
            } else {
                println!("[Warning] Volume value is incorrect, setting volume to 100");
            }
        };
        if let Some(latency_str) = cmd.value_of("LATENCY") {
            if let Ok(latency) = latency_str.parse::<usize>() {
                out.latency(latency);
            }
        };
        out
    }
    /// Changes machine type
    pub fn machine(&mut self, machine: ZXMachine) -> &mut Self {
        self.machine = machine;
        match machine {
            ZXMachine::Sinclair48K => self.ay_enabled = false,
            ZXMachine::Sinclair128K => self.ay_enabled = true,
        }
        self
    }
    /// changes screen scale
    pub fn scale(&mut self, scale: usize) -> &mut Self {
        // place into bounds
        if scale > 5 {
            self.scale = 2;
        } else {
            self.scale = scale;
        }
        self.screen_size = (SCREEN_WIDTH * self.scale, SCREEN_HEIGHT * self.scale);
        self
    }
    /// changes fastload flag
    pub fn fastload(&mut self, value: bool) -> &mut Self {
        self.fastload = value;
        self
    }
    /// changes lound latency
    pub fn latency(&mut self, latency: usize) -> &mut Self {
        self.latency = latency;
        self
    }
    /// Changes AY chip mode
    pub fn ay_mode(&mut self, mode: ZXAYMode) -> &mut Self {
        self.ay_enabled = true;
        self.ay_mode = mode;
        self
    }
    /// Changes ay state (on/off)
    pub fn ay(&mut self, state: bool) -> &mut Self {
        self.ay_enabled = state;
        self
    }
    /// Changes beeper state (on/off)
    pub fn beeper(&mut self, state: bool) -> &mut Self {
        self.beeper_enabled = state;
        self
    }
    /// changes sound flag
    pub fn sound(&mut self, state: bool) -> &mut Self {
        self.sound_enabled = state;
        self
    }

    /// Changes volume
    pub fn volume(&mut self, val: usize) -> &mut Self {
        self.volume = if val > 200 { 200 } else { val };
        self
    }
    /// cahnges kempston joy connection
    pub fn kempston(&mut self, value: bool) -> &mut Self {
        self.kempston = value;
        self
    }
    /// changes TAP path
    pub fn tap(&mut self, value: impl AsRef<Path>) -> &mut Self {
        self.tap = Some(value.as_ref().into());
        self
    }
    /// changes SNA path
    pub fn sna(&mut self, value: impl AsRef<Path>) -> &mut Self {
        self.sna = Some(value.as_ref().into());
        self
    }
    /// changes ROM path
    pub fn rom(&mut self, value: impl AsRef<Path>) -> &mut Self {
        self.rom = Some(value.as_ref().into());
        self
    }
    /// changes emulation speed
    pub fn speed(&mut self, value: EmulationSpeed) -> &mut Self {
        self.speed = value;
        self
    }
}
<commit_msg>Fixed compilation errors for clap 3.x<commit_after>use clap::{App, AppSettings, Arg};
use std::path::{Path, PathBuf};
use utils::EmulationSpeed;
use zx::constants::{SCREEN_HEIGHT, SCREEN_WIDTH};
use zx::machine::ZXMachine;
use zx::sound::ay::ZXAYMode;
// TODO: move comand line parsing here

/// Structure to handle all emulator runtime settings
pub struct RustzxSettings {
    pub machine: ZXMachine,
    pub speed: EmulationSpeed,
    pub fastload: bool,
    pub scale: usize,
    pub screen_size: (usize, usize),
    pub kempston: bool,
    pub ay_mode: ZXAYMode,
    pub ay_enabled: bool,
    pub beeper_enabled: bool,
    pub sound_enabled: bool,
    pub volume: usize,
    pub latency: usize,
    pub rom: Option<PathBuf>,
    pub tap: Option<PathBuf>,
    pub sna: Option<PathBuf>,
}

impl RustzxSettings {
    /// constructs new Settings
    pub fn new() -> RustzxSettings {
        RustzxSettings {
            machine: ZXMachine::Sinclair48K,
            speed: EmulationSpeed::Definite(1),
            fastload: false,
            scale: 2,
            screen_size: (SCREEN_WIDTH * 2, SCREEN_HEIGHT * 2),
            kempston: false,
            ay_mode: ZXAYMode::Mono,
            ay_enabled: false,
            beeper_enabled: true,
            sound_enabled: true,
            volume: 100,
            latency: 1024,
            rom: None,
            tap: None,
            sna: None,
        }
    }
    pub fn from_clap() -> RustzxSettings {
        // get defaults
        let mut out = Self::new();
        // parse cli
        let cmd = App::new("rustzx")
            .setting(AppSettings::ColoredHelp)
            .version(env!("CARGO_PKG_VERSION"))
            .author("Vladislav Nikonov <pacmancoder@gmail.com>")
            .about("ZX Spectrum emulator written in pure Rust")
            // machine settings
            .arg(
                Arg::new("128K")
                    .long("128k")
                    .about("Enables ZX Spectrum 128K mode"),
            )
            .arg(
                Arg::new("FASTLOAD")
                    .short('f')
                    .long("fastload")
                    .about("Accelerates standard tape loaders"),
            )
            // media files
            .arg(
                Arg::new("ROM")
                    .long("rom")
                    .value_name("ROM_PATH")
                    .about("Selects path to rom, otherwise default will be used"),
            )
            .arg(
                Arg::new("TAP")
                    .long("tap")
                    .value_name("TAP_PATH")
                    .about("Selects path to *.tap file"),
            )
            .arg(
                Arg::new("SNA")
                    .long("sna")
                    .value_name("SNA_PATH")
                    .about("Selects path to *.sna snapshot file"),
            )
            // devices
            .arg(Arg::new("KEMPSTON").short('k').long("kempston").about(
                "Enables Kempston joystick. Controlls via arrow keys and \
                 Alt buttons",
            ))
            // emulator settings
            .arg(
                Arg::new("SPEED")
                    .long("speed")
                    .value_name("SPEED_VALUE")
                    .about("Selects speed for emulator in integer multiplier form"),
            )
            .arg(
                Arg::new("SCALE")
                    .long("scale")
                    .value_name("SCALE_VALUE")
                    .about(
                        "Selects default screen size. possible values are positive \
                         integers. Default value is 2",
                    ),
            )
            // sound
            .arg(Arg::new("NOSOUND").long("nosound").about(
                "Disables sound. Use it when you have problems with audio \
                 playback",
            ))
            .arg(
                Arg::new("NOBEEPER")
                    .long("nobeeper")
                    .about("Disables beeper"),
            )
            .arg(
                Arg::new("AY")
                    .long("ay")
                    .value_name("AY_TYPE")
                    .possible_values(&["none", "mono", "abc", "acb"])
                    .about(
                        "Selects AY mode. Use none to disable. \
                         For stereo features use abc or acb, default is mono for \
                         128k and none for 48k.",
                    ),
            )
            .arg(
                Arg::new("VOLUME")
                    .long("volume")
                    .value_name("VOLUME_VALUE")
                    .about(
                        "Selects volume - value in range 0..200. Volume over 100 \
                         can cause sound artifacts",
                    ),
            )
            .arg(
                Arg::new("LATENCY")
                    .long("latency")
                    .short('l')
                    .value_name("SAMPLES")
                    .about(
                        "Selects audio latency. Default is 1024 samples. Set higher \
                         latency if emulator have sound glitches. Or if your \
                         machine can handle this - try to set it lower. Must be \
                         power of two.",
                    ),
            )
            .get_matches();
        // machine type
        if cmd.is_present("128K") {
            out.machine(ZXMachine::Sinclair128K);
        }
        if let Some(speed_str) = cmd.value_of("SPEED") {
            if let Ok(speed) = speed_str.parse::<usize>() {
                out.speed(EmulationSpeed::Definite(speed));
            }
        };
        if let Some(scale_str) = cmd.value_of("SCALE") {
            if let Ok(scale) = scale_str.parse::<usize>() {
                out.scale(scale);
            } else {
                println!("[Warning] Invalid scale factor");
            };
        }
        out.fastload(cmd.is_present("FASTLOAD"))
            .beeper(!cmd.is_present("NOBEEPER"))
            .sound(!cmd.is_present("NOSOUND"))
            .kempston(cmd.is_present("KEMPSTON"));
        if let Some(path) = cmd.value_of_os("ROM") {
            if Path::new(path).is_file() {
                out.rom(path);
            } else {
                println!(
                    "[Warning] ROM file \"{}\" not found",
                    path.to_string_lossy()
                );
            }
        }
        if let Some(path) = cmd.value_of_os("TAP") {
            if Path::new(path).is_file() {
                out.tap(path);
            } else {
                println!(
                    "[Warning] Tape file \"{}\" not found",
                    path.to_string_lossy()
                );
            }
        }
        if let Some(path) = cmd.value_of_os("SNA") {
            if out.machine == ZXMachine::Sinclair48K {
                if Path::new(path).is_file() {
                    out.sna(path);
                } else {
                    println!(
                        "[Warning] Snapshot file \"{}\" not found",
                        path.to_string_lossy()
                    );
                }
            } else {
                println!("[Warning] 128K SNA is not supported!");
            }
        }
        if let Some(value) = cmd.value_of("AY") {
            match value {
                "none" => out.ay(false),
                "mono" => out.ay_mode(ZXAYMode::Mono),
                "abc" => out.ay_mode(ZXAYMode::ABC),
                "acb" => out.ay_mode(ZXAYMode::ACB),
                _ => unreachable!(),
            };
        };
        if let Some(value) = cmd.value_of("VOLUME") {
            if let Ok(value) = value.parse::<usize>() {
                out.volume(value);
            } else {
                println!("[Warning] Volume value is incorrect, setting volume to 100");
            }
        };
        if let Some(latency_str) = cmd.value_of("LATENCY") {
            if let Ok(latency) = latency_str.parse::<usize>() {
                out.latency(latency);
            }
        };
        out
    }
    /// Changes machine type
    pub fn machine(&mut self, machine: ZXMachine) -> &mut Self {
        self.machine = machine;
        match machine {
            ZXMachine::Sinclair48K => self.ay_enabled = false,
            ZXMachine::Sinclair128K => self.ay_enabled = true,
        }
        self
    }
    /// changes screen scale
    pub fn scale(&mut self, scale: usize) -> &mut Self {
        // place into bounds
        if scale > 5 {
            self.scale = 2;
        } else {
            self.scale = scale;
        }
        self.screen_size = (SCREEN_WIDTH * self.scale, SCREEN_HEIGHT * self.scale);
        self
    }
    /// changes fastload flag
    pub fn fastload(&mut self, value: bool) -> &mut Self {
        self.fastload = value;
        self
    }
    /// changes lound latency
    pub fn latency(&mut self, latency: usize) -> &mut Self {
        self.latency = latency;
        self
    }
    /// Changes AY chip mode
    pub fn ay_mode(&mut self, mode: ZXAYMode) -> &mut Self {
        self.ay_enabled = true;
        self.ay_mode = mode;
        self
    }
    /// Changes ay state (on/off)
    pub fn ay(&mut self, state: bool) -> &mut Self {
        self.ay_enabled = state;
        self
    }
    /// Changes beeper state (on/off)
    pub fn beeper(&mut self, state: bool) -> &mut Self {
        self.beeper_enabled = state;
        self
    }
    /// changes sound flag
    pub fn sound(&mut self, state: bool) -> &mut Self {
        self.sound_enabled = state;
        self
    }

    /// Changes volume
    pub fn volume(&mut self, val: usize) -> &mut Self {
        self.volume = if val > 200 { 200 } else { val };
        self
    }
    /// cahnges kempston joy connection
    pub fn kempston(&mut self, value: bool) -> &mut Self {
        self.kempston = value;
        self
    }
    /// changes TAP path
    pub fn tap(&mut self, value: impl AsRef<Path>) -> &mut Self {
        self.tap = Some(value.as_ref().into());
        self
    }
    /// changes SNA path
    pub fn sna(&mut self, value: impl AsRef<Path>) -> &mut Self {
        self.sna = Some(value.as_ref().into());
        self
    }
    /// changes ROM path
    pub fn rom(&mut self, value: impl AsRef<Path>) -> &mut Self {
        self.rom = Some(value.as_ref().into());
        self
    }
    /// changes emulation speed
    pub fn speed(&mut self, value: EmulationSpeed) -> &mut Self {
        self.speed = value;
        self
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2014 Robert Clipsham <robert@octarineparrot.com>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

extern crate libc;

use std::collections::{RingBuf};
use std::cmp;
use std::ffi::CString;
use std::old_io::{IoResult, IoError};
use std::iter::repeat;
use std::mem;
use std::sync::Arc;

use bindings::bpf;
use old_packet::Packet;
use old_packet::ethernet::{EthernetHeader, MutableEthernetHeader};
use datalink::DataLinkChannelType;
use datalink::DataLinkChannelType::{Layer2, Layer3};
use internal;
use util::NetworkInterface;

// NOTE buffer must be word aligned.
pub fn datalink_channel(network_interface: &NetworkInterface,
                        write_buffer_size: usize,
                        read_buffer_size: usize,
                        channel_type: DataLinkChannelType)
    -> IoResult<(DataLinkSenderImpl, DataLinkReceiverImpl)> {
    #[cfg(target_os = "freebsd")]
    fn get_fd() -> libc::c_int {
        unsafe {
            libc::open(CString::from_slice("/dev/bpf").as_ptr(), libc::O_RDWR, 0)
        }
    }

    #[cfg(target_os = "macos")]
    fn get_fd() -> libc::c_int {
        // FIXME This is an arbitrary number of attempts
        for i in range(0, 1_000is) {
            let fd = unsafe {
                let file_name = format!("/dev/bpf{}", i);
                libc::open(CString::from_slice(file_name.as_bytes()).as_ptr(), libc::O_RDWR, 0)
            };
            if fd != -1 {
                return fd;
            }
        }
        return -1;
    }

    #[cfg(target_os = "freebsd")]
    fn set_feedback(fd: libc::c_int) -> Result<(), IoError> {
        let one: libc::c_uint = 1;
        if unsafe { bpf::ioctl(fd, bpf::BIOCFEEDBACK, &one) } == -1 {
            let err = IoError::last_error();
            unsafe { libc::close(fd); }
            return Err(err);
        }
        Ok(())
    }

    #[cfg(target_os = "macos")]
    fn set_feedback(_fd: libc::c_int) -> Result<(), IoError> {
        Ok(())
    }

    match channel_type {
        Layer2 => (),
        Layer3(_) => unimplemented!(),
    }

    let fd = get_fd();
    if fd == -1 {
        return Err(IoError::last_error());
    }
    let mut iface: bpf::ifreq = unsafe { mem::zeroed() };
    let mut i = 0;
    for c in network_interface.name.as_slice().bytes() {
        iface.ifr_name[i] = c as i8;
        i += 1;
    }

    let buflen = read_buffer_size as libc::c_uint;
    // NOTE Buffer length must be set before binding to an interface
    //      otherwise this will return Invalid Argument
    if unsafe { bpf::ioctl(fd, bpf::BIOCSBLEN, &buflen) } == -1 {
        let err = IoError::last_error();
        unsafe { libc::close(fd); }
        return Err(err);
    }

    // Set the interface to use
    if unsafe { bpf::ioctl(fd, bpf::BIOCSETIF, &iface) } == -1 {
        let err = IoError::last_error();
        unsafe { libc::close(fd); }
        return Err(err);
    }

    // Return from read as soon as packets are available - don't wait to fill the buffer
    let one: libc::c_uint = 1;
    if unsafe { bpf::ioctl(fd, bpf::BIOCIMMEDIATE, &one) } == -1 {
        let err = IoError::last_error();
        unsafe { libc::close(fd); }
        return Err(err);
    }

    let mut header_size = 0;

    // Get the device type
    let mut dlt: libc::c_uint = 0;
    if unsafe { bpf::ioctl(fd, bpf::BIOCGDLT, &mut dlt) } == -1 {
        let err = IoError::last_error();
        unsafe { libc::close(fd); }
        return Err(err);
    }

    // The loopback IoError::last_error()device does weird things
    // FIXME This should really just be another L2 packet header type
    if dlt == bpf::DLT_NULL {
        header_size = 4;

        // Allow packets to be read back after they are written
        match set_feedback(fd) {
            Err(e) => return Err(e),
            _ => ()
        }

    } else {
        // Don't fill in source MAC
        if unsafe { bpf::ioctl(fd, bpf::BIOCSHDRCMPLT, &one) } == -1 {
            let err = IoError::last_error();
            unsafe { libc::close(fd); }
            return Err(err);
        }
    }

    let fd = Arc::new(internal::FileDesc { fd: fd });
    let sender = DataLinkSenderImpl {
        fd: fd.clone(),
        write_buffer: repeat(0u8).take(write_buffer_size).collect(),
        header_size: header_size,
    };
    let receiver = DataLinkReceiverImpl {
        fd: fd,
        read_buffer: repeat(0u8).take(read_buffer_size).collect(),
        header_size: header_size,
    };

    Ok((sender, receiver))
}

pub struct DataLinkSenderImpl {
    fd: Arc<internal::FileDesc>,
    write_buffer: Vec<u8>,
    header_size: usize,
}

impl DataLinkSenderImpl {
    pub fn build_and_send<F>(&mut self, num_packets: usize, packet_size: usize,
                          func: &mut F) -> Option<IoResult<()>>
        where F : FnMut(MutableEthernetHeader)
    {
        let len = num_packets * (packet_size + self.header_size);
        if len >= self.write_buffer.len() {
            None
        } else {
            let min = cmp::min(self.write_buffer.len(), len);
            for chunk in self.write_buffer[..min]
                                          .chunks_mut(packet_size + self.header_size) {
                // If we're sending on the loopback device, the first 4 bytes must be set to
                // AF_INET
                if self.header_size == 4 {
                    unsafe {
                        *(chunk.as_mut_ptr() as *mut u32) = libc::AF_INET as u32;
                    }
                }
                {
                    let eh = MutableEthernetHeader::new(&mut chunk[self.header_size..]);
                    func(eh);
                }
                match unsafe { libc::write(self.fd.fd,
                                           chunk.as_ptr() as *const libc::c_void,
                                           chunk.len() as libc::size_t) } {
                    len if len == -1 => return Some(Err(IoError::last_error())),
                    _ => ()
                }
            }
            Some(Ok(()))
        }
    }

    pub fn send_to(&mut self, packet: EthernetHeader, _dst: Option<NetworkInterface>)
        -> Option<IoResult<()>> {
        match unsafe { libc::write(self.fd.fd,
                                   packet.packet().as_ptr() as *const libc::c_void,
                                   packet.packet().len() as libc::size_t) } {
            len if len == -1 => Some(Err(IoError::last_error())),
            _ => Some(Ok(()))
        }
    }
}

pub struct DataLinkReceiverImpl {
    fd: Arc<internal::FileDesc>,
    read_buffer: Vec<u8>,
    header_size: usize,
}

impl DataLinkReceiverImpl {
    pub fn iter<'a>(&'a mut self) -> DataLinkChannelIteratorImpl<'a> {
        let buflen = self.read_buffer.len();
        DataLinkChannelIteratorImpl {
            pc: self,
            // Enough room for minimally sized packets without reallocating
            packets: RingBuf::with_capacity(buflen / 64)
        }
    }
}

pub struct DataLinkChannelIteratorImpl<'a> {
    pc: &'a mut DataLinkReceiverImpl,
    packets: RingBuf<(usize, usize)>,
}

impl<'a> DataLinkChannelIteratorImpl<'a> {
    pub fn next<'c>(&'c mut self) -> IoResult<EthernetHeader<'c>> {
        if self.packets.is_empty() {
            let buflen = match unsafe {
                libc::read(self.pc.fd.fd,
                           self.pc.read_buffer.as_ptr() as *mut libc::c_void,
                           self.pc.read_buffer.len() as libc::size_t)
            } {
                len if len > 0 => len,
                _ => return Err(IoError::last_error())
            };
            let mut ptr = self.pc.read_buffer.as_mut_ptr();
            let end = unsafe { self.pc.read_buffer.as_ptr().offset(buflen as isize) };
            while (ptr as *const u8) < end {
                unsafe {
                    let packet: *const bpf::bpf_hdr = mem::transmute(ptr);
                    let start = ptr as isize +
                                (*packet).bh_hdrlen as isize -
                                self.pc.read_buffer.as_ptr() as isize;
                    self.packets.push_back((start as usize + self.pc.header_size,
                                      (*packet).bh_caplen as usize - self.pc.header_size));
                    let offset = (*packet).bh_hdrlen as isize + (*packet).bh_caplen as isize;
                    ptr = ptr.offset(bpf::BPF_WORDALIGN(offset));
                }
            }
        }
        let (start, len) = self.packets.pop_front().unwrap();
        Ok(EthernetHeader::new(&self.pc.read_buffer[start .. start + len]))
    }
}

<commit_msg>Fix OS X build.<commit_after>// Copyright (c) 2014 Robert Clipsham <robert@octarineparrot.com>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

extern crate libc;

use std::collections::{VecDeque};
use std::cmp;
use std::ffi::CString;
use std::old_io::{IoResult, IoError};
use std::iter::repeat;
use std::mem;
use std::sync::Arc;

use bindings::bpf;
use old_packet::Packet;
use old_packet::ethernet::{EthernetHeader, MutableEthernetHeader};
use datalink::DataLinkChannelType;
use datalink::DataLinkChannelType::{Layer2, Layer3};
use internal;
use util::NetworkInterface;

// NOTE buffer must be word aligned.
pub fn datalink_channel(network_interface: &NetworkInterface,
                        write_buffer_size: usize,
                        read_buffer_size: usize,
                        channel_type: DataLinkChannelType)
    -> IoResult<(DataLinkSenderImpl, DataLinkReceiverImpl)> {
    #[cfg(target_os = "freebsd")]
    fn get_fd() -> libc::c_int {
        unsafe {
            libc::open(CString::from_slice("/dev/bpf").as_ptr(), libc::O_RDWR, 0)
        }
    }

    #[cfg(target_os = "macos")]
    fn get_fd() -> libc::c_int {
        // FIXME This is an arbitrary number of attempts
        for i in range(0, 1_000is) {
            let fd = unsafe {
                let file_name = format!("/dev/bpf{}", i);
                libc::open(CString::from_slice(file_name.as_bytes()).as_ptr(), libc::O_RDWR, 0)
            };
            if fd != -1 {
                return fd;
            }
        }
        return -1;
    }

    #[cfg(target_os = "freebsd")]
    fn set_feedback(fd: libc::c_int) -> Result<(), IoError> {
        let one: libc::c_uint = 1;
        if unsafe { bpf::ioctl(fd, bpf::BIOCFEEDBACK, &one) } == -1 {
            let err = IoError::last_error();
            unsafe { libc::close(fd); }
            return Err(err);
        }
        Ok(())
    }

    #[cfg(target_os = "macos")]
    fn set_feedback(_fd: libc::c_int) -> Result<(), IoError> {
        Ok(())
    }

    match channel_type {
        Layer2 => (),
        Layer3(_) => unimplemented!(),
    }

    let fd = get_fd();
    if fd == -1 {
        return Err(IoError::last_error());
    }
    let mut iface: bpf::ifreq = unsafe { mem::zeroed() };
    let mut i = 0;
    for c in network_interface.name.as_slice().bytes() {
        iface.ifr_name[i] = c as i8;
        i += 1;
    }

    let buflen = read_buffer_size as libc::c_uint;
    // NOTE Buffer length must be set before binding to an interface
    //      otherwise this will return Invalid Argument
    if unsafe { bpf::ioctl(fd, bpf::BIOCSBLEN, &buflen) } == -1 {
        let err = IoError::last_error();
        unsafe { libc::close(fd); }
        return Err(err);
    }

    // Set the interface to use
    if unsafe { bpf::ioctl(fd, bpf::BIOCSETIF, &iface) } == -1 {
        let err = IoError::last_error();
        unsafe { libc::close(fd); }
        return Err(err);
    }

    // Return from read as soon as packets are available - don't wait to fill the buffer
    let one: libc::c_uint = 1;
    if unsafe { bpf::ioctl(fd, bpf::BIOCIMMEDIATE, &one) } == -1 {
        let err = IoError::last_error();
        unsafe { libc::close(fd); }
        return Err(err);
    }

    let mut header_size = 0;

    // Get the device type
    let mut dlt: libc::c_uint = 0;
    if unsafe { bpf::ioctl(fd, bpf::BIOCGDLT, &mut dlt) } == -1 {
        let err = IoError::last_error();
        unsafe { libc::close(fd); }
        return Err(err);
    }

    // The loopback IoError::last_error()device does weird things
    // FIXME This should really just be another L2 packet header type
    if dlt == bpf::DLT_NULL {
        header_size = 4;

        // Allow packets to be read back after they are written
        match set_feedback(fd) {
            Err(e) => return Err(e),
            _ => ()
        }

    } else {
        // Don't fill in source MAC
        if unsafe { bpf::ioctl(fd, bpf::BIOCSHDRCMPLT, &one) } == -1 {
            let err = IoError::last_error();
            unsafe { libc::close(fd); }
            return Err(err);
        }
    }

    let fd = Arc::new(internal::FileDesc { fd: fd });
    let sender = DataLinkSenderImpl {
        fd: fd.clone(),
        write_buffer: repeat(0u8).take(write_buffer_size).collect(),
        header_size: header_size,
    };
    let receiver = DataLinkReceiverImpl {
        fd: fd,
        read_buffer: repeat(0u8).take(read_buffer_size).collect(),
        header_size: header_size,
    };

    Ok((sender, receiver))
}

pub struct DataLinkSenderImpl {
    fd: Arc<internal::FileDesc>,
    write_buffer: Vec<u8>,
    header_size: usize,
}

impl DataLinkSenderImpl {
    pub fn build_and_send<F>(&mut self, num_packets: usize, packet_size: usize,
                          func: &mut F) -> Option<IoResult<()>>
        where F : FnMut(MutableEthernetHeader)
    {
        let len = num_packets * (packet_size + self.header_size);
        if len >= self.write_buffer.len() {
            None
        } else {
            let min = cmp::min(self.write_buffer.len(), len);
            for chunk in self.write_buffer[..min]
                                          .chunks_mut(packet_size + self.header_size) {
                // If we're sending on the loopback device, the first 4 bytes must be set to
                // AF_INET
                if self.header_size == 4 {
                    unsafe {
                        *(chunk.as_mut_ptr() as *mut u32) = libc::AF_INET as u32;
                    }
                }
                {
                    let eh = MutableEthernetHeader::new(&mut chunk[self.header_size..]);
                    func(eh);
                }
                match unsafe { libc::write(self.fd.fd,
                                           chunk.as_ptr() as *const libc::c_void,
                                           chunk.len() as libc::size_t) } {
                    len if len == -1 => return Some(Err(IoError::last_error())),
                    _ => ()
                }
            }
            Some(Ok(()))
        }
    }

    pub fn send_to(&mut self, packet: EthernetHeader, _dst: Option<NetworkInterface>)
        -> Option<IoResult<()>> {
        match unsafe { libc::write(self.fd.fd,
                                   packet.packet().as_ptr() as *const libc::c_void,
                                   packet.packet().len() as libc::size_t) } {
            len if len == -1 => Some(Err(IoError::last_error())),
            _ => Some(Ok(()))
        }
    }
}

pub struct DataLinkReceiverImpl {
    fd: Arc<internal::FileDesc>,
    read_buffer: Vec<u8>,
    header_size: usize,
}

impl DataLinkReceiverImpl {
    pub fn iter<'a>(&'a mut self) -> DataLinkChannelIteratorImpl<'a> {
        let buflen = self.read_buffer.len();
        DataLinkChannelIteratorImpl {
            pc: self,
            // Enough room for minimally sized packets without reallocating
            packets: VecDeque::with_capacity(buflen / 64)
        }
    }
}

pub struct DataLinkChannelIteratorImpl<'a> {
    pc: &'a mut DataLinkReceiverImpl,
    packets: VecDeque<(usize, usize)>,
}

impl<'a> DataLinkChannelIteratorImpl<'a> {
    pub fn next<'c>(&'c mut self) -> IoResult<EthernetHeader<'c>> {
        if self.packets.is_empty() {
            let buflen = match unsafe {
                libc::read(self.pc.fd.fd,
                           self.pc.read_buffer.as_ptr() as *mut libc::c_void,
                           self.pc.read_buffer.len() as libc::size_t)
            } {
                len if len > 0 => len,
                _ => return Err(IoError::last_error())
            };
            let mut ptr = self.pc.read_buffer.as_mut_ptr();
            let end = unsafe { self.pc.read_buffer.as_ptr().offset(buflen as isize) };
            while (ptr as *const u8) < end {
                unsafe {
                    let packet: *const bpf::bpf_hdr = mem::transmute(ptr);
                    let start = ptr as isize +
                                (*packet).bh_hdrlen as isize -
                                self.pc.read_buffer.as_ptr() as isize;
                    self.packets.push_back((start as usize + self.pc.header_size,
                                      (*packet).bh_caplen as usize - self.pc.header_size));
                    let offset = (*packet).bh_hdrlen as isize + (*packet).bh_caplen as isize;
                    ptr = ptr.offset(bpf::BPF_WORDALIGN(offset));
                }
            }
        }
        let (start, len) = self.packets.pop_front().unwrap();
        Ok(EthernetHeader::new(&self.pc.read_buffer[start .. start + len]))
    }
}

<|endoftext|>


<commit_before>// memory debug window
extern crate minifb;
use minifb::*;
use std::io::Write;
use c64;
mod font;

const DEBUG_W: usize = 640;
const DEBUG_H: usize = 416;

pub struct Debugger
{
    debug_window: minifb::Window,
    font: font::SysFont,
    window_buffer: Vec<u32>,
    mempage_offset: u16,
}

impl Debugger
{
    pub fn new() -> Debugger
    {
        Debugger {
            debug_window: Window::new("Debug window", DEBUG_W, DEBUG_H, Scale::X2, Vsync::No).unwrap(),
            font: font::SysFont::new(DEBUG_W, DEBUG_H),
            window_buffer: vec![0; DEBUG_W * DEBUG_H],
            mempage_offset: 0,
        }
    }

    pub fn render(&mut self, memory: &mut c64::memory::MemShared)
    {
        if self.debug_window.is_key_pressed(Key::F9, KeyRepeat::No)
        {
            self.mempage_offset += 0x400;
            if self.mempage_offset > 0x3C00 { self.mempage_offset = 0; }
        }
        // dump screen memory
        let mut start = 0x0000 + self.mempage_offset;

        let mut title = Vec::new();
        let _ = write!(&mut title, "Page ${:04x}-${:04x}", start, start + 0x400);
        self.font.draw_text(&mut self.window_buffer, 0, 0, &String::from_utf8(title).unwrap().to_owned()[..], 0x0A);
        let mut hex_offset_x = 0;
        let mut hex_offset_y = 27;
        for y in 0..25
        {
            for x in 0..40
            {
                let byte = memory.borrow_mut().get_ram_bank(c64::memory::MemType::RAM).read(start);
                self.font.draw_char(&mut self.window_buffer, 8*x as usize, 8 + 8*y as usize, byte, 0x05);

                let mut hex_value = Vec::new();
                let _ = write!(&mut hex_value, "{:02X}", byte);

                //let mut hex_color: u32 = (2*byte as u32) << 16;
                //hex_color |= (byte as u32) << 8;
                //hex_color |= byte as u32;
                //if hex_color < 0x00222222 { hex_color = 0x00222222; }

                self.font.draw_text(&mut self.window_buffer, hex_offset_x + x as usize, hex_offset_y + y as usize, &String::from_utf8(hex_value).unwrap().to_owned()[..], byte);
                hex_offset_x += 1;
                start += 1;
            }

            hex_offset_x = 0;
        }

        self.debug_window.update(&self.window_buffer);
    }
}
<commit_msg>[debug] added more diagnostic info<commit_after>// memory debug window
extern crate minifb;
use minifb::*;
use std::io::Write;
use c64;
use utils;
mod font;

const DEBUG_W: usize = 640;
const DEBUG_H: usize = 416;

pub struct Debugger
{
    debug_window: minifb::Window,
    font: font::SysFont,
    window_buffer: Vec<u32>,
    mempage_offset: u16,
}

impl Debugger
{
    pub fn new() -> Debugger
    {
        Debugger {
            debug_window: Window::new("Debug window", DEBUG_W, DEBUG_H, Scale::X2, Vsync::No).unwrap(),
            font: font::SysFont::new(DEBUG_W, DEBUG_H),
            window_buffer: vec![0; DEBUG_W * DEBUG_H],
            mempage_offset: 0,
        }
    }

    pub fn render(&mut self, memory: &mut c64::memory::MemShared)
    {
        if self.debug_window.is_key_pressed(Key::PageUp, KeyRepeat::Yes)
        {
            self.mempage_offset += 0x400;
            if self.mempage_offset > 0xFC00 { self.mempage_offset = 0; }
        }

        if self.debug_window.is_key_pressed(Key::PageDown, KeyRepeat::Yes)
        {
            if self.mempage_offset == 0x0000 { self.mempage_offset = 0x10000; }
            self.mempage_offset -= 0x400;
        }

        // dump memory page to screen
        let mut start = 0x0000 + self.mempage_offset;

        let mut title = Vec::new();
        let _ = write!(&mut title, "Page ${:04x}-${:04x}", start, start + 0x3FF);
        self.font.draw_text(&mut self.window_buffer, 0, 0, &String::from_utf8(title).unwrap().to_owned()[..], 0x0A);
        let mut hex_offset_x = 0;
        let mut hex_offset_y = 27;
        for y in 0..25
        {
            for x in 0..40
            {
                let byte = memory.borrow_mut().get_ram_bank(c64::memory::MemType::RAM).read(start);
                self.font.draw_char(&mut self.window_buffer, 8*x as usize, 8 + 8*y as usize, byte, 0x05);

                self.draw_hex(hex_offset_x + x as usize, hex_offset_y + y as usize, byte);
                hex_offset_x += 1;
                start += 1;
            }

            hex_offset_x = 0;
        }

        self.draw_registers(memory);

        self.debug_window.update(&self.window_buffer);
    }

    fn draw_hex(&mut self, x_pos: usize, y_pos: usize, byte: u8 )
    {
        let mut hex_value = Vec::new();
        let _ = write!(&mut hex_value, "{:02X}", byte);

        let mut base_color = utils::fetch_c64_color_rgba(byte >> 4);
        if base_color == 0 { base_color = 0x00333333; }
        //self.set_saturation(&mut base_color, (byte >> 4) as f64 / 15.0);

        // all black? make it at least somewhat visible
        if byte == 0 { base_color = 0x00101010; }

        self.font.draw_text_rgb(&mut self.window_buffer, x_pos, y_pos, &String::from_utf8(hex_value).unwrap().to_owned()[..], base_color);
    }

    fn draw_registers(&mut self, memory: &mut c64::memory::MemShared)
    {
        let d018 = memory.borrow_mut().get_ram_bank(c64::memory::MemType::IO).read(0xD018);
        let dd00 = memory.borrow_mut().get_ram_bank(c64::memory::MemType::IO).read(0xDD00);

        let mut vmatrix_txt = Vec::new();
        let mut char_txt = Vec::new();
        let mut bmp_txt = Vec::new();
        let mut bank_txt = Vec::new();
        let _ = write!(&mut vmatrix_txt, "  Screen: ${:04X}", (((d018 >> 4) & 0xF) as u16) * 0x400);
        let _ = write!(&mut char_txt, "    Char: ${:04X}", (((d018 >> 1) & 0x07) as u16) * 0x800);
        let _ = write!(&mut bmp_txt, "  Bitmap: ${:04X}", (((d018 >> 3) & 0x01) as u16) * 0x2000);
        let _ = write!(&mut bank_txt, "VIC bank: ${:04X}", dd00);
        self.font.draw_text(&mut self.window_buffer, 41, 1, &String::from_utf8(vmatrix_txt).unwrap().to_owned()[..], 0x0A);
        self.font.draw_text(&mut self.window_buffer, 41, 2, &String::from_utf8(char_txt).unwrap().to_owned()[..], 0x0A);
        self.font.draw_text(&mut self.window_buffer, 41, 3, &String::from_utf8(bmp_txt).unwrap().to_owned()[..], 0x0A);
        self.font.draw_text(&mut self.window_buffer, 41, 4, &String::from_utf8(bank_txt).unwrap().to_owned()[..], 0x0A);
    }

    fn set_saturation(&self, color: &mut u32, change: f64)
    {
        let Pr = 0.299;
        let Pg = 0.587;
        let Pb = 0.114;
        let mut r = ((*color >> 16) & 0xFF) as f64;
        let mut g = ((*color >> 8) & 0xFF) as f64;
        let mut b = (*color & 0xFF) as f64;

        let P = ((r*r*Pr + g*g*Pg + b*b*Pb) as f64).sqrt();

        r = P + (r - P) * change;
        g = P + (g - P) * change;
        b = P + (b - P) * change;

        *color = (r as u32) << 16;
        *color |= (g as u32) << 8;
        *color |= b as u32;
    }
}
<|endoftext|>


<commit_before>use super::{CellId, Mesh, PointId};
use crate::shapes::Shape;
use crate::StrError;
use russell_lab::{sort2, sort4};
use std::collections::HashMap;

/// Aliases (usize,usize) as the key of edges
///
/// # Note
///
/// Since the local numbering scheme runs over "corners" first, we can compare
/// edges using only two points; i.e., the middle points don't matter.
pub type EdgeKey = (usize, usize);

/// Aliases (usize,usize,usize,usize) as the key of faces
///
/// # Note
///
/// If a face has at most 3 points, the fourth entry in the key will be set to the total number of points.
/// In this way, we can compare 4-node (or more nodes) faces with each other. Since the local numbering
/// scheme runs over the "corners" first, the middle points don't matter.
pub type FaceKey = (usize, usize, usize, usize);

/// Holds the point ids of an edge (an entity belonging to a solid cell in 2D or a face in 3D)
#[derive(Clone, Debug)]
pub struct Edge {
    /// List of points defining this edge; in the right order (unsorted)
    pub points: Vec<PointId>,
}

/// Holds the point ids of a face (an entity belonging to a solid cell in 3D)
#[derive(Clone, Debug)]
pub struct Face {
    /// List of points defining this face; in the right order (unsorted)
    pub points: Vec<PointId>,
}

/// Extracts all edges (internal and boundary) in 2D
///
/// # Input
///
/// * `mesh` -- the Mesh
/// * `shapes` -- the shapes of cells (len == cells.len())
///
/// # Output
///
/// * Returns a map relating edge keys to `Vec<(cell_id, e)>` where:
///     - `cell_id` -- the id of the cell sharing the edge
///     - `e` -- is the cell's local edge index
pub fn all_edges_2d(mesh: &Mesh, shapes: &Vec<Shape>) -> Result<HashMap<EdgeKey, Vec<(CellId, usize)>>, StrError> {
    if mesh.space_ndim != 2 {
        return Err("this function works in 2D only");
    }
    let mut edges: HashMap<EdgeKey, Vec<(CellId, usize)>> = HashMap::new();
    mesh.cells.iter().zip(shapes).for_each(|(cell, shape)| {
        if shape.geo_ndim == 2 {
            for e in 0..shape.nedge {
                let mut edge_key: EdgeKey = (
                    cell.points[shape.edge_node_id(e, 0)],
                    cell.points[shape.edge_node_id(e, 1)],
                );
                sort2(&mut edge_key);
                let data = edges.entry(edge_key).or_insert(Vec::new());
                data.push((cell.id, e));
            }
        }
    });
    Ok(edges)
}

/// Extracts all faces (internal and boundary) in 3D
///
/// # Input
///
/// * `mesh` -- the Mesh
/// * `shapes` -- the shapes of cells (len == cells.len())
///
/// # Output
///
/// * Returns a map relating face keys to `Vec<(cell_id, f)>` where:
///     - `cell_id` -- the id of the cell sharing the face
///     - `f` -- is the cell's local face index
pub fn all_faces_3d(mesh: &Mesh, shapes: &Vec<Shape>) -> Result<HashMap<FaceKey, Vec<(CellId, usize)>>, StrError> {
    if mesh.space_ndim != 3 {
        return Err("this function works in 3D only");
    }
    let mut faces: HashMap<FaceKey, Vec<(CellId, usize)>> = HashMap::new();
    mesh.cells.iter().zip(shapes).for_each(|(cell, shape)| {
        if shape.geo_ndim == 3 {
            for f in 0..shape.nface {
                let mut face_key: FaceKey = if shape.face_nnode > 3 {
                    (
                        cell.points[shape.face_node_id(f, 0)],
                        cell.points[shape.face_node_id(f, 1)],
                        cell.points[shape.face_node_id(f, 2)],
                        cell.points[shape.face_node_id(f, 3)],
                    )
                } else {
                    (
                        cell.points[shape.face_node_id(f, 0)],
                        cell.points[shape.face_node_id(f, 1)],
                        cell.points[shape.face_node_id(f, 2)],
                        mesh.points.len(),
                    )
                };
                sort4(&mut face_key);
                let data = faces.entry(face_key).or_insert(Vec::new());
                data.push((cell.id, f));
            }
        }
    });
    Ok(faces)
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#[cfg(test)]
mod tests {
    use super::{all_edges_2d, all_faces_3d, Edge, Face};
    use crate::mesh::{allocate_shapes, Mesh, Samples};
    use crate::StrError;

    #[test]
    fn capture_some_wrong_input() {
        let mesh = Mesh {
            space_ndim: 1,
            points: Vec::new(),
            cells: Vec::new(),
        };
        assert_eq!(
            all_edges_2d(&mesh, &Vec::new()).err(),
            Some("this function works in 2D only")
        );
        assert_eq!(
            all_faces_3d(&mesh, &Vec::new()).err(),
            Some("this function works in 3D only")
        );
    }

    #[test]
    fn all_edges_2d_works() -> Result<(), StrError> {
        //  3---------2---------5
        //  |         |         |
        //  |   [0]   |   [1]   |
        //  |         |         |
        //  0---------1---------4
        let mesh = Samples::two_quads_horizontal();
        let shapes = allocate_shapes(&mesh)?;
        let edges = all_edges_2d(&mesh, &shapes)?;
        let mut keys: Vec<_> = edges.keys().collect();
        keys.sort();
        assert_eq!(keys, [&(0, 1), &(0, 3), &(1, 2), &(1, 4), &(2, 3), &(2, 5), &(4, 5)]);
        assert_eq!(edges.get(&(0, 1)).unwrap(), &[(0, 0)]);
        assert_eq!(edges.get(&(0, 3)).unwrap(), &[(0, 3)]);
        assert_eq!(edges.get(&(1, 2)).unwrap(), &[(0, 1), (1, 3)]);
        assert_eq!(edges.get(&(1, 4)).unwrap(), &[(1, 0)]);
        assert_eq!(edges.get(&(2, 3)).unwrap(), &[(0, 2)]);
        assert_eq!(edges.get(&(2, 5)).unwrap(), &[(1, 2)]);
        assert_eq!(edges.get(&(4, 5)).unwrap(), &[(1, 1)]);
        Ok(())
    }

    #[test]
    fn all_edges_2d_mixed_works() -> Result<(), StrError> {
        //           4---------3
        //           |         |
        //           |   [1]   |
        //           |         |
        //  0--------1---------2
        let mesh = Samples::mixed_shapes_2d();
        let shapes = allocate_shapes(&mesh)?;
        let edges = all_edges_2d(&mesh, &shapes)?;
        let mut keys: Vec<_> = edges.keys().collect();
        keys.sort();
        assert_eq!(keys, [&(1, 2), &(1, 4), &(2, 3), &(3, 4)]);
        assert_eq!(edges.get(&(1, 2)).unwrap(), &[(1, 0)]);
        assert_eq!(edges.get(&(1, 4)).unwrap(), &[(1, 3)]);
        assert_eq!(edges.get(&(2, 3)).unwrap(), &[(1, 1)]);
        assert_eq!(edges.get(&(3, 4)).unwrap(), &[(1, 2)]);
        Ok(())
    }

    #[test]
    fn all_faces_3d_works() -> Result<(), StrError> {
        //      8-------------11
        //     /.             /|
        //    / .            / |
        //   /  .           /  |
        //  /   .          /   |       id = 1
        // 9-------------10    |       attribute_id = 2
        // |    .         |    |
        // |    4---------|----7
        // |   /.         |   /|
        // |  / .         |  / |
        // | /  .         | /  |
        // |/   .         |/   |
        // 5--------------6    |       id = 0
        // |    .         |    |       attribute_id = 1
        // |    0---------|----3
        // |   /          |   /
        // |  /           |  /
        // | /            | /
        // |/             |/
        // 1--------------2
        let mesh = Samples::two_cubes_vertical();
        let shapes = allocate_shapes(&mesh)?;
        let faces = all_faces_3d(&mesh, &shapes)?;
        let mut keys: Vec<_> = faces.keys().collect();
        keys.sort();
        assert_eq!(
            keys,
            [
                &(0, 1, 2, 3),
                &(0, 1, 4, 5),
                &(0, 3, 4, 7),
                &(1, 2, 5, 6),
                &(2, 3, 6, 7),
                &(4, 5, 6, 7),
                &(4, 5, 8, 9),
                &(4, 7, 8, 11),
                &(5, 6, 9, 10),
                &(6, 7, 10, 11),
                &(8, 9, 10, 11),
            ]
        );
        assert_eq!(faces.get(&(0, 1, 2, 3)).unwrap(), &[(0, 4)]);
        assert_eq!(faces.get(&(0, 1, 4, 5)).unwrap(), &[(0, 2)]);
        assert_eq!(faces.get(&(0, 3, 4, 7)).unwrap(), &[(0, 0)]);
        assert_eq!(faces.get(&(1, 2, 5, 6)).unwrap(), &[(0, 1)]);
        assert_eq!(faces.get(&(2, 3, 6, 7)).unwrap(), &[(0, 3)]);
        assert_eq!(faces.get(&(4, 5, 6, 7)).unwrap(), &[(0, 5), (1, 4)]);
        assert_eq!(faces.get(&(4, 5, 8, 9)).unwrap(), &[(1, 2)]);
        assert_eq!(faces.get(&(4, 7, 8, 11)).unwrap(), &[(1, 0)]);
        assert_eq!(faces.get(&(5, 6, 9, 10)).unwrap(), &[(1, 1)]);
        assert_eq!(faces.get(&(6, 7, 10, 11)).unwrap(), &[(1, 3)]);
        assert_eq!(faces.get(&(8, 9, 10, 11)).unwrap(), &[(1, 5)]);
        Ok(())
    }

    #[test]
    fn all_faces_3d_mixed_works() -> Result<(), StrError> {
        //                       4------------7-----------10
        //                      /.           /|            |
        //                     / .          / |            |
        //                    /  .         /  |            |
        //                   /   .        /   |            |
        //                  5------------6    |            |
        //                  |    .       |`.  |            |
        //                  |    0-------|--`.3------------9
        //                  |   /        |   /`.          /
        //                  |  /         |  /   `.       /
        //                  | /          | /      `.    /
        //                  |/           |/         `. /
        //  12-----11-------1------------2------------8
        //
        let mesh = Samples::mixed_shapes_3d();
        let shapes = allocate_shapes(&mesh)?;
        let faces = all_faces_3d(&mesh, &shapes)?;
        let mut keys: Vec<_> = faces.keys().collect();
        keys.sort();
        assert_eq!(
            keys,
            [
                &(0, 1, 2, 3),
                &(0, 1, 4, 5),
                &(0, 3, 4, 7),
                &(1, 2, 5, 6),
                &(2, 3, 6, 7),
                &(2, 3, 6, 13),
                &(2, 3, 8, 13),
                &(2, 6, 8, 13),
                &(3, 6, 8, 13),
                &(4, 5, 6, 7),
            ]
        );
        assert_eq!(faces.get(&(0, 1, 2, 3)).unwrap(), &[(0, 4)]);
        assert_eq!(faces.get(&(0, 1, 4, 5)).unwrap(), &[(0, 2)]);
        assert_eq!(faces.get(&(0, 3, 4, 7)).unwrap(), &[(0, 0)]);
        assert_eq!(faces.get(&(1, 2, 5, 6)).unwrap(), &[(0, 1)]);
        assert_eq!(faces.get(&(2, 3, 6, 7)).unwrap(), &[(0, 3)]);
        assert_eq!(faces.get(&(2, 3, 6, 13)).unwrap(), &[(1, 0)]);
        assert_eq!(faces.get(&(2, 3, 8, 13)).unwrap(), &[(1, 2)]);
        assert_eq!(faces.get(&(2, 6, 8, 13)).unwrap(), &[(1, 1)]);
        assert_eq!(faces.get(&(3, 6, 8, 13)).unwrap(), &[(1, 3)]);
        assert_eq!(faces.get(&(4, 5, 6, 7)).unwrap(), &[(0, 5)]);
        Ok(())
    }

    #[test]
    fn derive_works() {
        let edge = Edge {
            points: vec![10, 20, 33],
        };
        let face = Face {
            points: vec![1, 2, 3, 4],
        };
        let edge_clone = edge.clone();
        let face_clone = face.clone();
        assert_eq!(format!("{:?}", edge), "Edge { points: [10, 20, 33] }");
        assert_eq!(format!("{:?}", face), "Face { points: [1, 2, 3, 4] }");
        assert_eq!(edge_clone.points.len(), 3);
        assert_eq!(face_clone.points.len(), 4);
    }
}
<commit_msg>Impl type alias for all edges and faces functions<commit_after>use super::{CellId, Mesh, PointId};
use crate::shapes::Shape;
use crate::StrError;
use russell_lab::{sort2, sort4};
use std::collections::HashMap;

/// Aliases (usize,usize) as the key of edges
///
/// # Note
///
/// Since the local numbering scheme runs over "corners" first, we can compare
/// edges using only two points; i.e., the middle points don't matter.
pub type EdgeKey = (usize, usize);

/// Aliases (usize,usize,usize,usize) as the key of faces
///
/// # Note
///
/// If a face has at most 3 points, the fourth entry in the key will be set to the total number of points.
/// In this way, we can compare 4-node (or more nodes) faces with each other. Since the local numbering
/// scheme runs over the "corners" first, the middle points don't matter.
pub type FaceKey = (usize, usize, usize, usize);

/// Holds the point ids of an edge (an entity belonging to a solid cell in 2D or a face in 3D)
#[derive(Clone, Debug)]
pub struct Edge {
    /// List of points defining this edge; in the right order (unsorted)
    pub points: Vec<PointId>,
}

/// Holds the point ids of a face (an entity belonging to a solid cell in 3D)
#[derive(Clone, Debug)]
pub struct Face {
    /// List of points defining this face; in the right order (unsorted)
    pub points: Vec<PointId>,
}

/// Maps edges to cells sharing the edge in (2D only)
pub type EdgesCellsMap2D = HashMap<EdgeKey, Vec<(CellId, usize)>>;

/// Maps faces to cells sharing the face (3D only)
pub type FacesCellsMap3D = HashMap<FaceKey, Vec<(CellId, usize)>>;

/// Extracts all edges (internal and boundary) in 2D
///
/// # Input
///
/// * `mesh` -- the Mesh
/// * `shapes` -- the shapes of cells (len == cells.len())
///
/// # Output
///
/// * Returns a map relating edge keys to `Vec<(cell_id, e)>` where:
///     - `cell_id` -- the id of the cell sharing the edge
///     - `e` -- is the cell's local edge index
pub fn all_edges_2d(mesh: &Mesh, shapes: &Vec<Shape>) -> Result<EdgesCellsMap2D, StrError> {
    if mesh.space_ndim != 2 {
        return Err("this function works in 2D only");
    }
    let mut edges: EdgesCellsMap2D = HashMap::new();
    mesh.cells.iter().zip(shapes).for_each(|(cell, shape)| {
        if shape.geo_ndim == 2 {
            for e in 0..shape.nedge {
                let mut edge_key: EdgeKey = (
                    cell.points[shape.edge_node_id(e, 0)],
                    cell.points[shape.edge_node_id(e, 1)],
                );
                sort2(&mut edge_key);
                let data = edges.entry(edge_key).or_insert(Vec::new());
                data.push((cell.id, e));
            }
        }
    });
    Ok(edges)
}

/// Extracts all faces (internal and boundary) in 3D
///
/// # Input
///
/// * `mesh` -- the Mesh
/// * `shapes` -- the shapes of cells (len == cells.len())
///
/// # Output
///
/// * Returns a map relating face keys to `Vec<(cell_id, f)>` where:
///     - `cell_id` -- the id of the cell sharing the face
///     - `f` -- is the cell's local face index
pub fn all_faces_3d(mesh: &Mesh, shapes: &Vec<Shape>) -> Result<FacesCellsMap3D, StrError> {
    if mesh.space_ndim != 3 {
        return Err("this function works in 3D only");
    }
    let mut faces: FacesCellsMap3D = HashMap::new();
    mesh.cells.iter().zip(shapes).for_each(|(cell, shape)| {
        if shape.geo_ndim == 3 {
            for f in 0..shape.nface {
                let mut face_key: FaceKey = if shape.face_nnode > 3 {
                    (
                        cell.points[shape.face_node_id(f, 0)],
                        cell.points[shape.face_node_id(f, 1)],
                        cell.points[shape.face_node_id(f, 2)],
                        cell.points[shape.face_node_id(f, 3)],
                    )
                } else {
                    (
                        cell.points[shape.face_node_id(f, 0)],
                        cell.points[shape.face_node_id(f, 1)],
                        cell.points[shape.face_node_id(f, 2)],
                        mesh.points.len(),
                    )
                };
                sort4(&mut face_key);
                let data = faces.entry(face_key).or_insert(Vec::new());
                data.push((cell.id, f));
            }
        }
    });
    Ok(faces)
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#[cfg(test)]
mod tests {
    use super::{all_edges_2d, all_faces_3d, Edge, Face};
    use crate::mesh::{allocate_shapes, Mesh, Samples};
    use crate::StrError;

    #[test]
    fn capture_some_wrong_input() {
        let mesh = Mesh {
            space_ndim: 1,
            points: Vec::new(),
            cells: Vec::new(),
        };
        assert_eq!(
            all_edges_2d(&mesh, &Vec::new()).err(),
            Some("this function works in 2D only")
        );
        assert_eq!(
            all_faces_3d(&mesh, &Vec::new()).err(),
            Some("this function works in 3D only")
        );
    }

    #[test]
    fn all_edges_2d_works() -> Result<(), StrError> {
        //  3---------2---------5
        //  |         |         |
        //  |   [0]   |   [1]   |
        //  |         |         |
        //  0---------1---------4
        let mesh = Samples::two_quads_horizontal();
        let shapes = allocate_shapes(&mesh)?;
        let edges = all_edges_2d(&mesh, &shapes)?;
        let mut keys: Vec<_> = edges.keys().collect();
        keys.sort();
        assert_eq!(keys, [&(0, 1), &(0, 3), &(1, 2), &(1, 4), &(2, 3), &(2, 5), &(4, 5)]);
        assert_eq!(edges.get(&(0, 1)).unwrap(), &[(0, 0)]);
        assert_eq!(edges.get(&(0, 3)).unwrap(), &[(0, 3)]);
        assert_eq!(edges.get(&(1, 2)).unwrap(), &[(0, 1), (1, 3)]);
        assert_eq!(edges.get(&(1, 4)).unwrap(), &[(1, 0)]);
        assert_eq!(edges.get(&(2, 3)).unwrap(), &[(0, 2)]);
        assert_eq!(edges.get(&(2, 5)).unwrap(), &[(1, 2)]);
        assert_eq!(edges.get(&(4, 5)).unwrap(), &[(1, 1)]);
        Ok(())
    }

    #[test]
    fn all_edges_2d_mixed_works() -> Result<(), StrError> {
        //           4---------3
        //           |         |
        //           |   [1]   |
        //           |         |
        //  0--------1---------2
        let mesh = Samples::mixed_shapes_2d();
        let shapes = allocate_shapes(&mesh)?;
        let edges = all_edges_2d(&mesh, &shapes)?;
        let mut keys: Vec<_> = edges.keys().collect();
        keys.sort();
        assert_eq!(keys, [&(1, 2), &(1, 4), &(2, 3), &(3, 4)]);
        assert_eq!(edges.get(&(1, 2)).unwrap(), &[(1, 0)]);
        assert_eq!(edges.get(&(1, 4)).unwrap(), &[(1, 3)]);
        assert_eq!(edges.get(&(2, 3)).unwrap(), &[(1, 1)]);
        assert_eq!(edges.get(&(3, 4)).unwrap(), &[(1, 2)]);
        Ok(())
    }

    #[test]
    fn all_faces_3d_works() -> Result<(), StrError> {
        //      8-------------11
        //     /.             /|
        //    / .            / |
        //   /  .           /  |
        //  /   .          /   |       id = 1
        // 9-------------10    |       attribute_id = 2
        // |    .         |    |
        // |    4---------|----7
        // |   /.         |   /|
        // |  / .         |  / |
        // | /  .         | /  |
        // |/   .         |/   |
        // 5--------------6    |       id = 0
        // |    .         |    |       attribute_id = 1
        // |    0---------|----3
        // |   /          |   /
        // |  /           |  /
        // | /            | /
        // |/             |/
        // 1--------------2
        let mesh = Samples::two_cubes_vertical();
        let shapes = allocate_shapes(&mesh)?;
        let faces = all_faces_3d(&mesh, &shapes)?;
        let mut keys: Vec<_> = faces.keys().collect();
        keys.sort();
        assert_eq!(
            keys,
            [
                &(0, 1, 2, 3),
                &(0, 1, 4, 5),
                &(0, 3, 4, 7),
                &(1, 2, 5, 6),
                &(2, 3, 6, 7),
                &(4, 5, 6, 7),
                &(4, 5, 8, 9),
                &(4, 7, 8, 11),
                &(5, 6, 9, 10),
                &(6, 7, 10, 11),
                &(8, 9, 10, 11),
            ]
        );
        assert_eq!(faces.get(&(0, 1, 2, 3)).unwrap(), &[(0, 4)]);
        assert_eq!(faces.get(&(0, 1, 4, 5)).unwrap(), &[(0, 2)]);
        assert_eq!(faces.get(&(0, 3, 4, 7)).unwrap(), &[(0, 0)]);
        assert_eq!(faces.get(&(1, 2, 5, 6)).unwrap(), &[(0, 1)]);
        assert_eq!(faces.get(&(2, 3, 6, 7)).unwrap(), &[(0, 3)]);
        assert_eq!(faces.get(&(4, 5, 6, 7)).unwrap(), &[(0, 5), (1, 4)]);
        assert_eq!(faces.get(&(4, 5, 8, 9)).unwrap(), &[(1, 2)]);
        assert_eq!(faces.get(&(4, 7, 8, 11)).unwrap(), &[(1, 0)]);
        assert_eq!(faces.get(&(5, 6, 9, 10)).unwrap(), &[(1, 1)]);
        assert_eq!(faces.get(&(6, 7, 10, 11)).unwrap(), &[(1, 3)]);
        assert_eq!(faces.get(&(8, 9, 10, 11)).unwrap(), &[(1, 5)]);
        Ok(())
    }

    #[test]
    fn all_faces_3d_mixed_works() -> Result<(), StrError> {
        //                       4------------7-----------10
        //                      /.           /|            |
        //                     / .          / |            |
        //                    /  .         /  |            |
        //                   /   .        /   |            |
        //                  5------------6    |            |
        //                  |    .       |`.  |            |
        //                  |    0-------|--`.3------------9
        //                  |   /        |   /`.          /
        //                  |  /         |  /   `.       /
        //                  | /          | /      `.    /
        //                  |/           |/         `. /
        //  12-----11-------1------------2------------8
        //
        let mesh = Samples::mixed_shapes_3d();
        let shapes = allocate_shapes(&mesh)?;
        let faces = all_faces_3d(&mesh, &shapes)?;
        let mut keys: Vec<_> = faces.keys().collect();
        keys.sort();
        assert_eq!(
            keys,
            [
                &(0, 1, 2, 3),
                &(0, 1, 4, 5),
                &(0, 3, 4, 7),
                &(1, 2, 5, 6),
                &(2, 3, 6, 7),
                &(2, 3, 6, 13),
                &(2, 3, 8, 13),
                &(2, 6, 8, 13),
                &(3, 6, 8, 13),
                &(4, 5, 6, 7),
            ]
        );
        assert_eq!(faces.get(&(0, 1, 2, 3)).unwrap(), &[(0, 4)]);
        assert_eq!(faces.get(&(0, 1, 4, 5)).unwrap(), &[(0, 2)]);
        assert_eq!(faces.get(&(0, 3, 4, 7)).unwrap(), &[(0, 0)]);
        assert_eq!(faces.get(&(1, 2, 5, 6)).unwrap(), &[(0, 1)]);
        assert_eq!(faces.get(&(2, 3, 6, 7)).unwrap(), &[(0, 3)]);
        assert_eq!(faces.get(&(2, 3, 6, 13)).unwrap(), &[(1, 0)]);
        assert_eq!(faces.get(&(2, 3, 8, 13)).unwrap(), &[(1, 2)]);
        assert_eq!(faces.get(&(2, 6, 8, 13)).unwrap(), &[(1, 1)]);
        assert_eq!(faces.get(&(3, 6, 8, 13)).unwrap(), &[(1, 3)]);
        assert_eq!(faces.get(&(4, 5, 6, 7)).unwrap(), &[(0, 5)]);
        Ok(())
    }

    #[test]
    fn derive_works() {
        let edge = Edge {
            points: vec![10, 20, 33],
        };
        let face = Face {
            points: vec![1, 2, 3, 4],
        };
        let edge_clone = edge.clone();
        let face_clone = face.clone();
        assert_eq!(format!("{:?}", edge), "Edge { points: [10, 20, 33] }");
        assert_eq!(format!("{:?}", face), "Face { points: [1, 2, 3, 4] }");
        assert_eq!(edge_clone.points.len(), 3);
        assert_eq!(face_clone.points.len(), 4);
    }
}
<|endoftext|>


<commit_before>use syntax;
use syntax::codemap::DUMMY_SP;
use syntax::ext::base::ExtCtxt;
use syntax::feature_gate::GatedCfg;

/// Create a fake ExtCtxt to perform macro quasiquotes outside of rustc plugins
pub fn with_fake_extctxt<T, F: Fn(&ExtCtxt) -> T>(f: F) -> T {
  let ps = syntax::parse::ParseSess::new();
  let mut fg_cfg = Vec::<GatedCfg>::new();

  let mut cx = syntax::ext::base::ExtCtxt::new(&ps, Vec::new(),
    syntax::ext::expand::ExpansionConfig::default("rust-peg".to_string()),
    &mut fg_cfg
  );

  cx.bt_push(syntax::codemap::ExpnInfo{
    call_site: DUMMY_SP,
    callee: syntax::codemap::NameAndSpan {
      name: "".to_string(),
      format: syntax::codemap::MacroBang,
      span: None,
      allow_internal_unstable: false,
    }
  });

  f(&cx)
}
<commit_msg>Update NameAndSpan after rustc refactor<commit_after>use syntax;
use syntax::codemap::DUMMY_SP;
use syntax::ext::base::ExtCtxt;
use syntax::feature_gate::GatedCfg;

/// Create a fake ExtCtxt to perform macro quasiquotes outside of rustc plugins
pub fn with_fake_extctxt<T, F: Fn(&ExtCtxt) -> T>(f: F) -> T {
  let ps = syntax::parse::ParseSess::new();
  let mut fg_cfg = Vec::<GatedCfg>::new();

  let mut cx = syntax::ext::base::ExtCtxt::new(&ps, Vec::new(),
    syntax::ext::expand::ExpansionConfig::default("rust-peg".to_string()),
    &mut fg_cfg
  );

  cx.bt_push(syntax::codemap::ExpnInfo{
    call_site: DUMMY_SP,
    callee: syntax::codemap::NameAndSpan {
      format: syntax::codemap::MacroBang(syntax::parse::token::intern("")),
      span: None,
      allow_internal_unstable: false,
    }
  });

  f(&cx)
}
<|endoftext|>


<commit_before>extern crate sfunc;

use std::rand::Rng;
use std::rand::distributions::{Normal, IndependentSample};

/// A Gaussian distribution.
pub struct Gaussian {
    /// The mean value.
    pub mu: f64,
    /// The standard deviation.
    pub sigma: f64,

    normal: Normal,
}

impl Gaussian {
    /// Create a Gaussian distribution with the mean value `mu` and standard
    /// deviation `sigma`.
    #[inline]
    pub fn new(mu: f64, sigma: f64) -> Gaussian {
        Gaussian {
            mu: mu,
            sigma: sigma,
            normal: Normal::new(mu, sigma),
        }
    }
}

impl ::Distribution<f64> for Gaussian {
    #[inline]
    fn cdf(&self, x: f64) -> f64 {
        use sfunc::erf;
        (1.0 + erf((x - self.mu) / (self.sigma * Float::sqrt2()))) / 2.0
    }

    /// Compute the inverse of the cumulative distribution function at
    /// probability `p`.
    ///
    /// The code is based on a [C implementation][1] by John Burkardt.
    ///
    /// [1]: http://people.sc.fsu.edu/~jburkardt/c_src/asa241/asa241.html
    fn inv_cdf(&self, p: f64) -> f64 {
        #[inline(always)]
        fn ln(x: f64) -> f64 { x.ln() }
        #[inline(always)]
        fn sqrt(x: f64) -> f64 { x.sqrt() }

        const CONST1: f64 = 0.180625;
        const CONST2: f64 = 1.6;
        const SPLIT1: f64 = 0.425;
        const SPLIT2: f64 = 5.0;
        const A: [f64, ..8] = [
            3.3871328727963666080e+00, 1.3314166789178437745e+02,
            1.9715909503065514427e+03, 1.3731693765509461125e+04,
            4.5921953931549871457e+04, 6.7265770927008700853e+04,
            3.3430575583588128105e+04, 2.5090809287301226727e+03,
        ];
        const B: [f64, ..8] = [
            1.0000000000000000000e+00, 4.2313330701600911252e+01,
            6.8718700749205790830e+02, 5.3941960214247511077e+03,
            2.1213794301586595867e+04, 3.9307895800092710610e+04,
            2.8729085735721942674e+04, 5.2264952788528545610e+03,
        ];
        const C: [f64, ..8] = [
            1.42343711074968357734e+00, 4.63033784615654529590e+00,
            5.76949722146069140550e+00, 3.64784832476320460504e+00,
            1.27045825245236838258e+00, 2.41780725177450611770e-01,
            2.27238449892691845833e-02, 7.74545014278341407640e-04,
        ];
        const D: [f64, ..8] = [
            1.00000000000000000000e+00, 2.05319162663775882187e+00,
            1.67638483018380384940e+00, 6.89767334985100004550e-01,
            1.48103976427480074590e-01, 1.51986665636164571966e-02,
            5.47593808499534494600e-04, 1.05075007164441684324e-09,
        ];
        const E: [f64, ..8] = [
            6.65790464350110377720e+00, 5.46378491116411436990e+00,
            1.78482653991729133580e+00, 2.96560571828504891230e-01,
            2.65321895265761230930e-02, 1.24266094738807843860e-03,
            2.71155556874348757815e-05, 2.01033439929228813265e-07,
        ];
        const F: [f64, ..8] = [
            1.00000000000000000000e+00, 5.99832206555887937690e-01,
            1.36929880922735805310e-01, 1.48753612908506148525e-02,
            7.86869131145613259100e-04, 1.84631831751005468180e-05,
            1.42151175831644588870e-07, 2.04426310338993978564e-15,
        ];

        #[inline(always)]
        fn poly(c: &[f64], x: f64) -> f64 {
            c[0] + x * (c[1] + x * (c[2] + x * (c[3] + x * (
            c[4] + x * (c[5] + x * (c[6] + x * (c[7])))))))
        }

        if p <= 0.0 {
            return Float::neg_infinity();
        }
        if 1.0 <= p {
            return Float::infinity();
        }

        let q = p - 0.5;

        if (if q < 0.0 { -q } else { q }) <= SPLIT1 {
            let x = CONST1 - q * q;
            return self.mu + self.sigma * q * poly(&A, x) / poly(&B, x);
        }

        let mut x = if q < 0.0 { p } else { 1.0 - p };

        x = sqrt(-ln(x));

        if x <= SPLIT2 {
            x -= CONST2;
            x = poly(&C, x) / poly(&D, x);
        } else {
            x -= SPLIT2;
            x = poly(&E, x) / poly(&F, x);
        }

        self.mu + self.sigma * if q < 0.0 { -x } else { x }
    }

    #[inline]
    fn sample<R: Rng>(&self, rng: &mut R) -> f64 {
        self.normal.ind_sample(rng)
    }
}

#[cfg(test)]
mod test {
    #[phase(plugin)] extern crate assert;

    use Distribution;
    use distributions::Gaussian;

    #[test]
    fn cdf() {
        let gaussian = Gaussian::new(1.0, 2.0);

        let x = vec![
            -4.0, -3.5, -3.0, -2.5, -2.0, -1.5, -1.0, -0.5, 0.0,
             0.5,  1.0,  1.5,  2.0,  2.5,  3.0,  3.5,  4.0,
        ];
        let p = vec![
            6.209665325776139e-03, 1.222447265504470e-02, 2.275013194817922e-02,
            4.005915686381709e-02, 6.680720126885809e-02, 1.056497736668553e-01,
            1.586552539314571e-01, 2.266273523768682e-01, 3.085375387259869e-01,
            4.012936743170763e-01, 5.000000000000000e-01, 5.987063256829237e-01,
            6.914624612740131e-01, 7.733726476231317e-01, 8.413447460685429e-01,
            8.943502263331446e-01, 9.331927987311419e-01,
        ];

        assert_close!(x.iter().map(|&x| gaussian.cdf(x)).collect::<Vec<_>>(), p);
    }

    #[test]
    fn inv_cdf() {
        let gaussian = Gaussian::new(-1.0, 0.25);

        let p = vec![
            0.00, 0.05, 0.10, 0.15, 0.20, 0.25, 0.30, 0.35, 0.40, 0.45, 0.50,
            0.55, 0.60, 0.65, 0.70, 0.75, 0.80, 0.85, 0.90, 0.95, 1.00,
        ];
        let x = vec![
             Float::neg_infinity(), -1.411213406737868e+00, -1.320387891386150e+00,
            -1.259108347373447e+00, -1.210405308393228e+00, -1.168622437549020e+00,
            -1.131100128177010e+00, -1.096330116601892e+00, -1.063336775783950e+00,
            -1.031415336713768e+00, -1.000000000000000e+00, -9.685846632862315e-01,
            -9.366632242160501e-01, -9.036698833981082e-01, -8.688998718229899e-01,
            -8.313775624509796e-01, -7.895946916067714e-01, -7.408916526265525e-01,
            -6.796121086138498e-01, -5.887865932621319e-01,  Float::infinity(),
        ];

        assert_close!(p.iter().map(|&p| gaussian.inv_cdf(p)).collect::<Vec<_>>(), x);
    }
}

#[cfg(test)]
mod bench {
    extern crate test;

    use {Distribution, Sampler};
    use distributions::{Gaussian, Uniform};

    #[bench]
    fn cdf(bench: &mut test::Bencher) {
        let mut rng = ::std::rand::task_rng();
        let gaussian = Gaussian::new(0.0, 1.0);
        let x = Sampler(&gaussian, &mut rng).take(1000).collect::<Vec<_>>();

        bench.iter(|| {
            test::black_box(x.iter().map(|&x| gaussian.cdf(x)).collect::<Vec<_>>())
        })
    }

    #[bench]
    fn inv_cdf(bench: &mut test::Bencher) {
        let mut rng = ::std::rand::task_rng();
        let gaussian = Gaussian::new(0.0, 1.0);
        let uniform = Uniform::new(0.0, 1.0);
        let p = Sampler(&uniform, &mut rng).take(1000).collect::<Vec<_>>();

        bench.iter(|| {
            test::black_box(p.iter().map(|&p| gaussian.inv_cdf(p)).collect::<Vec<_>>())
        })
    }
}
<commit_msg>Took into account the numeric reform<commit_after>extern crate sfunc;

use std::rand::Rng;
use std::rand::distributions::{Normal, IndependentSample};

/// A Gaussian distribution.
pub struct Gaussian {
    /// The mean value.
    pub mu: f64,
    /// The standard deviation.
    pub sigma: f64,

    normal: Normal,
}

impl Gaussian {
    /// Create a Gaussian distribution with the mean value `mu` and standard
    /// deviation `sigma`.
    #[inline]
    pub fn new(mu: f64, sigma: f64) -> Gaussian {
        Gaussian {
            mu: mu,
            sigma: sigma,
            normal: Normal::new(mu, sigma),
        }
    }
}

impl ::Distribution<f64> for Gaussian {
    #[inline]
    fn cdf(&self, x: f64) -> f64 {
        use std::num::Float;
        use sfunc::erf;
        (1.0 + erf((x - self.mu) / (self.sigma * Float::sqrt2()))) / 2.0
    }

    /// Compute the inverse of the cumulative distribution function at
    /// probability `p`.
    ///
    /// The code is based on a [C implementation][1] by John Burkardt.
    ///
    /// [1]: http://people.sc.fsu.edu/~jburkardt/c_src/asa241/asa241.html
    fn inv_cdf(&self, p: f64) -> f64 {
        use std::num::Float;

        #[inline(always)]
        fn ln(x: f64) -> f64 { x.ln() }
        #[inline(always)]
        fn sqrt(x: f64) -> f64 { x.sqrt() }

        const CONST1: f64 = 0.180625;
        const CONST2: f64 = 1.6;
        const SPLIT1: f64 = 0.425;
        const SPLIT2: f64 = 5.0;
        const A: [f64, ..8] = [
            3.3871328727963666080e+00, 1.3314166789178437745e+02,
            1.9715909503065514427e+03, 1.3731693765509461125e+04,
            4.5921953931549871457e+04, 6.7265770927008700853e+04,
            3.3430575583588128105e+04, 2.5090809287301226727e+03,
        ];
        const B: [f64, ..8] = [
            1.0000000000000000000e+00, 4.2313330701600911252e+01,
            6.8718700749205790830e+02, 5.3941960214247511077e+03,
            2.1213794301586595867e+04, 3.9307895800092710610e+04,
            2.8729085735721942674e+04, 5.2264952788528545610e+03,
        ];
        const C: [f64, ..8] = [
            1.42343711074968357734e+00, 4.63033784615654529590e+00,
            5.76949722146069140550e+00, 3.64784832476320460504e+00,
            1.27045825245236838258e+00, 2.41780725177450611770e-01,
            2.27238449892691845833e-02, 7.74545014278341407640e-04,
        ];
        const D: [f64, ..8] = [
            1.00000000000000000000e+00, 2.05319162663775882187e+00,
            1.67638483018380384940e+00, 6.89767334985100004550e-01,
            1.48103976427480074590e-01, 1.51986665636164571966e-02,
            5.47593808499534494600e-04, 1.05075007164441684324e-09,
        ];
        const E: [f64, ..8] = [
            6.65790464350110377720e+00, 5.46378491116411436990e+00,
            1.78482653991729133580e+00, 2.96560571828504891230e-01,
            2.65321895265761230930e-02, 1.24266094738807843860e-03,
            2.71155556874348757815e-05, 2.01033439929228813265e-07,
        ];
        const F: [f64, ..8] = [
            1.00000000000000000000e+00, 5.99832206555887937690e-01,
            1.36929880922735805310e-01, 1.48753612908506148525e-02,
            7.86869131145613259100e-04, 1.84631831751005468180e-05,
            1.42151175831644588870e-07, 2.04426310338993978564e-15,
        ];

        #[inline(always)]
        fn poly(c: &[f64], x: f64) -> f64 {
            c[0] + x * (c[1] + x * (c[2] + x * (c[3] + x * (
            c[4] + x * (c[5] + x * (c[6] + x * (c[7])))))))
        }

        if p <= 0.0 {
            return Float::neg_infinity();
        }
        if 1.0 <= p {
            return Float::infinity();
        }

        let q = p - 0.5;

        if (if q < 0.0 { -q } else { q }) <= SPLIT1 {
            let x = CONST1 - q * q;
            return self.mu + self.sigma * q * poly(&A, x) / poly(&B, x);
        }

        let mut x = if q < 0.0 { p } else { 1.0 - p };

        x = sqrt(-ln(x));

        if x <= SPLIT2 {
            x -= CONST2;
            x = poly(&C, x) / poly(&D, x);
        } else {
            x -= SPLIT2;
            x = poly(&E, x) / poly(&F, x);
        }

        self.mu + self.sigma * if q < 0.0 { -x } else { x }
    }

    #[inline]
    fn sample<R: Rng>(&self, rng: &mut R) -> f64 {
        self.normal.ind_sample(rng)
    }
}

#[cfg(test)]
mod test {
    #[phase(plugin)] extern crate assert;

    use Distribution;
    use distributions::Gaussian;

    #[test]
    fn cdf() {
        let gaussian = Gaussian::new(1.0, 2.0);

        let x = vec![
            -4.0, -3.5, -3.0, -2.5, -2.0, -1.5, -1.0, -0.5, 0.0,
             0.5,  1.0,  1.5,  2.0,  2.5,  3.0,  3.5,  4.0,
        ];
        let p = vec![
            6.209665325776139e-03, 1.222447265504470e-02, 2.275013194817922e-02,
            4.005915686381709e-02, 6.680720126885809e-02, 1.056497736668553e-01,
            1.586552539314571e-01, 2.266273523768682e-01, 3.085375387259869e-01,
            4.012936743170763e-01, 5.000000000000000e-01, 5.987063256829237e-01,
            6.914624612740131e-01, 7.733726476231317e-01, 8.413447460685429e-01,
            8.943502263331446e-01, 9.331927987311419e-01,
        ];

        assert_close!(x.iter().map(|&x| gaussian.cdf(x)).collect::<Vec<_>>(), p);
    }

    #[test]
    fn inv_cdf() {
        use std::num::Float;

        let gaussian = Gaussian::new(-1.0, 0.25);

        let p = vec![
            0.00, 0.05, 0.10, 0.15, 0.20, 0.25, 0.30, 0.35, 0.40, 0.45, 0.50,
            0.55, 0.60, 0.65, 0.70, 0.75, 0.80, 0.85, 0.90, 0.95, 1.00,
        ];
        let x = vec![
             Float::neg_infinity(), -1.411213406737868e+00, -1.320387891386150e+00,
            -1.259108347373447e+00, -1.210405308393228e+00, -1.168622437549020e+00,
            -1.131100128177010e+00, -1.096330116601892e+00, -1.063336775783950e+00,
            -1.031415336713768e+00, -1.000000000000000e+00, -9.685846632862315e-01,
            -9.366632242160501e-01, -9.036698833981082e-01, -8.688998718229899e-01,
            -8.313775624509796e-01, -7.895946916067714e-01, -7.408916526265525e-01,
            -6.796121086138498e-01, -5.887865932621319e-01,  Float::infinity(),
        ];

        assert_close!(p.iter().map(|&p| gaussian.inv_cdf(p)).collect::<Vec<_>>(), x);
    }
}

#[cfg(test)]
mod bench {
    extern crate test;

    use {Distribution, Sampler};
    use distributions::{Gaussian, Uniform};

    #[bench]
    fn cdf(bench: &mut test::Bencher) {
        let mut rng = ::std::rand::task_rng();
        let gaussian = Gaussian::new(0.0, 1.0);
        let x = Sampler(&gaussian, &mut rng).take(1000).collect::<Vec<_>>();

        bench.iter(|| {
            test::black_box(x.iter().map(|&x| gaussian.cdf(x)).collect::<Vec<_>>())
        })
    }

    #[bench]
    fn inv_cdf(bench: &mut test::Bencher) {
        let mut rng = ::std::rand::task_rng();
        let gaussian = Gaussian::new(0.0, 1.0);
        let uniform = Uniform::new(0.0, 1.0);
        let p = Sampler(&uniform, &mut rng).take(1000).collect::<Vec<_>>();

        bench.iter(|| {
            test::black_box(p.iter().map(|&p| gaussian.inv_cdf(p)).collect::<Vec<_>>())
        })
    }
}
<|endoftext|>


<commit_before>extern crate nalgebra as na;

use dstream::dstream2d::{TheWorld, DG, RawData, GridPoint};
use na::{Mat2, Vec2, Row};
use petgraph::{Graph};
use petgraph::graph::NodeIndex;
use petgraph::algo::*;
use petgraph::visit::*;

#[test]
fn test_graph_works_as_expected() {
    println!("-----graph behavior");
    let mut g = Graph::<(usize, usize), (usize, usize)>::new();

    let n1 = g.add_node((0,0));
    let n2 = g.add_node((0,1));
    let n3 = g.add_node((1,0));
    let n4 = g.add_node((1,4));
    let n5 = g.add_node((1,5));

    g.extend_with_edges(&[(n1, n2)]);
    g.extend_with_edges(&[(n1, n3)]);
    g.extend_with_edges(&[(n4, n5)]);

    let edge_count = g.edge_count();
    let node_count = g.node_count();

    println!("test edge count: {}", edge_count);
    println!("test node count: {}", node_count);

    for n in g.node_indices() {
        let nsu = g.neighbors_undirected(n);
        let esu = g.edges(n);
        println!("for node {}", n.index());
        for nu in nsu {
            println!("-- neighbor visited");
        }
    }

    //http://math.stackexchange.com/questions/551889/checking-if-a-graph-is-fully-connected
    println!("for graph with n nodes, then A^n, where A the adj matrix, should have no zero elements");
    let adj_mat = g.adjacency_matrix();

    fn convert_graph_adj_mat_to_nalgebra_mat2() {
        //TODO
        let g = Graph::<(usize, usize), (usize, usize)>::new();
        let mut m2 : Mat2<f64> = na::one();

        for n1 in g.node_indices() {
            let mut neighs_v = Vec::new();
            let neighs = g.neighbors_undirected(n1);
            //TODO ugly way to covert iterator to vector
            for neigh in neighs {
                neighs_v.push(neigh);
            }

            let mut the_row: Vec<f64> = Vec::new();
            let mut the_vec_rows: Vec2<f64> = na::zero();

            for n2 in g.node_indices() {
                if ! neighs_v.contains(&n2) {
                    println!("does not contain");
                    the_row.push(1.0);
                    *the_vec_rows.index_mut(1 as usize) = 1.0;

                } else {
                    the_row.push(0.0);
                }

            }
//            m2.set_row(n1.index(), the_row);
        }

    }

}

#[test]
fn test_mark_and_remove_and_reset_spore_adics() {
    //TODO
    assert!(false);
}

#[test]
fn test_is_a_grid_cluster() {
    //TODO
    assert!(false);
}

#[test]
fn test_is_inside_grid() {
    //TODO
    assert!(false);
}

#[test]
fn test_is_a_grid_group() {
    //TODO
    let dg1 = DG {i: 0, j: 0,
        updates_and_vals: Vec::new(), removed_as_spore_adic: Vec::new(),};
    let dg2 = DG {i: 1, j: 0,
        updates_and_vals: Vec::new(), removed_as_spore_adic: Vec::new(),};
    let dg3 = DG {i: 0, j: 1,
        updates_and_vals: Vec::new(), removed_as_spore_adic: Vec::new(),};
    let dg4 = DG {i: 1, j: 1,
        updates_and_vals: Vec::new(), removed_as_spore_adic: Vec::new(),};
    let dg5 = DG {i: 1, j: 4,
        updates_and_vals: Vec::new(), removed_as_spore_adic: Vec::new(),};
    let dg6 = DG {i: 1, j: 2,
        updates_and_vals: Vec::new(), removed_as_spore_adic: Vec::new(),};

    let result = TheWorld::is_a_grid_group(vec!(dg1.clone(), dg2.clone(), dg3.clone(), dg4.clone(), dg6.clone()));
    assert_eq!(true, result);

    let result2 = TheWorld::is_a_grid_group(vec!(dg1.clone(), dg2.clone(), dg3.clone(), dg4.clone(), dg5.clone()));
    assert_eq!(false, result2);

    let result3 = TheWorld::is_a_grid_group(vec!(dg1.clone(), dg2.clone(), dg3.clone(),));
    assert_eq!(true, result3);
}

#[test]
fn test_compute_grid_indxs() {
    let loc = (-6., 6.);
    let i_rn = (-10.0, 10.0);
    let j_rn = (-10.0, 10.0);
    let i_bins = 10 as usize;
    let j_bins = 10 as usize;

    let result = TheWorld::compute_grid_indxs(loc, i_rn, j_rn, i_bins, j_bins).unwrap();
    assert_eq!((2, 8), result);

}

#[test]
fn test_are_neighbors() {
    let dg1 = &DG {i: 0, j: 0,
        updates_and_vals: Vec::new(), removed_as_spore_adic: Vec::new(),};
    let dg2 = &DG {i: 1, j: 0,
        updates_and_vals: Vec::new(), removed_as_spore_adic: Vec::new(),};
    let dg3 = &DG {i: 1, j: 1,
        updates_and_vals: Vec::new(), removed_as_spore_adic: Vec::new(),};

    assert_eq!(true, TheWorld::are_neighbors(dg1, dg2));
    assert_eq!(true, TheWorld::are_neighbors(dg2, dg3));
    assert_eq!(false, TheWorld::are_neighbors(dg1, dg3));
}

#[test]
fn test_dg_update_and_get() {
    let mut dg = DG {i: 0, j:0, updates_and_vals: Vec::new(), removed_as_spore_adic: Vec::new(),};
    dg.update(1, vec!(100.0));

    dg.update(10, vec!(200.0));
    dg.update(20, vec!(300.0));

    assert_eq!((1, 100.0), dg.get_last_update_and_value_to(2));
    assert_eq!((10, 200.0), dg.get_last_update_and_value_to(14));
    assert_eq!((20, 300.0), dg.get_last_update_and_value_to(22));

    let v_at_t = dg.get_at_time(30);
    println!("t: {}, v: {}", v_at_t.0, v_at_t.1);
}

#[test]
fn test_removed_as_sporadic() {
    let mut dg = DG {i: 0, j:0, updates_and_vals: Vec::new(), removed_as_spore_adic: vec!(1, 2, 3, 4),};
    assert_eq!(1, dg.get_last_time_removed_as_sporadic_to(2));
    assert_eq!(4, dg.get_last_time_removed_as_sporadic_to(6));
}

#[test]
fn test_put_works() {
    let raw_data_1 = RawData{x: 1.0, y: -1.0, v: 123.45};
    let raw_data_2 = RawData{x: 5.0, y: -7.0, v: 23.45};
    let raw_data_3 = RawData{x: 5.0, y: -7.0, v: 83.45};
    let raw_data_4 = RawData{x: 15.0, y: -17.0, v: 83.45};

    let rd_vec = vec!(raw_data_1, raw_data_2, raw_data_3, raw_data_4);

    let t = 1;

    let default_vec : Vec<GridPoint> = Vec::new();
    let mut world = TheWorld{g_vec: Vec::new()};
    world.init(default_vec);
    let res1 = world.put(t, rd_vec.clone());
    let res2 = world.put(t + 1, rd_vec.clone());
    let res3 = world.put(t + 2, rd_vec.clone());

}<commit_msg>switch to dynamic matrix<commit_after>extern crate nalgebra as na;

use dstream::dstream2d::{TheWorld, DG, RawData, GridPoint};
use na::{Mat2, Vec2, Row, DMat};
use petgraph::{Graph};
use petgraph::graph::NodeIndex;
use petgraph::algo::*;
use petgraph::visit::*;

#[test]
fn test_graph_works_as_expected() {
    println!("-----graph behavior");
    let mut g = Graph::<(usize, usize), (usize, usize)>::new();

    let n1 = g.add_node((0,0));
    let n2 = g.add_node((0,1));
    let n3 = g.add_node((1,0));
    let n4 = g.add_node((1,4));
    let n5 = g.add_node((1,5));

    g.extend_with_edges(&[(n1, n2)]);
    g.extend_with_edges(&[(n1, n3)]);
    g.extend_with_edges(&[(n4, n5)]);

    let edge_count = g.edge_count();
    let node_count = g.node_count();

    println!("test edge count: {}", edge_count);
    println!("test node count: {}", node_count);

    for n in g.node_indices() {
        let nsu = g.neighbors_undirected(n);
        let esu = g.edges(n);
        println!("for node {}", n.index());
        for nu in nsu {
            println!("-- neighbor visited");
        }
    }

    //http://math.stackexchange.com/questions/551889/checking-if-a-graph-is-fully-connected
    println!("for graph with n nodes, then A^n, where A the adj matrix, should have no zero elements");
    let adj_mat = g.adjacency_matrix();

    fn convert_graph_adj_mat_to_nalgebra_mat() -> DMat<f64> {

        let g = Graph::<(usize, usize), (usize, usize)>::new();
        //TODO size
        let mut m2 : DMat<f64> = DMat::new_zeros(10,10);

        for n1 in g.node_indices() {
            let mut neighs_v = Vec::new();
            let neighs = g.neighbors_undirected(n1);
            //TODO ugly way to covert iterator to vector
            for neigh in neighs {
                neighs_v.push(neigh);
            }

            for n2 in g.node_indices() {
                if ! neighs_v.contains(&n2) {
                    println!("does not contain");
                    //TODO the indices:
                    (&mut m2)[(0,0)] = 1.0;

                } else {
                    //TODO the indices:
                    (&mut m2)[(0,0)] = 0.0;
                }
            }
        }
        m2
    }
}

#[test]
fn test_mark_and_remove_and_reset_spore_adics() {
    //TODO
    assert!(false);
}

#[test]
fn test_is_a_grid_cluster() {
    //TODO
    assert!(false);
}

#[test]
fn test_is_inside_grid() {
    //TODO
    assert!(false);
}

#[test]
fn test_is_a_grid_group() {
    //TODO
    let dg1 = DG {i: 0, j: 0,
        updates_and_vals: Vec::new(), removed_as_spore_adic: Vec::new(),};
    let dg2 = DG {i: 1, j: 0,
        updates_and_vals: Vec::new(), removed_as_spore_adic: Vec::new(),};
    let dg3 = DG {i: 0, j: 1,
        updates_and_vals: Vec::new(), removed_as_spore_adic: Vec::new(),};
    let dg4 = DG {i: 1, j: 1,
        updates_and_vals: Vec::new(), removed_as_spore_adic: Vec::new(),};
    let dg5 = DG {i: 1, j: 4,
        updates_and_vals: Vec::new(), removed_as_spore_adic: Vec::new(),};
    let dg6 = DG {i: 1, j: 2,
        updates_and_vals: Vec::new(), removed_as_spore_adic: Vec::new(),};

    let result = TheWorld::is_a_grid_group(vec!(dg1.clone(), dg2.clone(), dg3.clone(), dg4.clone(), dg6.clone()));
    assert_eq!(true, result);

    let result2 = TheWorld::is_a_grid_group(vec!(dg1.clone(), dg2.clone(), dg3.clone(), dg4.clone(), dg5.clone()));
    assert_eq!(false, result2);

    let result3 = TheWorld::is_a_grid_group(vec!(dg1.clone(), dg2.clone(), dg3.clone(),));
    assert_eq!(true, result3);
}

#[test]
fn test_compute_grid_indxs() {
    let loc = (-6., 6.);
    let i_rn = (-10.0, 10.0);
    let j_rn = (-10.0, 10.0);
    let i_bins = 10 as usize;
    let j_bins = 10 as usize;

    let result = TheWorld::compute_grid_indxs(loc, i_rn, j_rn, i_bins, j_bins).unwrap();
    assert_eq!((2, 8), result);

}

#[test]
fn test_are_neighbors() {
    let dg1 = &DG {i: 0, j: 0,
        updates_and_vals: Vec::new(), removed_as_spore_adic: Vec::new(),};
    let dg2 = &DG {i: 1, j: 0,
        updates_and_vals: Vec::new(), removed_as_spore_adic: Vec::new(),};
    let dg3 = &DG {i: 1, j: 1,
        updates_and_vals: Vec::new(), removed_as_spore_adic: Vec::new(),};

    assert_eq!(true, TheWorld::are_neighbors(dg1, dg2));
    assert_eq!(true, TheWorld::are_neighbors(dg2, dg3));
    assert_eq!(false, TheWorld::are_neighbors(dg1, dg3));
}

#[test]
fn test_dg_update_and_get() {
    let mut dg = DG {i: 0, j:0, updates_and_vals: Vec::new(), removed_as_spore_adic: Vec::new(),};
    dg.update(1, vec!(100.0));

    dg.update(10, vec!(200.0));
    dg.update(20, vec!(300.0));

    assert_eq!((1, 100.0), dg.get_last_update_and_value_to(2));
    assert_eq!((10, 200.0), dg.get_last_update_and_value_to(14));
    assert_eq!((20, 300.0), dg.get_last_update_and_value_to(22));

    let v_at_t = dg.get_at_time(30);
    println!("t: {}, v: {}", v_at_t.0, v_at_t.1);
}

#[test]
fn test_removed_as_sporadic() {
    let mut dg = DG {i: 0, j:0, updates_and_vals: Vec::new(), removed_as_spore_adic: vec!(1, 2, 3, 4),};
    assert_eq!(1, dg.get_last_time_removed_as_sporadic_to(2));
    assert_eq!(4, dg.get_last_time_removed_as_sporadic_to(6));
}

#[test]
fn test_put_works() {
    let raw_data_1 = RawData{x: 1.0, y: -1.0, v: 123.45};
    let raw_data_2 = RawData{x: 5.0, y: -7.0, v: 23.45};
    let raw_data_3 = RawData{x: 5.0, y: -7.0, v: 83.45};
    let raw_data_4 = RawData{x: 15.0, y: -17.0, v: 83.45};

    let rd_vec = vec!(raw_data_1, raw_data_2, raw_data_3, raw_data_4);

    let t = 1;

    let default_vec : Vec<GridPoint> = Vec::new();
    let mut world = TheWorld{g_vec: Vec::new()};
    world.init(default_vec);
    let res1 = world.put(t, rd_vec.clone());
    let res2 = world.put(t + 1, rd_vec.clone());
    let res3 = world.put(t + 2, rd_vec.clone());

}<|endoftext|>