<commit_before>#[cfg(test)]

extern crate image;
extern crate image_utils;

use std::fs::remove_file;
use std::path::Path;
use image::{ImageFormat, ColorType};
use image_utils::{info, Info, crop, resize};

#[test]
fn test_info_jpg() {
    let inf = info(&Path::new("./tests/images/test.jpg")).unwrap();
    assert_eq!(inf,
               Info {
                   format: ImageFormat::JPEG,
                   color: ColorType::RGB(8),
                   width: 510,
                   height: 350,
                   ratio: 510 as f32 / 350 as f32,
                   frames: 1,
               });
}

#[test]
fn test_info_jpg_tmp() {
    let inf = info(&Path::new("./tests/images/test.jpg.tmp")).unwrap();
    assert_eq!(inf,
               Info {
                   format: ImageFormat::JPEG,
                   color: ColorType::RGB(8),
                   width: 510,
                   height: 350,
                   ratio: 510 as f32 / 350 as f32,
                   frames: 1,
               });
}

#[test]
fn test_info_gif() {
    let inf = info(&Path::new("./tests/images/test.gif")).unwrap();
    assert_eq!(inf,
               Info {
                   format: ImageFormat::GIF,
                   color: ColorType::RGBA(8),
                   width: 500,
                   height: 265,
                   ratio: 500 as f32 / 265 as f32,
                   frames: 12,
               });
}

#[test]
fn test_info_gif_tmp() {
    let inf = info(&Path::new("./tests/images/test.gif.tmp")).unwrap();
    assert_eq!(inf,
               Info {
                   format: ImageFormat::GIF,
                   color: ColorType::RGBA(8),
                   width: 500,
                   height: 265,
                   ratio: 500 as f32 / 265 as f32,
                   frames: 12,
               });
}

#[test]
fn test_crop_jpg() {
    let dest = Path::new("./tests/images/cropped.jpg");
    match dest.exists() {
        true => remove_file(&dest).unwrap(),
        false => {}
    };
    crop(&Path::new("./tests/images/test.jpg"),
         10,
         10,
         100,
         100,
         &dest)
        .unwrap();
    let inf = info(&dest).unwrap();
    assert_eq!(inf,
               Info {
                   format: ImageFormat::JPEG,
                   color: ColorType::RGB(8),
                   width: 100,
                   height: 100,
                   ratio: 100 as f32 / 100 as f32,
                   frames: 1,
               });
}

#[test]
fn test_crop_jpg_tmp() {
    let dest = Path::new("./tests/images/cropped.jpg.tmp");
    match dest.exists() {
        true => remove_file(&dest).unwrap(),
        false => {}
    };
    crop(&Path::new("./tests/images/test.jpg.tmp"),
         10,
         10,
         100,
         100,
         &dest)
        .unwrap();
    let inf = info(&dest).unwrap();
    assert_eq!(inf,
               Info {
                   format: ImageFormat::JPEG,
                   color: ColorType::RGB(8),
                   width: 100,
                   height: 100,
                   ratio: 100 as f32 / 100 as f32,
                   frames: 1,
               });
}

#[test]
fn test_crop_gif() {
    let dest = Path::new("./tests/images/cropped.gif");
    match dest.exists() {
        true => remove_file(&dest).unwrap(),
        false => {}
    };
    crop(&Path::new("./tests/images/test.gif"),
         10,
         10,
         100,
         100,
         &dest)
        .unwrap();
    let inf = info(&dest).unwrap();
    assert_eq!(inf,
               Info {
                   format: ImageFormat::GIF,
                   color: ColorType::RGBA(8),
                   width: 100,
                   height: 100,
                   ratio: 100 as f32 / 100 as f32,
                   frames: 12,
               });
}

#[test]
fn test_crop_gif_tmp() {
    let dest = Path::new("./tests/images/cropped.gif.tmp");
    match dest.exists() {
        true => remove_file(&dest).unwrap(),
        false => {}
    };
    crop(&Path::new("./tests/images/test.gif.tmp"),
         10,
         10,
         100,
         100,
         &dest)
        .unwrap();
    let inf = info(&dest).unwrap();
    assert_eq!(inf,
               Info {
                   format: ImageFormat::GIF,
                   color: ColorType::RGBA(8),
                   width: 100,
                   height: 100,
                   ratio: 100 as f32 / 100 as f32,
                   frames: 12,
               });
}

#[test]
#[should_panic]
fn test_crop_jpg_x() {
    crop(&Path::new("./tests/images/test.jpg"),
         10,
         10,
         1000,
         100,
         &Path::new("./tests/images/cropped.jpg"))
        .unwrap();
}

#[test]
#[should_panic]
fn test_crop_jpg_y() {
    crop(&Path::new("./tests/images/test.jpg"),
         10,
         10,
         100,
         1000,
         &Path::new("./tests/images/cropped.jpg"))
        .unwrap();
}

#[test]
#[should_panic]
fn test_crop_gif_x() {
    crop(&Path::new("./tests/images/test.gif"),
         10,
         10,
         1000,
         100,
         &Path::new("./tests/images/cropped.gif"))
        .unwrap();
}

#[test]
#[should_panic]
fn test_crop_gif_y() {
    crop(&Path::new("./tests/images/test.gif"),
         10,
         10,
         100,
         1000,
         &Path::new("./tests/images/cropped.gif"))
        .unwrap();
}

#[test]
fn test_resize_jpg() {
    let dest = Path::new("./tests/images/resized.jpg");
    match dest.exists() {
        true => remove_file(&dest).unwrap(),
        false => {}
    };
    resize(&Path::new("./tests/images/test.jpg"), 200, 200, &dest).unwrap();
    let inf = info(&dest).unwrap();
    assert_eq!(inf,
               Info {
                   format: ImageFormat::JPEG,
                   color: ColorType::RGB(8),
                   width: 200,
                   height: 137,
                   ratio: 200 as f32 / 137 as f32,
                   frames: 1,
               });
}

#[test]
fn test_resize_jpg_tmp() {
    let dest = Path::new("./tests/images/resized.jpg.tmp");
    match dest.exists() {
        true => remove_file(&dest).unwrap(),
        false => {}
    };
    resize(&Path::new("./tests/images/test.jpg.tmp"), 200, 200, &dest).unwrap();
    let inf = info(&dest).unwrap();
    assert_eq!(inf,
               Info {
                   format: ImageFormat::JPEG,
                   color: ColorType::RGB(8),
                   width: 200,
                   height: 137,
                   ratio: 200 as f32 / 137 as f32,
                   frames: 1,
               });
}

#[test]
fn test_resize_gif() {
    let dest = Path::new("./tests/images/resized.gif");
    match dest.exists() {
        true => remove_file(&dest).unwrap(),
        false => {}
    };
    resize(&Path::new("./tests/images/test.gif"), 200, 200, &dest).unwrap();
    let inf = info(&dest).unwrap();
    assert_eq!(inf,
               Info {
                   format: ImageFormat::GIF,
                   color: ColorType::RGBA(8),
                   width: 200,
                   height: 106,
                   ratio: 200 as f32 / 106 as f32,
                   frames: 12,
               });
}

#[test]
fn test_resize_gif_tmp() {
    let dest = Path::new("./tests/images/resized.gif.tmp");
    match dest.exists() {
        true => remove_file(&dest).unwrap(),
        false => {}
    };
    resize(&Path::new("./tests/images/test.gif.tmp"), 200, 200, &dest).unwrap();
    let inf = info(&dest).unwrap();
    assert_eq!(inf,
               Info {
                   format: ImageFormat::GIF,
                   color: ColorType::RGBA(8),
                   width: 200,
                   height: 106,
                   ratio: 200 as f32 / 106 as f32,
                   frames: 12,
               });
}
<commit_msg>tests<commit_after>#[cfg(test)]

extern crate image;
extern crate image_utils;

use std::fs::remove_file;
use std::path::Path;
use image::{ImageFormat, ColorType};
use image_utils::{info, Info, crop, resize};

#[test]
fn test_info_jpg() {
    let inf = info(&Path::new("./tests/images/test.jpg")).unwrap();
    assert_eq!(inf,
               Info {
                   format: ImageFormat::JPEG,
                   color: ColorType::RGB(8),
                   width: 510,
                   height: 350,
                   ratio: 510 as f32 / 350 as f32,
                   frames: 1,
               });
}

#[test]
fn test_info_jpg_tmp() {
    let inf = info(&Path::new("./tests/images/test.jpg.tmp")).unwrap();
    assert_eq!(inf,
               Info {
                   format: ImageFormat::JPEG,
                   color: ColorType::RGB(8),
                   width: 510,
                   height: 350,
                   ratio: 510 as f32 / 350 as f32,
                   frames: 1,
               });
}

#[test]
fn test_info_gif() {
    let inf = info(&Path::new("./tests/images/test.gif")).unwrap();
    assert_eq!(inf,
               Info {
                   format: ImageFormat::GIF,
                   color: ColorType::RGBA(8),
                   width: 500,
                   height: 265,
                   ratio: 500 as f32 / 265 as f32,
                   frames: 12,
               });
}

#[test]
fn test_info_gif_tmp() {
    let inf = info(&Path::new("./tests/images/test.gif.tmp")).unwrap();
    assert_eq!(inf,
               Info {
                   format: ImageFormat::GIF,
                   color: ColorType::RGBA(8),
                   width: 500,
                   height: 265,
                   ratio: 500 as f32 / 265 as f32,
                   frames: 12,
               });
}

#[test]
fn test_crop_jpg() {
    let dest = Path::new("./tests/images/cropped.jpg");
    if dest.exists() {
        remove_file(&dest).unwrap();
    }
    crop(&Path::new("./tests/images/test.jpg"),
         10,
         10,
         100,
         100,
         &dest)
        .unwrap();
    let inf = info(&dest).unwrap();
    assert_eq!(inf,
               Info {
                   format: ImageFormat::JPEG,
                   color: ColorType::RGB(8),
                   width: 100,
                   height: 100,
                   ratio: 100 as f32 / 100 as f32,
                   frames: 1,
               });
}

#[test]
fn test_crop_jpg_tmp() {
    let dest = Path::new("./tests/images/cropped.jpg.tmp");
    if dest.exists() {
        remove_file(&dest).unwrap();
    }
    crop(&Path::new("./tests/images/test.jpg.tmp"),
         10,
         10,
         100,
         100,
         &dest)
        .unwrap();
    let inf = info(&dest).unwrap();
    assert_eq!(inf,
               Info {
                   format: ImageFormat::JPEG,
                   color: ColorType::RGB(8),
                   width: 100,
                   height: 100,
                   ratio: 100 as f32 / 100 as f32,
                   frames: 1,
               });
}

#[test]
fn test_crop_gif() {
    let dest = Path::new("./tests/images/cropped.gif");
    if dest.exists() {
        remove_file(&dest).unwrap();
    }
    crop(&Path::new("./tests/images/test.gif"),
         10,
         10,
         100,
         100,
         &dest)
        .unwrap();
    let inf = info(&dest).unwrap();
    assert_eq!(inf,
               Info {
                   format: ImageFormat::GIF,
                   color: ColorType::RGBA(8),
                   width: 100,
                   height: 100,
                   ratio: 100 as f32 / 100 as f32,
                   frames: 12,
               });
}

#[test]
fn test_crop_gif_tmp() {
    let dest = Path::new("./tests/images/cropped.gif.tmp");
    if dest.exists() {
        remove_file(&dest).unwrap();
    }
    crop(&Path::new("./tests/images/test.gif.tmp"),
         10,
         10,
         100,
         100,
         &dest)
        .unwrap();
    let inf = info(&dest).unwrap();
    assert_eq!(inf,
               Info {
                   format: ImageFormat::GIF,
                   color: ColorType::RGBA(8),
                   width: 100,
                   height: 100,
                   ratio: 100 as f32 / 100 as f32,
                   frames: 12,
               });
}

#[test]
#[should_panic]
fn test_crop_jpg_x() {
    crop(&Path::new("./tests/images/test.jpg"),
         10,
         10,
         1000,
         100,
         &Path::new("./tests/images/cropped.jpg"))
        .unwrap();
}

#[test]
#[should_panic]
fn test_crop_jpg_y() {
    crop(&Path::new("./tests/images/test.jpg"),
         10,
         10,
         100,
         1000,
         &Path::new("./tests/images/cropped.jpg"))
        .unwrap();
}

#[test]
#[should_panic]
fn test_crop_gif_x() {
    crop(&Path::new("./tests/images/test.gif"),
         10,
         10,
         1000,
         100,
         &Path::new("./tests/images/cropped.gif"))
        .unwrap();
}

#[test]
#[should_panic]
fn test_crop_gif_y() {
    crop(&Path::new("./tests/images/test.gif"),
         10,
         10,
         100,
         1000,
         &Path::new("./tests/images/cropped.gif"))
        .unwrap();
}

#[test]
fn test_resize_jpg() {
    let dest = Path::new("./tests/images/resized.jpg");
    if dest.exists() {
        remove_file(&dest).unwrap();
    }
    resize(&Path::new("./tests/images/test.jpg"), 200, 200, &dest).unwrap();
    let inf = info(&dest).unwrap();
    assert_eq!(inf,
               Info {
                   format: ImageFormat::JPEG,
                   color: ColorType::RGB(8),
                   width: 200,
                   height: 137,
                   ratio: 200 as f32 / 137 as f32,
                   frames: 1,
               });
}

#[test]
fn test_resize_jpg_tmp() {
    let dest = Path::new("./tests/images/resized.jpg.tmp");
    if dest.exists() {
        remove_file(&dest).unwrap();
    }
    resize(&Path::new("./tests/images/test.jpg.tmp"), 200, 200, &dest).unwrap();
    let inf = info(&dest).unwrap();
    assert_eq!(inf,
               Info {
                   format: ImageFormat::JPEG,
                   color: ColorType::RGB(8),
                   width: 200,
                   height: 137,
                   ratio: 200 as f32 / 137 as f32,
                   frames: 1,
               });
}

#[test]
fn test_resize_gif() {
    let dest = Path::new("./tests/images/resized.gif");
    if dest.exists() {
        remove_file(&dest).unwrap();
    }
    resize(&Path::new("./tests/images/test.gif"), 200, 200, &dest).unwrap();
    let inf = info(&dest).unwrap();
    assert_eq!(inf,
               Info {
                   format: ImageFormat::GIF,
                   color: ColorType::RGBA(8),
                   width: 200,
                   height: 106,
                   ratio: 200 as f32 / 106 as f32,
                   frames: 12,
               });
}

#[test]
fn test_resize_gif_tmp() {
    let dest = Path::new("./tests/images/resized.gif.tmp");
    if dest.exists() {
        remove_file(&dest).unwrap();
    }
    resize(&Path::new("./tests/images/test.gif.tmp"), 200, 200, &dest).unwrap();
    let inf = info(&dest).unwrap();
    assert_eq!(inf,
               Info {
                   format: ImageFormat::GIF,
                   color: ColorType::RGBA(8),
                   width: 200,
                   height: 106,
                   ratio: 200 as f32 / 106 as f32,
                   frames: 12,
               });
}
<|endoftext|>


<commit_before>#![allow(dead_code)]

use inotify::wrapper::{INotify, Watch, Event};
use futures::{Async, Poll};
use futures::stream::Stream;
use mio::deprecated::unix::Io;
use tokio_core::reactor::{Handle, PollEvented};

use std::path::Path;
use std::io;

/// Wraps an INotify object and provides asynchronous methods based on the inner object.
pub struct AsyncINotify {
    inner: INotify,
    io: PollEvented<Io>,

    cached_events: Vec<Event>,
}

impl AsyncINotify {
    pub fn init(handle: &Handle) -> io::Result<AsyncINotify> {
        AsyncINotify::init_with_flags(handle, 0)
    }

    pub fn init_with_flags(handle: &Handle, flags: isize) -> io::Result<AsyncINotify> {
        let inotify = try!(INotify::init_with_flags(flags));
        let evfd = Io::from_raw_fd(inotify.fd);

        let pollev = try!(PollEvented::new(evfd, handle));

        Ok(AsyncINotify {
            inner: inotify,
            io: pollev,
            cached_events: Vec::new(),
        })
    }

    pub fn add_watch(&self, path: &Path, mask: u32) -> io::Result<Watch> {
        self.inner.add_watch(path, mask)
    }

    pub fn rm_watch(&self, watch: Watch) -> io::Result<()> {
        self.inner.rm_watch(watch)
    }

    pub fn close(self) -> io::Result<()> {
        // FD is removed from loop by PollEvented::drop()
        self.inner.close()
    }
}

impl Stream for AsyncINotify {
    type Item = Event;
    type Error = io::Error;

    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        // BUG-ish: This returns cached events in a reversed order. Usually, that shouldn't be a
        // problem though.
        if self.cached_events.len() > 0 {
            if self.cached_events.len() == 1 {
                self.io.need_read()
            }
            return Ok(Async::Ready(self.cached_events.pop()));
        }

        match self.io.poll_read() {
            Async::NotReady => {
                return Ok(Async::NotReady);
            }
            Async::Ready(_) => (), // proceed
        }

        // the inner fd is non-blocking by default (set in the inotify crate)
        let events = try!(self.inner.available_events());

        // Only do vec operations if there are many events
        if events.len() < 1 {
            // If EWOULDBLOCK is returned, inotify returns an empty slice. Signal that we want
            // more.
            self.io.need_read();
            Ok(Async::NotReady)
        } else if events.len() == 1 {
            self.io.need_read();
            Ok(Async::Ready(Some(events[0].clone())))
        } else {
            // events.len() > 1
            self.cached_events.extend_from_slice(&events[1..]);
            Ok(Async::Ready(Some(events[0].clone())))
        }
    }
}
<commit_msg>Enhance documentation.<commit_after>#![allow(dead_code)]

use inotify::wrapper::{INotify, Watch, Event};
use futures::{Async, Poll};
use futures::stream::Stream;
use mio::deprecated::unix::Io;
use tokio_core::reactor::{Handle, PollEvented};

use std::path::Path;
use std::io;

/// Wraps an INotify object and provides asynchronous methods based on the inner object.
pub struct AsyncINotify {
    inner: INotify,
    io: PollEvented<Io>,

    cached_events: Vec<Event>,
}

impl AsyncINotify {
    /// Create a new inotify stream on the loop behind `handle`.
    pub fn init(handle: &Handle) -> io::Result<AsyncINotify> {
        AsyncINotify::init_with_flags(handle, 0)
    }

    /// Create a new inotify stream with the given inotify flags (`IN_NONBLOCK` or `IN_CLOEXEC`).
    pub fn init_with_flags(handle: &Handle, flags: isize) -> io::Result<AsyncINotify> {
        let inotify = try!(INotify::init_with_flags(flags));
        let evfd = Io::from_raw_fd(inotify.fd);

        let pollev = try!(PollEvented::new(evfd, handle));

        Ok(AsyncINotify {
            inner: inotify,
            io: pollev,
            cached_events: Vec::new(),
        })
    }

    /// Monitor `path` for the events in `mask`. For a list of events, see
    /// https://dermesser.github.io/tokio-inotify/doc/inotify/ffi/index.html (items prefixed with
    /// "Event")
    pub fn add_watch(&self, path: &Path, mask: u32) -> io::Result<Watch> {
        self.inner.add_watch(path, mask)
    }

    /// Remove an element currently watched.
    pub fn rm_watch(&self, watch: Watch) -> io::Result<()> {
        self.inner.rm_watch(watch)
    }

    /// Close the underlying file descriptor and remove it from the event loop.
    pub fn close(self) -> io::Result<()> {
        // FD is removed from loop by PollEvented::drop()
        self.inner.close()
    }
}

impl Stream for AsyncINotify {
    type Item = Event;
    type Error = io::Error;

    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        // BUG-ish: This returns cached events in a reversed order. Usually, that shouldn't be a
        // problem though.
        if self.cached_events.len() > 0 {
            if self.cached_events.len() == 1 {
                self.io.need_read()
            }
            return Ok(Async::Ready(self.cached_events.pop()));
        }

        match self.io.poll_read() {
            Async::NotReady => {
                return Ok(Async::NotReady);
            }
            Async::Ready(_) => (), // proceed
        }

        // the inner fd is non-blocking by default (set in the inotify crate)
        let events = try!(self.inner.available_events());

        // Only do vec operations if there are many events
        if events.len() < 1 {
            // If EWOULDBLOCK is returned, inotify returns an empty slice. Signal that we want
            // more.
            self.io.need_read();
            Ok(Async::NotReady)
        } else if events.len() == 1 {
            self.io.need_read();
            Ok(Async::Ready(Some(events[0].clone())))
        } else {
            // events.len() > 1
            self.cached_events.extend_from_slice(&events[1..]);
            Ok(Async::Ready(Some(events[0].clone())))
        }
    }
}
<|endoftext|>


<commit_before>/// Implementation of Stochastic universal sampling
/// https://en.wikipedia.org/wiki/Stochastic_universal_sampling
/// Runtime: O(n)
/// Memory Usage: O(n) or O(1) (in place variant)

extern crate rand;

use self::rand::{thread_rng, Rng};

pub struct RandomChoice;

impl RandomChoice {
    /// Chooses n samples by their weights. The greater their weights the more likely they get chosen.
    ///
    /// @invariant sum of weights must not overflow.
    /// @param samples The to be selected samples
    /// @param weights Weights that get chosen by their weight/probability. One weight can be greater 1.
    /// @param n Number of randomly chosen samples by weight.
    /// @return randomly selected samples by their weights
    pub fn random_choice<'a, T>(samples: &'a Vec<T>, weights: &Vec<f64>, n: usize) -> Vec<&'a T>{
        // TODO Check, if weight.len() > 0 and n > 0

        let sum:f64 = weights.iter().fold(0.0, |acc, &i| acc + i);
        let spoke_gap: f64 = sum / n as f64;

        // next_f64() ∈ [0.0, 1.0)
        let spin = thread_rng().next_f64() * spoke_gap;

        let mut i: usize = 0;
        let mut accumulated_weights = weights[0];
        let mut choices: Vec<&T> = Vec::with_capacity(n);
        let mut current_spoke: f64 = spin;

        for _ in 0 .. n {
            while accumulated_weights < current_spoke {
                i += 1;
                accumulated_weights += weights[i];
            }
            choices.push(&samples[i]);
            current_spoke += spoke_gap;
        }

        choices
    }

    pub fn random_choice_in_place<T: Copy>(samples: &mut Vec<T>, weights: &Vec<f64>) {
        // TODO Check, if weight.len() > 0 and n > 0
        let sum:f64 = weights.iter().fold(0.0, |acc, &i| acc + i);
        let n: usize = weights.len();
        let spoke_gap: f64 = sum / n as f64;

        // next_f64() ∈ [0.0, 1.0)
        let spin = thread_rng().next_f64() * spoke_gap;

        let mut j: usize = 0;
        let mut accumulated_weights = weights[0];
        let mut current_spoke: f64 = spin;

        for i in 0 .. n {
            while accumulated_weights < current_spoke {
                j += 1;
                accumulated_weights += weights[j];
            }
            samples[i] = samples[j];
            current_spoke += spoke_gap;
        }
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn test_random_choice() {
        let test_vec: Vec<f64> = vec![3.1, 1.2, 1.3, 2.0];
        //let sum:f64 = test_vec.iter().fold(0.0, |acc, &i| acc + i);

        //assert_eq!(6.0, sum);

        let choices = super::RandomChoice::random_choice(&test_vec, &test_vec, 4 as usize);

        for choice in choices {
            print!("{}, ", choice);
        }
    }

    #[test]
    fn test_random_choice_in_place() {
        let mut samples = vec!["hi", "this", "is", "a", "test!"];
        let weights: Vec<f64> = vec![1.0, 1.0, 1.0, 1.0, 1.0];

        super::RandomChoice::random_choice_in_place(&mut samples, &weights);

        for sample in samples {
            print!("{}, ", sample);
        }
    }

    #[test]
    fn test_random_choice_in_place_2() {
        struct Foo {j: i32, };
        let test1 = Foo {j: 1};
        let test2 = Foo {j: 2};
        let test3 = Foo {j: 3};
        let mut samples: Vec<&Foo> = Vec::new();

        samples.push(&test1);
        samples.push(&test2);
        samples.push(&test3);

        let weights: Vec<f64> = vec![1.0, 1.0, 1.0];

        super::RandomChoice::random_choice_in_place(&mut samples, &weights);

        for sample in samples {
            print!("foo{}, ", sample.j);
        }
    }
}
<commit_msg>use slices as argument<commit_after>/// Implementation of Stochastic universal sampling
/// https://en.wikipedia.org/wiki/Stochastic_universal_sampling
/// Runtime: O(n)
/// Memory Usage: O(n) or O(1) (in place variant)

extern crate rand;

use self::rand::{thread_rng, Rng};

pub struct RandomChoice;

impl RandomChoice {
    /// Chooses n samples by their weights. The greater their weights the more likely they get chosen.
    ///
    /// @invariant sum of weights must not overflow.
    /// @param samples The to be selected samples
    /// @param weights Weights that get chosen by their weight/probability. One weight can be greater 1.
    /// @param n Number of randomly chosen samples by weight.
    /// @return randomly selected samples by their weights
    pub fn random_choice<'a, T>(samples: &'a [T], weights: &[f64], n: usize) -> Vec<&'a T> {
        // TODO Check, if weight.len() > 0 and n > 0

        let sum:f64 = weights.iter().fold(0.0, |acc, &i| acc + i);
        let spoke_gap: f64 = sum / n as f64;

        // next_f64() ∈ [0.0, 1.0)
        let spin = thread_rng().next_f64() * spoke_gap;

        let mut i: usize = 0;
        let mut accumulated_weights = weights[0];
        let mut choices: Vec<&T> = Vec::with_capacity(n);
        let mut current_spoke: f64 = spin;

        for _ in 0 .. n {
            while accumulated_weights < current_spoke {
                i += 1;
                accumulated_weights += weights[i];
            }
            choices.push(&samples[i]);
            current_spoke += spoke_gap;
        }

        choices
    }

    pub fn random_choice_in_place<T: Clone>(samples: &mut [T], weights: &[f64]) {
        // TODO Check, if weight.len() > 0 and n > 0
        let sum:f64 = weights.iter().fold(0.0, |acc, &i| acc + i);
        let n: usize = weights.len();
        let spoke_gap: f64 = sum / n as f64;

        // next_f64() ∈ [0.0, 1.0)
        let spin = thread_rng().next_f64() * spoke_gap;

        let mut j: usize = 0;
        let mut accumulated_weights = weights[0];
        let mut current_spoke: f64 = spin;

        for i in 0 .. n {
            while accumulated_weights < current_spoke {
                j += 1;
                accumulated_weights += weights[j];
            }
            samples[i] = samples[j].clone();
            current_spoke += spoke_gap;
        }
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn test_random_choice() {
        let test_vec: Vec<f64> = vec![3.1, 1.2, 1.3, 2.0];
        //let sum:f64 = test_vec.iter().fold(0.0, |acc, &i| acc + i);

        //assert_eq!(6.0, sum);

        let choices = super::RandomChoice::random_choice(&test_vec, &test_vec, 4 as usize);

        for choice in choices {
            print!("{}, ", choice);
        }
    }

    #[test]
    fn test_random_choice_in_place() {
        let mut samples = vec!["hi", "this", "is", "a", "test!"];
        let weights: Vec<f64> = vec![1.0, 1.0, 1.0, 1.0, 1.0];

        super::RandomChoice::random_choice_in_place(&mut samples, &weights);

        for sample in samples {
            print!("{}, ", sample);
        }
    }

    #[test]
    fn test_random_choice_in_place_2() {
        struct Foo {j: i32, };
        let test1 = Foo {j: 1};
        let test2 = Foo {j: 2};
        let test3 = Foo {j: 3};
        let mut samples: Vec<&Foo> = Vec::new();

        samples.push(&test1);
        samples.push(&test2);
        samples.push(&test3);

        let weights: Vec<f64> = vec![1.0, 1.0, 1.0];

        super::RandomChoice::random_choice_in_place(&mut samples, &weights);

        for sample in samples {
            print!("foo{}, ", sample.j);
        }
    }
}
<|endoftext|>


<commit_before>use std::io;
use result::{ZipResult, ZipError};
use types::ZipFile;
use compression::CompressionMethod;
use spec;
use util;

pub fn central_header_to_zip_file<R: Reader+Seek>(reader: &mut R) -> ZipResult<ZipFile>
{
    // Parse central header
    let signature = try!(reader.read_le_u32());
    if signature != spec::CENTRAL_DIRECTORY_HEADER_SIGNATURE
    {
        return Err(ZipError::InvalidZipFile("Invalid Central Directory header"))
    }

    try!(reader.read_le_u16());
    try!(reader.read_le_u16());
    let flags = try!(reader.read_le_u16());
    let encrypted = flags & 1 == 1;
    let is_utf8 = flags & (1 << 11) != 0;
    let compression_method = try!(reader.read_le_u16());
    let last_mod_time = try!(reader.read_le_u16());
    let last_mod_date = try!(reader.read_le_u16());
    let crc32 = try!(reader.read_le_u32());
    let compressed_size = try!(reader.read_le_u32());
    let uncompressed_size = try!(reader.read_le_u32());
    let file_name_length = try!(reader.read_le_u16()) as uint;
    let extra_field_length = try!(reader.read_le_u16()) as uint;
    let file_comment_length = try!(reader.read_le_u16()) as uint;
    try!(reader.read_le_u16());
    try!(reader.read_le_u16());
    try!(reader.read_le_u32());
    let offset = try!(reader.read_le_u32()) as i64;
    let file_name_raw = try!(reader.read_exact(file_name_length));
    let extra_field = try!(reader.read_exact(extra_field_length));
    let file_comment_raw  = try!(reader.read_exact(file_comment_length));

    let file_name = match is_utf8
    {
        true => String::from_utf8_lossy(file_name_raw.as_slice()).into_string(),
        false => ::cp437::to_string(file_name_raw.as_slice()),
    };
    let file_comment = match is_utf8
    {
        true => String::from_utf8_lossy(file_comment_raw.as_slice()).into_string(),
        false => ::cp437::to_string(file_comment_raw.as_slice()),
    };

    // Remember end of central header
    let return_position = try!(reader.tell()) as i64;

    // Parse local header
    try!(reader.seek(offset, io::SeekSet));
    let signature = try!(reader.read_le_u32());
    if signature != spec::LOCAL_FILE_HEADER_SIGNATURE
    {
        return Err(ZipError::InvalidZipFile("Invalid local file header"))
    }

    try!(reader.seek(22, io::SeekCur));
    let file_name_length = try!(reader.read_le_u16()) as u64;
    let extra_field_length = try!(reader.read_le_u16()) as u64;
    let magic_and_header = 4 + 22 + 2 + 2;
    let data_start = offset as u64 + magic_and_header + file_name_length + extra_field_length;

    // Construct the result
    let mut result = ZipFile
    {
        encrypted: encrypted,
        compression_method: FromPrimitive::from_u16(compression_method).unwrap_or(CompressionMethod::Unknown),
        last_modified_time: util::msdos_datetime_to_tm(last_mod_time, last_mod_date),
        crc32: crc32,
        compressed_size: compressed_size as u64,
        uncompressed_size: uncompressed_size as u64,
        file_name: file_name,
        file_comment: file_comment,
        header_start: offset as u64,
        data_start: data_start,
    };

    try!(parse_extra_field(&mut result, extra_field.as_slice()));

    // Go back after the central header
    try!(reader.seek(return_position, io::SeekSet));

    Ok(result)
}

fn parse_extra_field(_file: &mut ZipFile, data: &[u8]) -> ZipResult<()>
{
    let mut reader = io::BufReader::new(data);
    while !reader.eof()
    {
        let kind = try!(reader.read_le_u16());
        let len = try!(reader.read_le_u16());
        debug!("Parsing extra block {:04x}", kind);
        match kind
        {
            _ => try!(reader.seek(len as i64, io::SeekCur)),
        }
    }
    Ok(())
}
<commit_msg>into_string -> into_owned<commit_after>use std::io;
use result::{ZipResult, ZipError};
use types::ZipFile;
use compression::CompressionMethod;
use spec;
use util;

pub fn central_header_to_zip_file<R: Reader+Seek>(reader: &mut R) -> ZipResult<ZipFile>
{
    // Parse central header
    let signature = try!(reader.read_le_u32());
    if signature != spec::CENTRAL_DIRECTORY_HEADER_SIGNATURE
    {
        return Err(ZipError::InvalidZipFile("Invalid Central Directory header"))
    }

    try!(reader.read_le_u16());
    try!(reader.read_le_u16());
    let flags = try!(reader.read_le_u16());
    let encrypted = flags & 1 == 1;
    let is_utf8 = flags & (1 << 11) != 0;
    let compression_method = try!(reader.read_le_u16());
    let last_mod_time = try!(reader.read_le_u16());
    let last_mod_date = try!(reader.read_le_u16());
    let crc32 = try!(reader.read_le_u32());
    let compressed_size = try!(reader.read_le_u32());
    let uncompressed_size = try!(reader.read_le_u32());
    let file_name_length = try!(reader.read_le_u16()) as uint;
    let extra_field_length = try!(reader.read_le_u16()) as uint;
    let file_comment_length = try!(reader.read_le_u16()) as uint;
    try!(reader.read_le_u16());
    try!(reader.read_le_u16());
    try!(reader.read_le_u32());
    let offset = try!(reader.read_le_u32()) as i64;
    let file_name_raw = try!(reader.read_exact(file_name_length));
    let extra_field = try!(reader.read_exact(extra_field_length));
    let file_comment_raw  = try!(reader.read_exact(file_comment_length));

    let file_name = match is_utf8
    {
        true => String::from_utf8_lossy(file_name_raw.as_slice()).into_owned(),
        false => ::cp437::to_string(file_name_raw.as_slice()),
    };
    let file_comment = match is_utf8
    {
        true => String::from_utf8_lossy(file_comment_raw.as_slice()).into_owned(),
        false => ::cp437::to_string(file_comment_raw.as_slice()),
    };

    // Remember end of central header
    let return_position = try!(reader.tell()) as i64;

    // Parse local header
    try!(reader.seek(offset, io::SeekSet));
    let signature = try!(reader.read_le_u32());
    if signature != spec::LOCAL_FILE_HEADER_SIGNATURE
    {
        return Err(ZipError::InvalidZipFile("Invalid local file header"))
    }

    try!(reader.seek(22, io::SeekCur));
    let file_name_length = try!(reader.read_le_u16()) as u64;
    let extra_field_length = try!(reader.read_le_u16()) as u64;
    let magic_and_header = 4 + 22 + 2 + 2;
    let data_start = offset as u64 + magic_and_header + file_name_length + extra_field_length;

    // Construct the result
    let mut result = ZipFile
    {
        encrypted: encrypted,
        compression_method: FromPrimitive::from_u16(compression_method).unwrap_or(CompressionMethod::Unknown),
        last_modified_time: util::msdos_datetime_to_tm(last_mod_time, last_mod_date),
        crc32: crc32,
        compressed_size: compressed_size as u64,
        uncompressed_size: uncompressed_size as u64,
        file_name: file_name,
        file_comment: file_comment,
        header_start: offset as u64,
        data_start: data_start,
    };

    try!(parse_extra_field(&mut result, extra_field.as_slice()));

    // Go back after the central header
    try!(reader.seek(return_position, io::SeekSet));

    Ok(result)
}

fn parse_extra_field(_file: &mut ZipFile, data: &[u8]) -> ZipResult<()>
{
    let mut reader = io::BufReader::new(data);
    while !reader.eof()
    {
        let kind = try!(reader.read_le_u16());
        let len = try!(reader.read_le_u16());
        debug!("Parsing extra block {:04x}", kind);
        match kind
        {
            _ => try!(reader.seek(len as i64, io::SeekCur)),
        }
    }
    Ok(())
}
<|endoftext|>


<commit_before>#[derive(Debug, Clone)]
pub struct RequestURI {
    base: String,
    query: String,
}

impl RequestURI {
    /// Create RequestURI type resource.
    pub fn new(base: String, query: String) -> RequestURI {
        RequestURI { base: base, query: query }
    }

    /// Construct requesting URL from RequestURI type resource.
    ///
    /// # Examples
    ///
    /// ```
    /// extern crate ruroonga_client as groonga;
    /// let uri_base = groonga::URIBase::new().build();
    /// let mut command = groonga::CommandQuery::new("select");
    /// command.set_argument(vec![("table", "Sites")]);
    /// let url = groonga::RequestURI::new(uri_base, command.encode()).url();
    /// ```
    pub fn url(self) -> String {
        let url = format!("{}{}", self.base, self.query);
        url
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use command_query::CommandQuery;
    use uri_base::URIBase;

    #[test]
    fn construct_request_uri() {
        let url = RequestURI::new("http://localhost:10041".to_string(),
                                  "/d/status".to_string()).url();
        assert_eq!("http://localhost:10041/d/status", url)
    }

    #[test]
    fn construct_with_actual_usage() {
        let uri_base = URIBase::new().build();
        let mut command = CommandQuery::new("select");
        command.set_argument(vec![("table", "Sites")]);
        let url = RequestURI::new(uri_base, command.encode()).url();
        assert_eq!("http://localhost:10041/d/select?table=Sites", url)
    }
}
<commit_msg>rustfmt<commit_after>#[derive(Debug, Clone)]
pub struct RequestURI {
    base: String,
    query: String,
}

impl RequestURI {
    /// Create RequestURI type resource.
    pub fn new(base: String, query: String) -> RequestURI {
        RequestURI {
            base: base,
            query: query,
        }
    }

    /// Construct requesting URL from RequestURI type resource.
    ///
    /// # Examples
    ///
    /// ```
    /// extern crate ruroonga_client as groonga;
    /// let uri_base = groonga::URIBase::new().build();
    /// let mut command = groonga::CommandQuery::new("select");
    /// command.set_argument(vec![("table", "Sites")]);
    /// let url = groonga::RequestURI::new(uri_base, command.encode()).url();
    /// ```
    pub fn url(self) -> String {
        let url = format!("{}{}", self.base, self.query);
        url
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use command_query::CommandQuery;
    use uri_base::URIBase;

    #[test]
    fn construct_request_uri() {
        let url = RequestURI::new("http://localhost:10041".to_string(),
                                  "/d/status".to_string())
                      .url();
        assert_eq!("http://localhost:10041/d/status", url)
    }

    #[test]
    fn construct_with_actual_usage() {
        let uri_base = URIBase::new().build();
        let mut command = CommandQuery::new("select");
        command.set_argument(vec![("table", "Sites")]);
        let url = RequestURI::new(uri_base, command.encode()).url();
        assert_eq!("http://localhost:10041/d/select?table=Sites", url)
    }
}
<|endoftext|>


<commit_before>//! DPLL Algorithm implementation with unit-clause propagation and
//! (TODO) pure literal assignment.

use satyrs::cnf::{CNF, Assignment, PartialAssignment};

#[allow(non_snake_case)]
pub fn DPLL(cnf: &CNF, verbose: bool) -> Option<Assignment> {
    let mut p_assn = PartialAssignment::new(cnf.nvar as usize);
    match _dpll(cnf, &mut p_assn, verbose) {
        Some(assn) => {
            Some(assn.assignment
                     .iter()
                     .map(|a| {
                         match *a {
                             Some(a) => a,
                             None => true,
                         }
                     })
                     .collect())
        }
        None => None,
    }
}

fn _dpll(cnf: &CNF, p_assn: &mut PartialAssignment, verbose: bool) -> Option<PartialAssignment> {
    if verbose {
        println!("====DPLL====\n");
        println!("{}\n{}", cnf, p_assn);
    }
    // If consistent set of literals, return True
    if cnf.clauses.is_empty() {
        let _p_assn = p_assn.clone();
        return Some(_p_assn);  // Display optional value
    }

    // If contains an empty clause return None
    for clause in cnf.clauses.values() {
        if clause.is_empty() {
            return None;
        }
    }

    // For every unit-clause, unit-propogate
    let mut _cnf = cnf.clone();
    for unit in cnf.units.iter() {
        // Previous versions of this for loop could have unit-propagated and
        // remove the unit clause here, so it's not necessary that the unit clause id
        // still exists in the clauses.
        if let Some(clause) = cnf.clauses.get(&unit) {
            // Then via unit propagation we've created an empty clause; no solution down this path
            if clause.is_empty() {
                return None;
            }
            let lit: i32 = zeroth!(clause);
            p_assn.assign_literal(lit);
            _cnf.unit_propagate(*unit); // Only propogate in the clone
            // TODO: Could have check for empty clauses in unit_propagate
        }
    }
    // Clone for the right literal, since we're going to propagate _cnf with the left literal
    let mut r_cnf = _cnf.clone();

    // TODO: For every pure literal, pure literal assign
    // Choose literal L for split
    let literal = match _cnf.clauses.values().next() {
        Some(clause) => {
            if !clause.is_empty() {
                Some(zeroth!(clause))
            } else {
                // This will return out of the *function* - we found an empty clause, so formula is
                // not satisfiable.
                return None;
            }
        }
        None => None,
    };

    if literal.is_none() {
        let _p_assn = p_assn.clone();
        return Some(_p_assn);
    }
    let lit = literal.unwrap();
    if verbose {
        if lit & 1 == 0 {
            // True
            println!("Splitting on {}", lit / 2);
        } else {
            // False
            println!("Splitting on -{}", lit / 2);
        }
    }
    // Propagate literal
    _cnf.propagate(lit);

    // Return DPLL with L and -L
    p_assn.assign_literal(lit);

    if verbose {
        println!("Trying left");
    }
    let left = _dpll(&_cnf, p_assn, verbose);
    // If this branch works, return left.
    if left.is_some() {
        return left;
    }

    // Otherwise, unassign this literal, assign its negation, and try the subsequent formula.
    let neg = lit ^ 1;
    p_assn.unassign_literal(lit);
    p_assn.assign_literal(neg);

    r_cnf.propagate(neg);
    if verbose {
        println!("Trying right");
    }
    _dpll(&r_cnf, p_assn, verbose)
}
<commit_msg>Implement pure literal propagation<commit_after>//! DPLL Algorithm implementation with unit-clause propagation and
//! pure literal assignment.

use satyrs::cnf::{CNF, Assignment, PartialAssignment};

#[allow(non_snake_case)]
pub fn DPLL(cnf: &CNF, verbose: bool) -> Option<Assignment> {
    let mut p_assn = PartialAssignment::new(cnf.nvar as usize);
    match _dpll(cnf, &mut p_assn, verbose) {
        Some(assn) => {
            Some(assn.assignment
                     .iter()
                     .map(|a| {
                         match *a {
                             Some(a) => a,
                             None => true,
                         }
                     })
                     .collect())
        }
        None => None,
    }
}

fn _dpll(cnf: &CNF, p_assn: &mut PartialAssignment, verbose: bool) -> Option<PartialAssignment> {
    if verbose {
        println!("====DPLL====\n");
        println!("{}\n{}", cnf, p_assn);
    }
    // If consistent set of literals, return True
    if cnf.clauses.is_empty() {
        let _p_assn = p_assn.clone();
        return Some(_p_assn);  // Display optional value
    }

    // If contains an empty clause return None
    for clause in cnf.clauses.values() {
        if clause.is_empty() {
            return None;
        }
    }

    // For every unit-clause, unit-propogate
    let mut _cnf = cnf.clone();
    for unit in cnf.units.iter() {
        // Previous versions of this for loop could have unit-propagated and
        // remove the unit clause here, so it's not necessary that the unit clause id
        // still exists in the clauses.
        if let Some(clause) = cnf.clauses.get(&unit) {
            // Then via unit propagation we've created an empty clause; no solution down this path
            if clause.is_empty() {
                return None;
            }
            let lit: i32 = zeroth!(clause);
            p_assn.assign_literal(lit);
            _cnf.unit_propagate(*unit); // Only propogate in the clone
            // TODO: Could have check for empty clauses in unit_propagate
        }
    }

    // Pure literal elimination
    // We can iterate through old cnf occurrences and propagate on new _cnf
    for lit in cnf.occurrences.keys() {
        let neg = *lit ^ 1;
        if !cnf.occurrences.contains_key(&neg) {
            p_assn.assign_literal(*lit);
            _cnf.propagate(*lit);
        }
    }

    // Clone for the right literal, since we're going to propagate _cnf with the left literal
    let mut r_cnf = _cnf.clone();

    // Choose literal L for split
    let literal = match _cnf.clauses.values().next() {
        Some(clause) => {
            if !clause.is_empty() {
                Some(zeroth!(clause))
            } else {
                // This will return out of the *function* - we found an empty clause, so formula is
                // not satisfiable.
                return None;
            }
        }
        None => None,
    };

    if literal.is_none() {
        let _p_assn = p_assn.clone();
        return Some(_p_assn);
    }
    let lit = literal.unwrap();
    if verbose {
        if lit & 1 == 0 {
            // True
            println!("Splitting on {}", lit / 2);
        } else {
            // False
            println!("Splitting on -{}", lit / 2);
        }
    }
    // Propagate literal
    _cnf.propagate(lit);

    // Return DPLL with L and -L
    p_assn.assign_literal(lit);

    if verbose {
        println!("Trying left");
    }
    let left = _dpll(&_cnf, p_assn, verbose);
    // If this branch works, return left.
    if left.is_some() {
        return left;
    }

    // Otherwise, unassign this literal, assign its negation, and try the subsequent formula.
    let neg = lit ^ 1;
    p_assn.unassign_literal(lit);
    p_assn.assign_literal(neg);

    r_cnf.propagate(neg);
    if verbose {
        println!("Trying right");
    }
    _dpll(&r_cnf, p_assn, verbose)
}
<|endoftext|>


<commit_before>use alloc::arc::{Arc, Weak};
use collections::{BTreeMap, VecDeque};
use core::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
use spin::{Mutex, Once, RwLock, RwLockReadGuard, RwLockWriteGuard};
use scheme::{AtomicSchemeId, ATOMIC_SCHEMEID_INIT, SchemeId};

use sync::WaitCondition;
use syscall::error::{Error, Result, EAGAIN, EBADF, EINVAL, EPIPE};
use syscall::flag::{F_GETFL, F_SETFL, O_ACCMODE, O_NONBLOCK};
use syscall::scheme::Scheme;

/// Pipes list
pub static PIPE_SCHEME_ID: AtomicSchemeId = ATOMIC_SCHEMEID_INIT;
static PIPE_NEXT_ID: AtomicUsize = ATOMIC_USIZE_INIT;
static PIPES: Once<RwLock<(BTreeMap<usize, Arc<PipeRead>>, BTreeMap<usize, Arc<PipeWrite>>)>> = Once::new();

/// Initialize pipes, called if needed
fn init_pipes() -> RwLock<(BTreeMap<usize, Arc<PipeRead>>, BTreeMap<usize, Arc<PipeWrite>>)> {
    RwLock::new((BTreeMap::new(), BTreeMap::new()))
}

/// Get the global pipes list, const
fn pipes() -> RwLockReadGuard<'static, (BTreeMap<usize, Arc<PipeRead>>, BTreeMap<usize, Arc<PipeWrite>>)> {
    PIPES.call_once(init_pipes).read()
}

/// Get the global schemes list, mutable
fn pipes_mut() -> RwLockWriteGuard<'static, (BTreeMap<usize, Arc<PipeRead>>, BTreeMap<usize, Arc<PipeWrite>>)> {
    PIPES.call_once(init_pipes).write()
}

pub fn pipe(flags: usize) -> (usize, usize) {
    let mut pipes = pipes_mut();
    let read_id = PIPE_NEXT_ID.fetch_add(1, Ordering::SeqCst);
    let write_id = PIPE_NEXT_ID.fetch_add(1, Ordering::SeqCst);
    let read = PipeRead::new(flags);
    let write = PipeWrite::new(flags, &read);
    pipes.0.insert(read_id, Arc::new(read));
    pipes.1.insert(write_id, Arc::new(write));
    (read_id, write_id)
}

pub struct PipeScheme;

impl PipeScheme {
    pub fn new(scheme_id: SchemeId) -> PipeScheme {
        PIPE_SCHEME_ID.store(scheme_id, Ordering::SeqCst);
        PipeScheme
    }
}

impl Scheme for PipeScheme {
    fn dup(&self, id: usize, _buf: &[u8]) -> Result<usize> {
        let mut pipes = pipes_mut();

        let read_option = if let Some(pipe) = pipes.0.get(&id) {
            Some(pipe.dup()?)
        } else {
            None
        };
        if let Some(pipe) = read_option {
            let pipe_id = PIPE_NEXT_ID.fetch_add(1, Ordering::SeqCst);
            pipes.0.insert(pipe_id, Arc::new(pipe));
            return Ok(pipe_id);
        }

        let write_option = if let Some(pipe) = pipes.1.get(&id) {
            Some(pipe.dup()?)
        } else {
            None
        };
        if let Some(pipe) = write_option {
            let pipe_id = PIPE_NEXT_ID.fetch_add(1, Ordering::SeqCst);
            pipes.1.insert(pipe_id, Arc::new(pipe));
            return Ok(pipe_id);
        }

        Err(Error::new(EBADF))
    }

    fn read(&self, id: usize, buf: &mut [u8]) -> Result<usize> {
        // Clone to prevent deadlocks
        let pipe = {
            let pipes = pipes();
            pipes.0.get(&id).map(|pipe| pipe.clone()).ok_or(Error::new(EBADF))?
        };

        pipe.read(buf)
    }

    fn write(&self, id: usize, buf: &[u8]) -> Result<usize> {
        // Clone to prevent deadlocks
        let pipe = {
            let pipes = pipes();
            pipes.1.get(&id).map(|pipe| pipe.clone()).ok_or(Error::new(EBADF))?
        };

        pipe.write(buf)
    }

    fn fcntl(&self, id: usize, cmd: usize, arg: usize) -> Result<usize> {
        let pipes = pipes();

        if let Some(pipe) = pipes.0.get(&id) {
            return pipe.fcntl(cmd, arg);
        }

        if let Some(pipe) = pipes.1.get(&id) {
            return pipe.fcntl(cmd, arg);
        }

        Err(Error::new(EBADF))
    }

    fn fpath(&self, _id: usize, buf: &mut [u8]) -> Result<usize> {
        let mut i = 0;
        let scheme_path = b"pipe:";
        while i < buf.len() && i < scheme_path.len() {
            buf[i] = scheme_path[i];
            i += 1;
        }
        Ok(i)
    }

    fn fsync(&self, _id: usize) -> Result<usize> {
        Ok(0)
    }

    fn close(&self, id: usize) -> Result<usize> {
        let mut pipes = pipes_mut();

        drop(pipes.0.remove(&id));
        drop(pipes.1.remove(&id));

        Ok(0)
    }
}

/// Read side of a pipe
pub struct PipeRead {
    flags: AtomicUsize,
    condition: Arc<WaitCondition>,
    vec: Arc<Mutex<VecDeque<u8>>>
}

impl PipeRead {
    pub fn new(flags: usize) -> Self {
        PipeRead {
            flags: AtomicUsize::new(flags),
            condition: Arc::new(WaitCondition::new()),
            vec: Arc::new(Mutex::new(VecDeque::new())),
        }
    }

    fn dup(&self) -> Result<Self> {
        Ok(PipeRead {
            flags: AtomicUsize::new(self.flags.load(Ordering::SeqCst)),
            condition: self.condition.clone(),
            vec: self.vec.clone()
        })
    }

    fn fcntl(&self, cmd: usize, arg: usize) -> Result<usize> {
        match cmd {
            F_GETFL => Ok(self.flags.load(Ordering::SeqCst)),
            F_SETFL => {
                self.flags.store(arg & ! O_ACCMODE, Ordering::SeqCst);
                Ok(0)
            },
            _ => Err(Error::new(EINVAL))
        }
    }

    fn read(&self, buf: &mut [u8]) -> Result<usize> {
        loop {
            {
                let mut vec = self.vec.lock();

                let mut i = 0;
                while i < buf.len() {
                    if let Some(b) = vec.pop_front() {
                        buf[i] = b;
                        i += 1;
                    } else {
                        break;
                    }
                }

                if i > 0 {
                    return Ok(i);
                }
            }

            if Arc::weak_count(&self.vec) == 0 {
                return Ok(0);
            } else if self.flags.load(Ordering::SeqCst) & O_NONBLOCK == O_NONBLOCK {
                return Err(Error::new(EAGAIN));
            } else {
                self.condition.wait();
            }
        }
    }
}

/// Read side of a pipe
pub struct PipeWrite {
    flags: AtomicUsize,
    condition: Arc<WaitCondition>,
    vec: Option<Weak<Mutex<VecDeque<u8>>>>
}

impl PipeWrite {
    pub fn new(flags: usize, read: &PipeRead) -> Self {
        PipeWrite {
            flags: AtomicUsize::new(flags),
            condition: read.condition.clone(),
            vec: Some(Arc::downgrade(&read.vec)),
        }
    }

    fn dup(&self) -> Result<Self> {
        Ok(PipeWrite {
            flags: AtomicUsize::new(self.flags.load(Ordering::SeqCst)),
            condition: self.condition.clone(),
            vec: self.vec.clone()
        })
    }

    fn fcntl(&self, cmd: usize, arg: usize) -> Result<usize> {
        match cmd {
            F_GETFL => Ok(self.flags.load(Ordering::SeqCst)),
            F_SETFL => {
                self.flags.store(arg & ! O_ACCMODE, Ordering::SeqCst);
                Ok(0)
            },
            _ => Err(Error::new(EINVAL))
        }
    }

    fn write(&self, buf: &[u8]) -> Result<usize> {
        if let Some(ref vec_weak) = self.vec {
            if let Some(vec_lock) = vec_weak.upgrade() {
                let mut vec = vec_lock.lock();

                for &b in buf.iter() {
                    vec.push_back(b);
                }

                self.condition.notify();

                Ok(buf.len())
            } else {
                Err(Error::new(EPIPE))
            }
        } else {
            panic!("PipeWrite dropped before write");
        }
    }
}

impl Drop for PipeWrite {
    fn drop(&mut self) {
        drop(self.vec.take());
        self.condition.notify();
    }
}
<commit_msg>Implement fstat() for pipe scheme<commit_after>use alloc::arc::{Arc, Weak};
use collections::{BTreeMap, VecDeque};
use core::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
use spin::{Mutex, Once, RwLock, RwLockReadGuard, RwLockWriteGuard};
use scheme::{AtomicSchemeId, ATOMIC_SCHEMEID_INIT, SchemeId};

use sync::WaitCondition;
use syscall::error::{Error, Result, EAGAIN, EBADF, EINVAL, EPIPE};
use syscall::flag::{F_GETFL, F_SETFL, O_ACCMODE, O_NONBLOCK, MODE_CHR};
use syscall::scheme::Scheme;
use syscall::data::Stat;

/// Pipes list
pub static PIPE_SCHEME_ID: AtomicSchemeId = ATOMIC_SCHEMEID_INIT;
static PIPE_NEXT_ID: AtomicUsize = ATOMIC_USIZE_INIT;
static PIPES: Once<RwLock<(BTreeMap<usize, Arc<PipeRead>>, BTreeMap<usize, Arc<PipeWrite>>)>> = Once::new();

/// Initialize pipes, called if needed
fn init_pipes() -> RwLock<(BTreeMap<usize, Arc<PipeRead>>, BTreeMap<usize, Arc<PipeWrite>>)> {
    RwLock::new((BTreeMap::new(), BTreeMap::new()))
}

/// Get the global pipes list, const
fn pipes() -> RwLockReadGuard<'static, (BTreeMap<usize, Arc<PipeRead>>, BTreeMap<usize, Arc<PipeWrite>>)> {
    PIPES.call_once(init_pipes).read()
}

/// Get the global schemes list, mutable
fn pipes_mut() -> RwLockWriteGuard<'static, (BTreeMap<usize, Arc<PipeRead>>, BTreeMap<usize, Arc<PipeWrite>>)> {
    PIPES.call_once(init_pipes).write()
}

pub fn pipe(flags: usize) -> (usize, usize) {
    let mut pipes = pipes_mut();
    let read_id = PIPE_NEXT_ID.fetch_add(1, Ordering::SeqCst);
    let write_id = PIPE_NEXT_ID.fetch_add(1, Ordering::SeqCst);
    let read = PipeRead::new(flags);
    let write = PipeWrite::new(flags, &read);
    pipes.0.insert(read_id, Arc::new(read));
    pipes.1.insert(write_id, Arc::new(write));
    (read_id, write_id)
}

pub struct PipeScheme;

impl PipeScheme {
    pub fn new(scheme_id: SchemeId) -> PipeScheme {
        PIPE_SCHEME_ID.store(scheme_id, Ordering::SeqCst);
        PipeScheme
    }
}

impl Scheme for PipeScheme {
    fn dup(&self, id: usize, _buf: &[u8]) -> Result<usize> {
        let mut pipes = pipes_mut();

        let read_option = if let Some(pipe) = pipes.0.get(&id) {
            Some(pipe.dup()?)
        } else {
            None
        };
        if let Some(pipe) = read_option {
            let pipe_id = PIPE_NEXT_ID.fetch_add(1, Ordering::SeqCst);
            pipes.0.insert(pipe_id, Arc::new(pipe));
            return Ok(pipe_id);
        }

        let write_option = if let Some(pipe) = pipes.1.get(&id) {
            Some(pipe.dup()?)
        } else {
            None
        };
        if let Some(pipe) = write_option {
            let pipe_id = PIPE_NEXT_ID.fetch_add(1, Ordering::SeqCst);
            pipes.1.insert(pipe_id, Arc::new(pipe));
            return Ok(pipe_id);
        }

        Err(Error::new(EBADF))
    }

    fn read(&self, id: usize, buf: &mut [u8]) -> Result<usize> {
        // Clone to prevent deadlocks
        let pipe = {
            let pipes = pipes();
            pipes.0.get(&id).map(|pipe| pipe.clone()).ok_or(Error::new(EBADF))?
        };

        pipe.read(buf)
    }

    fn write(&self, id: usize, buf: &[u8]) -> Result<usize> {
        // Clone to prevent deadlocks
        let pipe = {
            let pipes = pipes();
            pipes.1.get(&id).map(|pipe| pipe.clone()).ok_or(Error::new(EBADF))?
        };

        pipe.write(buf)
    }

    fn fcntl(&self, id: usize, cmd: usize, arg: usize) -> Result<usize> {
        let pipes = pipes();

        if let Some(pipe) = pipes.0.get(&id) {
            return pipe.fcntl(cmd, arg);
        }

        if let Some(pipe) = pipes.1.get(&id) {
            return pipe.fcntl(cmd, arg);
        }

        Err(Error::new(EBADF))
    }

    fn fpath(&self, _id: usize, buf: &mut [u8]) -> Result<usize> {
        let mut i = 0;
        let scheme_path = b"pipe:";
        while i < buf.len() && i < scheme_path.len() {
            buf[i] = scheme_path[i];
            i += 1;
        }
        Ok(i)
    }

    fn fstat(&self, _id: usize, stat: &mut Stat) -> Result<usize> {
        *stat = Stat {
            st_mode: MODE_CHR | 0o666,
            ..Default::default()
        };

        Ok(0)
    }

    fn fsync(&self, _id: usize) -> Result<usize> {
        Ok(0)
    }

    fn close(&self, id: usize) -> Result<usize> {
        let mut pipes = pipes_mut();

        drop(pipes.0.remove(&id));
        drop(pipes.1.remove(&id));

        Ok(0)
    }
}

/// Read side of a pipe
pub struct PipeRead {
    flags: AtomicUsize,
    condition: Arc<WaitCondition>,
    vec: Arc<Mutex<VecDeque<u8>>>
}

impl PipeRead {
    pub fn new(flags: usize) -> Self {
        PipeRead {
            flags: AtomicUsize::new(flags),
            condition: Arc::new(WaitCondition::new()),
            vec: Arc::new(Mutex::new(VecDeque::new())),
        }
    }

    fn dup(&self) -> Result<Self> {
        Ok(PipeRead {
            flags: AtomicUsize::new(self.flags.load(Ordering::SeqCst)),
            condition: self.condition.clone(),
            vec: self.vec.clone()
        })
    }

    fn fcntl(&self, cmd: usize, arg: usize) -> Result<usize> {
        match cmd {
            F_GETFL => Ok(self.flags.load(Ordering::SeqCst)),
            F_SETFL => {
                self.flags.store(arg & ! O_ACCMODE, Ordering::SeqCst);
                Ok(0)
            },
            _ => Err(Error::new(EINVAL))
        }
    }

    fn read(&self, buf: &mut [u8]) -> Result<usize> {
        loop {
            {
                let mut vec = self.vec.lock();

                let mut i = 0;
                while i < buf.len() {
                    if let Some(b) = vec.pop_front() {
                        buf[i] = b;
                        i += 1;
                    } else {
                        break;
                    }
                }

                if i > 0 {
                    return Ok(i);
                }
            }

            if Arc::weak_count(&self.vec) == 0 {
                return Ok(0);
            } else if self.flags.load(Ordering::SeqCst) & O_NONBLOCK == O_NONBLOCK {
                return Err(Error::new(EAGAIN));
            } else {
                self.condition.wait();
            }
        }
    }
}

/// Read side of a pipe
pub struct PipeWrite {
    flags: AtomicUsize,
    condition: Arc<WaitCondition>,
    vec: Option<Weak<Mutex<VecDeque<u8>>>>
}

impl PipeWrite {
    pub fn new(flags: usize, read: &PipeRead) -> Self {
        PipeWrite {
            flags: AtomicUsize::new(flags),
            condition: read.condition.clone(),
            vec: Some(Arc::downgrade(&read.vec)),
        }
    }

    fn dup(&self) -> Result<Self> {
        Ok(PipeWrite {
            flags: AtomicUsize::new(self.flags.load(Ordering::SeqCst)),
            condition: self.condition.clone(),
            vec: self.vec.clone()
        })
    }

    fn fcntl(&self, cmd: usize, arg: usize) -> Result<usize> {
        match cmd {
            F_GETFL => Ok(self.flags.load(Ordering::SeqCst)),
            F_SETFL => {
                self.flags.store(arg & ! O_ACCMODE, Ordering::SeqCst);
                Ok(0)
            },
            _ => Err(Error::new(EINVAL))
        }
    }

    fn write(&self, buf: &[u8]) -> Result<usize> {
        if let Some(ref vec_weak) = self.vec {
            if let Some(vec_lock) = vec_weak.upgrade() {
                let mut vec = vec_lock.lock();

                for &b in buf.iter() {
                    vec.push_back(b);
                }

                self.condition.notify();

                Ok(buf.len())
            } else {
                Err(Error::new(EPIPE))
            }
        } else {
            panic!("PipeWrite dropped before write");
        }
    }
}

impl Drop for PipeWrite {
    fn drop(&mut self) {
        drop(self.vec.take());
        self.condition.notify();
    }
}
<|endoftext|>


<commit_before>use Decimal;
use num::FromPrimitive;
use serde;
use serde::de::Unexpected;
use std::fmt;
use std::str::FromStr;

impl<'de> serde::Deserialize<'de> for Decimal {
    fn deserialize<D>(deserializer: D) -> Result<Decimal, D::Error>
    where
        D: serde::de::Deserializer<'de>,
    {
        deserializer.deserialize_any(DecimalVisitor)
    }
}

struct DecimalVisitor;

impl<'de> serde::de::Visitor<'de> for DecimalVisitor {
    type Value = Decimal;

    fn visit_f64<E>(self, value: f64) -> Result<Decimal, E>
    where
        E: serde::de::Error,
    {
        Decimal::from_str(&value.to_string()).map_err(|_| E::invalid_value(Unexpected::Float(value), &self))
    }

    fn visit_i64<E>(self, value: i64) -> Result<Decimal, E>
    where
        E: serde::de::Error,
    {
        match Decimal::from_i64(value) {
            Some(s) => Ok(s),
            None => Err(E::invalid_value(Unexpected::Signed(value), &self)),
        }
    }

    fn visit_u64<E>(self, value: u64) -> Result<Decimal, E>
    where
        E: serde::de::Error,
    {
        match Decimal::from_u64(value) {
            Some(s) => Ok(s),
            None => Err(E::invalid_value(Unexpected::Unsigned(value), &self)),
        }
    }

    fn visit_str<E>(self, value: &str) -> Result<Decimal, E>
    where
        E: serde::de::Error,
    {
        Decimal::from_str(value).map_err(|_| E::invalid_value(Unexpected::Str(value), &self))
    }

    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(
            formatter,
            "a Decimal type representing a fixed-point number"
        )
    }
}

impl serde::Serialize for Decimal {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: serde::Serializer,
    {
        serializer.serialize_str(&self.to_string())
    }
}

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

    use super::*;

    #[derive(Serialize, Deserialize, Debug)]
    struct Record {
        amount: Decimal,
    }

    #[test]
    fn deserialize_valid_decimal() {
        let data = [
            ("{\"amount\":\"1.234\"}", "1.234"),
            ("{\"amount\":1234}", "1234"),
            ("{\"amount\":1234.56}", "1234.56"),
        ];
        for &(serialized, value) in data.iter() {
            let result = serde_json::from_str(serialized);
            assert_eq!(
                true,
                result.is_ok(),
                "expected successful deseralization for {}. Error: {:?}",
                serialized,
                result.err().unwrap()
            );
            let record: Record = result.unwrap();
            assert_eq!(
                value,
                record.amount.to_string(),
                "expected: {}, actual: {}",
                value,
                record.amount.to_string()
            );
        }
    }

    #[test]
    #[should_panic]
    fn deserialize_invalid_decimal() {
        let serialized = "{\"amount\":\"foo\"}";
        let _: Record = serde_json::from_str(serialized).unwrap();
    }

    #[test]
    fn serialize_decimal() {
        let record = Record { amount: Decimal::new(1234, 3) };
        let serialized = serde_json::to_string(&record).unwrap();
        assert_eq!("{\"amount\":\"1.234\"}", serialized);
    }
}
<commit_msg>serde: try from_scientific when from_str fails<commit_after>use Decimal;
use num::FromPrimitive;
use serde;
use serde::de::Unexpected;
use std::fmt;
use std::str::FromStr;

impl<'de> serde::Deserialize<'de> for Decimal {
    fn deserialize<D>(deserializer: D) -> Result<Decimal, D::Error>
    where
        D: serde::de::Deserializer<'de>,
    {
        deserializer.deserialize_any(DecimalVisitor)
    }
}

struct DecimalVisitor;

impl<'de> serde::de::Visitor<'de> for DecimalVisitor {
    type Value = Decimal;

    fn visit_f64<E>(self, value: f64) -> Result<Decimal, E>
    where
        E: serde::de::Error,
    {
        Decimal::from_str(&value.to_string()).map_err(|_| E::invalid_value(Unexpected::Float(value), &self))
    }

    fn visit_i64<E>(self, value: i64) -> Result<Decimal, E>
    where
        E: serde::de::Error,
    {
        match Decimal::from_i64(value) {
            Some(s) => Ok(s),
            None => Err(E::invalid_value(Unexpected::Signed(value), &self)),
        }
    }

    fn visit_u64<E>(self, value: u64) -> Result<Decimal, E>
    where
        E: serde::de::Error,
    {
        match Decimal::from_u64(value) {
            Some(s) => Ok(s),
            None => Err(E::invalid_value(Unexpected::Unsigned(value), &self)),
        }
    }

    fn visit_str<E>(self, value: &str) -> Result<Decimal, E>
    where
        E: serde::de::Error,
    {
        Decimal::from_str(value)
            .or_else(|_| Decimal::from_scientific(value))
            .map_err(|_| E::invalid_value(Unexpected::Str(value), &self))
    }

    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(
            formatter,
            "a Decimal type representing a fixed-point number"
        )
    }
}

impl serde::Serialize for Decimal {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: serde::Serializer,
    {
        serializer.serialize_str(&self.to_string())
    }
}

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

    use super::*;

    #[derive(Serialize, Deserialize, Debug)]
    struct Record {
        amount: Decimal,
    }

    #[test]
    fn deserialize_valid_decimal() {
        let data = [
            ("{\"amount\":\"1.234\"}", "1.234"),
            ("{\"amount\":1234}", "1234"),
            ("{\"amount\":1234.56}", "1234.56"),
            ("{\"amount\":\"1.23456e3\"}", "1234.56"),
        ];
        for &(serialized, value) in data.iter() {
            let result = serde_json::from_str(serialized);
            assert_eq!(
                true,
                result.is_ok(),
                "expected successful deseralization for {}. Error: {:?}",
                serialized,
                result.err().unwrap()
            );
            let record: Record = result.unwrap();
            assert_eq!(
                value,
                record.amount.to_string(),
                "expected: {}, actual: {}",
                value,
                record.amount.to_string()
            );
        }
    }

    #[test]
    #[should_panic]
    fn deserialize_invalid_decimal() {
        let serialized = "{\"amount\":\"foo\"}";
        let _: Record = serde_json::from_str(serialized).unwrap();
    }

    #[test]
    fn serialize_decimal() {
        let record = Record { amount: Decimal::new(1234, 3) };
        let serialized = serde_json::to_string(&record).unwrap();
        assert_eq!("{\"amount\":\"1.234\"}", serialized);
    }
}
<|endoftext|>


<commit_before>import comm::*;
import libc::c_double;
import azure::*;
import azure::bindgen::*;
import azure::cairo;
import azure::cairo::bindgen::*;
import parser::html;
import parser::html::methods;
import result::extensions;

fn parse(filename: str) {
    let file_data = io::read_whole_file(filename).get();
    let reader = io::bytes_reader(file_data);
    let parser = html::parser(reader);
    loop {
        let t = parser.parse();
        log(error, #fmt("token: %?", t));
        if t == html::to_eof { break; }
    }
}

fn main(args: [str]) {
    if args.len() >= 2u {
        parse(args[1]);
    }

    // The platform event handler thread
    let osmain = platform::osmain::osmain();

    // The compositor
    let renderer = gfx::renderer::renderer(osmain);

    // The layout task
    let layout = layout::layout::layout(renderer);

    // The content task
    let content = content::content(layout);

    // Wait for keypress
    listen {|key_ch|
        send(osmain, platform::osmain::add_key_handler(key_ch));

        key_ch.recv();
    }

    // Shut everything down
    content.send(content::exit);
    layout.send(layout::layout::exit);

    listen {|wait_ch|
        renderer.send(gfx::renderer::exit(wait_ch));
        wait_ch.recv();
    }
    osmain.send(platform::osmain::exit);
}
<commit_msg>Trivial comment fix<commit_after>import comm::*;
import libc::c_double;
import azure::*;
import azure::bindgen::*;
import azure::cairo;
import azure::cairo::bindgen::*;
import parser::html;
import parser::html::methods;
import result::extensions;

fn parse(filename: str) {
    let file_data = io::read_whole_file(filename).get();
    let reader = io::bytes_reader(file_data);
    let parser = html::parser(reader);
    loop {
        let t = parser.parse();
        log(error, #fmt("token: %?", t));
        if t == html::to_eof { break; }
    }
}

fn main(args: [str]) {
    if args.len() >= 2u {
        parse(args[1]);
    }

    // The platform event handler thread
    let osmain = platform::osmain::osmain();

    // The renderer
    let renderer = gfx::renderer::renderer(osmain);

    // The layout task
    let layout = layout::layout::layout(renderer);

    // The content task
    let content = content::content(layout);

    // Wait for keypress
    listen {|key_ch|
        send(osmain, platform::osmain::add_key_handler(key_ch));

        key_ch.recv();
    }

    // Shut everything down
    content.send(content::exit);
    layout.send(layout::layout::exit);

    listen {|wait_ch|
        renderer.send(gfx::renderer::exit(wait_ch));
        wait_ch.recv();
    }
    osmain.send(platform::osmain::exit);
}
<|endoftext|>


<commit_before>use russell_lab::{Matrix, Vector};

/// Defines a (bi-linear) Hexahedron with 8 nodes
///
/// The natural coordinates range from -1 to +1 with the geometry centred @ 0
///
/// ```text
///              4________________7
///            ,'|              ,'|
///          ,'  |            ,'  |
///        ,'    |          ,'    |
///      ,'      |        ,'      |
///    5'===============6'        |
///    |         |      |         |
///    |         |      |         |
///    |         0_____ | ________3
///    |       ,'       |       ,'
///    |     ,'         |     ,'
///    |   ,'           |   ,'
///    | ,'             | ,'
///    1________________2'
/// ```
///
/// # Example
///
/// ```
/// // import
/// use gemlab::Hex8;
/// use russell_lab::Vector;
///
/// // geometry object
/// let mut geo = Hex8::new();
/// let ndim = geo.get_ndim();

/// // compute shape fn and deriv @ ksi=(0,0,0) for all nodes
/// let ksi = Vector::new(ndim);
/// geo.calc_shape(&ksi);
/// geo.calc_deriv(&ksi);

/// // get shape fn and deriv for node m
/// let m = 0;
/// let sm = geo.get_shape(m);
/// let mut dsm_dksi = Vector::new(ndim);
/// geo.get_deriv(&mut dsm_dksi, m);

/// // check shape fn and deriv @ ksi for node m
/// assert_eq!(sm, 0.125);
/// assert_eq!(
///     format!("{}", dsm_dksi),
///     "┌        ┐\n\
///      │ -0.125 │\n\
///      │ -0.125 │\n\
///      │ -0.125 │\n\
///      └        ┘"
/// );
/// ```
pub struct Hex8 {
    // natural coordinates (nnode, ndim)
    //
    // ```text
    // ξᵐ = vector{r, s, t} @ node m
    // coords = [ξ⁰, ξ¹, ξ², ξ³, ξ⁴, ξ⁵, ξ⁶, ξ⁷, ξ⁸]
    // ```
    coords: Vec<Vector>,

    // shape functions @ natural coordinate (nnode)
    //
    // ```text
    // shape[m](ξ) = Sᵐ(ξ)
    // ```
    shape: Vector,

    // derivatives of shape functions w.r.t natural coordinate (nnode, ndim)
    //
    // ```text
    // deriv[m][i](ξ) = ({dSᵐ(ξ)/dξ}_ξ)[i]
    // ```
    deriv: Matrix,
}

const NDIM: usize = 3;
const NNODE: usize = 8;

impl Hex8 {
    /// Creates a new object with pre-calculated shape fn and derivatives
    pub fn new() -> Self {
        Hex8 {
            #[rustfmt::skip]
            coords: vec![
                Vector::from(&[-1.0, -1.0, -1.0]),
                Vector::from(&[ 1.0, -1.0, -1.0]),
                Vector::from(&[ 1.0,  1.0, -1.0]),
                Vector::from(&[-1.0,  1.0, -1.0]),
                Vector::from(&[-1.0, -1.0,  1.0]),
                Vector::from(&[ 1.0, -1.0,  1.0]),
                Vector::from(&[ 1.0,  1.0,  1.0]),
                Vector::from(&[-1.0,  1.0,  1.0]),
            ],
            shape: Vector::new(NNODE),
            deriv: Matrix::new(NNODE, NDIM),
        }
    }

    /// Calculates the shape functions at natural coordinate
    pub fn calc_shape(&mut self, coord: &Vector) {
        let (r, s, t) = (coord[0], coord[1], coord[2]);

        self.shape[0] = (1.0 - r - s + r * s - t + s * t + r * t - r * s * t) / 8.0;
        self.shape[1] = (1.0 + r - s - r * s - t + s * t - r * t + r * s * t) / 8.0;
        self.shape[2] = (1.0 + r + s + r * s - t - s * t - r * t - r * s * t) / 8.0;
        self.shape[3] = (1.0 - r + s - r * s - t - s * t + r * t + r * s * t) / 8.0;
        self.shape[4] = (1.0 - r - s + r * s + t - s * t - r * t + r * s * t) / 8.0;
        self.shape[5] = (1.0 + r - s - r * s + t - s * t + r * t - r * s * t) / 8.0;
        self.shape[6] = (1.0 + r + s + r * s + t + s * t + r * t + r * s * t) / 8.0;
        self.shape[7] = (1.0 - r + s - r * s + t + s * t - r * t - r * s * t) / 8.0;
    }

    /// Calculates the derivatives of shape functions at natural coordinate
    pub fn calc_deriv(&mut self, coord: &Vector) {
        let (r, s, t) = (coord[0], coord[1], coord[2]);

        self.deriv[0][0] = (-1.0 + s + t - s * t) / 8.0;
        self.deriv[0][1] = (-1.0 + r + t - r * t) / 8.0;
        self.deriv[0][2] = (-1.0 + r + s - r * s) / 8.0;

        self.deriv[1][0] = (1.0 - s - t + s * t) / 8.0;
        self.deriv[1][1] = (-1.0 - r + t + r * t) / 8.0;
        self.deriv[1][2] = (-1.0 - r + s + r * s) / 8.0;

        self.deriv[2][0] = (1.0 + s - t - s * t) / 8.0;
        self.deriv[2][1] = (1.0 + r - t - r * t) / 8.0;
        self.deriv[2][2] = (-1.0 - r - s - r * s) / 8.0;

        self.deriv[3][0] = (-1.0 - s + t + s * t) / 8.0;
        self.deriv[3][1] = (1.0 - r - t + r * t) / 8.0;
        self.deriv[3][2] = (-1.0 + r - s + r * s) / 8.0;

        self.deriv[4][0] = (-1.0 + s - t + s * t) / 8.0;
        self.deriv[4][1] = (-1.0 + r - t + r * t) / 8.0;
        self.deriv[4][2] = (1.0 - r - s + r * s) / 8.0;

        self.deriv[5][0] = (1.0 - s + t - s * t) / 8.0;
        self.deriv[5][1] = (-1.0 - r - t - r * t) / 8.0;
        self.deriv[5][2] = (1.0 + r - s - r * s) / 8.0;

        self.deriv[6][0] = (1.0 + s + t + s * t) / 8.0;
        self.deriv[6][1] = (1.0 + r + t + r * t) / 8.0;
        self.deriv[6][2] = (1.0 + r + s + r * s) / 8.0;

        self.deriv[7][0] = (-1.0 - s - t - s * t) / 8.0;
        self.deriv[7][1] = (1.0 - r + t - r * t) / 8.0;
        self.deriv[7][2] = (1.0 - r + s - r * s) / 8.0;
    }

    /// Returns the previously computed shape function for node m
    pub fn get_shape(&self, m: usize) -> f64 {
        self.shape[m]
    }

    /// Returns the previously computed derivative of shape function for node m
    pub fn get_deriv(&self, deriv: &mut Vector, m: usize) {
        deriv[0] = self.deriv[m][0];
        deriv[1] = self.deriv[m][1];
        deriv[2] = self.deriv[m][2];
    }

    /// Returns the number of dimensions
    pub fn get_ndim(&self) -> usize {
        NDIM
    }

    /// Returns the number of nodes
    pub fn get_nnode(&self) -> usize {
        NNODE
    }

    /// Returns the natural coordinates @ node m
    pub fn get_coord(&self, coord: &mut Vector, m: usize) {
        coord[0] = self.coords[m][0];
        coord[1] = self.coords[m][1];
        coord[2] = self.coords[m][2];
    }
}

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

#[cfg(test)]
mod tests {
    use super::*;
    use russell_chk::*;

    // Holds arguments for numerical differentiation
    struct Arguments {
        geo: Hex8,      // geometry
        at_ksi: Vector, // at nat coord value
        ksi: Vector,    // temporary nat coord
        m: usize,       // shape: node index
        i: usize,       // nat coord: dimension index
    }

    // Computes the shape function @ m as a function of x = ksi[i]
    fn sm(x: f64, args: &mut Arguments) -> f64 {
        args.ksi[0] = args.at_ksi[0];
        args.ksi[1] = args.at_ksi[1];
        args.ksi[2] = args.at_ksi[2];
        args.ksi[args.i] = x;
        args.geo.calc_shape(&args.ksi);
        args.geo.get_shape(args.m)
    }

    #[test]
    fn new_works() {
        let geo = Hex8::new();
        assert_eq!(geo.coords.len(), NNODE);
        assert_eq!(geo.shape.dim(), NNODE);
        assert_eq!(geo.deriv.dims(), (NNODE, NDIM));
    }

    #[test]
    fn calc_shape_works() {
        let mut geo = Hex8::new();
        let mut ksi = Vector::new(NDIM);
        for m in 0..NNODE {
            geo.get_coord(&mut ksi, m);
            geo.calc_shape(&ksi);
            for n in 0..NNODE {
                let smn = geo.get_shape(n);
                if m == n {
                    assert_approx_eq!(smn, 1.0, 1e-15);
                } else {
                    assert_approx_eq!(smn, 0.0, 1e-15);
                }
            }
        }
    }

    #[test]
    fn calc_deriv_works() {
        let args = &mut Arguments {
            geo: Hex8::new(),
            at_ksi: Vector::from(&[0.25, 0.25, 0.25]),
            ksi: Vector::new(NDIM),
            m: 0,
            i: 0,
        };
        let mut geo = Hex8::new();
        let mut dsm_dksi = Vector::new(NDIM);
        geo.calc_deriv(&args.at_ksi);
        for m in 0..NNODE {
            geo.get_deriv(&mut dsm_dksi, m);
            args.m = m;
            for i in 0..NDIM {
                args.i = i;
                assert_deriv_approx_eq!(dsm_dksi[i], args.at_ksi[i], sm, args, 1e-13);
            }
        }
    }

    #[test]
    fn getters_work() {
        let geo = Hex8::new();
        assert_eq!(geo.get_ndim(), NDIM);
        assert_eq!(geo.get_nnode(), NNODE);
    }

    #[test]
    fn another() {}
}
<commit_msg>Improve doc<commit_after>use russell_lab::{Matrix, Vector};

/// Defines a (bi-linear) Hexahedron with 8 nodes
///
/// The natural coordinates range from -1 to +1 with the geometry centred @ 0
///
/// ```text
///              4________________7
///            ,'|              ,'|
///          ,'  |            ,'  |
///        ,'    |          ,'    |
///      ,'      |        ,'      |
///    5'===============6'        |
///    |         |      |         |
///    |         |      |         |
///    |         0_____ | ________3
///    |       ,'       |       ,'
///    |     ,'         |     ,'
///    |   ,'           |   ,'
///    | ,'             | ,'
///    1________________2'
/// ```
///
/// # Example
///
/// ```
/// // import
/// use gemlab::Hex8;
/// use russell_lab::Vector;
///
/// // geometry object
/// let mut geo = Hex8::new();
/// let ndim = geo.get_ndim();
///
/// // compute shape fn and deriv @ ksi=(0,0,0) for all nodes
/// let ksi = Vector::new(ndim);
/// geo.calc_shape(&ksi);
/// geo.calc_deriv(&ksi);
///
/// // get shape fn and deriv for node m
/// let m = 0;
/// let sm = geo.get_shape(m);
/// let mut dsm_dksi = Vector::new(ndim);
/// geo.get_deriv(&mut dsm_dksi, m);
///
/// // check shape fn and deriv @ ksi for node m
/// assert_eq!(sm, 0.125);
/// assert_eq!(
///     format!("{}", dsm_dksi),
///     "┌        ┐\n\
///      │ -0.125 │\n\
///      │ -0.125 │\n\
///      │ -0.125 │\n\
///      └        ┘"
/// );
/// ```
pub struct Hex8 {
    // natural coordinates (nnode, ndim)
    //
    // ```text
    // ξᵐ = vector{r, s, t} @ node m
    // coords = [ξ⁰, ξ¹, ξ², ξ³, ξ⁴, ξ⁵, ξ⁶, ξ⁷, ξ⁸]
    // ```
    coords: Vec<Vector>,

    // shape functions @ natural coordinate (nnode)
    //
    // ```text
    // shape[m](ξ) = Sᵐ(ξ)
    // ```
    shape: Vector,

    // derivatives of shape functions w.r.t natural coordinate (nnode, ndim)
    //
    // ```text
    // deriv[m][i](ξ) = ({dSᵐ(ξ)/dξ}_ξ)[i]
    // ```
    deriv: Matrix,
}

const NDIM: usize = 3;
const NNODE: usize = 8;

impl Hex8 {
    /// Creates a new object with pre-calculated shape fn and derivatives
    pub fn new() -> Self {
        Hex8 {
            #[rustfmt::skip]
            coords: vec![
                Vector::from(&[-1.0, -1.0, -1.0]),
                Vector::from(&[ 1.0, -1.0, -1.0]),
                Vector::from(&[ 1.0,  1.0, -1.0]),
                Vector::from(&[-1.0,  1.0, -1.0]),
                Vector::from(&[-1.0, -1.0,  1.0]),
                Vector::from(&[ 1.0, -1.0,  1.0]),
                Vector::from(&[ 1.0,  1.0,  1.0]),
                Vector::from(&[-1.0,  1.0,  1.0]),
            ],
            shape: Vector::new(NNODE),
            deriv: Matrix::new(NNODE, NDIM),
        }
    }

    /// Calculates the shape functions at natural coordinate
    ///
    /// ```text
    /// shape[m](ξ) = Sᵐ(ξ)
    /// ```
    ///
    /// # Example
    ///
    /// ```
    /// use gemlab::Hex8;
    /// use russell_lab::Vector;
    /// let mut geo = Hex8::new();
    /// let ndim = geo.get_ndim();
    /// let ksi = Vector::new(ndim);
    /// geo.calc_shape(&ksi);
    /// ```
    pub fn calc_shape(&mut self, coord: &Vector) {
        let (r, s, t) = (coord[0], coord[1], coord[2]);

        self.shape[0] = (1.0 - r - s + r * s - t + s * t + r * t - r * s * t) / 8.0;
        self.shape[1] = (1.0 + r - s - r * s - t + s * t - r * t + r * s * t) / 8.0;
        self.shape[2] = (1.0 + r + s + r * s - t - s * t - r * t - r * s * t) / 8.0;
        self.shape[3] = (1.0 - r + s - r * s - t - s * t + r * t + r * s * t) / 8.0;
        self.shape[4] = (1.0 - r - s + r * s + t - s * t - r * t + r * s * t) / 8.0;
        self.shape[5] = (1.0 + r - s - r * s + t - s * t + r * t - r * s * t) / 8.0;
        self.shape[6] = (1.0 + r + s + r * s + t + s * t + r * t + r * s * t) / 8.0;
        self.shape[7] = (1.0 - r + s - r * s + t + s * t - r * t - r * s * t) / 8.0;
    }

    /// Calculates the derivatives of shape functions at natural coordinate
    ///
    /// ```text
    /// deriv[m][i](ξ) = ({dSᵐ(ξ)/dξ}_ξ)[i]
    /// ```
    ///
    /// ```
    /// use gemlab::Hex8;
    /// use russell_lab::Vector;
    /// let mut geo = Hex8::new();
    /// let ndim = geo.get_ndim();
    /// let ksi = Vector::new(ndim);
    /// geo.calc_deriv(&ksi);
    /// ```
    pub fn calc_deriv(&mut self, coord: &Vector) {
        let (r, s, t) = (coord[0], coord[1], coord[2]);

        self.deriv[0][0] = (-1.0 + s + t - s * t) / 8.0;
        self.deriv[0][1] = (-1.0 + r + t - r * t) / 8.0;
        self.deriv[0][2] = (-1.0 + r + s - r * s) / 8.0;

        self.deriv[1][0] = (1.0 - s - t + s * t) / 8.0;
        self.deriv[1][1] = (-1.0 - r + t + r * t) / 8.0;
        self.deriv[1][2] = (-1.0 - r + s + r * s) / 8.0;

        self.deriv[2][0] = (1.0 + s - t - s * t) / 8.0;
        self.deriv[2][1] = (1.0 + r - t - r * t) / 8.0;
        self.deriv[2][2] = (-1.0 - r - s - r * s) / 8.0;

        self.deriv[3][0] = (-1.0 - s + t + s * t) / 8.0;
        self.deriv[3][1] = (1.0 - r - t + r * t) / 8.0;
        self.deriv[3][2] = (-1.0 + r - s + r * s) / 8.0;

        self.deriv[4][0] = (-1.0 + s - t + s * t) / 8.0;
        self.deriv[4][1] = (-1.0 + r - t + r * t) / 8.0;
        self.deriv[4][2] = (1.0 - r - s + r * s) / 8.0;

        self.deriv[5][0] = (1.0 - s + t - s * t) / 8.0;
        self.deriv[5][1] = (-1.0 - r - t - r * t) / 8.0;
        self.deriv[5][2] = (1.0 + r - s - r * s) / 8.0;

        self.deriv[6][0] = (1.0 + s + t + s * t) / 8.0;
        self.deriv[6][1] = (1.0 + r + t + r * t) / 8.0;
        self.deriv[6][2] = (1.0 + r + s + r * s) / 8.0;

        self.deriv[7][0] = (-1.0 - s - t - s * t) / 8.0;
        self.deriv[7][1] = (1.0 - r + t - r * t) / 8.0;
        self.deriv[7][2] = (1.0 - r + s - r * s) / 8.0;
    }

    /// Returns the previously computed shape function for node m
    ///
    /// ```text
    /// shape[m](ξ) = Sᵐ(ξ)
    /// ```
    pub fn get_shape(&self, m: usize) -> f64 {
        self.shape[m]
    }

    /// Returns the previously computed derivative of shape function for node m
    //
    // ```text
    // deriv[m][i](ξ) = ({dSᵐ(ξ)/dξ}_ξ)[i]
    // ```
    pub fn get_deriv(&self, deriv: &mut Vector, m: usize) {
        deriv[0] = self.deriv[m][0];
        deriv[1] = self.deriv[m][1];
        deriv[2] = self.deriv[m][2];
    }

    /// Returns the number of dimensions
    pub fn get_ndim(&self) -> usize {
        NDIM
    }

    /// Returns the number of nodes
    pub fn get_nnode(&self) -> usize {
        NNODE
    }

    /// Returns the natural coordinates @ node m
    //
    // ```text
    // coord = ξᵐ = vector{r, s, t} @ node m
    // ```
    pub fn get_coord(&self, coord: &mut Vector, m: usize) {
        coord[0] = self.coords[m][0];
        coord[1] = self.coords[m][1];
        coord[2] = self.coords[m][2];
    }
}

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

#[cfg(test)]
mod tests {
    use super::*;
    use russell_chk::*;

    // Holds arguments for numerical differentiation
    struct Arguments {
        geo: Hex8,      // geometry
        at_ksi: Vector, // at nat coord value
        ksi: Vector,    // temporary nat coord
        m: usize,       // shape: node index
        i: usize,       // nat coord: dimension index
    }

    // Computes the shape function @ m as a function of x = ksi[i]
    fn sm(x: f64, args: &mut Arguments) -> f64 {
        args.ksi[0] = args.at_ksi[0];
        args.ksi[1] = args.at_ksi[1];
        args.ksi[2] = args.at_ksi[2];
        args.ksi[args.i] = x;
        args.geo.calc_shape(&args.ksi);
        args.geo.get_shape(args.m)
    }

    #[test]
    fn new_works() {
        let geo = Hex8::new();
        assert_eq!(geo.coords.len(), NNODE);
        assert_eq!(geo.shape.dim(), NNODE);
        assert_eq!(geo.deriv.dims(), (NNODE, NDIM));
    }

    #[test]
    fn calc_shape_works() {
        let mut geo = Hex8::new();
        let mut ksi = Vector::new(NDIM);
        for m in 0..NNODE {
            geo.get_coord(&mut ksi, m);
            geo.calc_shape(&ksi);
            for n in 0..NNODE {
                let smn = geo.get_shape(n);
                if m == n {
                    assert_approx_eq!(smn, 1.0, 1e-15);
                } else {
                    assert_approx_eq!(smn, 0.0, 1e-15);
                }
            }
        }
    }

    #[test]
    fn calc_deriv_works() {
        let args = &mut Arguments {
            geo: Hex8::new(),
            at_ksi: Vector::from(&[0.25, 0.25, 0.25]),
            ksi: Vector::new(NDIM),
            m: 0,
            i: 0,
        };
        let mut geo = Hex8::new();
        let mut dsm_dksi = Vector::new(NDIM);
        geo.calc_deriv(&args.at_ksi);
        for m in 0..NNODE {
            geo.get_deriv(&mut dsm_dksi, m);
            args.m = m;
            for i in 0..NDIM {
                args.i = i;
                assert_deriv_approx_eq!(dsm_dksi[i], args.at_ksi[i], sm, args, 1e-13);
            }
        }
    }

    #[test]
    fn getters_work() {
        let geo = Hex8::new();
        assert_eq!(geo.get_ndim(), NDIM);
        assert_eq!(geo.get_nnode(), NNODE);
    }
}
<|endoftext|>