<commit_before>//! Defines common interfaces for interacting with statistical distributions and provides
//! concrete implementations for a variety of distributions.

use rand::Rng;
use super::result::Result;

pub use self::bernoulli::Bernoulli;
pub use self::binomial::Binomial;
pub use self::chi::Chi;
pub use self::chi_squared::ChiSquared;
pub use self::discrete_uniform::DiscreteUniform;
pub use self::exponential::Exponential;
pub use self::gamma::Gamma;
pub use self::log_normal::LogNormal;
pub use self::normal::Normal;
pub use self::poisson::Poisson;
pub use self::student_t::StudentT;
pub use self::triangular::Triangular;
pub use self::uniform::Uniform;
pub use self::weibull::Weibull;

mod bernoulli;
mod binomial;
mod chi;
mod chi_squared;
mod discrete_uniform;
mod exponential;
mod gamma;
mod log_normal;
mod normal;
mod poisson;
mod student_t;
mod triangular;
mod uniform;
mod weibull;

/// The `Distribution` trait is used to specify an interface
/// for sampling distributions
///
/// # Examples
///
/// A trivial implementation that just samples from the supplied
/// random number generator
///
/// ```
/// # extern crate rand;
/// # extern crate statrs;
///
/// use rand::Rng;
/// use statrs::distribution::Distribution;
///
/// struct Foo;
///
/// impl Distribution for Foo {
///     fn sample<R: Rng>(&self, r: &mut R) -> f64 {
///         r.next_f64()
///     }
/// }
///
/// # fn main() { }
/// ```
pub trait Distribution {
    /// Draws a random sample using the supplied random number generator
    fn sample<R: Rng>(&self, r: &mut R) -> f64;
}

/// The `Univariate` trait extends the `Distribution`
/// trait provides an interface for interacting with
/// univariate statistical distributions.
///
/// # Remarks
///
/// All methods provided by the `Univariate` trait are unchecked, meaning
/// they can panic if in an invalid state or encountering invalid input
/// depending on the implementing distribution. The `CheckedUnivariate`
/// trait provides a panic-safe interface for univariate distributions
pub trait Univariate : Distribution {
    /// Returns the mean for a given distribution. May panic depending
    /// on the implementor.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::{Univariate, Uniform};
    ///
    /// let n = Uniform::new(0.0, 1.0).unwrap();
    /// assert_eq!(0.5, n.mean());
    /// ```
    fn mean(&self) -> f64;

    /// Returns the variance for a given distribution. May panic depending
    /// on the implementor.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::{Univariate, Uniform};
    ///
    /// let n = Uniform::new(0.0, 1.0).unwrap();
    /// assert_eq!(1.0 / 12.0, n.variance());
    /// ```
    fn variance(&self) -> f64;

    /// Returns the standard deviation for a given distribution. May panic depending
    /// on the implementor.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::{Univariate, Uniform};
    ///
    /// let n = Uniform::new(0.0, 1.0).unwrap();
    /// assert_eq!((1f64 / 12f64).sqrt(), n.std_dev());
    /// ```
    fn std_dev(&self) -> f64;

    /// Returns the entropy for a given distribution. May panic depending
    /// on the implementor.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::{Univariate, Uniform};
    ///
    /// let n = Uniform::new(0.0, 1.0).unwrap();
    /// assert_eq!(0.0, n.entropy());
    /// ```
    fn entropy(&self) -> f64;

    /// Returns the skewness for a given distribution. May panic depending
    /// on the implementor.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::{Univariate, Uniform};
    ///
    /// let n = Uniform::new(0.0, 1.0).unwrap();
    /// assert_eq!(0.0, n.skewness());
    /// ```
    fn skewness(&self) -> f64;

    /// Returns the median for a given distribution. May panic depending
    /// on the implementor.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::{Univariate, Uniform};
    ///
    /// let n = Uniform::new(0.0, 1.0).unwrap();
    /// assert_eq!(0.5, n.median());
    /// ```
    fn median(&self) -> f64;

    /// Returns the cumulative distribution function calculated
    /// at `x` for a given distribution. May panic depending
    /// on the implementor.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::{Univariate, Uniform};
    ///
    /// let n = Uniform::new(0.0, 1.0).unwrap();
    /// assert_eq!(0.5, n.cdf(0.5));
    /// ```
    fn cdf(&self, x: f64) -> f64;
}

/// The `Continuous` trait extends the `Univariate`
/// trait and provides an interface for interacting with continuous
/// univariate statistical distributions
///
/// # Remarks
///
/// All methods provided by the `Continuous` trait are unchecked, meaning
/// they can panic if in an invalid state or encountering invalid input
/// depending on the implementing distribution. The `CheckedContinuous`
/// trait provides a panic-safe interface for continuous distributions
pub trait Continuous : Univariate {
    /// Returns the mode for a given distribution. May panic depending on
    /// the implementor.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::{Continuous, Uniform};
    ///
    /// let n = Uniform::new(0.0, 1.0).unwrap();
    /// assert_eq!(0.5, n.mode());
    /// ```
    fn mode(&self) -> f64;

    /// Returns the minimum value in the domain of a given distribution
    /// representable by a double-precision float. May panic depending on
    /// the implementor.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::{Continuous, Uniform};
    ///
    /// let n = Uniform::new(0.0, 1.0).unwrap();
    /// assert_eq!(0.0, n.min());
    /// ```
    fn min(&self) -> f64;

    /// Returns the maximum value in the domain of a given distribution
    /// representable by a double-precision float. May panic depending on
    /// the implementor.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::{Continuous, Uniform};
    ///
    /// let n = Uniform::new(0.0, 1.0).unwrap();
    /// assert_eq!(1.0, n.max());
    /// ```
    fn max(&self) -> f64;

    /// Returns the probability density function calculated at `x` for a given distribution.
    /// May panic depending on the implementor.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::{Continuous, Uniform};
    ///
    /// let n = Uniform::new(0.0, 1.0).unwrap();
    /// assert_eq!(1.0, n.pdf(0.5));
    /// ```
    fn pdf(&self, x: f64) -> f64;

    /// Returns the log of the probability density function calculated at `x` for a given distribution.
    /// May panic depending on the implementor.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::{Continuous, Uniform};
    ///
    /// let n = Uniform::new(0.0, 1.0).unwrap();
    /// assert_eq!(0.0, n.ln_pdf(0.5));
    /// ```
    fn ln_pdf(&self, x: f64) -> f64;
}

/// The `Discrete` trait extends the `Univariate`
/// trait and provides an interface for interacting with discrete
/// univariate statistical distributions
///
/// # Remarks
///
/// All methods provided by the `Discrete` trait are unchecked, meaning
/// they can panic if in an invalid state or encountering invalid input
/// depending on the implementing distribution. The `CheckedDiscrete` trait
/// provides a panic-safe interface for discrete distributions
pub trait Discrete : Univariate {
    /// Returns the mode for a given distribution. May panic depending on
    /// the implementor.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::{Discrete, Binomial};
    ///
    /// let n = Binomial::new(0.5, 10).unwrap();
    /// assert_eq!(5, n.mode());
    /// ```
    fn mode(&self) -> i64;

    /// Returns the minimum value in the domain of a given distribution
    /// representable by a 64-bit integer. May panic depending on
    /// the implementor.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::{Discrete, Binomial};
    ///
    /// let n = Binomial::new(0.5, 10).unwrap();
    /// assert_eq!(0, n.min());
    /// ```
    fn min(&self) -> i64;

    /// Returns the maximum value in the domain of a given distribution
    /// representable by a 64-bit integer. May panic depending on
    /// the implementor.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::{Discrete, Binomial};
    ///
    /// let n = Binomial::new(0.5, 10).unwrap();
    /// assert_eq!(10, n.max());
    /// ```
    fn max(&self) -> i64;

    /// Returns the probability mass function calculated at `x` for a given distribution.
    /// May panic depending on the implementor.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::{Discrete, Binomial};
    /// use statrs::prec;
    ///
    /// let n = Binomial::new(0.5, 10).unwrap();
    /// assert!(prec::almost_eq(n.pmf(5), 0.24609375, 1e-15));
    /// ```
    fn pmf(&self, x: i64) -> f64;

    /// Returns the log of the probability mass function calculated at `x` for a given distribution.
    /// May panic depending on the implementor.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::{Discrete, Binomial};
    /// use statrs::prec;
    ///
    /// let n = Binomial::new(0.5, 10).unwrap();
    /// assert!(prec::almost_eq(n.ln_pmf(5), (0.24609375f64).ln(), 1e-15));
    /// ```
    fn ln_pmf(&self, x: i64) -> f64;
}
<commit_msg>remove comments about checked distribution types<commit_after>//! Defines common interfaces for interacting with statistical distributions and provides
//! concrete implementations for a variety of distributions.

use rand::Rng;
use super::result::Result;

pub use self::bernoulli::Bernoulli;
pub use self::binomial::Binomial;
pub use self::chi::Chi;
pub use self::chi_squared::ChiSquared;
pub use self::discrete_uniform::DiscreteUniform;
pub use self::exponential::Exponential;
pub use self::gamma::Gamma;
pub use self::log_normal::LogNormal;
pub use self::normal::Normal;
pub use self::poisson::Poisson;
pub use self::student_t::StudentT;
pub use self::triangular::Triangular;
pub use self::uniform::Uniform;
pub use self::weibull::Weibull;

mod bernoulli;
mod binomial;
mod chi;
mod chi_squared;
mod discrete_uniform;
mod exponential;
mod gamma;
mod log_normal;
mod normal;
mod poisson;
mod student_t;
mod triangular;
mod uniform;
mod weibull;

/// The `Distribution` trait is used to specify an interface
/// for sampling distributions
///
/// # Examples
///
/// A trivial implementation that just samples from the supplied
/// random number generator
///
/// ```
/// # extern crate rand;
/// # extern crate statrs;
///
/// use rand::Rng;
/// use statrs::distribution::Distribution;
///
/// struct Foo;
///
/// impl Distribution for Foo {
///     fn sample<R: Rng>(&self, r: &mut R) -> f64 {
///         r.next_f64()
///     }
/// }
///
/// # fn main() { }
/// ```
pub trait Distribution {
    /// Draws a random sample using the supplied random number generator
    fn sample<R: Rng>(&self, r: &mut R) -> f64;
}

/// The `Univariate` trait extends the `Distribution`
/// trait provides an interface for interacting with
/// univariate statistical distributions.
///
/// # Remarks
///
/// All methods provided by the `Univariate` trait are unchecked, meaning
/// they can panic if in an invalid state or encountering invalid input
/// depending on the implementing distribution.
pub trait Univariate : Distribution {
    /// Returns the mean for a given distribution. May panic depending
    /// on the implementor.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::{Univariate, Uniform};
    ///
    /// let n = Uniform::new(0.0, 1.0).unwrap();
    /// assert_eq!(0.5, n.mean());
    /// ```
    fn mean(&self) -> f64;

    /// Returns the variance for a given distribution. May panic depending
    /// on the implementor.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::{Univariate, Uniform};
    ///
    /// let n = Uniform::new(0.0, 1.0).unwrap();
    /// assert_eq!(1.0 / 12.0, n.variance());
    /// ```
    fn variance(&self) -> f64;

    /// Returns the standard deviation for a given distribution. May panic depending
    /// on the implementor.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::{Univariate, Uniform};
    ///
    /// let n = Uniform::new(0.0, 1.0).unwrap();
    /// assert_eq!((1f64 / 12f64).sqrt(), n.std_dev());
    /// ```
    fn std_dev(&self) -> f64;

    /// Returns the entropy for a given distribution. May panic depending
    /// on the implementor.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::{Univariate, Uniform};
    ///
    /// let n = Uniform::new(0.0, 1.0).unwrap();
    /// assert_eq!(0.0, n.entropy());
    /// ```
    fn entropy(&self) -> f64;

    /// Returns the skewness for a given distribution. May panic depending
    /// on the implementor.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::{Univariate, Uniform};
    ///
    /// let n = Uniform::new(0.0, 1.0).unwrap();
    /// assert_eq!(0.0, n.skewness());
    /// ```
    fn skewness(&self) -> f64;

    /// Returns the median for a given distribution. May panic depending
    /// on the implementor.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::{Univariate, Uniform};
    ///
    /// let n = Uniform::new(0.0, 1.0).unwrap();
    /// assert_eq!(0.5, n.median());
    /// ```
    fn median(&self) -> f64;

    /// Returns the cumulative distribution function calculated
    /// at `x` for a given distribution. May panic depending
    /// on the implementor.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::{Univariate, Uniform};
    ///
    /// let n = Uniform::new(0.0, 1.0).unwrap();
    /// assert_eq!(0.5, n.cdf(0.5));
    /// ```
    fn cdf(&self, x: f64) -> f64;
}

/// The `Continuous` trait extends the `Univariate`
/// trait and provides an interface for interacting with continuous
/// univariate statistical distributions
///
/// # Remarks
///
/// All methods provided by the `Continuous` trait are unchecked, meaning
/// they can panic if in an invalid state or encountering invalid input
/// depending on the implementing distribution.
pub trait Continuous : Univariate {
    /// Returns the mode for a given distribution. May panic depending on
    /// the implementor.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::{Continuous, Uniform};
    ///
    /// let n = Uniform::new(0.0, 1.0).unwrap();
    /// assert_eq!(0.5, n.mode());
    /// ```
    fn mode(&self) -> f64;

    /// Returns the minimum value in the domain of a given distribution
    /// representable by a double-precision float. May panic depending on
    /// the implementor.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::{Continuous, Uniform};
    ///
    /// let n = Uniform::new(0.0, 1.0).unwrap();
    /// assert_eq!(0.0, n.min());
    /// ```
    fn min(&self) -> f64;

    /// Returns the maximum value in the domain of a given distribution
    /// representable by a double-precision float. May panic depending on
    /// the implementor.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::{Continuous, Uniform};
    ///
    /// let n = Uniform::new(0.0, 1.0).unwrap();
    /// assert_eq!(1.0, n.max());
    /// ```
    fn max(&self) -> f64;

    /// Returns the probability density function calculated at `x` for a given distribution.
    /// May panic depending on the implementor.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::{Continuous, Uniform};
    ///
    /// let n = Uniform::new(0.0, 1.0).unwrap();
    /// assert_eq!(1.0, n.pdf(0.5));
    /// ```
    fn pdf(&self, x: f64) -> f64;

    /// Returns the log of the probability density function calculated at `x` for a given distribution.
    /// May panic depending on the implementor.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::{Continuous, Uniform};
    ///
    /// let n = Uniform::new(0.0, 1.0).unwrap();
    /// assert_eq!(0.0, n.ln_pdf(0.5));
    /// ```
    fn ln_pdf(&self, x: f64) -> f64;
}

/// The `Discrete` trait extends the `Univariate`
/// trait and provides an interface for interacting with discrete
/// univariate statistical distributions
///
/// # Remarks
///
/// All methods provided by the `Discrete` trait are unchecked, meaning
/// they can panic if in an invalid state or encountering invalid input
/// depending on the implementing distribution.
pub trait Discrete : Univariate {
    /// Returns the mode for a given distribution. May panic depending on
    /// the implementor.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::{Discrete, Binomial};
    ///
    /// let n = Binomial::new(0.5, 10).unwrap();
    /// assert_eq!(5, n.mode());
    /// ```
    fn mode(&self) -> i64;

    /// Returns the minimum value in the domain of a given distribution
    /// representable by a 64-bit integer. May panic depending on
    /// the implementor.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::{Discrete, Binomial};
    ///
    /// let n = Binomial::new(0.5, 10).unwrap();
    /// assert_eq!(0, n.min());
    /// ```
    fn min(&self) -> i64;

    /// Returns the maximum value in the domain of a given distribution
    /// representable by a 64-bit integer. May panic depending on
    /// the implementor.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::{Discrete, Binomial};
    ///
    /// let n = Binomial::new(0.5, 10).unwrap();
    /// assert_eq!(10, n.max());
    /// ```
    fn max(&self) -> i64;

    /// Returns the probability mass function calculated at `x` for a given distribution.
    /// May panic depending on the implementor.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::{Discrete, Binomial};
    /// use statrs::prec;
    ///
    /// let n = Binomial::new(0.5, 10).unwrap();
    /// assert!(prec::almost_eq(n.pmf(5), 0.24609375, 1e-15));
    /// ```
    fn pmf(&self, x: i64) -> f64;

    /// Returns the log of the probability mass function calculated at `x` for a given distribution.
    /// May panic depending on the implementor.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::{Discrete, Binomial};
    /// use statrs::prec;
    ///
    /// let n = Binomial::new(0.5, 10).unwrap();
    /// assert!(prec::almost_eq(n.ln_pmf(5), (0.24609375f64).ln(), 1e-15));
    /// ```
    fn ln_pmf(&self, x: i64) -> f64;
}
<|endoftext|>


<commit_before>/// Gets the offset of a field. Used by container_of!
#[macro_export]
macro_rules! offset_of(
    ($ty:ty, $field:ident) => {
        &(*(0 as *const $ty)).$field as *const _ as usize
    }
);

/// Gets the parent struct from a pointer.
/// VERY unsafe. The parent struct _must_ be repr(C), and the
/// type passed to this macro _must_ match the type of the parent.
#[macro_export]
macro_rules! container_of (
    ($ptr: expr, $container: ty, $field: ident) => {
        ($ptr as *mut u8).offset(-(offset_of!($container, $field) as isize)) as *mut $container
    }
);

/// Convert a literal string to a C string.
/// Note: Does not check for internal nulls, nor does it do any conversions on
/// the grapheme clustors. Just passes the bytes as is.
/// So probably only works on ASCII.
#[macro_export]
macro_rules! c_str {
    ($s:expr) => {
        concat!($s, "\0").as_ptr() as *const i8
    }
}

#[macro_export]
/// Logs a message using wlroots' logging capability.
///
/// Possible values for `verb`:
///
/// * L_SILENT
/// * L_INFO
/// * L_DEBUG
/// * L_ERROR
macro_rules! wlr_log {
    ($verb: expr, $($msg:tt)*) => {{
        use $crate::wlroots_sys::_wlr_log;
        use $crate::wlroots_sys::log_importance_t::*;
        use ::std::ffi::CString;
        unsafe {
            let fmt = CString::new(format!($($msg)*))
                .expect("Could not convert log message to C string");
            let raw = fmt.into_raw();
            _wlr_log($verb, c_str!("[%s:%lu] %s"),
                    c_str!(file!()), line!(), raw);
            // Deallocate string
            CString::from_raw(raw);
        }
    }}
}

/// Defines a new struct that contains a variable number of listeners that
/// will trigger unsafe user-defined callbacks.
///
/// The structure that is defined is repr(C), has one `data` field with the
/// given user type, and a field for each `$listener`.
///
/// Each `$listener` has a getter method that lets you get the pointer to the
/// listener. This method is unsafe, since it returns a raw pointer.
/// To use it correctly, you need to ensure that the data it refers to never
/// moves (e.g keep it in a box). The primary purpose of this method is to pass
/// the listener pointer to other methods to register it for a Wayland event.
/// **A listener can only be registered to one event at a time**.
///
/// Finally, it also takes in a body for each `$listener` that is called
/// every time the event that is later hooked up to it is fired.
/// This method is inherently unsafe, because the user data hasn't been cast
/// from the void pointer yet. It is the user's job to write this safely.
/// To highlight this fact, the body of the function must be prefixed with
/// `unsafe`.
///
/// # Example
/// ```rust,no_run
/// #[macro_use] extern crate wlroots;
/// extern crate wlroots_sys;
/// #[macro_use] extern crate wayland_sys;
/// extern crate libc;
///
/// use wlroots::InputDevice;
/// use wlroots_sys::wlr_input_device;
///
/// // Handles input addition and removal.
/// pub trait InputManagerHandler {
///     // Callback triggered when an input device is added.
///     fn input_added(&mut self, InputDevice);
/// }
///
/// wayland_listener!(
///     // The name of the structure that will be defined.
///     InputManager,
///     // The type that's stored in the `data` field.
///     // Note that we use a Box here to achieve dynamic dispatch,
///     // it's not required for this type to be in a box.
///     Box<InputManagerHandler>,
///     [
///         // Adds a new listener called `add_listener`.
///         // Adds an unsafe function called `add_notify` that is triggered
///         // whenever add_listener is activated from a Wayland event.
///         add_listener => add_notify: |this: &mut InputManager, data: *mut libc::c_void,| unsafe {
///             let ref mut manager = this.data;
///             // Call the method defined above, wrapping it in a safe interface.
///             // It is your job to ensure that the code in here doesn't trigger UB!
///             manager.input_added(InputDevice::from_ptr(data as *mut wlr_input_device))
///         };
///     ]
/// );
/// # fn main() {}
/// ```
///
/// # Unsafety
/// Note that the purpose of this macro is to make it easy to generate unsafe
/// boiler plate for using listeners with Rust data.
///
/// However, there are a few things this macro doesn't protect against.
///
/// First and foremost, the data cannot move. The listeners assume that the
/// structure will never move, so in order to defend against this the generated
/// `new` method returns a Box version. **Do not move out of the box**.
///
/// Second, this macro doesn't protect against the stored data being unsized.
/// Passing a pointer of unsized data to C is UB, don't do it.
#[macro_export]
macro_rules! wayland_listener {
    ($struct_name: ident, $data: ty, $([
        $($listener: ident => $listener_func: ident :
          |$($func_arg:ident: $func_type:ty,)*| unsafe $body: block;)*])+) => {
        #[repr(C)]
        pub struct $struct_name {
            data: $data,
            $($($listener: $crate::wlroots_sys::wl_listener),*)*
        }

        impl $struct_name {
            pub fn new(data: $data) -> Box<$struct_name> {
                use $crate::wayland_sys::server::WAYLAND_SERVER_HANDLE;
                Box::new($struct_name {
                    data,
                    $($($listener: unsafe {
                        // NOTE Rationale for zeroed memory:
                        // * Need to pass a pointer to wl_list_init
                        // * The list is initialized by Wayland, which doesn't "drop"
                        // * The listener is written to without dropping any of the data
                        let mut listener: $crate::wlroots_sys::wl_listener = ::std::mem::zeroed();
                        ffi_dispatch!(WAYLAND_SERVER_HANDLE,
                                      wl_list_init,
                                      &mut listener.link as *mut _ as _);
                        ::std::ptr::write(&mut listener.notify, Some($struct_name::$listener_func));
                        listener
                    }),*)*
                })
            }

            $($(pub unsafe extern "C" fn $listener(&mut self)
                                                   -> *mut $crate::wlroots_sys::wl_listener {
                &mut self.$listener as *mut _
            })*)*

            $($(pub unsafe extern "C" fn $listener_func(listener:
                                                        *mut $crate::wlroots_sys::wl_listener,
                                                        data: *mut libc::c_void) {
                let manager: &mut $struct_name = &mut (*container_of!(listener,
                                                                      $struct_name,
                                                                      $listener));
                $crate::utils::handle_unwind(
                    ::std::panic::catch_unwind(
                        ::std::panic::AssertUnwindSafe(|| {
                            (|$($func_arg: $func_type,)*| { $body })(manager, data)
                        })));
            })*)*
        }
    }
}

/// Used to indicate what data is global compositor data.
/// It will automatically implement the CompositorData trait for the struct,
/// and also add a method to `Compositor` to unwrap the data from the fat
/// pointer.
#[macro_export]
macro_rules! compositor_data {
    ($struct_name: ty) => {
        impl<'a>::std::convert::From<&'a mut $crate::Compositor> for &'a mut $struct_name {
            fn from(compositor: &'a mut $crate::Compositor) -> &'a mut $struct_name {
                &mut *compositor.data.downcast_mut::<$struct_name>()
                    .unwrap_or_else(|| {
                        wlr_log!(L_ERROR, "Could not cast compositor state to {:#?}",
                                 stringify!($struct_name));
                        panic!("Could not cast compositor state to correct value")
                    })
            }
        }
    }
}
<commit_msg>Unexport macros, don't run macro doc test<commit_after>/// Gets the offset of a field. Used by container_of!
macro_rules! offset_of(
    ($ty:ty, $field:ident) => {
        &(*(0 as *const $ty)).$field as *const _ as usize
    }
);

/// Gets the parent struct from a pointer.
/// VERY unsafe. The parent struct _must_ be repr(C), and the
/// type passed to this macro _must_ match the type of the parent.
macro_rules! container_of (
    ($ptr: expr, $container: ty, $field: ident) => {
        ($ptr as *mut u8).offset(-(offset_of!($container, $field) as isize)) as *mut $container
    }
);

/// Convert a literal string to a C string.
/// Note: Does not check for internal nulls, nor does it do any conversions on
/// the grapheme clustors. Just passes the bytes as is.
/// So probably only works on ASCII.
#[macro_export]
macro_rules! c_str {
    ($s:expr) => {
        concat!($s, "\0").as_ptr() as *const i8
    }
}

/// Logs a message using wlroots' logging capability.
///
/// Possible values for `verb`:
///
/// * L_SILENT
/// * L_INFO
/// * L_DEBUG
/// * L_ERROR
#[macro_export]
macro_rules! wlr_log {
    ($verb: expr, $($msg:tt)*) => {{
        use $crate::wlroots_sys::_wlr_log;
        use $crate::wlroots_sys::log_importance_t::*;
        use ::std::ffi::CString;
        unsafe {
            let fmt = CString::new(format!($($msg)*))
                .expect("Could not convert log message to C string");
            let raw = fmt.into_raw();
            _wlr_log($verb, c_str!("[%s:%lu] %s"),
                    c_str!(file!()), line!(), raw);
            // Deallocate string
            CString::from_raw(raw);
        }
    }}
}

/// Defines a new struct that contains a variable number of listeners that
/// will trigger unsafe user-defined callbacks.
///
/// The structure that is defined is repr(C), has one `data` field with the
/// given user type, and a field for each `$listener`.
///
/// Each `$listener` has a getter method that lets you get the pointer to the
/// listener. This method is unsafe, since it returns a raw pointer.
/// To use it correctly, you need to ensure that the data it refers to never
/// moves (e.g keep it in a box). The primary purpose of this method is to pass
/// the listener pointer to other methods to register it for a Wayland event.
/// **A listener can only be registered to one event at a time**.
///
/// Finally, it also takes in a body for each `$listener` that is called
/// every time the event that is later hooked up to it is fired.
/// This method is inherently unsafe, because the user data hasn't been cast
/// from the void pointer yet. It is the user's job to write this safely.
/// To highlight this fact, the body of the function must be prefixed with
/// `unsafe`.
///
/// # Example
/// ```rust,no_run,ignore
/// #[macro_use] extern crate wlroots;
/// extern crate wlroots_sys;
/// #[macro_use] extern crate wayland_sys;
/// extern crate libc;
///
/// use wlroots::InputDevice;
/// use wlroots_sys::wlr_input_device;
///
/// // Handles input addition and removal.
/// pub trait InputManagerHandler {
///     // Callback triggered when an input device is added.
///     fn input_added(&mut self, InputDevice);
/// }
///
/// wayland_listener!(
///     // The name of the structure that will be defined.
///     InputManager,
///     // The type that's stored in the `data` field.
///     // Note that we use a Box here to achieve dynamic dispatch,
///     // it's not required for this type to be in a box.
///     Box<InputManagerHandler>,
///     [
///         // Adds a new listener called `add_listener`.
///         // Adds an unsafe function called `add_notify` that is triggered
///         // whenever add_listener is activated from a Wayland event.
///         add_listener => add_notify: |this: &mut InputManager, data: *mut libc::c_void,| unsafe {
///             let ref mut manager = this.data;
///             // Call the method defined above, wrapping it in a safe interface.
///             // It is your job to ensure that the code in here doesn't trigger UB!
///             manager.input_added(InputDevice::from_ptr(data as *mut wlr_input_device))
///         };
///     ]
/// );
/// # fn main() {}
/// ```
///
/// # Unsafety
/// Note that the purpose of this macro is to make it easy to generate unsafe
/// boiler plate for using listeners with Rust data.
///
/// However, there are a few things this macro doesn't protect against.
///
/// First and foremost, the data cannot move. The listeners assume that the
/// structure will never move, so in order to defend against this the generated
/// `new` method returns a Box version. **Do not move out of the box**.
///
/// Second, this macro doesn't protect against the stored data being unsized.
/// Passing a pointer of unsized data to C is UB, don't do it.
macro_rules! wayland_listener {
    ($struct_name: ident, $data: ty, $([
        $($listener: ident => $listener_func: ident :
          |$($func_arg:ident: $func_type:ty,)*| unsafe $body: block;)*])+) => {
        #[repr(C)]
        pub struct $struct_name {
            data: $data,
            $($($listener: $crate::wlroots_sys::wl_listener),*)*
        }

        impl $struct_name {
            pub fn new(data: $data) -> Box<$struct_name> {
                use $crate::wayland_sys::server::WAYLAND_SERVER_HANDLE;
                Box::new($struct_name {
                    data,
                    $($($listener: unsafe {
                        // NOTE Rationale for zeroed memory:
                        // * Need to pass a pointer to wl_list_init
                        // * The list is initialized by Wayland, which doesn't "drop"
                        // * The listener is written to without dropping any of the data
                        let mut listener: $crate::wlroots_sys::wl_listener = ::std::mem::zeroed();
                        ffi_dispatch!(WAYLAND_SERVER_HANDLE,
                                      wl_list_init,
                                      &mut listener.link as *mut _ as _);
                        ::std::ptr::write(&mut listener.notify, Some($struct_name::$listener_func));
                        listener
                    }),*)*
                })
            }

            $($(pub unsafe extern "C" fn $listener(&mut self)
                                                   -> *mut $crate::wlroots_sys::wl_listener {
                &mut self.$listener as *mut _
            })*)*

            $($(pub unsafe extern "C" fn $listener_func(listener:
                                                        *mut $crate::wlroots_sys::wl_listener,
                                                        data: *mut libc::c_void) {
                let manager: &mut $struct_name = &mut (*container_of!(listener,
                                                                      $struct_name,
                                                                      $listener));
                $crate::utils::handle_unwind(
                    ::std::panic::catch_unwind(
                        ::std::panic::AssertUnwindSafe(|| {
                            (|$($func_arg: $func_type,)*| { $body })(manager, data)
                        })));
            })*)*
        }
    }
}

/// Used to indicate what data is global compositor data.
/// It will automatically implement the CompositorData trait for the struct,
/// and also add a method to `Compositor` to unwrap the data from the fat
/// pointer.
#[macro_export]
macro_rules! compositor_data {
    ($struct_name: ty) => {
        impl<'a>::std::convert::From<&'a mut $crate::Compositor> for &'a mut $struct_name {
            fn from(compositor: &'a mut $crate::Compositor) -> &'a mut $struct_name {
                &mut *compositor.data.downcast_mut::<$struct_name>()
                    .unwrap_or_else(|| {
                        wlr_log!(L_ERROR, "Could not cast compositor state to {:#?}",
                                 stringify!($struct_name));
                        panic!("Could not cast compositor state to correct value")
                    })
            }
        }
    }
}
<|endoftext|>


<commit_before>//! Various macros

/// Generates an integer type `Name` where computations are done modulo `m`
#[macro_export]
macro_rules! define_modulo_ring(
($Name:ident, $m:expr) => (
#[deriving(PartialEq,Clone)]
struct $Name {
    value: i64
}
impl $Name {
    fn new(v: i64) -> $Name {
        let x=v%$m;
        if x < 0 {
            $Name { value: x + $m }
        } else {
            $Name { value: x }
        }
    }
}
impl core::fmt::Show for $Name {
    fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {
        write!(fmt, "{} (mod {})", self.value, $m)
    }
}
impl Add<$Name,$Name> for $Name {
    fn add(&self, other: &$Name) -> $Name {
        $Name { value: (self.value + other.value)%$m }
    }
}
impl Sub<$Name,$Name> for $Name {
    fn sub(&self, other: &$Name) -> $Name {
        $Name { value: (self.value - other.value)%$m }
    }
}
impl Mul<$Name,$Name> for $Name {
    fn mul(&self, other: &$Name) -> $Name {
        $Name { value: (self.value*other.value)%$m }
    }
}
impl Div<$Name,$Name> for $Name {
    fn div(&self, other: &$Name) -> $Name {
        let inv=algoritmoi::modint::invert_mod(other.value, $m);
        match inv {
            Some(i) => $Name::new(self.value*i),
            _ => fail!("Trying to divide by {} modulo {}", other.value, $m)
        }
    }
}
impl core::num::One for $Name {
    fn one() -> $Name {
        $Name { value: core::num::One::one() }
    }
}
impl core::num::Zero for $Name {
    fn zero() -> $Name {
        $Name { value: core::num::Zero::zero() }
    }
    fn is_zero(&self) -> bool {
        self.value%$m == 0
    }
}
impl FromPrimitive for $Name {
    fn from_i64(n: i64) -> Option<$Name> {
        Some($Name { value: n%$m })
    }
    fn from_u64(n: u64) -> Option<$Name> {
        Some($Name { value: (n%$m) as i64 })
    }
}
)
)

<commit_msg>Replaced an old reference to modint.<commit_after>//! Various macros

/// Generates an integer type `Name` where computations are done modulo `m`
#[macro_export]
macro_rules! define_modulo_ring(
($Name:ident, $m:expr) => (
#[deriving(PartialEq,Clone)]
struct $Name {
    value: i64
}
impl $Name {
    fn new(v: i64) -> $Name {
        let x=v%$m;
        if x < 0 {
            $Name { value: x + $m }
        } else {
            $Name { value: x }
        }
    }
}
impl core::fmt::Show for $Name {
    fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {
        write!(fmt, "{} (mod {})", self.value, $m)
    }
}
impl Add<$Name,$Name> for $Name {
    fn add(&self, other: &$Name) -> $Name {
        $Name { value: (self.value + other.value)%$m }
    }
}
impl Sub<$Name,$Name> for $Name {
    fn sub(&self, other: &$Name) -> $Name {
        $Name { value: (self.value - other.value)%$m }
    }
}
impl Mul<$Name,$Name> for $Name {
    fn mul(&self, other: &$Name) -> $Name {
        $Name { value: (self.value*other.value)%$m }
    }
}
impl Div<$Name,$Name> for $Name {
    fn div(&self, other: &$Name) -> $Name {
        let inv=algoritmoi::moduli::invert_mod(other.value, $m);
        match inv {
            Some(i) => $Name::new(self.value*i),
            _ => fail!("Trying to divide by {} modulo {}", other.value, $m)
        }
    }
}
impl core::num::One for $Name {
    fn one() -> $Name {
        $Name { value: core::num::One::one() }
    }
}
impl core::num::Zero for $Name {
    fn zero() -> $Name {
        $Name { value: core::num::Zero::zero() }
    }
    fn is_zero(&self) -> bool {
        self.value%$m == 0
    }
}
impl FromPrimitive for $Name {
    fn from_i64(n: i64) -> Option<$Name> {
        Some($Name { value: n%$m })
    }
    fn from_u64(n: u64) -> Option<$Name> {
        Some($Name { value: (n%$m) as i64 })
    }
}
)
)

<|endoftext|>


<commit_before>
macro_rules! bit_struct {
    (
        $(#[$attr:meta])*
        pub struct $struct_name:ident {
            $(pub $field_name:ident : $field_type:ty),+
        }
        deserialize($reader:ident) {
            $($field:ident : { $($tokens:tt)+ }),+
        }
    ) => (
        $(#[$attr])*
        pub struct $struct_name {
            $(pub $field_name: $field_type),+
        }
        impl ::base::Deserialize for $struct_name {
            fn deserialize($reader: &mut ::bitreader::BitReader) -> ::base::DeserializationResult<$struct_name> {
                $( bit_struct!(field $field : $reader : { $($tokens)+ } ); )+
                Ok($struct_name {
                    $($field_name: $field_name),+
                })
            }
        }
    );

    (field reserved : $reader:ident : { $bits:expr }) => (
        try!(::base::reserved($reader, $bits))
    );

    (field expect : $reader:ident : { bits: $bits:expr, reference: $value:expr }) => (
        try!(::base::expect($reader, $bits, $value))
    );

    (field crc : $reader:ident : { 32 }) => (
        try!($reader.skip(32));
    );

    (field $field:ident : $reader:ident : { value : $e:expr }) => (
        let $field = $e;
    );

    (field $field:ident : $reader:ident : { $bits:expr }) => (
        let $field = try!(::bitreader::ReadInto::read($reader, $bits));
    );

    (field $field:ident : $reader:ident : { $bits:expr, map: $closure:expr }) => (
        let $field = ($closure)(try!(::bitreader::ReadInto::read($reader, $bits)));
    );

    (field $field:ident : $reader:ident : { $bits:expr, type: $T:ty }) => (
        let $field: $T = try!(::bitreader::ReadInto::read($reader, $bits));
    );
}
<commit_msg>Add 'skip' special field to bit_struct!().<commit_after>
macro_rules! bit_struct {
    (
        $(#[$attr:meta])*
        pub struct $struct_name:ident {
            $(pub $field_name:ident : $field_type:ty),+
        }
        deserialize($reader:ident) {
            $($field:ident : { $($tokens:tt)+ }),+
        }
    ) => (
        $(#[$attr])*
        pub struct $struct_name {
            $(pub $field_name: $field_type),+
        }
        impl ::base::Deserialize for $struct_name {
            fn deserialize($reader: &mut ::bitreader::BitReader) -> ::base::DeserializationResult<$struct_name> {
                $( bit_struct!(field $field : $reader : { $($tokens)+ } ); )+
                Ok($struct_name {
                    $($field_name: $field_name),+
                })
            }
        }
    );

    (field reserved : $reader:ident : { $bits:expr }) => (
        try!(::base::reserved($reader, $bits))
    );

    (field expect : $reader:ident : { bits: $bits:expr, reference: $value:expr }) => (
        try!(::base::expect($reader, $bits, $value))
    );

    (field crc : $reader:ident : { 32 }) => (
        try!($reader.skip(32));
    );

    (field skip : $reader:ident : { $bits:expr }) => (
        try!($reader.skip($bits));
    );

    (field $field:ident : $reader:ident : { value : $e:expr }) => (
        let $field = $e;
    );

    (field $field:ident : $reader:ident : { $bits:expr }) => (
        let $field = try!(::bitreader::ReadInto::read($reader, $bits));
    );

    (field $field:ident : $reader:ident : { $bits:expr, map: $closure:expr }) => (
        let $field = ($closure)(try!(::bitreader::ReadInto::read($reader, $bits)));
    );

    (field $field:ident : $reader:ident : { $bits:expr, type: $T:ty }) => (
        let $field: $T = try!(::bitreader::ReadInto::read($reader, $bits));
    );
}
<|endoftext|>


<commit_before>//! This module is UNSTABLE, the reason is - recently added.
<commit_msg>ValueRef: writing nil value.<commit_after>//! This module is UNSTABLE, the reason is - recently added.

use std::convert::From;
use std::io::Write;

use super::super::value::ValueRef;
use super::*;

#[derive(Debug)]
pub struct Error(WriteError);

impl From<FixedValueWriteError> for Error {
    fn from(err: FixedValueWriteError) -> Error {
        match err {
            FixedValueWriteError(err) => Error(err)
        }
    }
}

pub fn write_value_ref<W>(wr: &mut W, val: &ValueRef) -> Result<(), Error>
    where W: Write
{
    match val {
        &ValueRef::Nil => try!(write_nil(wr)),
        _ => unimplemented!(),
    }

    Ok(())
}
<|endoftext|>


<commit_before>//! Define trait for general matrix

use std::cmp::min;
use ndarray::prelude::*;
use ndarray::LinalgScalar;
use lapack::c::Layout;

use error::LapackError;
use qr::ImplQR;
use svd::ImplSVD;
use norm::ImplNorm;
use solve::ImplSolve;

/// Methods for general matrices
pub trait Matrix: Sized {
    type Scalar;
    type Vector;
    type Permutator;
    /// number of (rows, columns)
    fn size(&self) -> (usize, usize);
    /// Layout (C/Fortran) of matrix
    fn layout(&self) -> Layout;
    /// Operator norm for L-1 norm
    fn norm_1(&self) -> Self::Scalar;
    /// Operator norm for L-inf norm
    fn norm_i(&self) -> Self::Scalar;
    /// Frobenius norm
    fn norm_f(&self) -> Self::Scalar;
    /// singular-value decomposition (SVD)
    fn svd(self) -> Result<(Self, Self::Vector, Self), LapackError>;
    /// QR decomposition
    fn qr(self) -> Result<(Self, Self), LapackError>;
    /// LU decomposition
    fn lu(self) -> Result<(Self::Permutator, Self, Self), LapackError>;
    /// permutate matrix
    fn permutate_column(self, p: &Self::Permutator) -> Self;
    /// permutate matrix
    fn permutate_row(self, p: &Self::Permutator) -> Self;
}

impl<A> Matrix for Array<A, (Ix, Ix)>
    where A: ImplQR + ImplSVD + ImplNorm + ImplSolve + LinalgScalar
{
    type Scalar = A;
    type Vector = Array<A, Ix>;
    type Permutator = Vec<i32>;

    fn size(&self) -> (usize, usize) {
        (self.rows(), self.cols())
    }
    fn layout(&self) -> Layout {
        let strides = self.strides();
        if strides[0] < strides[1] {
            Layout::ColumnMajor
        } else {
            Layout::RowMajor
        }
    }
    fn norm_1(&self) -> Self::Scalar {
        let (m, n) = self.size();
        let strides = self.strides();
        if strides[0] > strides[1] {
            ImplNorm::norm_i(n, m, self.clone().into_raw_vec())
        } else {
            ImplNorm::norm_1(m, n, self.clone().into_raw_vec())
        }
    }
    fn norm_i(&self) -> Self::Scalar {
        let (m, n) = self.size();
        let strides = self.strides();
        if strides[0] > strides[1] {
            ImplNorm::norm_1(n, m, self.clone().into_raw_vec())
        } else {
            ImplNorm::norm_i(m, n, self.clone().into_raw_vec())
        }
    }
    fn norm_f(&self) -> Self::Scalar {
        let (m, n) = self.size();
        ImplNorm::norm_f(m, n, self.clone().into_raw_vec())
    }
    fn svd(self) -> Result<(Self, Self::Vector, Self), LapackError> {
        let strides = self.strides();
        let (m, n) = if strides[0] > strides[1] {
            self.size()
        } else {
            let (n, m) = self.size();
            (m, n)
        };
        let (u, s, vt) = try!(ImplSVD::svd(m, n, self.clone().into_raw_vec()));
        let sv = Array::from_vec(s);
        if strides[0] > strides[1] {
            let ua = Array::from_vec(u).into_shape((n, n)).unwrap();
            let va = Array::from_vec(vt).into_shape((m, m)).unwrap();
            Ok((va, sv, ua))
        } else {
            let ua = Array::from_vec(u).into_shape((n, n)).unwrap().reversed_axes();
            let va = Array::from_vec(vt).into_shape((m, m)).unwrap().reversed_axes();
            Ok((ua, sv, va))
        }
    }
    fn qr(self) -> Result<(Self, Self), LapackError> {
        let (n, m) = self.size();
        let strides = self.strides();
        let k = min(n, m);
        let (q, r) = if strides[0] < strides[1] {
            try!(ImplQR::qr(m, n, self.clone().into_raw_vec()))
        } else {
            try!(ImplQR::lq(n, m, self.clone().into_raw_vec()))
        };
        let (qa, ra) = if strides[0] < strides[1] {
            (Array::from_vec(q).into_shape((m, n)).unwrap().reversed_axes(),
             Array::from_vec(r).into_shape((m, n)).unwrap().reversed_axes())
        } else {
            (Array::from_vec(q).into_shape((n, m)).unwrap(),
             Array::from_vec(r).into_shape((n, m)).unwrap())
        };
        let qm = if m > k {
            let (qsl, _) = qa.view().split_at(Axis(1), k);
            qsl.to_owned()
        } else {
            qa
        };
        let mut rm = if n > k {
            let (rsl, _) = ra.view().split_at(Axis(0), k);
            rsl.to_owned()
        } else {
            ra
        };
        for ((i, j), val) in rm.indexed_iter_mut() {
            if i > j {
                *val = A::zero();
            }
        }
        Ok((qm, rm))
    }
    fn lu(self) -> Result<(Self::Permutator, Self, Self), LapackError> {
        let (n, m) = self.size();
        let (p, l) = try!(ImplSolve::lu(self.layout(), n, m, self.clone().into_raw_vec()));
        let mut lm = Array::from_vec(l).into_shape((m, n)).unwrap();
        let mut um = Array::zeros((n, m));
        match self.layout() {
            Layout::ColumnMajor => {
                for ((i, j), val) in um.indexed_iter_mut() {
                    if i < j {
                        *val = lm[(i, j)];
                    } else if i == j {
                        *val = A::one();
                    }
                }
                for ((i, j), val) in lm.indexed_iter_mut() {
                    if i < j {
                        *val = A::zero();
                    }
                }
                Ok((p, um.reversed_axes(), lm.reversed_axes()))
            }
            Layout::RowMajor => {
                for ((i, j), val) in um.indexed_iter_mut() {
                    if i > j {
                        *val = lm[(i, j)];
                    } else if i == j {
                        *val = A::one();
                    }
                }
                for ((i, j), val) in lm.indexed_iter_mut() {
                    if i > j {
                        *val = A::zero();
                    }
                }
                Ok((p, lm, um))
            }
        }
    }
    fn permutate_column(self, p: &Self::Permutator) -> Self {
        let (n, m) = self.size();
        let pd = ImplSolve::permutate_column(self.layout(), n, m, self.clone().into_raw_vec(), p);
        match self.layout() {
            Layout::ColumnMajor => Array::from_vec(pd).into_shape((m, n)).unwrap().reversed_axes(),
            Layout::RowMajor => Array::from_vec(pd).into_shape((m, n)).unwrap(),
        }
    }
    fn permutate_row(self, p: &Self::Permutator) -> Self {
        let (n, m) = self.size();
        let pd = ImplSolve::permutate_column(self.layout(), m, n, self.clone().into_raw_vec(), p);
        Array::from_vec(pd).into_shape((n, m)).unwrap()
    }
}
<commit_msg>Bug fixed<commit_after>//! Define trait for general matrix

use std::cmp::min;
use ndarray::prelude::*;
use ndarray::LinalgScalar;
use lapack::c::Layout;

use error::LapackError;
use qr::ImplQR;
use svd::ImplSVD;
use norm::ImplNorm;
use solve::ImplSolve;

/// Methods for general matrices
pub trait Matrix: Sized {
    type Scalar;
    type Vector;
    type Permutator;
    /// number of (rows, columns)
    fn size(&self) -> (usize, usize);
    /// Layout (C/Fortran) of matrix
    fn layout(&self) -> Layout;
    /// Operator norm for L-1 norm
    fn norm_1(&self) -> Self::Scalar;
    /// Operator norm for L-inf norm
    fn norm_i(&self) -> Self::Scalar;
    /// Frobenius norm
    fn norm_f(&self) -> Self::Scalar;
    /// singular-value decomposition (SVD)
    fn svd(self) -> Result<(Self, Self::Vector, Self), LapackError>;
    /// QR decomposition
    fn qr(self) -> Result<(Self, Self), LapackError>;
    /// LU decomposition
    fn lu(self) -> Result<(Self::Permutator, Self, Self), LapackError>;
    /// permutate matrix
    fn permutate_column(self, p: &Self::Permutator) -> Self;
    /// permutate matrix
    fn permutate_row(self, p: &Self::Permutator) -> Self;
}

impl<A> Matrix for Array<A, (Ix, Ix)>
    where A: ImplQR + ImplSVD + ImplNorm + ImplSolve + LinalgScalar
{
    type Scalar = A;
    type Vector = Array<A, Ix>;
    type Permutator = Vec<i32>;

    fn size(&self) -> (usize, usize) {
        (self.rows(), self.cols())
    }
    fn layout(&self) -> Layout {
        let strides = self.strides();
        if strides[0] < strides[1] {
            Layout::ColumnMajor
        } else {
            Layout::RowMajor
        }
    }
    fn norm_1(&self) -> Self::Scalar {
        let (m, n) = self.size();
        let strides = self.strides();
        if strides[0] > strides[1] {
            ImplNorm::norm_i(n, m, self.clone().into_raw_vec())
        } else {
            ImplNorm::norm_1(m, n, self.clone().into_raw_vec())
        }
    }
    fn norm_i(&self) -> Self::Scalar {
        let (m, n) = self.size();
        let strides = self.strides();
        if strides[0] > strides[1] {
            ImplNorm::norm_1(n, m, self.clone().into_raw_vec())
        } else {
            ImplNorm::norm_i(m, n, self.clone().into_raw_vec())
        }
    }
    fn norm_f(&self) -> Self::Scalar {
        let (m, n) = self.size();
        ImplNorm::norm_f(m, n, self.clone().into_raw_vec())
    }
    fn svd(self) -> Result<(Self, Self::Vector, Self), LapackError> {
        let strides = self.strides();
        let (m, n) = if strides[0] > strides[1] {
            self.size()
        } else {
            let (n, m) = self.size();
            (m, n)
        };
        let (u, s, vt) = try!(ImplSVD::svd(m, n, self.clone().into_raw_vec()));
        let sv = Array::from_vec(s);
        if strides[0] > strides[1] {
            let ua = Array::from_vec(u).into_shape((n, n)).unwrap();
            let va = Array::from_vec(vt).into_shape((m, m)).unwrap();
            Ok((va, sv, ua))
        } else {
            let ua = Array::from_vec(u).into_shape((n, n)).unwrap().reversed_axes();
            let va = Array::from_vec(vt).into_shape((m, m)).unwrap().reversed_axes();
            Ok((ua, sv, va))
        }
    }
    fn qr(self) -> Result<(Self, Self), LapackError> {
        let (n, m) = self.size();
        let strides = self.strides();
        let k = min(n, m);
        let (q, r) = if strides[0] < strides[1] {
            try!(ImplQR::qr(m, n, self.clone().into_raw_vec()))
        } else {
            try!(ImplQR::lq(n, m, self.clone().into_raw_vec()))
        };
        let (qa, ra) = if strides[0] < strides[1] {
            (Array::from_vec(q).into_shape((m, n)).unwrap().reversed_axes(),
             Array::from_vec(r).into_shape((m, n)).unwrap().reversed_axes())
        } else {
            (Array::from_vec(q).into_shape((n, m)).unwrap(),
             Array::from_vec(r).into_shape((n, m)).unwrap())
        };
        let qm = if m > k {
            let (qsl, _) = qa.view().split_at(Axis(1), k);
            qsl.to_owned()
        } else {
            qa
        };
        let mut rm = if n > k {
            let (rsl, _) = ra.view().split_at(Axis(0), k);
            rsl.to_owned()
        } else {
            ra
        };
        for ((i, j), val) in rm.indexed_iter_mut() {
            if i > j {
                *val = A::zero();
            }
        }
        Ok((qm, rm))
    }
    fn lu(self) -> Result<(Self::Permutator, Self, Self), LapackError> {
        let (n, m) = self.size();
        let (p, l) = try!(ImplSolve::lu(self.layout(), n, m, self.clone().into_raw_vec()));
        let mut lm = Array::from_vec(l).into_shape((m, n)).unwrap();
        let mut um = Array::zeros((n, m));
        match self.layout() {
            Layout::ColumnMajor => {
                println!("ColumnMajor");
                for ((i, j), val) in um.indexed_iter_mut() {
                    if i < j {
                        *val = lm[(i, j)];
                    } else if i == j {
                        *val = A::one();
                    }
                }
                for ((i, j), val) in lm.indexed_iter_mut() {
                    if i < j {
                        *val = A::zero();
                    }
                }
                Ok((p, um.reversed_axes(), lm.reversed_axes()))
            }
            Layout::RowMajor => {
                println!("RowMajor");
                for ((i, j), val) in um.indexed_iter_mut() {
                    if i <= j {
                        *val = lm[(i, j)];
                    }
                }
                for ((i, j), val) in lm.indexed_iter_mut() {
                    if i < j {
                        *val = A::zero();
                    } else if i == j {
                        *val = A::one();
                    }
                }
                Ok((p, lm, um))
            }
        }
    }
    fn permutate_column(self, p: &Self::Permutator) -> Self {
        let (n, m) = self.size();
        let pd = ImplSolve::permutate_column(self.layout(), n, m, self.clone().into_raw_vec(), p);
        match self.layout() {
            Layout::ColumnMajor => Array::from_vec(pd).into_shape((m, n)).unwrap().reversed_axes(),
            Layout::RowMajor => Array::from_vec(pd).into_shape((m, n)).unwrap(),
        }
    }
    fn permutate_row(self, p: &Self::Permutator) -> Self {
        let (n, m) = self.size();
        let pd = ImplSolve::permutate_column(self.layout(), m, n, self.clone().into_raw_vec(), p);
        Array::from_vec(pd).into_shape((n, m)).unwrap()
    }
}
<|endoftext|>


<commit_before>//! # Glulx memory mapping
//!
//! The Glulx machine memory consists of a ROM and RAM, which themselves
//! are separated into several different groups.
//!
//!
//! ## Program Provided Values
//!
//! The following values are defined by the given program:
//!
//! * RAMSTART -- Specifies the starting point of the RAM
//! * EXTSTART -- Specifies start of zeroed section of RAM
//! * ENDMEM -- Specifies the ending point of the RAM
//!
//!
//! ## ROM
//!
//! The ROM is defined by the following:
//!
//! * The ROM ranges from 0x00000000 to RAMSTART.
//! * The Header ranges from 0x00000000 to 0x00000024.
//! * The ROM is read-only.
//! * The ROM must be at least 0x100 bytes long.
//! * The ROM usually (but not always) contains all the executable code
//! and constants for the loaded program.
//!
//!
//! ## RAM
//!
//! The RAM is defined by the following:
//!
//! * The RAM ranges from RAMSTART to ENDMEM
//! * The RAM from EXTSTART to ENDMEM is initialized to all zeros.
//! * The RAM can be 0x0 bytes long.
//!
//! ## Misc
//!
//! * RAMSTART, EXTSTART, and ENDMEM must be aligned on 0x100 byte
//! boundries
//! * A Glulx gamefile only stores data from 0x0 to EXTSTART.

use byteorder::{BigEndian, ByteOrder};

/// Glulx magic number
const MAGIC_NUMBER: u32 = 0x476C756C;

/// Minimum supported glulx target
const MIN_VERSION: u32 = 0x0020000;

/// Maximum supported glulx target
const MAX_VERSION: u32 = 0x00301FF;

/// Struct representing a glulx memory object.
pub struct GlulxMemory {
    heap_mode: bool,
    memory: Vec<u8>,
}

impl GlulxMemory {

    /// This takes a rom, validates it to verify that it is a valid
    /// Glulx rom, and retuns either an error string or a `GlulxMemory`
    /// TODO: Replace error string with custom glulx error type.
    pub fn from_rom(rom: Vec<u8>) -> Result<GlulxMemory, String> {
        // Validate magic number.
        let magic_number = BigEndian::read_u32(&rom[0x0..0x4]);
        if magic_number != MAGIC_NUMBER {
            return Err("executable code starts with invalid magic number"
                .to_string());
        }

        // Validate glulx version.
        let glulx_version = BigEndian::read_u32(&rom[0x4..0x8]);
        if glulx_version < MIN_VERSION {
            return Err("executable code glulx version is less than 2.0.0"
                .to_string());
        } else if glulx_version > MAX_VERSION {
            return Err("executable code glulx version is greater than 3.1.x"
                .to_string());
        }

        // Validate ramstart value.
        let ramstart = BigEndian::read_u32(&rom[0x8..0xC]);
        if ramstart < 0x100 {
            return Err("ramstart is less than 0x100 bytes".to_string());
        } else if ramstart % 0x100 != 0 {
            return Err("ramstart is misaligned".to_string());
        }

        // Validate extstart value.
        let extstart = BigEndian::read_u32(&rom[0xC..0x10]);
        if extstart < ramstart {
            return Err("extstart is less than ramstart".to_string());
        } else if extstart % 0x100 != 0 {
            return Err("extstart is misaligned".to_string());
        }

        // Validate endmem value.
        let endmem = BigEndian::read_u32(&rom[0x10..0x14]);
        if endmem < extstart {
            return Err("endmem is less than extstart".to_string());
        } else if endmem % 0x100 != 0 {
            return Err("endmem is misaligned".to_string());
        }

        // Validate stack size.
        let stack_size = BigEndian::read_u32(&rom[0x14..0x18]);
        if stack_size % 0x100 != 0 {
            return Err("stack size is misaligned".to_string());
        }

        if endmem as usize != rom.len() {
            return Err("rom size is not correct".to_string());
        }

        let checksum = BigEndian::read_u32(&rom[0x20..0x24]);
        let sum = {
            let mut sum = 0u32;
            for i in 0..rom.len()/4 {
                sum = sum.wrapping_add(BigEndian::read_u32(&rom[i*4..]));
            }
            sum.wrapping_sub(checksum)
        };
        if checksum != sum {
            return Err("rom checksum is not correct".to_string());
        }

        let mut rom = rom;
        let ext_size = (endmem - extstart) as usize;
        rom.reserve_exact(ext_size);
        rom.resize(endmem as usize, 0x0);

        Ok(GlulxMemory { heap_mode: false, memory: rom })
    }

    pub fn zero_range(&mut self, size: u32, ptr: u32){
        for i in ptr as usize..(ptr + size) as usize {
            self.memory[i] = 0;
        }
    }

    pub fn copy_range(&mut self, size: u32, from_ptr: u32, to_ptr: u32){
        let to_ptr = to_ptr as usize;
        let from_ptr = from_ptr as usize;

        for i in 0x0..size as usize {
            self.memory[to_ptr + i] = self.memory[from_ptr + i];
        }
    }

    // Header value functions.

    /// The glulx magic number, stored from `0x0..0x4` in the header.
    /// This number is unique to all glulx games. This value should be
    /// `0x476C756C`, which is equivalent to `b"Glul"`.
    fn magic_number(&self) -> u32 {
        BigEndian::read_u32(&self.memory[..0x4])
    }

    /// The glulx version number, stored from `0x4..0x8` in the header.
    /// First two bytes store the major version number. The next byte
    /// stores the minor version number. The final byte stores the patch
    /// version number.
    pub fn glulx_version(&self) -> u32 {
        BigEndian::read_u32(&self.memory[0x4..0x8])
    }

    /// The address indicating the start of the RAM, stored from
    /// `0x4..0x8` in the header. TODO: MOAR DATA
    fn ramstart(&self) -> u32 {
        BigEndian::read_u32(&self.memory[0x8..0xC])
    }

    fn extstart(&self) -> u32 {
        BigEndian::read_u32(&self.memory[0xC..0x10])
    }

    fn endmem(&self) -> u32 {
        BigEndian::read_u32(&self.memory[0x10..0x14])
    }

    pub fn stack_size(&self) -> u32 {
        BigEndian::read_u32(&self.memory[0x14..0x18])
    }

    pub fn start_func(&self) -> u32 {
        BigEndian::read_u32(&self.memory[0x18..0x1C])
    }

    fn decoding_tbl(&self) -> u32 {
        BigEndian::read_u32(&self.memory[0x1C..0x20])
    }

    /// The sum of the intial contents of memory, considered as an array
    /// of `u32`s. When calculated, the checksum value is considered to
    /// be `0`.
    fn checksum(&self) -> u32 {
        BigEndian::read_u32(&self.memory[0x20..0x24])
    }

    pub fn get_mem_size(&self) -> u32 {
        self.memory.len() as u32
    }

    /// Sets the memory size to the given value. This call only works if
    /// there is no active heap, the given value is a multiple of 0x100,
    /// and the value is greater than the ENDMEM value identified in the
    /// header.
    pub fn set_mem_size(&mut self, value: u32) -> u32 {
        if self.heap_mode
                && value % 0x100 == 0
                && value >= self.endmem() {
            self.memory.resize(value as usize, 0x0);
            0
        } else {
            1
        }
    }
}

pub trait Memory<T> {
    fn read(&self, ptr: u32) -> T;
    fn write(&mut self, ptr: u32, value: T);
    fn ram_read(&self, ptr: u32) -> T;
    fn ram_write(&mut self, ptr: u32, value: T);
}

impl Memory<u8> for GlulxMemory {
    fn read(&self, ptr: u32) -> u8 {
        self.memory[ptr as usize]
    }

    fn write(&mut self, ptr: u32, value: u8) {
        self.memory[ptr as usize] = value
    }

    fn ram_read(&self, ptr: u32) -> u8 {
        let ptr = (ptr + self.ramstart()) as usize;
        self.memory[ptr]
    }

    fn ram_write(&mut self, ptr: u32, value: u8) {
        let ptr = (ptr + self.ramstart()) as usize;
        self.memory[ptr] = value
    }
}

impl Memory<u16> for GlulxMemory {
    fn read(&self, ptr: u32) -> u16 {
        BigEndian::read_u16(&self.memory[ptr as usize..])
    }

    fn write(&mut self, ptr: u32, value: u16) {
        BigEndian::write_u16(&mut self.memory[ptr as usize..], value)
    }

    fn ram_read(&self, ptr: u32) -> u16 {
        let ptr = (ptr + self.ramstart()) as usize;
        BigEndian::read_u16(&self.memory[ptr..])
    }

    fn ram_write(&mut self, ptr: u32, value: u16) {
        let ptr = (ptr + self.ramstart()) as usize;
        BigEndian::write_u16(&mut self.memory[ptr..], value)
    }
}

impl Memory<u32> for GlulxMemory {
    fn read(&self, ptr: u32) -> u32 {
        BigEndian::read_u32(&self.memory[ptr as usize..])
    }

    fn write(&mut self, ptr: u32, value: u32) {
        BigEndian::write_u32(&mut self.memory[ptr as usize..], value)
    }

    fn ram_read(&self, ptr: u32) -> u32 {
        let ptr = (ptr + self.ramstart()) as usize;
        BigEndian::read_u32(&self.memory[ptr..])
    }

    fn ram_write(&mut self, ptr: u32, value: u32) {
        let ptr = (ptr + self.ramstart()) as usize;
        BigEndian::write_u32(&mut self.memory[ptr..], value)
    }
}

impl Memory<i32> for GlulxMemory {
    fn read(&self, ptr: u32) -> i32 {
        BigEndian::read_i32(&self.memory[ptr as usize..])
    }

    fn write(&mut self, ptr: u32, value: i32) {
        BigEndian::write_i32(&mut self.memory[ptr as usize..], value)
    }

    fn ram_read(&self, ptr: u32) -> i32 {
        let ptr = (ptr + self.ramstart()) as usize;
        BigEndian::read_i32(&self.memory[ptr..])
    }

    fn ram_write(&mut self, ptr: u32, value: i32) {
        let ptr = (ptr + self.ramstart()) as usize;
        BigEndian::write_i32(&mut self.memory[ptr..], value)
    }
}

impl Memory<f32> for GlulxMemory {
    fn read(&self, ptr: u32) -> f32 {
        BigEndian::read_f32(&self.memory[ptr as usize..])
    }

    fn write(&mut self, ptr: u32, value: f32) {
        BigEndian::write_f32(&mut self.memory[ptr as usize..], value)
    }

    fn ram_read(&self, ptr: u32) -> f32 {
        let ptr = (ptr + self.ramstart()) as usize;
        BigEndian::read_f32(&self.memory[ptr..])
    }

    fn ram_write(&mut self, ptr: u32, value: f32) {
        let ptr = (ptr + self.ramstart()) as usize;
        BigEndian::write_f32(&mut self.memory[ptr..], value)
    }
}
<commit_msg>changed endmem versus rom len check to allow rom length to be shorter than the endmem position<commit_after>//! # Glulx memory mapping
//!
//! The Glulx machine memory consists of a ROM and RAM, which themselves
//! are separated into several different groups.
//!
//!
//! ## Program Provided Values
//!
//! The following values are defined by the given program:
//!
//! * RAMSTART -- Specifies the starting point of the RAM
//! * EXTSTART -- Specifies start of zeroed section of RAM
//! * ENDMEM -- Specifies the ending point of the RAM
//!
//!
//! ## ROM
//!
//! The ROM is defined by the following:
//!
//! * The ROM ranges from 0x00000000 to RAMSTART.
//! * The Header ranges from 0x00000000 to 0x00000024.
//! * The ROM is read-only.
//! * The ROM must be at least 0x100 bytes long.
//! * The ROM usually (but not always) contains all the executable code
//! and constants for the loaded program.
//!
//!
//! ## RAM
//!
//! The RAM is defined by the following:
//!
//! * The RAM ranges from RAMSTART to ENDMEM
//! * The RAM from EXTSTART to ENDMEM is initialized to all zeros.
//! * The RAM can be 0x0 bytes long.
//!
//! ## Misc
//!
//! * RAMSTART, EXTSTART, and ENDMEM must be aligned on 0x100 byte
//! boundries
//! * A Glulx gamefile only stores data from 0x0 to EXTSTART.

use byteorder::{BigEndian, ByteOrder};

/// Glulx magic number
const MAGIC_NUMBER: u32 = 0x476C756C;

/// Minimum supported glulx target
const MIN_VERSION: u32 = 0x0020000;

/// Maximum supported glulx target
const MAX_VERSION: u32 = 0x00301FF;

/// Struct representing a glulx memory object.
pub struct GlulxMemory {
    heap_mode: bool,
    memory: Vec<u8>,
}

impl GlulxMemory {

    /// This takes a rom, validates it to verify that it is a valid
    /// Glulx rom, and retuns either an error string or a `GlulxMemory`
    /// TODO: Replace error string with custom glulx error type.
    pub fn from_rom(rom: Vec<u8>) -> Result<GlulxMemory, String> {
        // Validate magic number.
        let magic_number = BigEndian::read_u32(&rom[0x0..0x4]);
        if magic_number != MAGIC_NUMBER {
            return Err("executable code starts with invalid magic number"
                .to_string());
        }

        // Validate glulx version.
        let glulx_version = BigEndian::read_u32(&rom[0x4..0x8]);
        if glulx_version < MIN_VERSION {
            return Err("executable code glulx version is less than 2.0.0"
                .to_string());
        } else if glulx_version > MAX_VERSION {
            return Err("executable code glulx version is greater than 3.1.x"
                .to_string());
        }

        // Validate ramstart value.
        let ramstart = BigEndian::read_u32(&rom[0x8..0xC]);
        if ramstart < 0x100 {
            return Err("ramstart is less than 0x100 bytes".to_string());
        } else if ramstart % 0x100 != 0 {
            return Err("ramstart is misaligned".to_string());
        }

        // Validate extstart value.
        let extstart = BigEndian::read_u32(&rom[0xC..0x10]);
        if extstart < ramstart {
            return Err("extstart is less than ramstart".to_string());
        } else if extstart % 0x100 != 0 {
            return Err("extstart is misaligned".to_string());
        }

        // Validate endmem value.
        let endmem = BigEndian::read_u32(&rom[0x10..0x14]);
        if endmem < extstart {
            return Err("endmem is less than extstart".to_string());
        } else if endmem % 0x100 != 0 {
            return Err("endmem is misaligned".to_string());
        }

        // Validate stack size.
        let stack_size = BigEndian::read_u32(&rom[0x14..0x18]);
        if stack_size % 0x100 != 0 {
            return Err("stack size is misaligned".to_string());
        }

        if endmem as usize >= rom.len() {
            return Err("rom size is not correct".to_string());
        }

        let checksum = BigEndian::read_u32(&rom[0x20..0x24]);
        let sum = {
            let mut sum = 0u32;
            for i in 0..rom.len()/4 {
                sum = sum.wrapping_add(BigEndian::read_u32(&rom[i*4..]));
            }
            sum.wrapping_sub(checksum)
        };
        if checksum != sum {
            return Err("rom checksum is not correct".to_string());
        }

        let mut rom = rom;
        let ext_size = (endmem - extstart) as usize;
        rom.reserve_exact(ext_size);
        rom.resize(endmem as usize, 0x0);

        Ok(GlulxMemory { heap_mode: false, memory: rom })
    }

    pub fn zero_range(&mut self, size: u32, ptr: u32){
        for i in ptr as usize..(ptr + size) as usize {
            self.memory[i] = 0;
        }
    }

    pub fn copy_range(&mut self, size: u32, from_ptr: u32, to_ptr: u32){
        let to_ptr = to_ptr as usize;
        let from_ptr = from_ptr as usize;

        for i in 0x0..size as usize {
            self.memory[to_ptr + i] = self.memory[from_ptr + i];
        }
    }

    // Header value functions.

    /// The glulx magic number, stored from `0x0..0x4` in the header.
    /// This number is unique to all glulx games. This value should be
    /// `0x476C756C`, which is equivalent to `b"Glul"`.
    fn magic_number(&self) -> u32 {
        BigEndian::read_u32(&self.memory[..0x4])
    }

    /// The glulx version number, stored from `0x4..0x8` in the header.
    /// First two bytes store the major version number. The next byte
    /// stores the minor version number. The final byte stores the patch
    /// version number.
    pub fn glulx_version(&self) -> u32 {
        BigEndian::read_u32(&self.memory[0x4..0x8])
    }

    /// The address indicating the start of the RAM, stored from
    /// `0x4..0x8` in the header. TODO: MOAR DATA
    fn ramstart(&self) -> u32 {
        BigEndian::read_u32(&self.memory[0x8..0xC])
    }

    fn extstart(&self) -> u32 {
        BigEndian::read_u32(&self.memory[0xC..0x10])
    }

    fn endmem(&self) -> u32 {
        BigEndian::read_u32(&self.memory[0x10..0x14])
    }

    pub fn stack_size(&self) -> u32 {
        BigEndian::read_u32(&self.memory[0x14..0x18])
    }

    pub fn start_func(&self) -> u32 {
        BigEndian::read_u32(&self.memory[0x18..0x1C])
    }

    fn decoding_tbl(&self) -> u32 {
        BigEndian::read_u32(&self.memory[0x1C..0x20])
    }

    /// The sum of the intial contents of memory, considered as an array
    /// of `u32`s. When calculated, the checksum value is considered to
    /// be `0`.
    fn checksum(&self) -> u32 {
        BigEndian::read_u32(&self.memory[0x20..0x24])
    }

    pub fn get_mem_size(&self) -> u32 {
        self.memory.len() as u32
    }

    /// Sets the memory size to the given value. This call only works if
    /// there is no active heap, the given value is a multiple of 0x100,
    /// and the value is greater than the ENDMEM value identified in the
    /// header.
    pub fn set_mem_size(&mut self, value: u32) -> u32 {
        if self.heap_mode
                && value % 0x100 == 0
                && value >= self.endmem() {
            self.memory.resize(value as usize, 0x0);
            0
        } else {
            1
        }
    }
}

pub trait Memory<T> {
    fn read(&self, ptr: u32) -> T;
    fn write(&mut self, ptr: u32, value: T);
    fn ram_read(&self, ptr: u32) -> T;
    fn ram_write(&mut self, ptr: u32, value: T);
}

impl Memory<u8> for GlulxMemory {
    fn read(&self, ptr: u32) -> u8 {
        self.memory[ptr as usize]
    }

    fn write(&mut self, ptr: u32, value: u8) {
        self.memory[ptr as usize] = value
    }

    fn ram_read(&self, ptr: u32) -> u8 {
        let ptr = (ptr + self.ramstart()) as usize;
        self.memory[ptr]
    }

    fn ram_write(&mut self, ptr: u32, value: u8) {
        let ptr = (ptr + self.ramstart()) as usize;
        self.memory[ptr] = value
    }
}

impl Memory<u16> for GlulxMemory {
    fn read(&self, ptr: u32) -> u16 {
        BigEndian::read_u16(&self.memory[ptr as usize..])
    }

    fn write(&mut self, ptr: u32, value: u16) {
        BigEndian::write_u16(&mut self.memory[ptr as usize..], value)
    }

    fn ram_read(&self, ptr: u32) -> u16 {
        let ptr = (ptr + self.ramstart()) as usize;
        BigEndian::read_u16(&self.memory[ptr..])
    }

    fn ram_write(&mut self, ptr: u32, value: u16) {
        let ptr = (ptr + self.ramstart()) as usize;
        BigEndian::write_u16(&mut self.memory[ptr..], value)
    }
}

impl Memory<u32> for GlulxMemory {
    fn read(&self, ptr: u32) -> u32 {
        BigEndian::read_u32(&self.memory[ptr as usize..])
    }

    fn write(&mut self, ptr: u32, value: u32) {
        BigEndian::write_u32(&mut self.memory[ptr as usize..], value)
    }

    fn ram_read(&self, ptr: u32) -> u32 {
        let ptr = (ptr + self.ramstart()) as usize;
        BigEndian::read_u32(&self.memory[ptr..])
    }

    fn ram_write(&mut self, ptr: u32, value: u32) {
        let ptr = (ptr + self.ramstart()) as usize;
        BigEndian::write_u32(&mut self.memory[ptr..], value)
    }
}

impl Memory<i32> for GlulxMemory {
    fn read(&self, ptr: u32) -> i32 {
        BigEndian::read_i32(&self.memory[ptr as usize..])
    }

    fn write(&mut self, ptr: u32, value: i32) {
        BigEndian::write_i32(&mut self.memory[ptr as usize..], value)
    }

    fn ram_read(&self, ptr: u32) -> i32 {
        let ptr = (ptr + self.ramstart()) as usize;
        BigEndian::read_i32(&self.memory[ptr..])
    }

    fn ram_write(&mut self, ptr: u32, value: i32) {
        let ptr = (ptr + self.ramstart()) as usize;
        BigEndian::write_i32(&mut self.memory[ptr..], value)
    }
}

impl Memory<f32> for GlulxMemory {
    fn read(&self, ptr: u32) -> f32 {
        BigEndian::read_f32(&self.memory[ptr as usize..])
    }

    fn write(&mut self, ptr: u32, value: f32) {
        BigEndian::write_f32(&mut self.memory[ptr as usize..], value)
    }

    fn ram_read(&self, ptr: u32) -> f32 {
        let ptr = (ptr + self.ramstart()) as usize;
        BigEndian::read_f32(&self.memory[ptr..])
    }

    fn ram_write(&mut self, ptr: u32, value: f32) {
        let ptr = (ptr + self.ramstart()) as usize;
        BigEndian::write_f32(&mut self.memory[ptr..], value)
    }
}
<|endoftext|>


<commit_before>use std::ops::{Add, Sub, Div};
use std::collections::HashMap;
use std::iter::FromIterator;
use std::iter::repeat;
use std::fmt::{Debug, Formatter, Error};
use std::cmp::Ordering::Equal;
use std::ops::Drop;
use std::cmp;
use std::path::Path;
use std::io::{BufWriter, Write, BufReader, Read, BufRead};
use std::fs::File;
use std::mem;

#[derive(Clone)]
pub struct WordVec {
    pub word: String,
    pub count: u64,
    vec: Vec<f32>,
}

impl PartialEq for WordVec {
    fn eq(&self, other: &WordVec) -> bool {
        self.vec == other.vec
    }
}

impl Debug for WordVec {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
        try!(self.word.fmt(fmt));
        try!(fmt.write_str(": "));
        try!(self.count.fmt(fmt));
        try!(fmt.write_str(", "));
        self.vec.iter().take(5).collect::<Vec<_>>().fmt(fmt)
    }
}

impl WordVec {

    fn dot_prod(&self, other: &WordVec) -> f32 {
        self.vec.iter()
                .zip(other.vec.iter())
                .map(|(x, y)| x * y)
                .fold(0.0, |x, y| x + y)
    }

    fn magnitude(&self) -> f32 {
        self.vec.iter()
                .map(|x| x * x)
                .fold(0.0, |x, y| x + y)
                .sqrt()
    }

    pub fn distance(&self, other: &WordVec) -> f32 {
        self.vec.iter().zip(other.vec.iter())
                .map(|(x, y)| (x - y)*(x - y))
                .fold(0.0, |x, y| x + y)
                .sqrt()
    }

    fn new(word: String, num_words: usize) -> WordVec {
        WordVec {
            word: word,
            count: 0,
            vec: repeat(0.0).take(num_words).collect(),
        }
    }

    fn normalize(&mut self) {
        let count = self.count as f32;
        for f in &mut self.vec {
            *f /= count;
        }
    }

    fn inc(&mut self, i: usize) {
        self.vec[i] += 1.0;
    }

}

impl Div<i32> for WordVec {
    type Output = WordVec;

    fn div(mut self, i: i32) -> WordVec {
        for f in &mut self.vec {
            *f /= i as f32;
        }

        self
    }
}

impl<'a> Add<&'a WordVec> for WordVec {
    type Output = WordVec;

    fn add(self, other: &WordVec) -> WordVec {
        debug_assert!(self.vec.len() == other.vec.len());
        let mut newvec = WordVec {
            word: format!("{} + {}", &self.word, &other.word),
            count: 0,
            vec: self.vec,
        };

        for i in 0..newvec.vec.len() {
            newvec.vec[i] += other.vec[i];
        }

        newvec
    }
}

impl<'a> Sub<&'a WordVec> for WordVec {
    type Output = WordVec;

    fn sub(self, other: &WordVec) -> WordVec {
        debug_assert!(self.vec.len() == other.vec.len());
        let mut newvec = WordVec {
            word: format!("{} - {}", &self.word, &other.word),
            count: 0,
            vec: self.vec,
        };

        for i in 0..(newvec.vec.len()) {
            newvec.vec[i] -= other.vec[i];
        }

        newvec
    }
}

#[derive(Clone, PartialEq, Debug)]
pub struct LanguageModel {
    words: HashMap<String, usize>,
    word_vecs: Vec<WordVec>,
}

pub struct LanguageModelBuilder {
    window_radius: usize,
    words: HashMap<String, usize>,
    word_vecs: Vec<WordVec>,
    sentence: Vec<Option<usize>>,
}

pub struct WordAcceptor<'a> {
    builder: &'a mut LanguageModelBuilder,
}

impl LanguageModelBuilder {
    pub fn new(window_radius: usize, words: Vec<String>) -> LanguageModelBuilder {

        let word_vecs = words.iter()
                             .map(|s| WordVec::new(s.clone(), words.len()))
                             .collect();

        let words = HashMap::from_iter(
                        words.into_iter()
                             .enumerate()
                             .map(|(a, b)| (b, a)));

        LanguageModelBuilder {
            window_radius: window_radius,
            words: words,
            word_vecs: word_vecs,
            sentence: vec![],
        }
    }

    pub fn build(mut self) -> LanguageModel {
        for vec in self.word_vecs.iter_mut() {
            vec.normalize();
        }

        LanguageModel {
            words: self.words,
            word_vecs: self.word_vecs,
        }
    }

    pub fn new_sentence<'a>(&'a mut self) -> WordAcceptor<'a> {
        WordAcceptor {
            builder: self,
        }
    }

    fn word_seen(&mut self, word: usize) {
        self.word_vecs[word].count += 1;
    }
}

impl<'a> WordAcceptor<'a> {
    pub fn add_word(&mut self, word: &str) {
        let idx_opt = self.builder.words.get(word).map(|w| *w);

        if let Some(next_idx) = idx_opt {
            self.builder.word_seen(next_idx);
            self.builder.sentence.push(Some(next_idx));
        }
        else {
            self.builder.sentence.push(None);
        }
    }
}

impl<'a> Drop for WordAcceptor<'a> {
    fn drop(&mut self) {
        let LanguageModelBuilder {
            ref mut sentence,
            ref mut word_vecs,
            window_radius,
            ..
        } = *self.builder;

        for (i, &word_idx) in sentence.iter().enumerate() {
            let start = cmp::max(0, i as isize - window_radius as isize) as usize;
            let end = cmp::min(sentence.len(), i + window_radius + 1);
            for &j in &sentence[start..end] {
                match (word_idx, j) {
                    (Some(w), Some(j)) if w != j =>
                        word_vecs[w].inc(j),
                    _ => {},
                }
            }
        }

        sentence.clear();
    }
}

impl LanguageModel {
    pub fn get(&self, word: &str) -> Option<&WordVec> {
        self.words.get(word).map(|i| &self.word_vecs[*i])
    }

    pub fn nearest_words(&self, word: &WordVec) -> Vec<&WordVec> {
        let mut vec_refs = self.word_vecs.iter().filter_map(|w| {
            let dist = w.distance(word);
            if w.word != word.word {
                Some((dist, w))
            } else {
                None
            }
        }).collect::<Vec<_>>();
        vec_refs.sort_by(|a, b| a.0.partial_cmp(&b.0).unwrap_or_else(|| {
            println!("bad vector: {:?}, {:?}", a, b);
            Equal
        }));
        vec_refs.into_iter().map(|x| x.1).collect()
    }

    pub fn save(&self, path: &Path) {
        let mut file = BufWriter::new(File::create(path).unwrap());

        write_raw(self.word_vecs.len(), &mut file);
        file.write(&[b'\n']).unwrap();

        for vec in &self.word_vecs {
            file.write(vec.word.as_bytes()).unwrap();
            file.write(&[b':']).unwrap();
            let count = vec.count;
            write_raw(count, &mut file);
            for f in &vec.vec {
                write_raw(*f, &mut file)
            }
            file.write(&[b'\n']).unwrap();
        }

    }

    pub fn load(path: &Path) -> LanguageModel {
        let mut file = BufReader::new(File::open(path).unwrap());
        let mut word_vecs = Vec::new();

        let size: u64 = unsafe { read_raw::<u64, _>(&mut file) };
        read_byte(b'\n', &mut file);

        for _ in 0..size {
            let mut word: Vec<u8> = Vec::new();
            file.read_until(b':', &mut word).unwrap();
            assert_eq!(Some(b':'), word.pop());
            let word = String::from_utf8(word).unwrap();
            let count: u64 = unsafe { read_raw::<u64, _>(&mut file) };

            let mut vec: Vec<f32> = repeat(0f32).take(size as usize).collect();
            for f in &mut vec{
                unsafe {
                    *f = read_raw::<f32, _>(&mut file);
                }
            }

            read_byte(b'\n', &mut file);

            word_vecs.push(WordVec {
                word: word,
                count: count,
                vec: vec,
            });
        }

        let words: HashMap<_, _> = word_vecs.iter()
                                            .map(|v| v.word.clone())
                                            .enumerate()
                                            .map(|(i, w)| (w, i))
                                            .collect();

        LanguageModel {
            words: words,
            word_vecs: word_vecs,
        }
    }
}

fn read_byte<R: Read>(b: u8, read: &mut R) {
    let buf = &mut [0];
    read.read(buf).unwrap();
    assert_eq!(&[b], buf);
}

unsafe fn read_raw<T: Copy, R: Read>(reader: &mut BufReader<R>) -> T {
    let mut buffer = [0u8; 64];
    let t_size = mem::size_of::<T>();
    assert!(t_size <= buffer.len());

    let mut remainder = t_size;
    while remainder > 0 {
        let bytes_read = reader.read(&mut buffer[(t_size-remainder)..t_size]).unwrap();
        remainder -= bytes_read;
    }
    // println!("{:?}", &buffer[..]);
    // assert_eq!(t_size, size);

    unsafe {
        let bptr: *mut T = mem::transmute((&buffer).as_ptr());
        *bptr
    }
}

fn write_raw<T: Copy, F: Write>(t: T, writer: &mut BufWriter<F>) {
    let mut buffer = [0u8; 64];
    let t_size = mem::size_of::<T>();
    assert!(t_size <= buffer.len());
    unsafe {
        let bptr: *mut T = mem::transmute((&buffer).as_ptr());
        *bptr = t;
    }

    writer.write(&buffer[0..t_size]);
}

#[cfg(test)]
mod test {
    use super::{WordVec, LanguageModel, LanguageModelBuilder};
    use std::path::Path;

    fn get_model() -> LanguageModel {
        let words = "foo bar baz blort".words().map(|w| w.to_string()).collect::<Vec<_>>();
        let mut builder = LanguageModelBuilder::new(1, words);

        let input = "x foo bar baz x x x x x x x blort".words();

        {
            let mut acc = builder.new_sentence();
            for word in input {
                acc.add_word(word);
            }
        }

        builder.build()
    }

    #[test]
    fn test_accept_sentences() {
        let model = get_model();
        let foo = model.get("foo").unwrap();
        let baz = model.get("baz").unwrap();
        let bar = model.get("bar").unwrap();
        let blort = model.get("blort").unwrap();

        assert!(foo.distance(baz) < foo.distance(blort));
        assert!(foo.distance(bar) == bar.distance(baz));
    }

    #[test]
    fn test_serialization() {
        let model = get_model();
        let path = Path::new("/tmp/model.data");
        model.save(&path);

        let loaded_model = LanguageModel::load(path);
        assert_eq!(model, loaded_model);
    }
}
<commit_msg>Tidy-up.<commit_after>use std::ops::{Add, Sub, Div};
use std::collections::HashMap;
use std::iter::FromIterator;
use std::iter::repeat;
use std::fmt::{Debug, Formatter, Error};
use std::cmp::Ordering::Equal;
use std::ops::Drop;
use std::cmp;
use std::path::Path;
use std::io::{BufWriter, Write, BufReader, Read, BufRead};
use std::fs::File;
use std::mem;

#[derive(Clone)]
pub struct WordVec {
    pub word: String,
    pub count: u64,
    vec: Vec<f32>,
}

impl PartialEq for WordVec {
    fn eq(&self, other: &WordVec) -> bool {
        self.vec == other.vec
    }
}

impl Debug for WordVec {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
        try!(self.word.fmt(fmt));
        try!(fmt.write_str(": "));
        try!(self.count.fmt(fmt));
        try!(fmt.write_str(", "));
        self.vec.iter().take(5).collect::<Vec<_>>().fmt(fmt)
    }
}

impl WordVec {

    fn dot_prod(&self, other: &WordVec) -> f32 {
        self.vec.iter()
                .zip(other.vec.iter())
                .map(|(x, y)| x * y)
                .fold(0.0, |x, y| x + y)
    }

    fn magnitude(&self) -> f32 {
        self.vec.iter()
                .map(|x| x * x)
                .fold(0.0, |x, y| x + y)
                .sqrt()
    }

    pub fn distance(&self, other: &WordVec) -> f32 {
        self.vec.iter().zip(other.vec.iter())
                .map(|(x, y)| (x - y)*(x - y))
                .fold(0.0, |x, y| x + y)
                .sqrt()
    }

    fn new(word: String, num_words: usize) -> WordVec {
        WordVec {
            word: word,
            count: 0,
            vec: repeat(0.0).take(num_words).collect(),
        }
    }

    fn normalize(&mut self) {
        let count = self.count as f32;
        for f in &mut self.vec {
            *f /= count;
        }
    }

    fn inc(&mut self, i: usize) {
        self.vec[i] += 1.0;
    }

}

impl Div<i32> for WordVec {
    type Output = WordVec;

    fn div(mut self, i: i32) -> WordVec {
        for f in &mut self.vec {
            *f /= i as f32;
        }

        self
    }
}

impl<'a> Add<&'a WordVec> for WordVec {
    type Output = WordVec;

    fn add(self, other: &WordVec) -> WordVec {
        debug_assert!(self.vec.len() == other.vec.len());
        let mut newvec = WordVec {
            word: format!("{} + {}", &self.word, &other.word),
            count: 0,
            vec: self.vec,
        };

        for i in 0..newvec.vec.len() {
            newvec.vec[i] += other.vec[i];
        }

        newvec
    }
}

impl<'a> Sub<&'a WordVec> for WordVec {
    type Output = WordVec;

    fn sub(self, other: &WordVec) -> WordVec {
        debug_assert!(self.vec.len() == other.vec.len());
        let mut newvec = WordVec {
            word: format!("{} - {}", &self.word, &other.word),
            count: 0,
            vec: self.vec,
        };

        for i in 0..(newvec.vec.len()) {
            newvec.vec[i] -= other.vec[i];
        }

        newvec
    }
}

#[derive(Clone, PartialEq, Debug)]
pub struct LanguageModel {
    words: HashMap<String, usize>,
    word_vecs: Vec<WordVec>,
}

pub struct LanguageModelBuilder {
    window_radius: usize,
    words: HashMap<String, usize>,
    word_vecs: Vec<WordVec>,
    sentence: Vec<Option<usize>>,
}

pub struct WordAcceptor<'a> {
    builder: &'a mut LanguageModelBuilder,
}

impl LanguageModelBuilder {
    pub fn new(window_radius: usize, words: Vec<String>) -> LanguageModelBuilder {

        let word_vecs = words.iter()
                             .map(|s| WordVec::new(s.clone(), words.len()))
                             .collect();

        let words = HashMap::from_iter(
                        words.into_iter()
                             .enumerate()
                             .map(|(a, b)| (b, a)));

        LanguageModelBuilder {
            window_radius: window_radius,
            words: words,
            word_vecs: word_vecs,
            sentence: vec![],
        }
    }

    pub fn build(mut self) -> LanguageModel {
        for vec in self.word_vecs.iter_mut() {
            vec.normalize();
        }

        LanguageModel {
            words: self.words,
            word_vecs: self.word_vecs,
        }
    }

    pub fn new_sentence<'a>(&'a mut self) -> WordAcceptor<'a> {
        WordAcceptor {
            builder: self,
        }
    }

    fn word_seen(&mut self, word: usize) {
        self.word_vecs[word].count += 1;
    }
}

impl<'a> WordAcceptor<'a> {
    pub fn add_word(&mut self, word: &str) {
        let idx_opt = self.builder.words.get(word).map(|w| *w);

        if let Some(next_idx) = idx_opt {
            self.builder.word_seen(next_idx);
            self.builder.sentence.push(Some(next_idx));
        }
        else {
            self.builder.sentence.push(None);
        }
    }
}

impl<'a> Drop for WordAcceptor<'a> {
    fn drop(&mut self) {
        let LanguageModelBuilder {
            ref mut sentence,
            ref mut word_vecs,
            window_radius,
            ..
        } = *self.builder;

        for (i, &word_idx) in sentence.iter().enumerate() {
            let start = cmp::max(0, i as isize - window_radius as isize) as usize;
            let end = cmp::min(sentence.len(), i + window_radius + 1);
            for &j in &sentence[start..end] {
                match (word_idx, j) {
                    (Some(w), Some(j)) if w != j =>
                        word_vecs[w].inc(j),
                    _ => {},
                }
            }
        }

        sentence.clear();
    }
}

impl LanguageModel {
    pub fn get(&self, word: &str) -> Option<&WordVec> {
        self.words.get(word).map(|i| &self.word_vecs[*i])
    }

    pub fn nearest_words(&self, word: &WordVec) -> Vec<&WordVec> {
        let mut vec_refs = self.word_vecs.iter().filter_map(|w| {
            let dist = w.distance(word);
            if w.word != word.word {
                Some((dist, w))
            } else {
                None
            }
        }).collect::<Vec<_>>();
        vec_refs.sort_by(|a, b| a.0.partial_cmp(&b.0).unwrap_or_else(|| {
            println!("bad vector: {:?}, {:?}", a, b);
            Equal
        }));
        vec_refs.into_iter().map(|x| x.1).collect()
    }

    pub fn save(&self, path: &Path) {
        let mut file = BufWriter::new(File::create(path).unwrap());

        write_raw(self.word_vecs.len(), &mut file);
        file.write(&[b'\n']).unwrap();

        for vec in &self.word_vecs {
            file.write(vec.word.as_bytes()).unwrap();
            file.write(&[b':']).unwrap();
            let count = vec.count;
            write_raw(count, &mut file);
            for f in &vec.vec {
                write_raw(*f, &mut file)
            }
            file.write(&[b'\n']).unwrap();
        }

    }

    pub fn load(path: &Path) -> LanguageModel {
        let mut file = BufReader::new(File::open(path).unwrap());
        let mut word_vecs = Vec::new();

        let size: u64 = unsafe { read_raw::<u64, _>(&mut file) };
        read_byte(b'\n', &mut file);

        for _ in 0..size {
            let mut word: Vec<u8> = Vec::new();
            file.read_until(b':', &mut word).unwrap();
            assert_eq!(Some(b':'), word.pop());
            let word = String::from_utf8(word).unwrap();
            let count: u64 = unsafe { read_raw::<u64, _>(&mut file) };

            let mut vec: Vec<f32> = repeat(0f32).take(size as usize).collect();
            for f in &mut vec {
                unsafe {
                    *f = read_raw::<f32, _>(&mut file);
                }
            }

            read_byte(b'\n', &mut file);

            word_vecs.push(WordVec {
                word: word,
                count: count,
                vec: vec,
            });
        }

        let words: HashMap<_, _> = word_vecs.iter()
                                            .map(|v| v.word.clone())
                                            .enumerate()
                                            .map(|(i, w)| (w, i))
                                            .collect();

        LanguageModel {
            words: words,
            word_vecs: word_vecs,
        }
    }
}

fn read_byte<R: Read>(b: u8, read: &mut R) {
    let buf = &mut [0];
    while read.read(buf).unwrap() == 0 {}
    assert_eq!(&[b], buf);
}

unsafe fn read_raw<T: Copy, R: Read>(reader: &mut BufReader<R>) -> T {
    let mut buffer = [0u8; 64];
    let t_size = mem::size_of::<T>();
    assert!(t_size <= buffer.len());

    let mut remainder = t_size;
    while remainder > 0 {
        let bytes_read = reader.read(&mut buffer[(t_size-remainder)..t_size]).unwrap();
        remainder -= bytes_read;
    }

    let bptr: *mut T = mem::transmute((&buffer).as_ptr());
    *bptr
}

fn write_raw<T: Copy, F: Write>(t: T, writer: &mut BufWriter<F>) {
    let mut buffer = [0u8; 64];
    let t_size = mem::size_of::<T>();
    assert!(t_size <= buffer.len());
    unsafe {
        let bptr: *mut T = mem::transmute((&buffer).as_ptr());
        *bptr = t;
    }

    writer.write(&buffer[0..t_size]);
}

#[cfg(test)]
mod test {
    use super::{WordVec, LanguageModel, LanguageModelBuilder};
    use std::path::Path;

    fn get_model() -> LanguageModel {
        let words = "foo bar baz blort".words().map(|w| w.to_string()).collect::<Vec<_>>();
        let mut builder = LanguageModelBuilder::new(1, words);

        let input = "x foo bar baz x x x x x x x blort".words();

        {
            let mut acc = builder.new_sentence();
            for word in input {
                acc.add_word(word);
            }
        }

        builder.build()
    }

    #[test]
    fn test_accept_sentences() {
        let model = get_model();
        let foo = model.get("foo").unwrap();
        let baz = model.get("baz").unwrap();
        let bar = model.get("bar").unwrap();
        let blort = model.get("blort").unwrap();

        assert!(foo.distance(baz) < foo.distance(blort));
        assert!(foo.distance(bar) == bar.distance(baz));
    }

    #[test]
    fn test_serialization() {
        let model = get_model();
        let path = Path::new("/tmp/model.data");
        model.save(&path);

        let loaded_model = LanguageModel::load(path);
        assert_eq!(model, loaded_model);
    }
}
<|endoftext|>