<commit_before>// Take a look at the license at the top of the repository in the LICENSE file.

#![doc = include_str!("../README.md")]
#![allow(unknown_lints)]
#![deny(missing_docs)]
#![deny(rustdoc::broken_intra_doc_links)]
#![allow(clippy::upper_case_acronyms)]
#![allow(clippy::non_send_fields_in_send_ty)]
#![allow(renamed_and_removed_lints)]
#![allow(unknown_lints)]

#[cfg(feature = "debug")]
#[doc(hidden)]
#[allow(unused)]
macro_rules! sysinfo_debug {
    ($($x:tt)*) => {{
        eprintln!($($x)*);
    }}
}

#[cfg(not(feature = "debug"))]
#[doc(hidden)]
#[allow(unused)]
macro_rules! sysinfo_debug {
    ($($x:tt)*) => {{}};
}

cfg_if::cfg_if! {
    if #[cfg(feature = "unknown-ci")] {
        // This is used in CI to check that the build for unknown targets is compiling fine.
        mod unknown;
        use unknown as sys;

        #[cfg(test)]
        pub(crate) const MIN_USERS: usize = 0;
    } else if #[cfg(any(target_os = "macos", target_os = "ios"))] {
        mod apple;
        use apple as sys;
        extern crate core_foundation_sys;

        #[cfg(test)]
        pub(crate) const MIN_USERS: usize = 1;
    } else if #[cfg(windows)] {
        mod windows;
        use windows as sys;
        extern crate winapi;
        extern crate ntapi;

        #[cfg(test)]
        pub(crate) const MIN_USERS: usize = 1;
    } else if #[cfg(any(target_os = "linux", target_os = "android"))] {
        mod linux;
        use linux as sys;
        pub(crate) mod users;

        #[cfg(test)]
        pub(crate) const MIN_USERS: usize = 1;
    } else if #[cfg(target_os = "freebsd")] {
        mod freebsd;
        use freebsd as sys;
        pub(crate) mod users;

        #[cfg(test)]
        pub(crate) const MIN_USERS: usize = 1;
    } else {
        mod unknown;
        use unknown as sys;

        #[cfg(test)]
        pub(crate) const MIN_USERS: usize = 0;
    }
}

pub use common::{
    get_current_pid, AsU32, DiskType, DiskUsage, Gid, LoadAvg, NetworksIter, Pid,
    ProcessRefreshKind, ProcessStatus, RefreshKind, Signal, Uid, User,
};
pub use sys::{Component, Disk, NetworkData, Networks, Process, Processor, System};
pub use traits::{
    ComponentExt, DiskExt, NetworkExt, NetworksExt, ProcessExt, ProcessorExt, SystemExt, UserExt,
};

#[cfg(feature = "c-interface")]
pub use c_interface::*;

#[cfg(feature = "c-interface")]
mod c_interface;
mod common;
mod debug;
mod system;
mod traits;
mod utils;

/// This function is only used on linux targets, on the other platforms it does nothing and returns
/// `false`.
///
/// On linux, to improve performance, we keep a `/proc` file open for each process we index with
/// a maximum number of files open equivalent to half of the system limit.
///
/// The problem is that some users might need all the available file descriptors so we need to
/// allow them to change this limit.
///
/// Note that if you set a limit bigger than the system limit, the system limit will be set.
///
/// Returns `true` if the new value has been set.
///
/// ```no_run
/// use sysinfo::{System, SystemExt, set_open_files_limit};
///
/// // We call the function before any call to the processes update.
/// if !set_open_files_limit(10) {
///     // It'll always return false on non-linux targets.
///     eprintln!("failed to update the open files limit...");
/// }
/// let s = System::new_all();
/// ```
pub fn set_open_files_limit(mut _new_limit: isize) -> bool {
    cfg_if::cfg_if! {
        if #[cfg(all(not(feature = "unknown-ci"), any(target_os = "linux", target_os = "android")))]
        {
            if _new_limit < 0 {
                _new_limit = 0;
            }
            let max = sys::system::get_max_nb_fds();
            if _new_limit > max {
                _new_limit = max;
            }
            if let Ok(ref mut x) = unsafe { sys::system::REMAINING_FILES.lock() } {
                // If files are already open, to be sure that the number won't be bigger when those
                // files are closed, we subtract the current number of opened files to the new
                // limit.
                let diff = max - **x;
                **x = _new_limit - diff;
                true
            } else {
                false
            }
        } else {
            false
        }
    }
}

#[cfg(test)]
mod test {
    use crate::*;

    #[cfg(feature = "unknown-ci")]
    #[test]
    fn check_unknown_ci_feature() {
        assert!(!System::IS_SUPPORTED);
    }

    #[test]
    fn check_process_memory_usage() {
        let mut s = System::new();
        s.refresh_all();

        if System::IS_SUPPORTED {
            // No process should have 0 as memory usage.
            #[cfg(not(feature = "apple-sandbox"))]
            assert!(!s.processes().iter().all(|(_, proc_)| proc_.memory() == 0));
        } else {
            // There should be no process, but if there is one, its memory usage should be 0.
            assert!(s.processes().iter().all(|(_, proc_)| proc_.memory() == 0));
        }
    }

    #[test]
    fn check_memory_usage() {
        let mut s = System::new();

        assert_eq!(s.total_memory(), 0);
        assert_eq!(s.free_memory(), 0);
        assert_eq!(s.available_memory(), 0);
        assert_eq!(s.used_memory(), 0);
        assert_eq!(s.total_swap(), 0);
        assert_eq!(s.free_swap(), 0);
        assert_eq!(s.used_swap(), 0);

        s.refresh_memory();
        if System::IS_SUPPORTED {
            assert!(s.total_memory() > 0);
            assert!(s.used_memory() > 0);
            if s.total_swap() > 0 {
                // I think it's pretty safe to assume that there is still some swap left...
                assert!(s.free_swap() > 0);
            }
        } else {
            assert_eq!(s.total_memory(), 0);
            assert_eq!(s.used_memory(), 0);
            assert_eq!(s.total_swap(), 0);
            assert_eq!(s.free_swap(), 0);
        }
    }

    #[cfg(target_os = "linux")]
    #[test]
    fn check_processes_cpu_usage() {
        if !System::IS_SUPPORTED {
            return;
        }
        let mut s = System::new();

        s.refresh_processes();
        // All CPU usage will start at zero until the second refresh
        assert!(s
            .processes()
            .iter()
            .all(|(_, proc_)| proc_.cpu_usage() == 0.0));

        // Wait a bit to update CPU usage values
        std::thread::sleep(std::time::Duration::from_millis(100));
        s.refresh_processes();
        assert!(s
            .processes()
            .iter()
            .all(|(_, proc_)| proc_.cpu_usage() >= 0.0
                && proc_.cpu_usage() <= (s.processors().len() as f32) * 100.0));
        assert!(s
            .processes()
            .iter()
            .any(|(_, proc_)| proc_.cpu_usage() > 0.0));
    }

    #[test]
    fn check_users() {
        let mut s = System::new();
        assert!(s.users().is_empty());
        s.refresh_users_list();
        assert!(s.users().len() >= MIN_USERS);

        let mut s = System::new();
        assert!(s.users().is_empty());
        s.refresh_all();
        assert!(s.users().is_empty());

        let s = System::new_all();
        assert!(s.users().len() >= MIN_USERS);
    }

    #[test]
    fn check_uid_gid() {
        let mut s = System::new();
        assert!(s.users().is_empty());
        s.refresh_users_list();
        let users = s.users();
        assert!(users.len() >= MIN_USERS);

        if System::IS_SUPPORTED {
            #[cfg(not(target_os = "windows"))]
            {
                let user = users
                    .iter()
                    .find(|u| u.name() == "root")
                    .expect("no root user");
                assert_eq!(*user.uid(), 0);
                assert_eq!(*user.gid(), 0);
                if let Some(user) = users.iter().find(|u| *u.gid() > 0) {
                    assert!(*user.uid() > 0);
                    assert!(*user.gid() > 0);
                }
            }
            #[cfg(not(target_os = "windows"))]
            {
                assert!(users.iter().filter(|u| *u.uid() > 0).count() > 0);
            }
        }
    }

    #[test]
    fn check_system_info() {
        // We don't want to test on unsupported systems.
        if System::IS_SUPPORTED {
            let s = System::new();
            assert!(!s.name().expect("Failed to get system name").is_empty());

            assert!(!s
                .kernel_version()
                .expect("Failed to get kernel version")
                .is_empty());

            assert!(!s.os_version().expect("Failed to get os version").is_empty());

            assert!(!s
                .long_os_version()
                .expect("Failed to get long OS version")
                .is_empty());
        }
    }

    #[test]
    fn check_host_name() {
        // We don't want to test on unsupported systems.
        if System::IS_SUPPORTED {
            let s = System::new();
            assert!(s.host_name().is_some());
        }
    }

    #[test]
    fn check_refresh_process_return_value() {
        // We don't want to test on unsupported systems.
        if System::IS_SUPPORTED {
            let _pid = get_current_pid().expect("Failed to get current PID");

            #[cfg(not(feature = "apple-sandbox"))]
            {
                let mut s = System::new();
                // First check what happens in case the process isn't already in our process list.
                assert!(s.refresh_process(_pid));
                // Then check that it still returns true if the process is already in our process list.
                assert!(s.refresh_process(_pid));
            }
        }
    }

    #[test]
    fn ensure_is_supported_is_set_correctly() {
        if MIN_USERS > 0 {
            assert!(System::IS_SUPPORTED);
        } else {
            assert!(!System::IS_SUPPORTED);
        }
    }

    #[test]
    fn check_processors_number() {
        let mut s = System::new();

        // This information isn't retrieved by default.
        assert!(s.processors().is_empty());
        if System::IS_SUPPORTED {
            // The physical cores count is recomputed every time the function is called, so the
            // information must be relevant even with nothing initialized.
            let physical_cores_count = s
                .physical_core_count()
                .expect("failed to get number of physical cores");

            s.refresh_cpu();
            // The processors shouldn't be empty anymore.
            assert!(!s.processors().is_empty());

            // In case we are running inside a VM, it's possible to not have a physical core, only
            // logical ones, which is why we don't test `physical_cores_count > 0`.
            let physical_cores_count2 = s
                .physical_core_count()
                .expect("failed to get number of physical cores");
            assert!(physical_cores_count2 <= s.processors().len());
            assert_eq!(physical_cores_count, physical_cores_count2);
        } else {
            assert_eq!(s.physical_core_count(), None);
        }
        assert!(s.physical_core_count().unwrap_or(0) <= s.processors().len());
    }
}
<commit_msg>Fix panic when changing the limit of open files<commit_after>// Take a look at the license at the top of the repository in the LICENSE file.

#![doc = include_str!("../README.md")]
#![allow(unknown_lints)]
#![deny(missing_docs)]
#![deny(rustdoc::broken_intra_doc_links)]
#![allow(clippy::upper_case_acronyms)]
#![allow(clippy::non_send_fields_in_send_ty)]
#![allow(renamed_and_removed_lints)]
#![allow(unknown_lints)]

#[cfg(feature = "debug")]
#[doc(hidden)]
#[allow(unused)]
macro_rules! sysinfo_debug {
    ($($x:tt)*) => {{
        eprintln!($($x)*);
    }}
}

#[cfg(not(feature = "debug"))]
#[doc(hidden)]
#[allow(unused)]
macro_rules! sysinfo_debug {
    ($($x:tt)*) => {{}};
}

cfg_if::cfg_if! {
    if #[cfg(feature = "unknown-ci")] {
        // This is used in CI to check that the build for unknown targets is compiling fine.
        mod unknown;
        use unknown as sys;

        #[cfg(test)]
        pub(crate) const MIN_USERS: usize = 0;
    } else if #[cfg(any(target_os = "macos", target_os = "ios"))] {
        mod apple;
        use apple as sys;
        extern crate core_foundation_sys;

        #[cfg(test)]
        pub(crate) const MIN_USERS: usize = 1;
    } else if #[cfg(windows)] {
        mod windows;
        use windows as sys;
        extern crate winapi;
        extern crate ntapi;

        #[cfg(test)]
        pub(crate) const MIN_USERS: usize = 1;
    } else if #[cfg(any(target_os = "linux", target_os = "android"))] {
        mod linux;
        use linux as sys;
        pub(crate) mod users;

        #[cfg(test)]
        pub(crate) const MIN_USERS: usize = 1;
    } else if #[cfg(target_os = "freebsd")] {
        mod freebsd;
        use freebsd as sys;
        pub(crate) mod users;

        #[cfg(test)]
        pub(crate) const MIN_USERS: usize = 1;
    } else {
        mod unknown;
        use unknown as sys;

        #[cfg(test)]
        pub(crate) const MIN_USERS: usize = 0;
    }
}

pub use common::{
    get_current_pid, AsU32, DiskType, DiskUsage, Gid, LoadAvg, NetworksIter, Pid,
    ProcessRefreshKind, ProcessStatus, RefreshKind, Signal, Uid, User,
};
pub use sys::{Component, Disk, NetworkData, Networks, Process, Processor, System};
pub use traits::{
    ComponentExt, DiskExt, NetworkExt, NetworksExt, ProcessExt, ProcessorExt, SystemExt, UserExt,
};

#[cfg(feature = "c-interface")]
pub use c_interface::*;

#[cfg(feature = "c-interface")]
mod c_interface;
mod common;
mod debug;
mod system;
mod traits;
mod utils;

/// This function is only used on linux targets, on the other platforms it does nothing and returns
/// `false`.
///
/// On linux, to improve performance, we keep a `/proc` file open for each process we index with
/// a maximum number of files open equivalent to half of the system limit.
///
/// The problem is that some users might need all the available file descriptors so we need to
/// allow them to change this limit.
///
/// Note that if you set a limit bigger than the system limit, the system limit will be set.
///
/// Returns `true` if the new value has been set.
///
/// ```no_run
/// use sysinfo::{System, SystemExt, set_open_files_limit};
///
/// // We call the function before any call to the processes update.
/// if !set_open_files_limit(10) {
///     // It'll always return false on non-linux targets.
///     eprintln!("failed to update the open files limit...");
/// }
/// let s = System::new_all();
/// ```
pub fn set_open_files_limit(mut _new_limit: isize) -> bool {
    cfg_if::cfg_if! {
        if #[cfg(all(not(feature = "unknown-ci"), any(target_os = "linux", target_os = "android")))]
        {
            if _new_limit < 0 {
                _new_limit = 0;
            }
            let max = sys::system::get_max_nb_fds();
            if _new_limit > max {
                _new_limit = max;
            }
            if let Ok(ref mut x) = unsafe { sys::system::REMAINING_FILES.lock() } {
                // If files are already open, to be sure that the number won't be bigger when those
                // files are closed, we subtract the current number of opened files to the new
                // limit.
                let diff = max.saturating_sub(**x);
                **x = _new_limit.saturating_sub(diff);
                true
            } else {
                false
            }
        } else {
            false
        }
    }
}

#[cfg(test)]
mod test {
    use crate::*;

    #[cfg(feature = "unknown-ci")]
    #[test]
    fn check_unknown_ci_feature() {
        assert!(!System::IS_SUPPORTED);
    }

    #[test]
    fn check_process_memory_usage() {
        let mut s = System::new();
        s.refresh_all();

        if System::IS_SUPPORTED {
            // No process should have 0 as memory usage.
            #[cfg(not(feature = "apple-sandbox"))]
            assert!(!s.processes().iter().all(|(_, proc_)| proc_.memory() == 0));
        } else {
            // There should be no process, but if there is one, its memory usage should be 0.
            assert!(s.processes().iter().all(|(_, proc_)| proc_.memory() == 0));
        }
    }

    #[test]
    fn check_memory_usage() {
        let mut s = System::new();

        assert_eq!(s.total_memory(), 0);
        assert_eq!(s.free_memory(), 0);
        assert_eq!(s.available_memory(), 0);
        assert_eq!(s.used_memory(), 0);
        assert_eq!(s.total_swap(), 0);
        assert_eq!(s.free_swap(), 0);
        assert_eq!(s.used_swap(), 0);

        s.refresh_memory();
        if System::IS_SUPPORTED {
            assert!(s.total_memory() > 0);
            assert!(s.used_memory() > 0);
            if s.total_swap() > 0 {
                // I think it's pretty safe to assume that there is still some swap left...
                assert!(s.free_swap() > 0);
            }
        } else {
            assert_eq!(s.total_memory(), 0);
            assert_eq!(s.used_memory(), 0);
            assert_eq!(s.total_swap(), 0);
            assert_eq!(s.free_swap(), 0);
        }
    }

    #[cfg(target_os = "linux")]
    #[test]
    fn check_processes_cpu_usage() {
        if !System::IS_SUPPORTED {
            return;
        }
        let mut s = System::new();

        s.refresh_processes();
        // All CPU usage will start at zero until the second refresh
        assert!(s
            .processes()
            .iter()
            .all(|(_, proc_)| proc_.cpu_usage() == 0.0));

        // Wait a bit to update CPU usage values
        std::thread::sleep(std::time::Duration::from_millis(100));
        s.refresh_processes();
        assert!(s
            .processes()
            .iter()
            .all(|(_, proc_)| proc_.cpu_usage() >= 0.0
                && proc_.cpu_usage() <= (s.processors().len() as f32) * 100.0));
        assert!(s
            .processes()
            .iter()
            .any(|(_, proc_)| proc_.cpu_usage() > 0.0));
    }

    #[test]
    fn check_users() {
        let mut s = System::new();
        assert!(s.users().is_empty());
        s.refresh_users_list();
        assert!(s.users().len() >= MIN_USERS);

        let mut s = System::new();
        assert!(s.users().is_empty());
        s.refresh_all();
        assert!(s.users().is_empty());

        let s = System::new_all();
        assert!(s.users().len() >= MIN_USERS);
    }

    #[test]
    fn check_uid_gid() {
        let mut s = System::new();
        assert!(s.users().is_empty());
        s.refresh_users_list();
        let users = s.users();
        assert!(users.len() >= MIN_USERS);

        if System::IS_SUPPORTED {
            #[cfg(not(target_os = "windows"))]
            {
                let user = users
                    .iter()
                    .find(|u| u.name() == "root")
                    .expect("no root user");
                assert_eq!(*user.uid(), 0);
                assert_eq!(*user.gid(), 0);
                if let Some(user) = users.iter().find(|u| *u.gid() > 0) {
                    assert!(*user.uid() > 0);
                    assert!(*user.gid() > 0);
                }
            }
            #[cfg(not(target_os = "windows"))]
            {
                assert!(users.iter().filter(|u| *u.uid() > 0).count() > 0);
            }
        }
    }

    #[test]
    fn check_system_info() {
        // We don't want to test on unsupported systems.
        if System::IS_SUPPORTED {
            let s = System::new();
            assert!(!s.name().expect("Failed to get system name").is_empty());

            assert!(!s
                .kernel_version()
                .expect("Failed to get kernel version")
                .is_empty());

            assert!(!s.os_version().expect("Failed to get os version").is_empty());

            assert!(!s
                .long_os_version()
                .expect("Failed to get long OS version")
                .is_empty());
        }
    }

    #[test]
    fn check_host_name() {
        // We don't want to test on unsupported systems.
        if System::IS_SUPPORTED {
            let s = System::new();
            assert!(s.host_name().is_some());
        }
    }

    #[test]
    fn check_refresh_process_return_value() {
        // We don't want to test on unsupported systems.
        if System::IS_SUPPORTED {
            let _pid = get_current_pid().expect("Failed to get current PID");

            #[cfg(not(feature = "apple-sandbox"))]
            {
                let mut s = System::new();
                // First check what happens in case the process isn't already in our process list.
                assert!(s.refresh_process(_pid));
                // Then check that it still returns true if the process is already in our process list.
                assert!(s.refresh_process(_pid));
            }
        }
    }

    #[test]
    fn ensure_is_supported_is_set_correctly() {
        if MIN_USERS > 0 {
            assert!(System::IS_SUPPORTED);
        } else {
            assert!(!System::IS_SUPPORTED);
        }
    }

    #[test]
    fn check_processors_number() {
        let mut s = System::new();

        // This information isn't retrieved by default.
        assert!(s.processors().is_empty());
        if System::IS_SUPPORTED {
            // The physical cores count is recomputed every time the function is called, so the
            // information must be relevant even with nothing initialized.
            let physical_cores_count = s
                .physical_core_count()
                .expect("failed to get number of physical cores");

            s.refresh_cpu();
            // The processors shouldn't be empty anymore.
            assert!(!s.processors().is_empty());

            // In case we are running inside a VM, it's possible to not have a physical core, only
            // logical ones, which is why we don't test `physical_cores_count > 0`.
            let physical_cores_count2 = s
                .physical_core_count()
                .expect("failed to get number of physical cores");
            assert!(physical_cores_count2 <= s.processors().len());
            assert_eq!(physical_cores_count, physical_cores_count2);
        } else {
            assert_eq!(s.physical_core_count(), None);
        }
        assert!(s.physical_core_count().unwrap_or(0) <= s.processors().len());
    }
}
<|endoftext|>


<commit_before>//! # RdxSort
//!
//! This crate implements [Radix Sort](https://en.wikipedia.org/wiki/Radix_sort) for slices of
//! different data types, either directly or by exploiting the implementation of other data types.
//!
//! The main reason for implementing yet another sorting algorithm is that most sorting algorithms
//! are comparative methods. To sort data, they rely on a function that compares data elements. It
//! can be proven that this leads to a runtime complexity of `O(n*log(n))` in average and `O(n^2)`
//! in the worst case. In contrast to that, Radix Sort exploits that fact that many data types have
//! a limited range of possible values and within that range a limited resolution (that also holds
//! for floating point numbers). For a detailed explanation see the
//! [Wikipedia article](https://en.wikipedia.org/wiki/Radix_sort). The result of this special
//! treatment is a lowered and constant complexity of `O(n*k)` where `k` is the number of fixed
//! rounds required to sort a specific data type.
//!
//!
//! ## Supported Data Types
//!
//! Currently, the following data types are supported:
//!
//! - **bool:** simple split into 2 junks
//! - **char:** behaves like `u32`
//! - **unsigned integers:** native implementation, depending on the width
//! - **signed integers:** splitting into positive and negative parts and using the unsigned
//!   implementation
//! - **floats:** splits data into `-∞`, `(-∞,-0)`, `-0`, `+0`, `(+0,+∞)`, `+∞` and treating the two
//!   ranges as unsigned integer values. [Subnormals](https://en.wikipedia.org/wiki/Denormal_number)
//!   and `NaN`s are not supported!
//! - **arrays, tuples:** use the implementation of the inner data types
//! - *custom data types...: fill in the provided template trait*
//!
//!
//! ## Example
//!
//! ```
//! use rdxsort::*;
//!
//! fn main() {
//!     let mut data = vec![2, 10, 0, 1];
//!     data.rdxsort();
//!     assert!(data == vec![0, 1, 2, 10]);
//! }
//! ```
//!
//!
//! ## Performance
//!
//! Of course the lower runtime complexity of Radix Sort shows its power when sorting certain data
//! types. The advantage depends on the size and complexity of the type. While short unsigned
//! integers benefit the most, long types do not show that huge improvements. The following listing
//! shows the runtime in ns required for sorting data sets of different sizes. The data sets are
//! sampled using an uniform distribution. The best algorithm out of the following is marked:
//!
//! - [quicksort](https://crates.io/crates/quicksort)
//! - rdxsort (this crate)
//! - [standard library](https://doc.rust-lang.org/std/vec/struct.Vec.html#method.sort_by)
//!
//! Keep in mind that the results may vary depending on the hardware, compiler version, operating
//! system version and configuration and the weather.
//!
//!
//! ### Small (1'000 elements)
//!
//! For small data sets Radix Sort can be an advantage for data types with up to 32 bits size. For
//! 64 bits, standard library sorting should be preferred.
//!
//! | type | quicksort | rdxsort | std |
//! |-----:|----------:|--------:|----:|
//! | `bool` | `4,070` | **`2,246`** | `26,068` |
//! | `char` | `31,121` | **`20,204`** | `34,051` |
//! | `f32` | `79,714` | **`25,825`** | `77,774` |
//! | `f64` | `80,954` | **`52,262`** | `79,431` |
//! | `i16` | `32,896` | **`12,496`** | `31,167` |
//! | `i32` | `32,854` | **`22,009`** | `30,713` |
//! | `i64` | `33,064` | `53,366` | **`31,669`** |
//! | `i8` | `24,819` | **`8,190`** | `46,281` |
//! | `u16` | `35,252` | **`9,937`** | `33,946` |
//! | `u32` | `33,002` | **`19,202`** | `33,627` |
//! | `u64` | **`32,986`** | `47,739` | `33,204` |
//! | `u8` | `25,425` | **`5,170`** | `47,369` |
//!
//!
//! ### Medium (10'000 elements)
//!
//! For medium data sets Radix Sort could be blindly used for all data types since the disadvantage
//! for types with 64 bits is quite small.
//!
//! | type | quicksort | rdxsort | std |
//! |-----:|----------:|--------:|----:|
//! | `bool` | `52,211` | **`22,083`** | `400,111` |
//! | `char` | `655,553` | **`192,328`** | `508,557` |
//! | `f32` | `1,086,882` | **`230,670`** | `1,117,565` |
//! | `f64` | `1,095,529` | **`417,104`** | `1,152,340` |
//! | `i16` | `665,131` | **`108,128`** | `455,047` |
//! | `i32` | `650,501` | **`202,533`** | `460,097` |
//! | `i64` | `669,643` | **`378,480`** | `470,572` |
//! | `i8` | `383,545` | **`65,521`** | `617,405` |
//! | `u16` | `675,060` | **`78,424`** | `508,264` |
//! | `u32` | `670,348` | **`177,068`** | `511,134` |
//! | `u64` | `664,549` | **`342,935`** | `517,176` |
//! | `u8` | `386,572` | **`37,012`** | `655,377` |
//!
//!
//! ### Large (100'000 elements)
//!
//! For large data sets, Radix Sort is great for all data types.
//!
//! | type | quicksort | rdxsort | std |
//! |-----:|----------:|--------:|----:|
//! | `bool` | `815,653` | **`216,809`** | `4,900,426` |
//! | `char` | `8,131,402` | **`2,538,064`** | `6,333,865` |
//! | `f32` | `13,554,291` | **`3,264,657`** | `14,340,082` |
//! | `f64` | `13,746,190` | **`7,122,334`** | `15,563,206` |
//! | `i16` | `8,235,642` | **`1,248,289`** | `5,575,196` |
//! | `i32` | `8,184,902` | **`2,494,882`** | `5,852,913` |
//! | `i64` | `8,222,482` | **`5,446,507`** | `6,561,292` |
//! | `i8` | `3,664,532` | **`703,288`** | `7,118,816` |
//! | `u16` | `8,272,903` | **`866,833`** | `6,291,101` |
//! | `u32` | `8,193,408` | **`2,051,413`** | `6,395,163` |
//! | `u64` | `8,179,078` | **`4,393,579`** | `7,216,868` |
//! | `u8` | `3,681,361` | **`367,240`** | `7,816,775` |
//!
//!
//! ## Implementing New Types
//!
//! This crate enables you to add support for new types by implementing `RdxSortTemplate`. It
//! describes how data is sorted into buckets and how many rounds of sorting are scheduled.
//!
//! ```
//! use rdxsort::*;
//!
//! // `Clone` is required for `RdxSort`
//! // `PartialEq` is only required for the equality assert, not for the actual sorting
//! #[derive(Clone, PartialEq)]
//! struct Foo {
//!     a: u8,
//!     b: u8,
//! }
//!
//! impl RdxSortTemplate for Foo {
//!     // using `#[inline]` is generally recommended since it helps
//!     // the compiler to optimize the sorting algorithm
//!     #[inline]
//!     fn cfg_nbuckets() -> usize {
//!         // usually too high, but works as a simple demonstration
//!         // `256 = 2^8`
//!         256
//!     }
//!
//!     #[inline]
//!     fn cfg_nrounds() -> usize {
//!         // one per sub-type
//!         2
//!     }
//!
//!     #[inline]
//!     fn get_bucket(&self, round: usize) -> usize {
//!         // return the least significant digit first
//!         if round == 0 {
//!             self.b as usize
//!         } else {
//!             self.a as usize
//!         }
//!     }
//!
//!     #[inline]
//!     fn reverse(_round: usize, _bucket: usize) -> bool {
//!         // not required in our case
//!         false
//!     }
//! }
//!
//! fn main() {
//!     let mut data = vec![
//!         Foo{a: 5, b: 2},
//!         Foo{a: 0, b: 1},
//!         Foo{a: 5, b: 1},
//!         Foo{a: 0, b: 2},
//!     ];
//!     data.rdxsort();
//!
//!     let reference = vec![
//!         Foo{a: 0, b: 1},
//!         Foo{a: 0, b: 2},
//!         Foo{a: 5, b: 1},
//!         Foo{a: 5, b: 2},
//!     ];
//!     assert!(data == reference);
//! }
//! ```

extern crate core;

/// Radix Sort implementation for some type
pub trait RdxSort {
    /// Execute Radix Sort, overwrites (unsorted) content of the type.
    fn rdxsort(&mut self);
}

#[macro_use] mod template;

mod array;
mod bool;
mod char;
mod floats;
mod signed_integer;
mod tuple;
mod unsigned_integer;

pub use template::RdxSortTemplate;
<commit_msg>update docs<commit_after>//! # RdxSort
//!
//! This crate implements [Radix Sort](https://en.wikipedia.org/wiki/Radix_sort) for slices of
//! different data types, either directly or by exploiting the implementation of other data types.
//!
//! The main reason for implementing yet another sorting algorithm is that most sorting algorithms
//! are comparative methods. To sort data, they rely on a function that compares data elements. It
//! can be proven that this leads to a runtime complexity of `O(n*log(n))` in average and `O(n^2)`
//! in the worst case. In contrast to that, Radix Sort exploits that fact that many data types have
//! a limited range of possible values and within that range a limited resolution (that also holds
//! for floating point numbers). For a detailed explanation see the
//! [Wikipedia article](https://en.wikipedia.org/wiki/Radix_sort). The result of this special
//! treatment is a lowered and constant complexity of `O(n*k)` where `k` is the number of fixed
//! rounds required to sort a specific data type.
//!
//!
//! ## Supported Data Types
//!
//! Currently, the following data types are supported:
//!
//! - **bool:** simple split into 2 junks
//! - **char:** behaves like `u32`
//! - **unsigned integers:** native implementation, depending on the width
//! - **signed integers:** splitting into positive and negative parts and using the unsigned
//!   implementation
//! - **floats:** splitting of data into positive and negative numbers and treating the two
//!   ranges as unsigned integer values. `NaN`s are not supported!
//! - **arrays, tuples:** use the implementation of the inner data types
//! - *custom data types...: fill in the provided template trait*
//!
//!
//! ## Example
//!
//! ```
//! use rdxsort::*;
//!
//! fn main() {
//!     let mut data = vec![2, 10, 0, 1];
//!     data.rdxsort();
//!     assert!(data == vec![0, 1, 2, 10]);
//! }
//! ```
//!
//!
//! ## Performance
//!
//! Of course the lower runtime complexity of Radix Sort shows its power when sorting certain data
//! types. The advantage depends on the size and complexity of the type. While short unsigned
//! integers benefit the most, long types do not show that huge improvements. The following listing
//! shows the runtime in ns required for sorting data sets of different sizes. The data sets are
//! sampled using an uniform distribution. The best algorithm out of the following is marked:
//!
//! - [quicksort](https://crates.io/crates/quicksort)
//! - rdxsort (this crate)
//! - [standard library](https://doc.rust-lang.org/std/vec/struct.Vec.html#method.sort_by)
//!
//! Keep in mind that the results may vary depending on the hardware, compiler version, operating
//! system version and configuration and the weather.
//!
//!
//! ### Small (1'000 elements)
//!
//! For small data sets Radix Sort can be an advantage for data types with up to 32 bits size. For
//! 64 bits, standard library sorting should be preferred.
//!
//! | type | quicksort | rdxsort | std |
//! |-----:|----------:|--------:|----:|
//! | `bool` | `4,070` | **`2,246`** | `26,068` |
//! | `char` | `31,121` | **`20,204`** | `34,051` |
//! | `f32` | `79,714` | **`25,825`** | `77,774` |
//! | `f64` | `80,954` | **`52,262`** | `79,431` |
//! | `i16` | `32,896` | **`12,496`** | `31,167` |
//! | `i32` | `32,854` | **`22,009`** | `30,713` |
//! | `i64` | `33,064` | `53,366` | **`31,669`** |
//! | `i8` | `24,819` | **`8,190`** | `46,281` |
//! | `u16` | `35,252` | **`9,937`** | `33,946` |
//! | `u32` | `33,002` | **`19,202`** | `33,627` |
//! | `u64` | **`32,986`** | `47,739` | `33,204` |
//! | `u8` | `25,425` | **`5,170`** | `47,369` |
//!
//!
//! ### Medium (10'000 elements)
//!
//! For medium data sets Radix Sort could be blindly used for all data types since the disadvantage
//! for types with 64 bits is quite small.
//!
//! | type | quicksort | rdxsort | std |
//! |-----:|----------:|--------:|----:|
//! | `bool` | `52,211` | **`22,083`** | `400,111` |
//! | `char` | `655,553` | **`192,328`** | `508,557` |
//! | `f32` | `1,086,882` | **`230,670`** | `1,117,565` |
//! | `f64` | `1,095,529` | **`417,104`** | `1,152,340` |
//! | `i16` | `665,131` | **`108,128`** | `455,047` |
//! | `i32` | `650,501` | **`202,533`** | `460,097` |
//! | `i64` | `669,643` | **`378,480`** | `470,572` |
//! | `i8` | `383,545` | **`65,521`** | `617,405` |
//! | `u16` | `675,060` | **`78,424`** | `508,264` |
//! | `u32` | `670,348` | **`177,068`** | `511,134` |
//! | `u64` | `664,549` | **`342,935`** | `517,176` |
//! | `u8` | `386,572` | **`37,012`** | `655,377` |
//!
//!
//! ### Large (100'000 elements)
//!
//! For large data sets, Radix Sort is great for all data types.
//!
//! | type | quicksort | rdxsort | std |
//! |-----:|----------:|--------:|----:|
//! | `bool` | `815,653` | **`216,809`** | `4,900,426` |
//! | `char` | `8,131,402` | **`2,538,064`** | `6,333,865` |
//! | `f32` | `13,554,291` | **`3,264,657`** | `14,340,082` |
//! | `f64` | `13,746,190` | **`7,122,334`** | `15,563,206` |
//! | `i16` | `8,235,642` | **`1,248,289`** | `5,575,196` |
//! | `i32` | `8,184,902` | **`2,494,882`** | `5,852,913` |
//! | `i64` | `8,222,482` | **`5,446,507`** | `6,561,292` |
//! | `i8` | `3,664,532` | **`703,288`** | `7,118,816` |
//! | `u16` | `8,272,903` | **`866,833`** | `6,291,101` |
//! | `u32` | `8,193,408` | **`2,051,413`** | `6,395,163` |
//! | `u64` | `8,179,078` | **`4,393,579`** | `7,216,868` |
//! | `u8` | `3,681,361` | **`367,240`** | `7,816,775` |
//!
//!
//! ## Implementing New Types
//!
//! This crate enables you to add support for new types by implementing `RdxSortTemplate`. It
//! describes how data is sorted into buckets and how many rounds of sorting are scheduled.
//!
//! ```
//! use rdxsort::*;
//!
//! // `Clone` is required for `RdxSort`
//! // `PartialEq` is only required for the equality assert, not for the actual sorting
//! #[derive(Clone, PartialEq)]
//! struct Foo {
//!     a: u8,
//!     b: u8,
//! }
//!
//! impl RdxSortTemplate for Foo {
//!     // using `#[inline]` is generally recommended since it helps
//!     // the compiler to optimize the sorting algorithm
//!     #[inline]
//!     fn cfg_nbuckets() -> usize {
//!         // usually too high, but works as a simple demonstration
//!         // `256 = 2^8`
//!         256
//!     }
//!
//!     #[inline]
//!     fn cfg_nrounds() -> usize {
//!         // one per sub-type
//!         2
//!     }
//!
//!     #[inline]
//!     fn get_bucket(&self, round: usize) -> usize {
//!         // return the least significant digit first
//!         if round == 0 {
//!             self.b as usize
//!         } else {
//!             self.a as usize
//!         }
//!     }
//!
//!     #[inline]
//!     fn reverse(_round: usize, _bucket: usize) -> bool {
//!         // not required in our case
//!         false
//!     }
//! }
//!
//! fn main() {
//!     let mut data = vec![
//!         Foo{a: 5, b: 2},
//!         Foo{a: 0, b: 1},
//!         Foo{a: 5, b: 1},
//!         Foo{a: 0, b: 2},
//!     ];
//!     data.rdxsort();
//!
//!     let reference = vec![
//!         Foo{a: 0, b: 1},
//!         Foo{a: 0, b: 2},
//!         Foo{a: 5, b: 1},
//!         Foo{a: 5, b: 2},
//!     ];
//!     assert!(data == reference);
//! }
//! ```

extern crate core;

/// Radix Sort implementation for some type
pub trait RdxSort {
    /// Execute Radix Sort, overwrites (unsorted) content of the type.
    fn rdxsort(&mut self);
}

#[macro_use] mod template;

mod array;
mod bool;
mod char;
mod floats;
mod signed_integer;
mod tuple;
mod unsigned_integer;

pub use template::RdxSortTemplate;
<|endoftext|>


<commit_before>#![deny(warnings)]
//! # Sqlite support for the `r2d2` connection pool.
//!
//! Library crate: [r2d2-sqlite](https://crates.io/crates/r2d2-sqlite/)
//!
//! Integrated with: [r2d2](https://crates.io/crates/r2d2)
//! and [rusqlite](https://crates.io/crates/rusqlite)
//!
//! ## Example
//!
//! ```rust,no_run
//! extern crate r2d2;
//! extern crate r2d2_sqlite;
//! extern crate rusqlite;
//!
//! use std::thread;
//! use r2d2_sqlite::SqliteConnectionManager;
//!
//! fn main() {
//!     let config = r2d2::Config::default();
//!     let manager = SqliteConnectionManager::new("file.db");
//!     let pool = r2d2::Pool::new(config, manager).unwrap();
//!
//!     for i in 0..10i32 {
//!         let pool = pool.clone();
//!         thread::spawn(move || {
//!             let conn = pool.get().unwrap();
//!             conn.execute("INSERT INTO foo (bar) VALUES (?)", &[&i]).unwrap();
//!         });
//!     }
//! }
//! ```
extern crate r2d2;
extern crate rusqlite;

use rusqlite::{Connection, Error, OpenFlags};
use std::path::{Path,PathBuf};

enum ConnectionConfig {
    File(PathBuf, OpenFlags),
}

/// An `r2d2::ManageConnection` for `rusqlite::Connection`s.
pub struct SqliteConnectionManager {
    config: ConnectionConfig,
}

impl SqliteConnectionManager {
    /// Creates a new `SqliteConnectionManager` from file.
    ///
    /// See `rusqlite::Connection::open`
    pub fn new<P:AsRef<Path>>(path: P) -> Self {
        Self::new_with_flags(path, OpenFlags::default())
    }

    /// Creates a new `SqliteConnectionManager` from file with open flags.
    ///
    /// See `rusqlite::Connection::open_with_flags`
    pub fn new_with_flags<P:AsRef<Path>>(path: P, flags: OpenFlags) -> Self {
        SqliteConnectionManager { config: ConnectionConfig::File(path.as_ref().to_path_buf(), flags) }
    }
}

impl r2d2::ManageConnection for SqliteConnectionManager {
    type Connection = Connection;
    type Error = rusqlite::Error;

    fn connect(&self) -> Result<Connection, Error> {
        match self.config {
                ConnectionConfig::File(ref path, flags) => Connection::open_with_flags(path, flags),
            }
            .map_err(Into::into)
    }

    fn is_valid(&self, conn: &mut Connection) -> Result<(), Error> {
        conn.execute_batch("").map_err(Into::into)
    }

    fn has_broken(&self, _: &mut Connection) -> bool {
        false
    }
}
<commit_msg>Formatting<commit_after>#![deny(warnings)]
//! # Sqlite support for the `r2d2` connection pool.
//!
//! Library crate: [r2d2-sqlite](https://crates.io/crates/r2d2-sqlite/)
//!
//! Integrated with: [r2d2](https://crates.io/crates/r2d2)
//! and [rusqlite](https://crates.io/crates/rusqlite)
//!
//! ## Example
//!
//! ```rust,no_run
//! extern crate r2d2;
//! extern crate r2d2_sqlite;
//! extern crate rusqlite;
//!
//! use std::thread;
//! use r2d2_sqlite::SqliteConnectionManager;
//!
//! fn main() {
//!     let config = r2d2::Config::default();
//!     let manager = SqliteConnectionManager::new("file.db");
//!     let pool = r2d2::Pool::new(config, manager).unwrap();
//!
//!     for i in 0..10i32 {
//!         let pool = pool.clone();
//!         thread::spawn(move || {
//!             let conn = pool.get().unwrap();
//!             conn.execute("INSERT INTO foo (bar) VALUES (?)", &[&i]).unwrap();
//!         });
//!     }
//! }
//! ```
extern crate r2d2;
extern crate rusqlite;

use rusqlite::{Connection, Error, OpenFlags};
use std::path::{Path,PathBuf};

enum ConnectionConfig {
    File(PathBuf, OpenFlags),
}

/// An `r2d2::ManageConnection` for `rusqlite::Connection`s.
pub struct SqliteConnectionManager {
    config: ConnectionConfig,
}

impl SqliteConnectionManager {
    /// Creates a new `SqliteConnectionManager` from file.
    ///
    /// See `rusqlite::Connection::open`
    pub fn new<P:AsRef<Path>>(path: P) -> Self {
        Self::new_with_flags(path, OpenFlags::default())
    }

    /// Creates a new `SqliteConnectionManager` from file with open flags.
    ///
    /// See `rusqlite::Connection::open_with_flags`
    pub fn new_with_flags<P:AsRef<Path>>(path: P, flags: OpenFlags) -> Self {
        SqliteConnectionManager {
            config: ConnectionConfig::File(path.as_ref().to_path_buf(), flags)
        }
    }
}

impl r2d2::ManageConnection for SqliteConnectionManager {
    type Connection = Connection;
    type Error = rusqlite::Error;

    fn connect(&self) -> Result<Connection, Error> {
        match self.config {
                ConnectionConfig::File(ref path, flags) => Connection::open_with_flags(path, flags),
            }
            .map_err(Into::into)
    }

    fn is_valid(&self, conn: &mut Connection) -> Result<(), Error> {
        conn.execute_batch("").map_err(Into::into)
    }

    fn has_broken(&self, _: &mut Connection) -> bool {
        false
    }
}
<|endoftext|>


<commit_before>/*!
```
extern crate hertz;
extern crate mel;

fn main() {
    let sample_rate = 44100;
    let window_size = 4096;
    let power_spectrum_size = window_size / 2;
    let filter_count = 100;

    let mut calls: usize = 0;

    for (row, col, value) in mel::enumerate_mel_scaling_matrix(
        sample_rate,
        window_size,
        power_spectrum_size,
        filter_count,
    ) {
        calls += 1;
    }
    assert_eq!(calls, power_spectrum_size * filter_count);
}
```
*/

extern crate ndarray;
use ndarray::ArrayBase;

#[macro_use]
extern crate nalgebra;
use nalgebra::ApproxEq;

extern crate num;
use num::{Float, FromPrimitive};

extern crate hertz;
extern crate apodize;

extern crate itertools;
use itertools::linspace;

macro_rules! f64_from_usize {
    ($val:expr) => {
        <f64>::from_usize($val)
            .expect("type `f64` can't represent a specific value of type `usize` on this architecture.");
    }
}

macro_rules! usize_from_f64 {
    ($val:expr) => {
        <usize>::from_f64($val)
            .expect("type `usize` can't represent a specific value of type `f64` on this architecture.");
    }
}

#[inline]
pub fn hertz_from_mel(mel: f64) -> f64 {
    700. * ((10.).powf(mel / 2595.) - 1.)
}

#[inline]
pub fn mel_from_hertz(hertz: f64) -> f64 {
    2595. * (1. + hertz / 700.).log10()
}

#[test]
fn test_mel() {
    assert_approx_eq_eps!(
        549.64, mel_from_hertz(440.), 0.01);
    assert_approx_eq_eps!(
        440., hertz_from_mel(549.64), 0.01);

    let mel = 0.;
    assert_approx_eq!(mel, mel_from_hertz(hertz_from_mel(mel)));
    let mel = 100.;
    assert_approx_eq_eps!(
        mel, mel_from_hertz(hertz_from_mel(mel)), 0.0001);
    let mel = 3000.;
    assert_approx_eq_eps!(
        mel, mel_from_hertz(hertz_from_mel(mel)), 0.0001);

    let hertz = 0.;
    assert_approx_eq!(hertz, hertz_from_mel(mel_from_hertz(hertz)));
    let hertz = 1000.;
    assert_approx_eq!(hertz, hertz_from_mel(mel_from_hertz(hertz)));
    let hertz = 44100. / 2.;
    assert_approx_eq!(hertz, hertz_from_mel(mel_from_hertz(hertz)));
}

/// col index changes fastest
pub struct MelScalingMatrixEnumerator<WindowIter> {
    // parameters

    /// equivalent to col count
    input_size: usize,
    /// equivalent to row count
    output_size: usize,

    mel_from_hertz: fn(f64) -> f64,
    hertz_from_mel: fn(f64) -> f64,

    max_hertz: f64,

    window_function: fn(usize) -> WindowIter,

    // state

    row_index: usize,
    col_index: usize,

    start_mels_iter: itertools::Linspace<f64>,
    end_mels_iter: itertools::Linspace<f64>,

    // this gets set anew for every row
    window_start: usize,
    window_size: usize,
    window_iter: WindowIter
}

impl<WindowIter> MelScalingMatrixEnumerator<WindowIter>
    where WindowIter: Iterator<Item=f64>
{
    #[inline]
    pub fn is_done(&self) -> bool {
        self.is_last_row() && self.is_last_col()
    }

    #[inline]
    pub fn is_last_row(&self) -> bool {
        self.output_size <= self.row_index
    }

    #[inline]
    pub fn is_last_col(&self) -> bool {
        self.input_size <= self.col_index
    }

    #[inline]
    pub fn index(&self) -> usize {
        self.row_index * self.input_size + self.col_index
    }

    #[inline]
    pub fn remaining(&self) -> usize {
        // TODO is this off by one ?
        self.len() - self.index()
    }
}

impl<WindowIter> Iterator for MelScalingMatrixEnumerator<WindowIter>
    where WindowIter: Iterator<Item=f64>
{
    type Item = (usize, usize, f64);

    #[inline]
    fn next(&mut self) -> Option<(usize, usize, f64)> {
        if self.is_done() {
            return None;
        }

        // start a new row
        if self.is_last_col() {
            self.col_index = 0;
            self.row_index += 1;

            let start_mel = self.start_mels_iter.next().unwrap();
            let end_mel = self.end_mels_iter.next().unwrap();

            let hertz_from_mel = self.hertz_from_mel;
            let start_hertz = hertz_from_mel(start_mel);
            let end_hertz = hertz_from_mel(end_mel);

            // TODO maybe round or floor or ceil here
            self.window_start = usize_from_f64!(
                start_hertz /
                self.max_hertz *
                f64_from_usize!(self.output_size));

            let window_end = usize_from_f64!(
                end_hertz /
                self.max_hertz *
                f64_from_usize!(self.output_size));

            self.window_size = window_end - self.window_start;

            let window_function = self.window_function;
            self.window_iter = window_function(self.window_size);
        }

        let col = self.col_index;

        let value = if col < self.window_start {
            match self.window_iter.next() {
                Some(value) => {
                    value / f64_from_usize!(self.window_size)
                },
                None => 0.
            }
        } else {
            0.
        };

        self.col_index += 1;
        Some((self.row_index, col, value))
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        let remaining = self.remaining();
        (remaining, Some(remaining))
    }
}

impl<WindowIter> ExactSizeIterator for MelScalingMatrixEnumerator<WindowIter>
    where WindowIter: Iterator<Item=f64>
{
    #[inline]
    fn len(&self) -> usize {
        self.input_size * self.output_size
    }
}

/// (or many vectors at once in form of a matrix)
/// to transform that vector into mel space.
/// efficiently
/// rows are mel
/// cols are freq
/// TODO get frequency index pair for nth mel
/// TODO enumerate scaling vector
/// TODO which dimension first
pub fn enumerate_mel_scaling_matrix_base<WindowIter>(
    // TODO more descriptive argument names
    min_hertz: f64,
    max_hertz: f64,
    // TODO shape
    input_size: usize,
    output_size: usize,
    mel_from_hertz: fn(f64) -> f64,
    hertz_from_mel: fn(f64) -> f64,
    window_function: fn(usize) -> WindowIter
) -> MelScalingMatrixEnumerator<WindowIter>
    where WindowIter: Iterator<Item=f64>
{
    assert!(min_hertz < max_hertz);
    assert!(output_size < input_size);
    assert!(0 < output_size);
    assert!(0 < input_size);

    let min_mel = mel_from_hertz(min_hertz);
    let max_mel = mel_from_hertz(max_hertz);

    let mut start_mels_iter = linspace(min_mel, max_mel, output_size);
    let mut end_mels_iter = linspace(max_mel, max_mel, output_size);
    end_mels_iter.next();

    let start_mel = start_mels_iter.next().unwrap();
    let end_mel = end_mels_iter.next().unwrap();

    let start_hertz = hertz_from_mel(start_mel);
    let end_hertz = hertz_from_mel(end_mel);

    // TODO maybe round or floor or ceil here
    let start_index = usize_from_f64!(
        start_hertz / max_hertz * f64_from_usize!(output_size));

    let end_index = usize_from_f64!(
        end_hertz / max_hertz * f64_from_usize!(output_size));

    let window_size = end_index - start_index;

    let window_iter = window_function(window_size);

    MelScalingMatrixEnumerator::<WindowIter> {
        // parameters
        input_size: input_size,
        output_size: output_size,
        window_function: window_function,
        hertz_from_mel: hertz_from_mel,
        mel_from_hertz: mel_from_hertz,
        max_hertz: max_hertz,

        // state
        row_index: 0,
        col_index: 0,

        start_mels_iter: start_mels_iter,
        end_mels_iter: end_mels_iter,

        window_start: start_index,
        window_size: window_size,
        window_iter: window_iter,
    }
}

/// one filter per row
pub fn enumerate_mel_scaling_matrix(
    sample_rate: usize,
    window_size: usize,
    input_size: usize,
    output_size: usize,
) -> MelScalingMatrixEnumerator<apodize::TriangularWindowIter>
{
    enumerate_mel_scaling_matrix_base(
        hertz::rayleigh(
            f64_from_usize!(sample_rate),
            f64_from_usize!(window_size)),
        hertz::nyquist(f64_from_usize!(sample_rate)),
        input_size,
        output_size,
        mel_from_hertz,
        hertz_from_mel,
        apodize::triangular_iter
    )
}

// TODO test that identity matrix with
// output_size = input_size
// and conversion functions = identity

// TODO test in a small scale that scaling matrixes are correct
// then test it in emir directly and check correctness visually
<commit_msg>make iteration run through without crashing albeit with wrong vals<commit_after>/*!
```
extern crate hertz;
extern crate mel;

fn main() {
    let sample_rate = 44100;
    let window_size = 4096;
    let power_spectrum_size = window_size / 2;
    let filter_count = 100;

    let mut calls: usize = 0;

    for (row, col, value) in mel::enumerate_mel_scaling_matrix(
        sample_rate,
        window_size,
        power_spectrum_size,
        filter_count,
    ) {
        calls += 1;
    }
    assert_eq!(calls, power_spectrum_size * filter_count);
}
```
*/

extern crate ndarray;
use ndarray::ArrayBase;

#[macro_use]
extern crate nalgebra;
use nalgebra::ApproxEq;

extern crate num;
use num::{Float, FromPrimitive};

extern crate hertz;
extern crate apodize;

extern crate itertools;
use itertools::linspace;

macro_rules! f64_from_usize {
    ($val:expr) => {
        <f64>::from_usize($val)
            .expect("type `f64` can't represent a specific value of type `usize` on this architecture.");
    }
}

macro_rules! usize_from_f64 {
    ($val:expr) => {
        <usize>::from_f64($val)
            .expect("type `usize` can't represent a specific value of type `f64` on this architecture.");
    }
}

#[inline]
pub fn hertz_from_mel(mel: f64) -> f64 {
    700. * ((10.).powf(mel / 2595.) - 1.)
}

#[inline]
pub fn mel_from_hertz(hertz: f64) -> f64 {
    2595. * (1. + hertz / 700.).log10()
}

#[test]
fn test_mel() {
    assert_approx_eq_eps!(
        549.64, mel_from_hertz(440.), 0.01);
    assert_approx_eq_eps!(
        440., hertz_from_mel(549.64), 0.01);

    let mel = 0.;
    assert_approx_eq!(mel, mel_from_hertz(hertz_from_mel(mel)));
    let mel = 100.;
    assert_approx_eq_eps!(
        mel, mel_from_hertz(hertz_from_mel(mel)), 0.0001);
    let mel = 3000.;
    assert_approx_eq_eps!(
        mel, mel_from_hertz(hertz_from_mel(mel)), 0.0001);

    let hertz = 0.;
    assert_approx_eq!(hertz, hertz_from_mel(mel_from_hertz(hertz)));
    let hertz = 1000.;
    assert_approx_eq!(hertz, hertz_from_mel(mel_from_hertz(hertz)));
    let hertz = 44100. / 2.;
    assert_approx_eq!(hertz, hertz_from_mel(mel_from_hertz(hertz)));
}

/// col index changes fastest
pub struct MelScalingMatrixEnumerator<WindowIter> {
    // parameters

    /// equivalent to col count
    input_size: usize,
    /// equivalent to row count
    output_size: usize,

    mel_from_hertz: fn(f64) -> f64,
    hertz_from_mel: fn(f64) -> f64,

    max_hertz: f64,

    window_function: fn(usize) -> WindowIter,

    // state

    row_index: usize,
    col_index: usize,

    start_mels_iter: itertools::Linspace<f64>,
    end_mels_iter: itertools::Linspace<f64>,

    // this gets set anew for every row
    window_start: usize,
    window_size: usize,
    window_iter: WindowIter
}

impl<WindowIter> MelScalingMatrixEnumerator<WindowIter>
    where WindowIter: Iterator<Item=f64>
{
    #[inline]
    pub fn is_done(&self) -> bool {
        self.is_after_last_row() && self.is_after_last_col()
    }

    #[inline]
    pub fn is_after_last_row(&self) -> bool {
        self.output_size <= self.row_index
    }

    #[inline]
    pub fn is_after_last_col(&self) -> bool {
        self.input_size <= self.col_index
    }

    #[inline]
    pub fn index(&self) -> usize {
        self.row_index * self.input_size + self.col_index
    }

    #[inline]
    pub fn remaining(&self) -> usize {
        // TODO is this off by one ?
        self.len() - self.index()
    }
}

impl<WindowIter> Iterator for MelScalingMatrixEnumerator<WindowIter>
    where WindowIter: Iterator<Item=f64>
{
    type Item = (usize, usize, f64);

    #[inline]
    fn next(&mut self) -> Option<(usize, usize, f64)> {
        if self.is_done() {
            return None;
        }

        // start a new row/filter
        if self.is_after_last_col() {
            self.col_index = 0;
            self.row_index += 1;
            if self.is_after_last_row() {
                return None;
            }

            let start_mel = self.start_mels_iter.next()
                .expect("self.start_mels_iter.next()");
            let end_mel = self.end_mels_iter.next()
                .expect("self.end_mels_iter.next()");

            let hertz_from_mel = self.hertz_from_mel;
            let start_hertz = hertz_from_mel(start_mel);
            let end_hertz = hertz_from_mel(end_mel);

            // TODO maybe round or floor or ceil here
            self.window_start = usize_from_f64!(
                start_hertz /
                self.max_hertz *
                f64_from_usize!(self.output_size));

            let window_end = usize_from_f64!(
                end_hertz /
                self.max_hertz *
                f64_from_usize!(self.output_size));

            self.window_size = window_end - self.window_start;

            let window_function = self.window_function;
            self.window_iter = window_function(self.window_size);
        }

        let col = self.col_index;

        let value = if col < self.window_start {
            match self.window_iter.next() {
                Some(value) => {
                    value / f64_from_usize!(self.window_size)
                },
                None => 0.
            }
        } else {
            0.
        };

        self.col_index += 1;
        Some((self.row_index, col, value))
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        let remaining = self.remaining();
        (remaining, Some(remaining))
    }
}

impl<WindowIter> ExactSizeIterator for MelScalingMatrixEnumerator<WindowIter>
    where WindowIter: Iterator<Item=f64>
{
    #[inline]
    fn len(&self) -> usize {
        self.input_size * self.output_size
    }
}

/// (or many vectors at once in form of a matrix)
/// to transform that vector into mel space.
/// efficiently
/// rows are mel
/// cols are freq
/// TODO get frequency index pair for nth mel
/// TODO enumerate scaling vector
/// TODO which dimension first
pub fn enumerate_mel_scaling_matrix_base<WindowIter>(
    // TODO more descriptive argument names
    min_hertz: f64,
    max_hertz: f64,
    // TODO shape
    input_size: usize,
    output_size: usize,
    mel_from_hertz: fn(f64) -> f64,
    hertz_from_mel: fn(f64) -> f64,
    window_function: fn(usize) -> WindowIter
) -> MelScalingMatrixEnumerator<WindowIter>
    where WindowIter: Iterator<Item=f64>
{
    assert!(min_hertz < max_hertz);
    assert!(output_size < input_size);
    assert!(0 < output_size);
    assert!(0 < input_size);

    let min_mel = mel_from_hertz(min_hertz);
    let max_mel = mel_from_hertz(max_hertz);

    // initially start_mels_iter == end_mels_iter
    let mut start_mels_iter = linspace(min_mel, max_mel, output_size + 1);
    let mut end_mels_iter = linspace(max_mel, max_mel, output_size + 1);
    end_mels_iter.next();

    let start_mel = start_mels_iter.next().unwrap();
    let end_mel = end_mels_iter.next().unwrap();

    let start_hertz = hertz_from_mel(start_mel);
    let end_hertz = hertz_from_mel(end_mel);

    // TODO maybe round or floor or ceil here
    let start_index = usize_from_f64!(
        start_hertz / max_hertz * f64_from_usize!(output_size));

    let end_index = usize_from_f64!(
        end_hertz / max_hertz * f64_from_usize!(output_size));

    let window_size = end_index - start_index;

    let window_iter = window_function(window_size);

    MelScalingMatrixEnumerator::<WindowIter> {
        // parameters
        input_size: input_size,
        output_size: output_size,
        window_function: window_function,
        hertz_from_mel: hertz_from_mel,
        mel_from_hertz: mel_from_hertz,
        max_hertz: max_hertz,

        // state
        row_index: 0,
        col_index: 0,

        start_mels_iter: start_mels_iter,
        end_mels_iter: end_mels_iter,

        window_start: start_index,
        window_size: window_size,
        window_iter: window_iter,
    }
}

/// one filter per row
pub fn enumerate_mel_scaling_matrix(
    sample_rate: usize,
    window_size: usize,
    input_size: usize,
    output_size: usize,
) -> MelScalingMatrixEnumerator<apodize::TriangularWindowIter>
{
    enumerate_mel_scaling_matrix_base(
        hertz::rayleigh(
            f64_from_usize!(sample_rate),
            f64_from_usize!(window_size)),
        hertz::nyquist(f64_from_usize!(sample_rate)),
        input_size,
        output_size,
        mel_from_hertz,
        hertz_from_mel,
        apodize::triangular_iter
    )
}

// TODO test that identity matrix with
// output_size = input_size
// and conversion functions = identity

// TODO test in a small scale that scaling matrixes are correct
// then test it in emir directly and check correctness visually
<|endoftext|>


<commit_before>use memory::{Memory, low_nibble, high_nibble, low_byte, high_byte};
use extensions::Incrementor;
use ops::{mod};
use std::num::One;

pub struct Cpu<'a> {
    reg: Registers,
    mem: &'a mut Memory
}

impl<'a> Cpu<'a> {
    pub fn new(memory: &'a mut Memory) -> Cpu<'a> {
        return Cpu{reg: Registers::new(), mem: memory}
    }

    /// Execute a cycle on the cpu
    pub fn tick(&mut self) {
        let instr = self.fetch_instruction();

        let a = self.reg.a.read();
        let b = self.reg.b.read();
        let c = self.reg.c.read();
        let d = self.reg.d.read();
        let e = self.reg.e.read();
        let h = self.reg.h.read();
        let l = self.reg.l.read();
        let sp = self.reg.sp.read();

        match instr {
            0x00 => ops::nop(), // NOP
            0x01 => ops::ld_next_two_byte_into_reg_pair(self.mem, &mut self.reg.pc, &mut self.reg.b, &mut self.reg.c), // LD BC, nn
            0x02 => ops::write_value_to_memory_at_address(self.mem, self.reg.a.read(), self.reg.b.read(), self.reg.c.read()), // LD (BC), A
            0x03 => ops::increment_register_pair(&mut self.reg.b, &mut self.reg.c), // INC BC
            0x04 => ops::increment_register(&mut self.reg.b, &mut self.reg.f), // INC B
            0x05 => ops::decrement_register(&mut self.reg.b, &mut self.reg.f), // DEC B
            0x06 => ops::ld_immediate(self.mem, &mut self.reg.pc, &mut self.reg.b), // LD B, n
            0x07 => ops::rotate_left_with_carry(&mut self.reg.a, &mut self.reg.f), // RLC A
            0x08 => ops::write_sp_to_address_immediate(self.mem, &mut self.reg.pc, &self.reg.sp), // LD (nn), SP
            0x09 => ops::add_register_pair_to_register_pair(&mut self.reg.h, &mut self.reg.l, b, c, &mut self.reg.f), // ADD HL, BC
            0x0A => ops::ld_from_reg_pair_as_address(self.mem, &mut self.reg.a, &mut self.reg.b, &mut self.reg.c), // LD A, (BC)
            0x0B => ops::decrement_register_pair(&mut self.reg.b, &mut self.reg.c), // DEC BC
            0x0C => ops::increment_register(&mut self.reg.c, &mut self.reg.f), // INC C
            0x0D => ops::decrement_register(&mut self.reg.c, &mut self.reg.f), // DEC C
            0x0E => ops::ld_immediate(self.mem, &mut self.reg.pc, &mut self.reg.c), // LD C, n
            0x0F => ops::rotate_right_with_carry(&mut self.reg.a, &mut self.reg.f), // RRC A
            0x10 => error!("STOP Op Code not implemented and is being used"), // STOP
            0x11 => ops::ld_next_two_byte_into_reg_pair(self.mem, &mut self.reg.pc, &mut self.reg.d, &mut self.reg.e), // LD DE, nn
            0x12 => ops::write_value_to_memory_at_address(self.mem, self.reg.a.read(), self.reg.d.read(), self.reg.e.read()), // LD (DE), A
            0x13 => ops::increment_register_pair(&mut self.reg.d, &mut self.reg.e), // INC DE
            0x14 => ops::increment_register(&mut self.reg.d, &mut self.reg.f), // INC D
            0x15 => ops::decrement_register(&mut self.reg.d, &mut self.reg.f), // DEC D
            0x16 => ops::ld_immediate(self.mem, &mut self.reg.pc, &mut self.reg.d), // LD D, n
            0x17 => ops::rotate_left_with_carry(&mut self.reg.a, &mut self.reg.f), // RL A
            0x18 => ops::jump_by_signed_immediate(self.mem, &mut self.reg.pc), // JR n
            0x19 => ops::add_register_pair_to_register_pair(&mut self.reg.h, &mut self.reg.l, d, e, &mut self.reg.f), // Add HL, DE
            0x1A => ops::ld_from_reg_pair_as_address(self.mem, &mut self.reg.a, &mut self.reg.d, &mut self.reg.e), // LD A, (DE)
            0x1B => ops::decrement_register_pair(&mut self.reg.d, &mut self.reg.e), // DEC DE
            0x1C => ops::increment_register(&mut self.reg.e, &mut self.reg.f), // INC E
            0x1E => ops::decrement_register(&mut self.reg.e, &mut self.reg.f), // DEC E
            0x1F => ops::rotate_right_with_carry(&mut self.reg.a, &mut self.reg.f), // RR A
            0x20 => ops::relative_jmp_by_signed_immediate_if_not_flag(self.mem, &mut self.reg.pc, &self.reg.f, ZeroFlag), // JR NZ, n
            0x21 => ops::ld_next_two_byte_into_reg_pair(self.mem, &mut self.reg.pc, &mut self.reg.h, &mut self.reg.l), // LD HL, nn
            0x22 => ops::write_value_to_memory_at_address_and_increment_register(self.mem, self.reg.a.read(), &mut self.reg.h, &mut self.reg.l), // LDI (HL), A
            0x23 => ops::increment_register_pair(&mut self.reg.h, &mut self.reg.l), // INC HL
            0x24 => ops::increment_register(&mut self.reg.h, &mut self.reg.f), // INC H
            0x25 => ops::decrement_register(&mut self.reg.h, &mut self.reg.f), // DEC H
            0x26 => ops::ld_immediate(self.mem, &mut self.reg.pc, &mut self.reg.h), // LD H, n
            0x27 => error!("DAA instruction not implemented and is being used"),
            0x28 => ops::relative_jmp_by_signed_immediate_if_flag(self.mem, &mut self.reg.pc, &self.reg.f, ZeroFlag), // JR Z, n
            0x29 => ops::add_register_pair_to_register_pair(&mut self.reg.h, &mut self.reg.l, h, l, &mut self.reg.f), // ADD HL, HL
            0x2A => ops::ld_from_address_pointed_to_by_register_pair_and_increment_register_pair(self.mem, &mut self.reg.a, &mut self.reg.h, &mut self.reg.l), // LDI A, HL
            0x2B => ops::decrement_register_pair(&mut self.reg.h, &mut self.reg.l), // DEC HL
            0x2C => ops::increment_register(&mut self.reg.l, &mut self.reg.f), // INC L
            0x2D => ops::decrement_register(&mut self.reg.l, &mut self.reg.f), // DEC L
            0x2E => ops::ld_immediate(self.mem, &mut self.reg.pc, &mut self.reg.l), // LD L, d8
            0x2F => ops::complement(&mut self.reg.a, &mut self.reg.f), // CPL
            0x30 => ops::relative_jmp_by_signed_immediate_if_not_flag(self.mem, &mut self.reg.pc, &self.reg.f, CarryFlag), // JR NC, n
            0x31 => ops::ld_next_two_bytes_into_reg(self.mem, &mut self.reg.pc, &mut self.reg.sp), // LD SP, nn
            0x32 => ops::write_value_to_memory_at_address_and_decrement_register(self.mem, self.reg.a.read(), &mut self.reg.h, &mut self.reg.l), // LDI (HL), A
            0x33 => self.reg.sp.increment(), // INC SP
            0x34 => ops::increment_value_at_address(self.mem, self.reg.h.read(), self.reg.l.read(), &mut self.reg.f),
            0x35 => ops::decrement_value_at_address(self.mem, self.reg.h.read(), self.reg.l.read(), &mut self.reg.f),
            0x36 => ops::ld_immediate_into_address(self.mem, &mut self.reg.pc, self.reg.h.read(), self.reg.l.read()),
            0x37 => ops::set_flag(&mut self.reg.f, CarryFlag),
            0x38 => ops::relative_jmp_by_signed_immediate_if_flag(self.mem, &mut self.reg.pc, &mut self.reg.f, CarryFlag),
            0x39 => ops::add_register_pair_to_register_pair(&mut self.reg.h, &mut self.reg.l, high_byte(sp), low_byte(sp), &mut self.reg.f), // ADD HL, SP
            0x3A => ops::ld_from_address_pointed_to_by_register_pair_and_decrement_register_pair(self.mem, &mut self.reg.a, &mut self.reg.h, &mut self.reg.l), // LDD A, HL
            0x3B => self.reg.sp.decrement(), // INC SP
            0x3C => ops::increment_register(&mut self.reg.a, &mut self.reg.f), // INC A
            0x3D => ops::decrement_register(&mut self.reg.a, &mut self.reg.f), // DEC A
            0x3E => ops::ld_immediate(self.mem, &mut self.reg.pc, &mut self.reg.a), // LD A, d8
            0x3F => ops::reset_flag(&mut self.reg.f, CarryFlag), // CCF
            0x40 => ops::copy_value_into_register(&mut self.reg.b, b), // LD B, B
            0x41 => ops::copy_value_into_register(&mut self.reg.b, c), // LD B, C
            0x42 => ops::copy_value_into_register(&mut self.reg.b, d), // LD B, D
            0x43 => ops::copy_value_into_register(&mut self.reg.b, e), // LD B, E
            0x44 => ops::copy_value_into_register(&mut self.reg.b, h), // LD B, H
            0x45 => ops::copy_value_into_register(&mut self.reg.b, l), // LD B, L
            _ => return
        }
    }

    /// Fetches the instruction pointed to by the program counter
    /// and increments the pc by 1
    fn fetch_instruction(&mut self) -> u8 {
        let instr = self.mem.read_byte(self.reg.pc.read());
        self.reg.pc.increment();
        return instr;
    }
}

struct Registers {
    a: Register<u8>, b: Register<u8>, c: Register<u8>,
    d: Register<u8>, e: Register<u8>, f: Register<Flags>,
    h: Register<u8>, l: Register<u8>, // 8-bit registers

    pc: Register<u16>, sp: Register<u16>, // 16-bit registers
    m: Register<u16>, t: Register<u16> // clock
}

impl Registers {
    fn new() -> Registers {
        return Registers{
            a: Register::new(0),
            b: Register::new(0),
            c: Register::new(0),
            d: Register::new(0),
            e: Register::new(0),
            f: Register::new(Flags::empty()),
            h: Register::new(0),
            l: Register::new(0),

            pc: Register::new(0x100),
            sp: Register::new(0xFFFE),

            m: Register::new(0),
            t: Register::new(0)
        }
    }
}

pub struct Register<T: Copy> {
    val: T
}

impl<T: Copy> Register<T> {
    pub fn new(i: T) -> Register<T> {
        return Register { val: i };
    }

    pub fn read(&self) -> T {
        return self.val;
    }

    pub fn write(&mut self, i: T) {
        self.val = i;
    }
}

impl<T: Copy + Unsigned>  Register<T> {
    pub fn increment(&mut self) {
        let i = self.val;
        self.write(i + One::one());
    }

    pub fn decrement(&mut self) {
        let i = self.val;
        self.write(i - One::one());
    }
}

bitflags! {
    flags Flags: u8 {
        const ZeroFlag       = 0b10000000,
        const SubtractFlag   = 0b01000000,
        const HalfCarryFlag  = 0b00100000,
        const CarryFlag      = 0b00010000,
    }
}

#[test]
fn test_Register_new() {
    let reg: Register<u8> = Register::new(10);
    assert!(reg.val == 10);
}

#[test]
fn test_Register_read() {
    let reg: Register<u32> = Register::new(5);
    assert!(reg.read() == 5);
}

#[test]
fn test_Register_write() {
    let mut reg: Register<u16> = Register::new(483);

    reg.write(5);
    assert!(reg.val == 5);
}

#[test]
fn test_Register_increment() {
    let mut reg: Register<u16> = Register::new(483);

    reg.increment();
    assert!(reg.val == 484);

}

#[test]
fn test_Register_decrement() {
    let mut reg: Register<u16> = Register::new(401);

    reg.decrement();
    assert!(reg.val == 400);

}

#[test]
fn test_Registers_new() {
    let a = Registers::new();
    assert!(a.pc.read() == 0x100);
    assert!(a.sp.read() == 0xFFFE);
}
<commit_msg>Opcodes 0x46 - 0x4F<commit_after>use memory::{Memory, low_nibble, high_nibble, low_byte, high_byte};
use extensions::Incrementor;
use ops::{mod};
use std::num::One;

pub struct Cpu<'a> {
    reg: Registers,
    mem: &'a mut Memory
}

impl<'a> Cpu<'a> {
    pub fn new(memory: &'a mut Memory) -> Cpu<'a> {
        return Cpu{reg: Registers::new(), mem: memory}
    }

    /// Execute a cycle on the cpu
    pub fn tick(&mut self) {
        let instr = self.fetch_instruction();

        let a = self.reg.a.read();
        let b = self.reg.b.read();
        let c = self.reg.c.read();
        let d = self.reg.d.read();
        let e = self.reg.e.read();
        let h = self.reg.h.read();
        let l = self.reg.l.read();
        let sp = self.reg.sp.read();

        match instr {
            0x00 => ops::nop(), // NOP
            0x01 => ops::ld_next_two_byte_into_reg_pair(self.mem, &mut self.reg.pc, &mut self.reg.b, &mut self.reg.c), // LD BC, nn
            0x02 => ops::write_value_to_memory_at_address(self.mem, self.reg.a.read(), self.reg.b.read(), self.reg.c.read()), // LD (BC), A
            0x03 => ops::increment_register_pair(&mut self.reg.b, &mut self.reg.c), // INC BC
            0x04 => ops::increment_register(&mut self.reg.b, &mut self.reg.f), // INC B
            0x05 => ops::decrement_register(&mut self.reg.b, &mut self.reg.f), // DEC B
            0x06 => ops::ld_immediate(self.mem, &mut self.reg.pc, &mut self.reg.b), // LD B, n
            0x07 => ops::rotate_left_with_carry(&mut self.reg.a, &mut self.reg.f), // RLC A
            0x08 => ops::write_sp_to_address_immediate(self.mem, &mut self.reg.pc, &self.reg.sp), // LD (nn), SP
            0x09 => ops::add_register_pair_to_register_pair(&mut self.reg.h, &mut self.reg.l, b, c, &mut self.reg.f), // ADD HL, BC
            0x0A => ops::ld_from_reg_pair_as_address(self.mem, &mut self.reg.a, &mut self.reg.b, &mut self.reg.c), // LD A, (BC)
            0x0B => ops::decrement_register_pair(&mut self.reg.b, &mut self.reg.c), // DEC BC
            0x0C => ops::increment_register(&mut self.reg.c, &mut self.reg.f), // INC C
            0x0D => ops::decrement_register(&mut self.reg.c, &mut self.reg.f), // DEC C
            0x0E => ops::ld_immediate(self.mem, &mut self.reg.pc, &mut self.reg.c), // LD C, n
            0x0F => ops::rotate_right_with_carry(&mut self.reg.a, &mut self.reg.f), // RRC A
            0x10 => error!("STOP Op Code not implemented and is being used"), // STOP
            0x11 => ops::ld_next_two_byte_into_reg_pair(self.mem, &mut self.reg.pc, &mut self.reg.d, &mut self.reg.e), // LD DE, nn
            0x12 => ops::write_value_to_memory_at_address(self.mem, self.reg.a.read(), self.reg.d.read(), self.reg.e.read()), // LD (DE), A
            0x13 => ops::increment_register_pair(&mut self.reg.d, &mut self.reg.e), // INC DE
            0x14 => ops::increment_register(&mut self.reg.d, &mut self.reg.f), // INC D
            0x15 => ops::decrement_register(&mut self.reg.d, &mut self.reg.f), // DEC D
            0x16 => ops::ld_immediate(self.mem, &mut self.reg.pc, &mut self.reg.d), // LD D, n
            0x17 => ops::rotate_left_with_carry(&mut self.reg.a, &mut self.reg.f), // RL A
            0x18 => ops::jump_by_signed_immediate(self.mem, &mut self.reg.pc), // JR n
            0x19 => ops::add_register_pair_to_register_pair(&mut self.reg.h, &mut self.reg.l, d, e, &mut self.reg.f), // Add HL, DE
            0x1A => ops::ld_from_reg_pair_as_address(self.mem, &mut self.reg.a, &mut self.reg.d, &mut self.reg.e), // LD A, (DE)
            0x1B => ops::decrement_register_pair(&mut self.reg.d, &mut self.reg.e), // DEC DE
            0x1C => ops::increment_register(&mut self.reg.e, &mut self.reg.f), // INC E
            0x1E => ops::decrement_register(&mut self.reg.e, &mut self.reg.f), // DEC E
            0x1F => ops::rotate_right_with_carry(&mut self.reg.a, &mut self.reg.f), // RR A
            0x20 => ops::relative_jmp_by_signed_immediate_if_not_flag(self.mem, &mut self.reg.pc, &self.reg.f, ZeroFlag), // JR NZ, n
            0x21 => ops::ld_next_two_byte_into_reg_pair(self.mem, &mut self.reg.pc, &mut self.reg.h, &mut self.reg.l), // LD HL, nn
            0x22 => ops::write_value_to_memory_at_address_and_increment_register(self.mem, self.reg.a.read(), &mut self.reg.h, &mut self.reg.l), // LDI (HL), A
            0x23 => ops::increment_register_pair(&mut self.reg.h, &mut self.reg.l), // INC HL
            0x24 => ops::increment_register(&mut self.reg.h, &mut self.reg.f), // INC H
            0x25 => ops::decrement_register(&mut self.reg.h, &mut self.reg.f), // DEC H
            0x26 => ops::ld_immediate(self.mem, &mut self.reg.pc, &mut self.reg.h), // LD H, n
            0x27 => error!("DAA instruction not implemented and is being used"),
            0x28 => ops::relative_jmp_by_signed_immediate_if_flag(self.mem, &mut self.reg.pc, &self.reg.f, ZeroFlag), // JR Z, n
            0x29 => ops::add_register_pair_to_register_pair(&mut self.reg.h, &mut self.reg.l, h, l, &mut self.reg.f), // ADD HL, HL
            0x2A => ops::ld_from_address_pointed_to_by_register_pair_and_increment_register_pair(self.mem, &mut self.reg.a, &mut self.reg.h, &mut self.reg.l), // LDI A, HL
            0x2B => ops::decrement_register_pair(&mut self.reg.h, &mut self.reg.l), // DEC HL
            0x2C => ops::increment_register(&mut self.reg.l, &mut self.reg.f), // INC L
            0x2D => ops::decrement_register(&mut self.reg.l, &mut self.reg.f), // DEC L
            0x2E => ops::ld_immediate(self.mem, &mut self.reg.pc, &mut self.reg.l), // LD L, d8
            0x2F => ops::complement(&mut self.reg.a, &mut self.reg.f), // CPL
            0x30 => ops::relative_jmp_by_signed_immediate_if_not_flag(self.mem, &mut self.reg.pc, &self.reg.f, CarryFlag), // JR NC, n
            0x31 => ops::ld_next_two_bytes_into_reg(self.mem, &mut self.reg.pc, &mut self.reg.sp), // LD SP, nn
            0x32 => ops::write_value_to_memory_at_address_and_decrement_register(self.mem, self.reg.a.read(), &mut self.reg.h, &mut self.reg.l), // LDI (HL), A
            0x33 => self.reg.sp.increment(), // INC SP
            0x34 => ops::increment_value_at_address(self.mem, self.reg.h.read(), self.reg.l.read(), &mut self.reg.f),
            0x35 => ops::decrement_value_at_address(self.mem, self.reg.h.read(), self.reg.l.read(), &mut self.reg.f),
            0x36 => ops::ld_immediate_into_address(self.mem, &mut self.reg.pc, self.reg.h.read(), self.reg.l.read()),
            0x37 => ops::set_flag(&mut self.reg.f, CarryFlag),
            0x38 => ops::relative_jmp_by_signed_immediate_if_flag(self.mem, &mut self.reg.pc, &mut self.reg.f, CarryFlag),
            0x39 => ops::add_register_pair_to_register_pair(&mut self.reg.h, &mut self.reg.l, high_byte(sp), low_byte(sp), &mut self.reg.f), // ADD HL, SP
            0x3A => ops::ld_from_address_pointed_to_by_register_pair_and_decrement_register_pair(self.mem, &mut self.reg.a, &mut self.reg.h, &mut self.reg.l), // LDD A, HL
            0x3B => self.reg.sp.decrement(), // INC SP
            0x3C => ops::increment_register(&mut self.reg.a, &mut self.reg.f), // INC A
            0x3D => ops::decrement_register(&mut self.reg.a, &mut self.reg.f), // DEC A
            0x3E => ops::ld_immediate(self.mem, &mut self.reg.pc, &mut self.reg.a), // LD A, d8
            0x3F => ops::reset_flag(&mut self.reg.f, CarryFlag), // CCF
            0x40 => ops::copy_value_into_register(&mut self.reg.b, b), // LD B, B
            0x41 => ops::copy_value_into_register(&mut self.reg.b, c), // LD B, C
            0x42 => ops::copy_value_into_register(&mut self.reg.b, d), // LD B, D
            0x43 => ops::copy_value_into_register(&mut self.reg.b, e), // LD B, E
            0x44 => ops::copy_value_into_register(&mut self.reg.b, h), // LD B, H
            0x45 => ops::copy_value_into_register(&mut self.reg.b, l), // LD B, L
            0x46 => ops::ld_from_reg_pair_as_address(self.mem, &mut self.reg.b, self.reg.h, self.reg.l), // LD B, (HL)
            0x47 => ops::copy_value_into_register(&mut self.reg.b, a), // LD B, A
            0x48 => ops::copy_value_into_register(&mut self.reg.c, b), // LD C, B
            0x49 => ops::copy_value_into_register(&mut self.reg.c, c), // LD C, C
            0x4A => ops::copy_value_into_register(&mut self.reg.c, d), // LD C, D
            0x4B => ops::copy_value_into_register(&mut self.reg.c, e), // LD C, E
            0x4C => ops::copy_value_into_register(&mut self.reg.c, h), // LD C, H
            0x4D => ops::copy_value_into_register(&mut self.reg.c, l), // LD C, L
            0x4E => ops::ld_from_reg_pair_as_address(self.mem, &mut self.reg.b, self.reg.h, self.reg.l), // LD C, (HL)
            0x4F => ops::copy_value_into_register(&mut self.reg.c, a), // LD C, A
            _ => return
        }
    }

    /// Fetches the instruction pointed to by the program counter
    /// and increments the pc by 1
    fn fetch_instruction(&mut self) -> u8 {
        let instr = self.mem.read_byte(self.reg.pc.read());
        self.reg.pc.increment();
        return instr;
    }
}

struct Registers {
    a: Register<u8>, b: Register<u8>, c: Register<u8>,
    d: Register<u8>, e: Register<u8>, f: Register<Flags>,
    h: Register<u8>, l: Register<u8>, // 8-bit registers

    pc: Register<u16>, sp: Register<u16>, // 16-bit registers
    m: Register<u16>, t: Register<u16> // clock
}

impl Registers {
    fn new() -> Registers {
        return Registers{
            a: Register::new(0),
            b: Register::new(0),
            c: Register::new(0),
            d: Register::new(0),
            e: Register::new(0),
            f: Register::new(Flags::empty()),
            h: Register::new(0),
            l: Register::new(0),

            pc: Register::new(0x100),
            sp: Register::new(0xFFFE),

            m: Register::new(0),
            t: Register::new(0)
        }
    }
}

pub struct Register<T: Copy> {
    val: T
}

impl<T: Copy> Register<T> {
    pub fn new(i: T) -> Register<T> {
        return Register { val: i };
    }

    pub fn read(&self) -> T {
        return self.val;
    }

    pub fn write(&mut self, i: T) {
        self.val = i;
    }
}

impl<T: Copy + Unsigned>  Register<T> {
    pub fn increment(&mut self) {
        let i = self.val;
        self.write(i + One::one());
    }

    pub fn decrement(&mut self) {
        let i = self.val;
        self.write(i - One::one());
    }
}

bitflags! {
    flags Flags: u8 {
        const ZeroFlag       = 0b10000000,
        const SubtractFlag   = 0b01000000,
        const HalfCarryFlag  = 0b00100000,
        const CarryFlag      = 0b00010000,
    }
}

#[test]
fn test_Register_new() {
    let reg: Register<u8> = Register::new(10);
    assert!(reg.val == 10);
}

#[test]
fn test_Register_read() {
    let reg: Register<u32> = Register::new(5);
    assert!(reg.read() == 5);
}

#[test]
fn test_Register_write() {
    let mut reg: Register<u16> = Register::new(483);

    reg.write(5);
    assert!(reg.val == 5);
}

#[test]
fn test_Register_increment() {
    let mut reg: Register<u16> = Register::new(483);

    reg.increment();
    assert!(reg.val == 484);

}

#[test]
fn test_Register_decrement() {
    let mut reg: Register<u16> = Register::new(401);

    reg.decrement();
    assert!(reg.val == 400);

}

#[test]
fn test_Registers_new() {
    let a = Registers::new();
    assert!(a.pc.read() == 0x100);
    assert!(a.sp.read() == 0xFFFE);
}
<|endoftext|>


<commit_before>//
// Author: Joshua Holmes
//

use std::error::Error;
use std::fs::File;
use std::io::{self, Read};
use std::path::Path;

use opcode::OpCode;

/// How many bytes of system memory there are
pub const MEMORY_LENGTH: usize = 0xFFF;
/// How many items our stack holds
pub const STACK_LENGTH: usize = 0xF;
/// The number of data registers we have
pub const NUM_REGISTERS: usize = 0xF;
/// The address at which the system's font data starts in memory
pub const FONT_SET_START_ADDR: usize = 0x000;
/// The address in memory where the user program begins
pub const USER_PROGRAM_START_ADDR: usize = 0x200;
/// The fontset of the interpreter that can be referenced by user programs
pub const FONT_SET: [u8; 80] = [ 0xF0, 0x90, 0x90, 0x90, 0xF0,   // 0x0
                                 0x20, 0x60, 0x20, 0x20, 0x70,   // 0x1
                                 0xF0, 0x10, 0xF0, 0x80, 0xF0,   // 0x2
                                 0xF0, 0x10, 0xF0, 0x10, 0xF0,   // 0x3
                                 0x90, 0x90, 0xF0, 0x10, 0x10,   // 0x4
                                 0xF0, 0x80, 0xF0, 0x10, 0xF0,   // 0x5
                                 0xF0, 0x80, 0xF0, 0x90, 0xF0,   // 0x6
                                 0xF0, 0x10, 0x20, 0x40, 0x40,   // 0x7
                                 0xF0, 0x90, 0xF0, 0x90, 0xF0,   // 0x8
                                 0xF0, 0x90, 0xF0, 0x10, 0xF0,   // 0x9
                                 0xF0, 0x90, 0xF0, 0x90, 0x90,   // 0xA
                                 0xE0, 0x90, 0xE0, 0x90, 0xE0,   // 0xB
                                 0xF0, 0x80, 0x80, 0x80, 0xF0,   // 0xC
                                 0xE0, 0x90, 0x90, 0x90, 0xE0,   // 0xD
                                 0xF0, 0x80, 0xF0, 0x80, 0xF0,   // 0xE
                                 0xF0, 0x80, 0xF0, 0x80, 0x80 ]; // 0xF

#[derive(Debug)]
pub enum ProgramLoadError {
    IoError(io::Error),
}

impl From<io::Error> for ProgramLoadError {
    fn from(err: io::Error) -> Self {
        ProgramLoadError::IoError(err)
    }
}

/// Structure to represent the virtual CPU and perform execution
pub struct Cpu {
    /// the main system memory
    pub memory: [u8; MEMORY_LENGTH],
    /// the system data registers, V0 through VF
    pub data_registers: [u8; NUM_REGISTERS],
    /// the I register, used for storing addresses
    pub i_register: u16,
    /// the delay timer, decreased at 60Hz by default when non-zero
    pub delay_timer: u8,
    /// the sound timer, decreased at 60Hz by default when non-zero
    pub sound_timer: u8,
    /// the program counter, points to the current instruction in memory
    pub program_counter: usize,
    /// the stack pointer, points to the current index in the stack
    pub stack_pointer: usize,
    /// the call stack, stores return addresses from subroutines
    pub stack: [u16; STACK_LENGTH],
    /// use this to know if the PC is past the end of the program
    pub program_length: usize,
}

impl Cpu {
    /// Init the system from a file path pointing to a CHIP-8 program file
    pub fn init_from_file_path(filepath: &str) -> Result<Cpu, ProgramLoadError> {
        let path = Path::new(filepath);

        let mut file = match File::open(&path) {
            Err(e) => panic!("Couldn't open program file. Error message: {}", Error::description(&e)),
            Ok(file) => file,
        };

        Cpu::init_from_file(&mut file)
    }

    /// Init the system from a File that contains a CHIP-8 program
    pub fn init_from_file(file: &mut File) -> Result<Cpu, ProgramLoadError> {
        // read the program into a buffer
        let mut buf = Vec::new();

        match file.read_to_end(&mut buf) {
            Err(e) => panic!("Couldn't read program file. Error message: {}", Error::description(&e)),
            Ok(_) => (),
        };

        Cpu::init_from_buffer(buf)
    }

    /// Init the system from a byte vector containing a CHIP-8 program
    pub fn init_from_buffer(buf: Vec<u8>) -> Result<Cpu, ProgramLoadError> {
        // copy the user program into system memory
        if buf.len() > MEMORY_LENGTH - USER_PROGRAM_START_ADDR {
            panic!("Program file too big to fit into system memory. Size: {}", buf.len())
        }

        let mut memory = [0u8; MEMORY_LENGTH];

        for (i, x) in buf.iter().enumerate() {
            memory[USER_PROGRAM_START_ADDR + i] = *x;
        }

        // copy the font set into system memory
        for (arr_index, buf_index) in (FONT_SET_START_ADDR..FONT_SET_START_ADDR + FONT_SET.len()).enumerate() {
            memory[buf_index] = FONT_SET[arr_index];
        }

        Ok(Cpu{
            memory: memory,
            data_registers: [0u8; NUM_REGISTERS],
            i_register: 0,
            delay_timer: 0,
            sound_timer: 0,
            program_counter: USER_PROGRAM_START_ADDR,
            stack_pointer: 0,
            stack: [0u16; STACK_LENGTH],
            program_length: buf.len(),
        })
    }

    /// Fetches one opcode from memory and executes it.
    pub fn fetch_and_execute(&mut self) -> bool {
        // if the program counter is past the program, then we've completed execution
        if self.program_counter >= USER_PROGRAM_START_ADDR + self.program_length {
            return false;
        }

        // fetch the instruction and execute it
        let instruction = ((self.memory[self.program_counter] as u16) << 8) | (self.memory[self.program_counter + 1] as u16);
        let opcode = match OpCode::from_u16(instruction) {
            Some(o) => o,
            None => panic!("Error! Unimplemented opcode 0x{:4X}", instruction),
        };

        println!("{}", opcode.disasm_str);
        (opcode.operation)(&opcode.args, &mut *self);

        true
    }
}<commit_msg>Very crudely implement the 60Hz timers for delay and sound timer<commit_after>//
// Author: Joshua Holmes
//

use std::cmp::Ordering;
use std::error::Error;
use std::fs::File;
use std::io::{self, Read};
use std::path::Path;
use std::time::{SystemTime, Duration};

use opcode::OpCode;

/// How many bytes of system memory there are
pub const MEMORY_LENGTH: usize = 0xFFF;
/// How many items our stack holds
pub const STACK_LENGTH: usize = 0xF;
/// The number of data registers we have
pub const NUM_REGISTERS: usize = 0xF;
/// The address at which the system's font data starts in memory
pub const FONT_SET_START_ADDR: usize = 0x000;
/// The address in memory where the user program begins
pub const USER_PROGRAM_START_ADDR: usize = 0x200;
/// The fontset of the interpreter that can be referenced by user programs
pub const FONT_SET: [u8; 80] = [ 0xF0, 0x90, 0x90, 0x90, 0xF0,   // 0x0
                                 0x20, 0x60, 0x20, 0x20, 0x70,   // 0x1
                                 0xF0, 0x10, 0xF0, 0x80, 0xF0,   // 0x2
                                 0xF0, 0x10, 0xF0, 0x10, 0xF0,   // 0x3
                                 0x90, 0x90, 0xF0, 0x10, 0x10,   // 0x4
                                 0xF0, 0x80, 0xF0, 0x10, 0xF0,   // 0x5
                                 0xF0, 0x80, 0xF0, 0x90, 0xF0,   // 0x6
                                 0xF0, 0x10, 0x20, 0x40, 0x40,   // 0x7
                                 0xF0, 0x90, 0xF0, 0x90, 0xF0,   // 0x8
                                 0xF0, 0x90, 0xF0, 0x10, 0xF0,   // 0x9
                                 0xF0, 0x90, 0xF0, 0x90, 0x90,   // 0xA
                                 0xE0, 0x90, 0xE0, 0x90, 0xE0,   // 0xB
                                 0xF0, 0x80, 0x80, 0x80, 0xF0,   // 0xC
                                 0xE0, 0x90, 0x90, 0x90, 0xE0,   // 0xD
                                 0xF0, 0x80, 0xF0, 0x80, 0xF0,   // 0xE
                                 0xF0, 0x80, 0xF0, 0x80, 0x80 ]; // 0xF

#[derive(Debug)]
pub enum ProgramLoadError {
    IoError(io::Error),
}

impl From<io::Error> for ProgramLoadError {
    fn from(err: io::Error) -> Self {
        ProgramLoadError::IoError(err)
    }
}

/// Structure to represent the virtual CPU and perform execution
pub struct Cpu {
    /// the main system memory
    pub memory: [u8; MEMORY_LENGTH],
    /// the system data registers, V0 through VF
    pub data_registers: [u8; NUM_REGISTERS],
    /// the I register, used for storing addresses
    pub i_register: u16,
    /// the delay timer, decreased at 60Hz by default when non-zero
    pub delay_timer: u8,
    /// the sound timer, decreased at 60Hz by default when non-zero
    pub sound_timer: u8,
    /// the program counter, points to the current instruction in memory
    pub program_counter: usize,
    /// the stack pointer, points to the current index in the stack
    pub stack_pointer: usize,
    /// the call stack, stores return addresses from subroutines
    pub stack: [u16; STACK_LENGTH],
    /// use this to know if the PC is past the end of the program
    pub program_length: usize,
    /// the timestamp of the last timer decrement
    last_timer_decrease: SystemTime,
}

impl Cpu {
    /// Init the system from a file path pointing to a CHIP-8 program file
    pub fn init_from_file_path(filepath: &str) -> Result<Cpu, ProgramLoadError> {
        let path = Path::new(filepath);

        let mut file = match File::open(&path) {
            Err(e) => panic!("Couldn't open program file. Error message: {}", Error::description(&e)),
            Ok(file) => file,
        };

        Cpu::init_from_file(&mut file)
    }

    /// Init the system from a File that contains a CHIP-8 program
    pub fn init_from_file(file: &mut File) -> Result<Cpu, ProgramLoadError> {
        // read the program into a buffer
        let mut buf = Vec::new();

        match file.read_to_end(&mut buf) {
            Err(e) => panic!("Couldn't read program file. Error message: {}", Error::description(&e)),
            Ok(_) => (),
        };

        Cpu::init_from_buffer(buf)
    }

    /// Init the system from a byte vector containing a CHIP-8 program
    pub fn init_from_buffer(buf: Vec<u8>) -> Result<Cpu, ProgramLoadError> {
        // copy the user program into system memory
        if buf.len() > MEMORY_LENGTH - USER_PROGRAM_START_ADDR {
            panic!("Program file too big to fit into system memory. Size: {}", buf.len())
        }

        let mut memory = [0u8; MEMORY_LENGTH];

        for (i, x) in buf.iter().enumerate() {
            memory[USER_PROGRAM_START_ADDR + i] = *x;
        }

        // copy the font set into system memory
        for (arr_index, buf_index) in (FONT_SET_START_ADDR..FONT_SET_START_ADDR + FONT_SET.len()).enumerate() {
            memory[buf_index] = FONT_SET[arr_index];
        }

        Ok(Cpu{
            memory: memory,
            data_registers: [0u8; NUM_REGISTERS],
            i_register: 0,
            delay_timer: 0,
            sound_timer: 0,
            program_counter: USER_PROGRAM_START_ADDR,
            stack_pointer: 0,
            stack: [0u16; STACK_LENGTH],
            program_length: buf.len(),
            last_timer_decrease: SystemTime::now(),
        })
    }

    /// Fetches one opcode from memory and executes it.
    pub fn fetch_and_execute(&mut self) -> bool {
        // if the program counter is past the program, then we've completed execution
        if self.program_counter >= USER_PROGRAM_START_ADDR + self.program_length {
            return false;
        }

        // fetch the instruction and execute it
        let instruction = ((self.memory[self.program_counter] as u16) << 8) | (self.memory[self.program_counter + 1] as u16);
        let opcode = match OpCode::from_u16(instruction) {
            Some(o) => o,
            None => panic!("Error! Unimplemented opcode 0x{:4X}", instruction),
        };

        println!("{}", opcode.disasm_str);
        (opcode.operation)(&opcode.args, &mut *self);

        // see if we need to decrement the timers
        let curr_time = SystemTime::now();

        match curr_time.duration_since(self.last_timer_decrease).unwrap().cmp(&Duration::new(0, 16_666_666)) {
            Ordering::Greater => {
                // decrement the timers
                if self.delay_timer > 0 {
                    self.delay_timer -= 1;
                }

                if self.sound_timer > 0 {
                    self.sound_timer -= 1;
                }

                self.last_timer_decrease = curr_time;
            },
            _ => ()
        }

        true
    }
}<|endoftext|>


<commit_before>//!  Linear algebra package for [rust-ndarray](https://github.com/bluss/rust-ndarray) using LAPACK via [stainless-steel/lapack](https://github.com/stainless-steel/lapack)
//!
//!  Linear algebra methods
//!  -----------------------
//!  - [QR decomposition](qr/trait.QR.html)
//!  - [singular value decomposition](svd/trait.SVD.html)
//!  - [solve linear problem](solve/index.html)
//!  - [solve linear problem for triangular matrix](triangular/trait.SolveTriangular.html)
//!  - [inverse matrix](solve/trait.Inverse.html)
//!  - [eigenvalue decomposition for Hermite matrix](eigh/trait.Eigh.html)
//!
//!  Utilites
//!  -----------
//!  - [assertions for array](index.html#macros)
//!  - [generator functions](generate/index.html)
//!  - [Scalar trait](types/trait.Field.html)

extern crate blas;
extern crate lapack;
extern crate num_traits;
extern crate num_complex;
extern crate rand;
#[macro_use(s)]
extern crate ndarray;
#[macro_use]
extern crate enum_error_derive;
#[macro_use]
extern crate derive_new;

#[macro_use]
pub mod types;
pub mod error;
pub mod layout;
pub mod lapack_traits;

pub mod cholesky;
pub mod eigh;
pub mod opnorm;
pub mod qr;
pub mod solve;
pub mod svd;
pub mod triangular;

pub mod generate;
pub mod assert;
pub mod norm;
pub mod trace;

pub use assert::*;
pub use generate::*;
pub use layout::*;
pub use types::*;

pub use cholesky::*;
pub use eigh::*;
pub use norm::*;
pub use opnorm::*;
pub use qr::*;
pub use solve::*;
pub use svd::*;
pub use trace::*;
pub use triangular::*;
<commit_msg>Add document for self-consuming trait<commit_after>//!  Linear algebra package for [rust-ndarray](https://github.com/bluss/rust-ndarray) using LAPACK via [stainless-steel/lapack](https://github.com/stainless-steel/lapack)
//!
//!  Linear algebra methods
//!  -----------------------
//!  - [QR decomposition](qr/trait.QR.html)
//!  - [singular value decomposition](svd/trait.SVD.html)
//!  - [solve linear problem](solve/index.html)
//!  - [solve linear problem for triangular matrix](triangular/trait.SolveTriangular.html)
//!  - [inverse matrix](solve/trait.Inverse.html)
//!  - [eigenvalue decomposition for Hermite matrix][eigh]
//!
//!  [eigh]:eigh/trait.Eigh.html
//!
//!  Utilities
//!  -----------
//!  - [assertions for array](index.html#macros)
//!  - [generator functions](generate/index.html)
//!  - [Scalar trait](types/trait.Field.html)
//!
//!  Usage
//!  ------
//!  Most functions in this crate is defined as [self-consuming trait technique][sct] like [serde]
//!  does.
//!
//!  For example, we can execute [eigh][eigh] using three types of interfaces:
//!
//!  ```rust
//!  let a = random((3, 3));
//!  let (eval, evec) = a.eigh(UPLO::Upper)?;
//!  let (eval, evec) = (&a).eigh(UPLO::Upper)?;
//!  let (eval, evec) = (&mut a).eigh(UPLO::Upper)?;
//!  ```
//!
//!  The first type `a.eigh()` consumes `a`, and the memory of `a` is used for `evec`.
//!  The second type `(&a).eigh()` consumes the reference (not `a` itself),
//!  and the memory for `evec` is newly allocated.
//!  The last one `(&mut a).eigh()` is similar to the first one;
//!  It borrows `a` mutably, and rewrite it to contains `evec`.
//!  In all cases, the array `eval` is newly allocated.
//!
//!  [sct]:https://github.com/serde-rs/serde/releases/tag/v0.9.0
//!  [serde]:https://github.com/serde-rs/serde

extern crate blas;
extern crate lapack;
extern crate num_traits;
extern crate num_complex;
extern crate rand;
#[macro_use(s)]
extern crate ndarray;
#[macro_use]
extern crate enum_error_derive;
#[macro_use]
extern crate derive_new;

#[macro_use]
pub mod types;
pub mod error;
pub mod layout;
pub mod lapack_traits;

pub mod cholesky;
pub mod eigh;
pub mod opnorm;
pub mod qr;
pub mod solve;
pub mod svd;
pub mod triangular;

pub mod generate;
pub mod assert;
pub mod norm;
pub mod trace;

pub use assert::*;
pub use generate::*;
pub use layout::*;
pub use types::*;

pub use cholesky::*;
pub use eigh::*;
pub use norm::*;
pub use opnorm::*;
pub use qr::*;
pub use solve::*;
pub use svd::*;
pub use trace::*;
pub use triangular::*;
<|endoftext|>