<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

// A very basic BlobImageRenderer that can only render a checkerboard pattern.

use std::collections::HashMap;
use std::sync::Arc;
use std::sync::Mutex;
use webrender::api::*;

// Serialize/deserialize the blob.

pub fn serialize_blob(color: ColorU) -> Vec<u8> {
    vec![color.r, color.g, color.b, color.a]
}

fn deserialize_blob(blob: &[u8]) -> Result<ColorU, ()> {
    let mut iter = blob.iter();
    return match (iter.next(), iter.next(), iter.next(), iter.next()) {
        (Some(&r), Some(&g), Some(&b), Some(&a)) => Ok(ColorU::new(r, g, b, a)),
        (Some(&a), None, None, None) => Ok(ColorU::new(a, a, a, a)),
        _ => Err(()),
    };
}

// This is the function that applies the deserialized drawing commands and generates
// actual image data.
fn render_blob(
    color: ColorU,
    descriptor: &BlobImageDescriptor,
    tile: Option<TileOffset>,
) -> BlobImageResult {
    // Allocate storage for the result. Right now the resource cache expects the
    // tiles to have have no stride or offset.
    let mut texels = Vec::with_capacity((descriptor.width * descriptor.height * 4) as usize);

    // Generate a per-tile pattern to see it in the demo. For a real use case it would not
    // make sense for the rendered content to depend on its tile.
    let tile_checker = match tile {
        Some(tile) => (tile.x % 2 == 0) != (tile.y % 2 == 0),
        None => true,
    };

    for y in 0 .. descriptor.height {
        for x in 0 .. descriptor.width {
            // Apply the tile's offset. This is important: all drawing commands should be
            // translated by this offset to give correct results with tiled blob images.
            let x2 = x + descriptor.offset.x as u32;
            let y2 = y + descriptor.offset.y as u32;

            // Render a simple checkerboard pattern
            let checker = if (x2 % 20 >= 10) != (y2 % 20 >= 10) {
                1
            } else {
                0
            };
            // ..nested in the per-tile checkerboard pattern
            let tc = if tile_checker { 0 } else { (1 - checker) * 40 };

            match descriptor.format {
                ImageFormat::BGRA8 => {
                    texels.push(color.b * checker + tc);
                    texels.push(color.g * checker + tc);
                    texels.push(color.r * checker + tc);
                    texels.push(color.a * checker + tc);
                }
                ImageFormat::R8 => {
                    texels.push(color.a * checker + tc);
                }
                _ => {
                    return Err(BlobImageError::Other(
                        format!("Unsupported image format {:?}", descriptor.format),
                    ));
                }
            }
        }
    }

    Ok(RasterizedBlobImage {
        data: texels,
        width: descriptor.width,
        height: descriptor.height,
    })
}

pub struct BlobCallbacks {
    pub request: Box<Fn(&BlobImageRequest) + Send + 'static>,
    pub resolve: Box<Fn() + Send + 'static>,
}

impl BlobCallbacks {
    pub fn new() -> Self {
        BlobCallbacks { request: Box::new(|_|()), resolve: Box::new(|| (())) }
    }
}

pub struct CheckerboardRenderer {
    image_cmds: HashMap<ImageKey, ColorU>,
    callbacks: Arc<Mutex<BlobCallbacks>>,

    // The images rendered in the current frame (not kept here between frames).
    rendered_images: HashMap<BlobImageRequest, BlobImageResult>,
}

impl CheckerboardRenderer {
    pub fn new(callbacks: Arc<Mutex<BlobCallbacks>>) -> Self {
        CheckerboardRenderer {
            callbacks,
            image_cmds: HashMap::new(),
            rendered_images: HashMap::new(),
        }
    }
}

impl BlobImageRenderer for CheckerboardRenderer {
    fn add(&mut self, key: ImageKey, cmds: BlobImageData, _: Option<TileSize>) {
        self.image_cmds
            .insert(key, deserialize_blob(&cmds[..]).unwrap());
    }

    fn update(&mut self, key: ImageKey, cmds: BlobImageData, _dirty_rect: Option<DeviceUintRect>) {
        // Here, updating is just replacing the current version of the commands with
        // the new one (no incremental updates).
        self.image_cmds
            .insert(key, deserialize_blob(&cmds[..]).unwrap());
    }

    fn delete(&mut self, key: ImageKey) {
        self.image_cmds.remove(&key);
    }

    fn request(
        &mut self,
        _resources: &BlobImageResources,
        request: BlobImageRequest,
        descriptor: &BlobImageDescriptor,
        _dirty_rect: Option<DeviceUintRect>,
    ) {
        (self.callbacks.lock().unwrap().request)(&request);
        assert!(!self.rendered_images.contains_key(&request));
        // This method is where we kick off our rendering jobs.
        // It should avoid doing work on the calling thread as much as possible.
        // In this example we will use the thread pool to render individual tiles.

        // Gather the input data to send to a worker thread.
        let cmds = self.image_cmds.get(&request.key).unwrap();

        let result = render_blob(*cmds, descriptor, request.tile);

        self.rendered_images.insert(request, result);
    }

    fn resolve(&mut self, request: BlobImageRequest) -> BlobImageResult {
        (self.callbacks.lock().unwrap().resolve)();
        self.rendered_images.remove(&request).unwrap()
    }

    fn delete_font(&mut self, _key: FontKey) {}

    fn delete_font_instance(&mut self, _key: FontInstanceKey) {}
}
<commit_msg>Auto merge of #2661 - jrmuizel:tiled-blob-renderer, r=kvark<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

// A very basic BlobImageRenderer that can only render a checkerboard pattern.

use std::collections::HashMap;
use std::sync::Arc;
use std::sync::Mutex;
use webrender::api::*;

// Serialize/deserialize the blob.

pub fn serialize_blob(color: ColorU) -> Vec<u8> {
    vec![color.r, color.g, color.b, color.a]
}

fn deserialize_blob(blob: &[u8]) -> Result<ColorU, ()> {
    let mut iter = blob.iter();
    return match (iter.next(), iter.next(), iter.next(), iter.next()) {
        (Some(&r), Some(&g), Some(&b), Some(&a)) => Ok(ColorU::new(r, g, b, a)),
        (Some(&a), None, None, None) => Ok(ColorU::new(a, a, a, a)),
        _ => Err(()),
    };
}

// This is the function that applies the deserialized drawing commands and generates
// actual image data.
fn render_blob(
    color: ColorU,
    descriptor: &BlobImageDescriptor,
    tile: Option<TileOffset>,
    dirty_rect: Option<DeviceUintRect>,
) -> BlobImageResult {
    // Allocate storage for the result. Right now the resource cache expects the
    // tiles to have have no stride or offset.
    let mut texels = vec![0u8; (descriptor.width * descriptor.height * descriptor.format.bytes_per_pixel()) as usize];

    // Generate a per-tile pattern to see it in the demo. For a real use case it would not
    // make sense for the rendered content to depend on its tile.
    let tile_checker = match tile {
        Some(tile) => (tile.x % 2 == 0) != (tile.y % 2 == 0),
        None => true,
    };

    let dirty_rect = dirty_rect.unwrap_or(DeviceUintRect::new(
        DeviceUintPoint::new(0, 0),
        DeviceUintSize::new(descriptor.width, descriptor.height)));

    for y in dirty_rect.min_y() .. dirty_rect.max_y() {
        for x in dirty_rect.min_x() .. dirty_rect.max_x() {
            // Apply the tile's offset. This is important: all drawing commands should be
            // translated by this offset to give correct results with tiled blob images.
            let x2 = x + descriptor.offset.x as u32;
            let y2 = y + descriptor.offset.y as u32;

            // Render a simple checkerboard pattern
            let checker = if (x2 % 20 >= 10) != (y2 % 20 >= 10) {
                1
            } else {
                0
            };
            // ..nested in the per-tile checkerboard pattern
            let tc = if tile_checker { 0 } else { (1 - checker) * 40 };

            match descriptor.format {
                ImageFormat::BGRA8 => {
                    texels[((y * descriptor.width + x) * 4 + 0) as usize] = color.b * checker + tc;
                    texels[((y * descriptor.width + x) * 4 + 1) as usize] = color.g * checker + tc;
                    texels[((y * descriptor.width + x) * 4 + 2) as usize] = color.r * checker + tc;
                    texels[((y * descriptor.width + x) * 4 + 3) as usize] = color.a * checker + tc;
                }
                ImageFormat::R8 => {
                    texels[(y * descriptor.width + x) as usize] = color.a * checker + tc;
                }
                _ => {
                    return Err(BlobImageError::Other(
                        format!("Unsupported image format {:?}", descriptor.format),
                    ));
                }
            }
        }
    }

    Ok(RasterizedBlobImage {
        data: texels,
        width: descriptor.width,
        height: descriptor.height,
    })
}

pub struct BlobCallbacks {
    pub request: Box<Fn(&BlobImageRequest) + Send + 'static>,
    pub resolve: Box<Fn() + Send + 'static>,
}

impl BlobCallbacks {
    pub fn new() -> Self {
        BlobCallbacks { request: Box::new(|_|()), resolve: Box::new(|| (())) }
    }
}

pub struct CheckerboardRenderer {
    image_cmds: HashMap<ImageKey, ColorU>,
    callbacks: Arc<Mutex<BlobCallbacks>>,

    // The images rendered in the current frame (not kept here between frames).
    rendered_images: HashMap<BlobImageRequest, BlobImageResult>,
}

impl CheckerboardRenderer {
    pub fn new(callbacks: Arc<Mutex<BlobCallbacks>>) -> Self {
        CheckerboardRenderer {
            callbacks,
            image_cmds: HashMap::new(),
            rendered_images: HashMap::new(),
        }
    }
}

impl BlobImageRenderer for CheckerboardRenderer {
    fn add(&mut self, key: ImageKey, cmds: BlobImageData, _: Option<TileSize>) {
        self.image_cmds
            .insert(key, deserialize_blob(&cmds[..]).unwrap());
    }

    fn update(&mut self, key: ImageKey, cmds: BlobImageData, _dirty_rect: Option<DeviceUintRect>) {
        // Here, updating is just replacing the current version of the commands with
        // the new one (no incremental updates).
        self.image_cmds
            .insert(key, deserialize_blob(&cmds[..]).unwrap());
    }

    fn delete(&mut self, key: ImageKey) {
        self.image_cmds.remove(&key);
    }

    fn request(
        &mut self,
        _resources: &BlobImageResources,
        request: BlobImageRequest,
        descriptor: &BlobImageDescriptor,
        dirty_rect: Option<DeviceUintRect>,
    ) {
        (self.callbacks.lock().unwrap().request)(&request);
        assert!(!self.rendered_images.contains_key(&request));
        // This method is where we kick off our rendering jobs.
        // It should avoid doing work on the calling thread as much as possible.
        // In this example we will use the thread pool to render individual tiles.

        // Gather the input data to send to a worker thread.
        let cmds = self.image_cmds.get(&request.key).unwrap();

        let result = render_blob(*cmds, descriptor, request.tile, dirty_rect);

        self.rendered_images.insert(request, result);
    }

    fn resolve(&mut self, request: BlobImageRequest) -> BlobImageResult {
        (self.callbacks.lock().unwrap().resolve)();
        self.rendered_images.remove(&request).unwrap()
    }

    fn delete_font(&mut self, _key: FontKey) {}

    fn delete_font_instance(&mut self, _key: FontInstanceKey) {}
}
<|endoftext|>


<commit_before>//! Polygon.

use crate::{Angle, Canvas, Ellipse, FlatIterPath, Paint, Rotate, Subdivide, Translate, P2, V2};
use arrayvec::ArrayVec;
use itertools::Itertools;
use std::iter::{DoubleEndedIterator, FromIterator};

#[derive(Debug, Clone, PartialEq)]
pub struct Polygon {
    vertices: Vec<P2>,
}

impl Polygon {
    /// Returns an iterator over the polygon's vertices.
    pub fn vertices<'a>(&'a self) -> impl DoubleEndedIterator<Item = P2> + Clone + 'a {
        self.vertices.iter().copied()
    }

    /// Returns an iterator over unique references to the polgyon's vertices.
    pub fn vertices_mut<'a>(&'a mut self) -> impl DoubleEndedIterator<Item = &'a mut P2> + 'a {
        self.vertices.iter_mut()
    }

    /// Returns an iterator over each vertex in the form (left neighbor, vertex, right neighbor).
    pub fn vertices_with_neighbors<'a>(&'a self) -> impl Iterator<Item = (P2, P2, P2)> + 'a {
        let last_iter = self.vertices().rev().take(1);
        last_iter
            .clone()
            .chain(self.vertices())
            .chain(last_iter)
            .tuple_windows()
    }
}

impl Paint for Polygon {
    fn paint(&self, canvas: &mut Canvas) {
        canvas.paint(FlatIterPath::new(self.vertices(), /*closed=*/ true))
    }
}

impl Paint for &Polygon {
    fn paint(&self, canvas: &mut Canvas) {
        (**self).paint(canvas);
    }
}

impl Subdivide for Polygon {
    fn subdivide(self) -> Self {
        let from_start = self.vertices();
        let skipped = self.vertices().skip(1).chain(self.vertices().take(1));

        from_start
            .zip(skipped)
            .flat_map(|(a, b)| {
                let midpoint = a + ((b + (a.to_vector() * -1.)) * 0.5).to_vector();
                ArrayVec::from([a, midpoint]).into_iter()
            })
            .collect::<Self>()
    }
}

impl Rotate for Polygon {
    fn rotate(mut self, pivot: P2, theta: Angle) -> Self {
        self.vertices_mut().for_each(|v| {
            *v = v.rotate(pivot, theta);
        });

        self
    }
}

impl Translate for Polygon {
    fn translate(mut self, translation: V2) -> Self {
        self.vertices.iter_mut().for_each(|p| *p += translation);
        self
    }
}

impl<I> From<I> for Polygon
where
    I: Iterator<Item = P2>,
{
    fn from(src: I) -> Self {
        Self {
            vertices: src.collect(),
        }
    }
}

impl FromIterator<P2> for Polygon {
    fn from_iter<T>(iter: T) -> Self
    where
        T: IntoIterator<Item = P2>,
    {
        Self {
            vertices: iter.into_iter().collect(),
        }
    }
}
<commit_msg>Remove unused import<commit_after>//! Polygon.

use crate::{Angle, Canvas, FlatIterPath, Paint, Rotate, Subdivide, Translate, P2, V2};
use arrayvec::ArrayVec;
use itertools::Itertools;
use std::iter::{DoubleEndedIterator, FromIterator};

#[derive(Debug, Clone, PartialEq)]
pub struct Polygon {
    vertices: Vec<P2>,
}

impl Polygon {
    /// Returns an iterator over the polygon's vertices.
    pub fn vertices<'a>(&'a self) -> impl DoubleEndedIterator<Item = P2> + Clone + 'a {
        self.vertices.iter().copied()
    }

    /// Returns an iterator over unique references to the polgyon's vertices.
    pub fn vertices_mut<'a>(&'a mut self) -> impl DoubleEndedIterator<Item = &'a mut P2> + 'a {
        self.vertices.iter_mut()
    }

    /// Returns an iterator over each vertex in the form (left neighbor, vertex, right neighbor).
    pub fn vertices_with_neighbors<'a>(&'a self) -> impl Iterator<Item = (P2, P2, P2)> + 'a {
        let last_iter = self.vertices().rev().take(1);
        last_iter
            .clone()
            .chain(self.vertices())
            .chain(last_iter)
            .tuple_windows()
    }
}

impl Paint for Polygon {
    fn paint(&self, canvas: &mut Canvas) {
        canvas.paint(FlatIterPath::new(self.vertices(), /*closed=*/ true))
    }
}

impl Paint for &Polygon {
    fn paint(&self, canvas: &mut Canvas) {
        (**self).paint(canvas);
    }
}

impl Subdivide for Polygon {
    fn subdivide(self) -> Self {
        let from_start = self.vertices();
        let skipped = self.vertices().skip(1).chain(self.vertices().take(1));

        from_start
            .zip(skipped)
            .flat_map(|(a, b)| {
                let midpoint = a + ((b + (a.to_vector() * -1.)) * 0.5).to_vector();
                ArrayVec::from([a, midpoint]).into_iter()
            })
            .collect::<Self>()
    }
}

impl Rotate for Polygon {
    fn rotate(mut self, pivot: P2, theta: Angle) -> Self {
        self.vertices_mut().for_each(|v| {
            *v = v.rotate(pivot, theta);
        });

        self
    }
}

impl Translate for Polygon {
    fn translate(mut self, translation: V2) -> Self {
        self.vertices.iter_mut().for_each(|p| *p += translation);
        self
    }
}

impl<I> From<I> for Polygon
where
    I: Iterator<Item = P2>,
{
    fn from(src: I) -> Self {
        Self {
            vertices: src.collect(),
        }
    }
}

impl FromIterator<P2> for Polygon {
    fn from_iter<T>(iter: T) -> Self
    where
        T: IntoIterator<Item = P2>,
    {
        Self {
            vertices: iter.into_iter().collect(),
        }
    }
}
<|endoftext|>


<commit_before>use frame::ChannelAssignment;

// Decode left and side channels to left and right channels.
//
// Two channels, left and side (difference) that transforms the difference
// into the right channel.
pub fn decode_left_side(buffer: &mut [i32]) {
  let block_size = buffer.len() / 2;

  for i in 0..block_size {
    let left = buffer[i];
    let side = buffer[i + block_size];

    // right channel
    buffer[i + block_size] = left - side;
  }
}

// Decode side and right channels to left and right channels.
//
// Two channels, side (difference) and right that transforms the difference
// into the left channel.
pub fn decode_right_side(buffer: &mut [i32]) {
  let block_size = buffer.len() / 2;

  for i in 0..block_size {
    let side  = buffer[i];
    let right = buffer[i + block_size];

    // left channel
    buffer[i] = side + right;
  }
}

pub fn decode_middle_side(buffer: &mut [i32]) {
  let block_size = buffer.len() / 2;

  for i in 0..block_size {
    let mut middle = buffer[i];
    let side       = buffer[i + block_size];

    middle = (middle << 1) | (side & 1);

    // left and right channel
    buffer[i]              = (middle + side) >> 1;
    buffer[i + block_size] = (middle - side) >> 1;
  }
}

/// Decode the current frame buffer
///
/// * `Independent` - does nothing to buffer because this channel assignment
///   is already correct.
/// * `LeftSide` - decode left and side channels to left and right channels.
/// * `RightSide` - decode side and right channels to left and right
///   channels.
/// * `MiddleSide` - decode midpoint and side channels to left and right
///   channels.
pub fn decode(channel_assignment: ChannelAssignment, buffer: &mut [i32]) {
  match channel_assignment {
    ChannelAssignment::Independent => return,
    ChannelAssignment::LeftSide    => decode_left_side(buffer),
    ChannelAssignment::RightSide   => decode_right_side(buffer),
    ChannelAssignment::MiddleSide  => decode_middle_side(buffer),
  }
}

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

  #[test]
  fn test_decode_left_side() {
    let mut channels = [ 2, 5, 83, 113, 127, -63, -45, -15
                       , 7, 38, 142, 238, 0, -152, -52, -18
                       ];
    let result       = [-5, -33, -59, -125, 127, 89, 7, 3];

    decode_left_side(&mut channels);

    assert_eq!(&channels[8..16], &result);
  }

  #[test]
  fn test_decode_right_side() {
    let mut channels = [ 7, 38, 142, 238, 0, -152, -52, -18
                       , -5, -33, -59, -125, 127, 89, 7, 3
                       ];
    let result       = [2, 5, 83, 113, 127, -63, -45, -15];

    decode_right_side(&mut channels);

    assert_eq!(&channels[0..8], &result);
  }

  #[test]
  fn test_decode_middle_side() {
    let mut channels = [ -2, -14, 12, -6, 127, 13, -19, -6
                       , 7, 38, 142, 238, 0, -152, -52, -18
                       ];
    let results      = [ 2, 5, 83, 113, 127, -63, -45, -15
                       , -5, -33, -59, -125, 127, 89, 7, 3
                       ];

    decode_middle_side(&mut channels);

    assert_eq!(&channels, &results);
  }

  #[test]
  fn test_decode() {
    let mut channels = [ 2, 5, 83, 113, 127, -63, -45, -15
                       , 7, 38, 142, 238, 0, -152, -52, -18
                       ];

    let results = [ [ 2, 5, 83, 113, 127, -63, -45, -15
                    , 7, 38, 142, 238, 0, -152, -52, -18
                    ],
                    [ 2, 5, 83, 113, 127, -63, -45, -15
                    ,-5, -33, -59, -125, 127, 89, 7, 3
                    ]
                  ];

    decode(ChannelAssignment::Independent, &mut channels);
    assert_eq!(&channels, &results[0]);

    channels = [ 2, 5, 83, 113, 127, -63, -45, -15
               , 7, 38, 142, 238, 0, -152, -52, -18
               ];

    decode(ChannelAssignment::LeftSide, &mut channels);
    assert_eq!(&channels, &results[1]);

    channels = [ 7, 38, 142, 238, 0, -152, -52, -18
               , -5, -33, -59, -125, 127, 89, 7, 3
               ];

    decode(ChannelAssignment::RightSide, &mut channels);
    assert_eq!(&channels, &results[1]);

    channels = [ -2, -14, 12, -6, 127, 13, -19, -6
               , 7, 38, 142, 238, 0, -152, -52, -18
               ];

    decode(ChannelAssignment::MiddleSide, &mut channels);
    assert_eq!(&channels, &results[1]);
  }
}
<commit_msg>Add explanation for `decode_middle_side`<commit_after>use frame::ChannelAssignment;

// Decode left and side channels to left and right channels.
//
// Two channels, left and side (difference) that transforms the difference
// into the right channel.
pub fn decode_left_side(buffer: &mut [i32]) {
  let block_size = buffer.len() / 2;

  for i in 0..block_size {
    let left = buffer[i];
    let side = buffer[i + block_size];

    // right channel
    buffer[i + block_size] = left - side;
  }
}

// Decode side and right channels to left and right channels.
//
// Two channels, side (difference) and right that transforms the difference
// into the left channel.
pub fn decode_right_side(buffer: &mut [i32]) {
  let block_size = buffer.len() / 2;

  for i in 0..block_size {
    let side  = buffer[i];
    let right = buffer[i + block_size];

    // left channel
    buffer[i] = side + right;
  }
}

// Decode midpoint and side channels to left and right channels.
//
// Two channels, midpoint (average) and side (difference) that transforms
// the average and difference into the left and right channels.
pub fn decode_middle_side(buffer: &mut [i32]) {
  let block_size = buffer.len() / 2;

  for i in 0..block_size {
    let mut middle = buffer[i];
    let side       = buffer[i + block_size];

    middle = (middle << 1) | (side & 1);

    // left and right channel
    buffer[i]              = (middle + side) >> 1;
    buffer[i + block_size] = (middle - side) >> 1;
  }
}

/// Decode the current frame buffer
///
/// * `Independent` - does nothing to buffer because this channel assignment
///   is already correct.
/// * `LeftSide` - decode left and side channels to left and right channels.
/// * `RightSide` - decode side and right channels to left and right
///   channels.
/// * `MiddleSide` - decode midpoint and side channels to left and right
///   channels.
pub fn decode(channel_assignment: ChannelAssignment, buffer: &mut [i32]) {
  match channel_assignment {
    ChannelAssignment::Independent => return,
    ChannelAssignment::LeftSide    => decode_left_side(buffer),
    ChannelAssignment::RightSide   => decode_right_side(buffer),
    ChannelAssignment::MiddleSide  => decode_middle_side(buffer),
  }
}

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

  #[test]
  fn test_decode_left_side() {
    let mut channels = [ 2, 5, 83, 113, 127, -63, -45, -15
                       , 7, 38, 142, 238, 0, -152, -52, -18
                       ];
    let result       = [-5, -33, -59, -125, 127, 89, 7, 3];

    decode_left_side(&mut channels);

    assert_eq!(&channels[8..16], &result);
  }

  #[test]
  fn test_decode_right_side() {
    let mut channels = [ 7, 38, 142, 238, 0, -152, -52, -18
                       , -5, -33, -59, -125, 127, 89, 7, 3
                       ];
    let result       = [2, 5, 83, 113, 127, -63, -45, -15];

    decode_right_side(&mut channels);

    assert_eq!(&channels[0..8], &result);
  }

  #[test]
  fn test_decode_middle_side() {
    let mut channels = [ -2, -14, 12, -6, 127, 13, -19, -6
                       , 7, 38, 142, 238, 0, -152, -52, -18
                       ];
    let results      = [ 2, 5, 83, 113, 127, -63, -45, -15
                       , -5, -33, -59, -125, 127, 89, 7, 3
                       ];

    decode_middle_side(&mut channels);

    assert_eq!(&channels, &results);
  }

  #[test]
  fn test_decode() {
    let mut channels = [ 2, 5, 83, 113, 127, -63, -45, -15
                       , 7, 38, 142, 238, 0, -152, -52, -18
                       ];

    let results = [ [ 2, 5, 83, 113, 127, -63, -45, -15
                    , 7, 38, 142, 238, 0, -152, -52, -18
                    ],
                    [ 2, 5, 83, 113, 127, -63, -45, -15
                    ,-5, -33, -59, -125, 127, 89, 7, 3
                    ]
                  ];

    decode(ChannelAssignment::Independent, &mut channels);
    assert_eq!(&channels, &results[0]);

    channels = [ 2, 5, 83, 113, 127, -63, -45, -15
               , 7, 38, 142, 238, 0, -152, -52, -18
               ];

    decode(ChannelAssignment::LeftSide, &mut channels);
    assert_eq!(&channels, &results[1]);

    channels = [ 7, 38, 142, 238, 0, -152, -52, -18
               , -5, -33, -59, -125, 127, 89, 7, 3
               ];

    decode(ChannelAssignment::RightSide, &mut channels);
    assert_eq!(&channels, &results[1]);

    channels = [ -2, -14, 12, -6, 127, 13, -19, -6
               , 7, 38, 142, 238, 0, -152, -52, -18
               ];

    decode(ChannelAssignment::MiddleSide, &mut channels);
    assert_eq!(&channels, &results[1]);
  }
}
<|endoftext|>


<commit_before>extern crate rand;
extern crate timely;
extern crate differential_dataflow;

use std::time::Instant;

use rand::{Rng, SeedableRng, StdRng};

use timely::dataflow::*;
use timely::dataflow::operators::*;

use differential_dataflow::Collection;
use differential_dataflow::operators::*;
use differential_dataflow::collection::LeastUpperBound;

type Node = u32;
type Edge = (Node, Node);

fn main() {

    let nodes: u32 = std::env::args().nth(1).unwrap().parse().unwrap();
    let edges: u32 = std::env::args().nth(2).unwrap().parse().unwrap();
    let batch: u32 = std::env::args().nth(3).unwrap().parse().unwrap();

    println!("performing reachability on {} nodes, {} edges:", nodes, edges);

    // define a new computational scope, in which to run BFS
    timely::execute_from_args(std::env::args().skip(4), move |computation| {

        let timer = Instant::now();

        // define BFS dataflow; return handles to roots and edges inputs
        let (mut graph, mut roots, probe) = computation.scoped(|scope| {
            let (root_input, roots) = scope.new_input();
            let (edge_input, graph) = scope.new_input();
            let probe = reach(&Collection::new(graph), &Collection::new(roots)).probe().0;
            (edge_input, root_input, probe)
        });

        let seed: &[_] = &[1, 2, 3, 4];
        let mut rng1: StdRng = SeedableRng::from_seed(seed);    // rng for edge additions
        let mut rng2: StdRng = SeedableRng::from_seed(seed);    // rng for edge deletions

        if computation.index() == 0 {
            // trickle edges in to dataflow
            for _ in 0..(edges/1000) {
                for _ in 0..1000 {
                    graph.send(((rng1.gen_range(0, nodes), rng1.gen_range(0, nodes)), 1));
                }
                computation.step();
            }
        }

        if computation.index() == 0 {
            println!("loaded; elapsed: {:?}", timer.elapsed());
        }

        roots.advance_to(1);
        graph.advance_to(1);
        computation.step_while(|| probe.lt(graph.time()));

        if computation.index() == 0 {
            println!("stable; elapsed: {:?}", timer.elapsed());
        }
        for i in 0..10 {
            roots.send((i, 1));
            roots.advance_to(2 + i);
            graph.advance_to(2 + i);

            let timer = ::std::time::Instant::now();
            computation.step_while(|| probe.lt(graph.time()));
            if computation.index() == 0 {
                println!("query; elapsed: {:?}", timer.elapsed());
            }
        }

        let mut changes = Vec::new();
        for wave in 0..10 {
            for _ in 0..batch {
                changes.push(((rng1.gen_range(0, nodes), rng1.gen_range(0, nodes)), 1));
                changes.push(((rng2.gen_range(0, nodes), rng2.gen_range(0, nodes)),-1));
            }

            let timer = ::std::time::Instant::now();
            let round = *graph.epoch();
            if computation.index() == 0 {
                while let Some(change) = changes.pop() {
                    graph.send(change);
                }
            }
            roots.advance_to(round + 1);
            graph.advance_to(round + 1);

            computation.step_while(|| probe.lt(graph.time()));

            if computation.index() == 0 {
                println!("wave {}: avg {:?}", wave, timer.elapsed() / (batch as u32));
            }
        }
    }).unwrap();
}

// returns pairs (n, s) indicating node n can be reached from a root in s steps.
fn reach<G: Scope>(edges: &Collection<G, Edge>, roots: &Collection<G, Node>) -> Collection<G, (Node, Node)>
where G::Timestamp: LeastUpperBound {

    let roots = roots.map(|x| (x,x));

    roots.iterate(|inner| {

        let edges = edges.enter(&inner.scope());
        let roots = roots.enter(&inner.scope());

        inner.join_map(&edges, |_k,&l,&d| (d, l))
             .concat(&roots)
             .distinct()
     })
}
<commit_msg>updated for measurement taking<commit_after>extern crate rand;
extern crate timely;
extern crate differential_dataflow;

use std::time::Instant;

use rand::{Rng, SeedableRng, StdRng};

use timely::dataflow::*;
use timely::dataflow::operators::*;

use differential_dataflow::Collection;
use differential_dataflow::operators::*;
use differential_dataflow::collection::LeastUpperBound;

type Node = u32;
type Edge = (Node, Node);

fn main() {

    let nodes: u32 = std::env::args().nth(1).unwrap().parse().unwrap();
    let edges: u32 = std::env::args().nth(2).unwrap().parse().unwrap();
    let batch: u32 = std::env::args().nth(3).unwrap().parse().unwrap();
    let waves: u32 = std::env::args().nth(4).unwrap().parse().unwrap();

    println!("performing reachability on {} nodes, {} edges:", nodes, edges);

    // define a new computational scope, in which to run BFS
    timely::execute_from_args(std::env::args().skip(4), move |computation| {

        let timer = Instant::now();

        // define BFS dataflow; return handles to roots and edges inputs
        let (mut graph, mut roots, probe) = computation.scoped(|scope| {

            let (root_input, roots) = scope.new_input();
            let roots = Collection::new(roots);

            let (edge_input, graph) = scope.new_input();
            let graph = Collection::new(graph);

            let probe = reach(&graph, &roots).probe().0;
            (edge_input, root_input, probe)
        });

        let seed: &[_] = &[1, 2, 3, 4];
        let mut rng1: StdRng = SeedableRng::from_seed(seed);    // rng for edge additions
        let mut rng2: StdRng = SeedableRng::from_seed(seed);    // rng for edge deletions

        if computation.index() == 0 {
            // trickle edges in to dataflow
            for _ in 0..(edges/1000) {
                for _ in 0..1000 {
                    graph.send(((rng1.gen_range(0, nodes), rng1.gen_range(0, nodes)), 1));
                }
                computation.step();
            }
        }

        if computation.index() == 0 {
            println!("loaded; elapsed: {:?}", timer.elapsed());
        }

        roots.advance_to(1);
        graph.advance_to(1);
        computation.step_while(|| probe.lt(graph.time()));

        if computation.index() == 0 {
            println!("stable; elapsed: {:?}", timer.elapsed());
        }
        for i in 0..10 {
            roots.send((i, 1));
            roots.advance_to(2 + i);
            graph.advance_to(2 + i);

            let timer = ::std::time::Instant::now();
            computation.step_while(|| probe.lt(graph.time()));
            if computation.index() == 0 {
                println!("query; elapsed: {:?}", timer.elapsed());
            }
        }

        let mut changes = Vec::new();
        for wave in 0..waves {
            for _ in 0..batch {
                changes.push(((rng1.gen_range(0, nodes), rng1.gen_range(0, nodes)), 1));
                changes.push(((rng2.gen_range(0, nodes), rng2.gen_range(0, nodes)),-1));
            }

            let timer = ::std::time::Instant::now();
            let round = *graph.epoch();
            if computation.index() == 0 {
                while let Some(change) = changes.pop() {
                    graph.send(change);
                }
            }
            roots.advance_to(round + 1);
            graph.advance_to(round + 1);

            computation.step_while(|| probe.lt(graph.time()));

            if computation.index() == 0 {
                let elapsed = timer.elapsed();
                let nanos = elapsed.as_secs() * 1_000_000_000 + elapsed.subsec_nanos() as u64;
                // println!("wave {}: avg {:?}", wave, nanos / (batch as u32));
                println!("{}", (nanos as f64) / 1000000000.0f64);
            }
        }
    }).unwrap();
}

// returns pairs (n, s) indicating node n can be reached from a root in s steps.
fn reach<G: Scope>(edges: &Collection<G, Edge>, roots: &Collection<G, Node>) -> Collection<G, (Node, Node)>
where G::Timestamp: LeastUpperBound {

    let roots = roots.map(|x| (x,x));

    roots.iterate(|inner| {

        let edges = edges.enter(&inner.scope());
        let roots = roots.enter(&inner.scope());

        inner.join_map(&edges, |_k,&l,&d| (d, l))
             .concat(&roots)
             .distinct()
     })
}
<|endoftext|>


<commit_before>//! Provides special functions related to the [beta](https://en.wikipedia.org/wiki/Beta_function)
//! function

use std::f64;
use error::StatsError;
use function::gamma;
use prec;

/// Computes the natural logarithm
/// of the beta function
/// where `a` is the first beta parameter
/// and `b` is the second beta parameter
/// and `a > 0`, `b > 0`.
///
/// # Panics
///
/// if `a <= 0.0` or `b <= 0.0`
pub fn ln_beta(a: f64, b: f64) -> f64 {
    assert!(a > 0.0, format!("{}", StatsError::ArgMustBePositive("a")));
    assert!(b > 0.0, format!("{}", StatsError::ArgMustBePositive("b")));
    gamma::ln_gamma(a) + gamma::ln_gamma(b) - gamma::ln_gamma(a + b)
}

/// Computes the beta function
/// where `a` is the first beta parameter
/// and `b` is the second beta parameter.
///
///
/// # Panics
///
/// if `a <= 0.0` or `b <= 0.0`
pub fn beta(a: f64, b: f64) -> f64 {
    ln_beta(a, b).exp()
}

/// Computes the lower incomplete (unregularized) beta function
/// `B(a,b,x) = int(t^(a-1)*(1-t)^(b-1),t=0..x)` for `a > 0, b > 0, 1 >= x >= 0`
/// where `a` is the first beta parameter, `b` is the second beta parameter, and
/// `x` is the upper limit of the integral
///
/// # Panics
///
/// If `a < 0.0`, `b < 0.0`, `x < 0.0`, or `x > 1.0`
pub fn beta_inc(a: f64, b: f64, x: f64) -> f64 {
    beta_reg(a, b, x) * beta(a, b)
}

/// Computes the regularized lower incomplete beta function
/// `I_x(a,b) = 1/Beta(a,b) * int(t^(a-1)*(1-t)^(b-1), t=0..x)`
/// `a > 0`, `b > 0`, `1 >= x >= 0` where `a` is the first beta parameter,
/// `b` is the second beta parameter, and `x` is the upper limit of the
/// integral.
///
/// # Panics
///
/// if `a < 0.0`, `b < 0.0`, `x < 0.0`, or `x > 1.0`
pub fn beta_reg(a: f64, b: f64, x: f64) -> f64 {
    assert!(a >= 0.0, format!("{}", StatsError::ArgNotNegative("a")));
    assert!(b >= 0.0, format!("{}", StatsError::ArgNotNegative("b")));
    assert!(x >= 0.0 && x <= 1.0,
            format!("{}", StatsError::ArgIntervalIncl("x", 0.0, 1.0)));

    let bt = match x {
        0.0 | 1.0 => 0.0,
        _ => {
            (gamma::ln_gamma(a + b) - gamma::ln_gamma(a) - gamma::ln_gamma(b) + a * x.ln() +
             b * (1.0 - x).ln())
                .exp()
        }
    };
    let symm_transform = x >= (a + 1.0) / (a + b + 2.0);
    let eps = prec::F64_PREC;
    let fpmin = f64::MIN_POSITIVE / eps;

    let mut a = a;
    let mut b = b;
    let mut x = x;
    if symm_transform {
        let swap = a;
        x = 1.0 - x;
        a = b;
        b = swap;
    }

    let qab = a + b;
    let qap = a + 1.0;
    let qam = a - 1.0;
    let mut c = 1.0;
    let mut d = 1.0 - qab * x / qap;

    if d.abs() < fpmin {
        d = fpmin;
    }
    d = 1.0 / d;
    let mut h = d;

    for m in 1..141 {
        let m = m as f64;
        let m2 = m * 2.0;
        let mut aa = m * (b - m) * x / ((qam + m2) * (a + m2));
        d = 1.0 + aa * d;

        if d.abs() < fpmin {
            d = fpmin;
        }

        c = 1.0 + aa / c;
        if c.abs() < fpmin {
            c = fpmin;
        }

        d = 1.0 / d;
        h = h * d * c;
        aa = -(a + m) * (qab + m) * x / ((a + m2) * (qap + m2));
        d = 1.0 + aa * d;

        if d.abs() < fpmin {
            d = fpmin;
        }

        c = 1.0 + aa / c;

        if c.abs() < fpmin {
            c = fpmin;
        }

        d = 1.0 / d;
        let del = d * c;
        h *= del;

        if (del - 1.0).abs() <= eps {
            return if symm_transform {
                1.0 - bt * h / a
            } else {
                bt * h / a
            };
        }
    }

    if symm_transform {
        1.0 - bt * h / a
    } else {
        bt * h / a
    }
}

#[cfg_attr(rustfmt, rustfmt_skip)]
#[cfg(test)]
mod test {
    #[test]
    fn test_ln_beta() {
        assert_almost_eq!(super::ln_beta(0.5, 0.5), 1.144729885849400174144, 1e-15);
        assert_almost_eq!(super::ln_beta(1.0, 0.5), 0.6931471805599453094172, 1e-14);
        assert_almost_eq!(super::ln_beta(2.5, 0.5), 0.163900632837673937284, 1e-15);
        assert_almost_eq!(super::ln_beta(0.5, 1.0), 0.6931471805599453094172, 1e-14);
        assert_almost_eq!(super::ln_beta(1.0, 1.0), 0.0, 1e-15);
        assert_almost_eq!(super::ln_beta(2.5, 1.0), -0.9162907318741550651835, 1e-14);
        assert_almost_eq!(super::ln_beta(0.5, 2.5), 0.163900632837673937284, 1e-15);
        assert_almost_eq!(super::ln_beta(1.0, 2.5), -0.9162907318741550651835, 1e-14);
        assert_almost_eq!(super::ln_beta(2.5, 2.5), -2.608688089402107300388, 1e-14);
    }

    #[test]
    fn test_beta() {
        assert_almost_eq!(super::beta(0.5, 0.5), 3.141592653589793238463, 1e-15);
        assert_almost_eq!(super::beta(1.0, 0.5), 2.0, 1e-14);
        assert_almost_eq!(super::beta(2.5, 0.5), 1.17809724509617246442, 1e-15);
        assert_almost_eq!(super::beta(0.5, 1.0), 2.0, 1e-14);
        assert_almost_eq!(super::beta(1.0, 1.0), 1.0, 1e-15);
        assert_almost_eq!(super::beta(2.5, 1.0), 0.4, 1e-14);
        assert_almost_eq!(super::beta(0.5, 2.5), 1.17809724509617246442, 1e-15);
        assert_almost_eq!(super::beta(1.0, 2.5), 0.4, 1e-14);
        assert_almost_eq!(super::beta(2.5, 2.5), 0.073631077818510779026, 1e-15);
    }

    #[test]
    fn test_beta_reg() {
        assert_almost_eq!(super::beta_reg(0.5, 0.5, 0.5), 0.5, 1e-15);
        assert_eq!(super::beta_reg(0.5, 0.5, 1.0), 1.0);
        assert_almost_eq!(super::beta_reg(1.0, 0.5, 0.5), 0.292893218813452475599, 1e-15);
        assert_eq!(super::beta_reg(1.0, 0.5, 1.0), 1.0);
        assert_almost_eq!(super::beta_reg(2.5, 0.5, 0.5), 0.07558681842161243795, 1e-16);
        assert_eq!(super::beta_reg(2.5, 0.5, 1.0), 1.0);
        assert_almost_eq!(super::beta_reg(0.5, 1.0, 0.5), 0.7071067811865475244, 1e-15);
        assert_eq!(super::beta_reg(0.5, 1.0, 1.0), 1.0);
        assert_almost_eq!(super::beta_reg(1.0, 1.0, 0.5), 0.5, 1e-15);
        assert_eq!(super::beta_reg(1.0, 1.0, 1.0), 1.0);
        assert_almost_eq!(super::beta_reg(2.5, 1.0, 0.5), 0.1767766952966368811, 1e-15);
        assert_eq!(super::beta_reg(2.5, 1.0, 1.0), 1.0);
        assert_eq!(super::beta_reg(0.5, 2.5, 0.5), 0.92441318157838756205);
        assert_eq!(super::beta_reg(0.5, 2.5, 1.0), 1.0);
        assert_almost_eq!(super::beta_reg(1.0, 2.5, 0.5), 0.8232233047033631189, 1e-15);
        assert_eq!(super::beta_reg(1.0, 2.5, 1.0), 1.0);
        assert_almost_eq!(super::beta_reg(2.5, 2.5, 0.5), 0.5, 1e-15);
        assert_eq!(super::beta_reg(2.5, 2.5, 1.0), 1.0);
    }

    #[test]
    #[should_panic]
    fn test_beta_reg_neg() {
        super::beta_reg(0.5, 0.5, -1.0);
    }

    #[test]
    #[should_panic]
    fn test_beta_reg_over_one() {
        super::beta_reg(0.5, 0.5, 2.5);
    }
}
<commit_msg>complete beta tests<commit_after>//! Provides special functions related to the [beta](https://en.wikipedia.org/wiki/Beta_function)
//! function

use std::f64;
use error::StatsError;
use function::gamma;
use prec;

/// Computes the natural logarithm
/// of the beta function
/// where `a` is the first beta parameter
/// and `b` is the second beta parameter
/// and `a > 0`, `b > 0`.
///
/// # Panics
///
/// if `a <= 0.0` or `b <= 0.0`
pub fn ln_beta(a: f64, b: f64) -> f64 {
    assert!(a > 0.0, format!("{}", StatsError::ArgMustBePositive("a")));
    assert!(b > 0.0, format!("{}", StatsError::ArgMustBePositive("b")));
    gamma::ln_gamma(a) + gamma::ln_gamma(b) - gamma::ln_gamma(a + b)
}

/// Computes the beta function
/// where `a` is the first beta parameter
/// and `b` is the second beta parameter.
///
///
/// # Panics
///
/// if `a <= 0.0` or `b <= 0.0`
pub fn beta(a: f64, b: f64) -> f64 {
    ln_beta(a, b).exp()
}

/// Computes the lower incomplete (unregularized) beta function
/// `B(a,b,x) = int(t^(a-1)*(1-t)^(b-1),t=0..x)` for `a > 0, b > 0, 1 >= x >= 0`
/// where `a` is the first beta parameter, `b` is the second beta parameter, and
/// `x` is the upper limit of the integral
///
/// # Panics
///
/// If `a < 0.0`, `b < 0.0`, `x < 0.0`, or `x > 1.0`
pub fn beta_inc(a: f64, b: f64, x: f64) -> f64 {
    beta_reg(a, b, x) * beta(a, b)
}

/// Computes the regularized lower incomplete beta function
/// `I_x(a,b) = 1/Beta(a,b) * int(t^(a-1)*(1-t)^(b-1), t=0..x)`
/// `a > 0`, `b > 0`, `1 >= x >= 0` where `a` is the first beta parameter,
/// `b` is the second beta parameter, and `x` is the upper limit of the
/// integral.
///
/// # Panics
///
/// if `a < 0.0`, `b < 0.0`, `x < 0.0`, or `x > 1.0`
pub fn beta_reg(a: f64, b: f64, x: f64) -> f64 {
    assert!(a >= 0.0, format!("{}", StatsError::ArgNotNegative("a")));
    assert!(b >= 0.0, format!("{}", StatsError::ArgNotNegative("b")));
    assert!(x >= 0.0 && x <= 1.0,
            format!("{}", StatsError::ArgIntervalIncl("x", 0.0, 1.0)));

    let bt = match x {
        0.0 | 1.0 => 0.0,
        _ => {
            (gamma::ln_gamma(a + b) - gamma::ln_gamma(a) - gamma::ln_gamma(b) + a * x.ln() +
             b * (1.0 - x).ln())
                .exp()
        }
    };
    let symm_transform = x >= (a + 1.0) / (a + b + 2.0);
    let eps = prec::F64_PREC;
    let fpmin = f64::MIN_POSITIVE / eps;

    let mut a = a;
    let mut b = b;
    let mut x = x;
    if symm_transform {
        let swap = a;
        x = 1.0 - x;
        a = b;
        b = swap;
    }

    let qab = a + b;
    let qap = a + 1.0;
    let qam = a - 1.0;
    let mut c = 1.0;
    let mut d = 1.0 - qab * x / qap;

    if d.abs() < fpmin {
        d = fpmin;
    }
    d = 1.0 / d;
    let mut h = d;

    for m in 1..141 {
        let m = m as f64;
        let m2 = m * 2.0;
        let mut aa = m * (b - m) * x / ((qam + m2) * (a + m2));
        d = 1.0 + aa * d;

        if d.abs() < fpmin {
            d = fpmin;
        }

        c = 1.0 + aa / c;
        if c.abs() < fpmin {
            c = fpmin;
        }

        d = 1.0 / d;
        h = h * d * c;
        aa = -(a + m) * (qab + m) * x / ((a + m2) * (qap + m2));
        d = 1.0 + aa * d;

        if d.abs() < fpmin {
            d = fpmin;
        }

        c = 1.0 + aa / c;

        if c.abs() < fpmin {
            c = fpmin;
        }

        d = 1.0 / d;
        let del = d * c;
        h *= del;

        if (del - 1.0).abs() <= eps {
            return if symm_transform {
                1.0 - bt * h / a
            } else {
                bt * h / a
            };
        }
    }

    if symm_transform {
        1.0 - bt * h / a
    } else {
        bt * h / a
    }
}

#[cfg_attr(rustfmt, rustfmt_skip)]
#[cfg(test)]
mod test {
    #[test]
    fn test_ln_beta() {
        assert_almost_eq!(super::ln_beta(0.5, 0.5), 1.144729885849400174144, 1e-15);
        assert_almost_eq!(super::ln_beta(1.0, 0.5), 0.6931471805599453094172, 1e-14);
        assert_almost_eq!(super::ln_beta(2.5, 0.5), 0.163900632837673937284, 1e-15);
        assert_almost_eq!(super::ln_beta(0.5, 1.0), 0.6931471805599453094172, 1e-14);
        assert_almost_eq!(super::ln_beta(1.0, 1.0), 0.0, 1e-15);
        assert_almost_eq!(super::ln_beta(2.5, 1.0), -0.9162907318741550651835, 1e-14);
        assert_almost_eq!(super::ln_beta(0.5, 2.5), 0.163900632837673937284, 1e-15);
        assert_almost_eq!(super::ln_beta(1.0, 2.5), -0.9162907318741550651835, 1e-14);
        assert_almost_eq!(super::ln_beta(2.5, 2.5), -2.608688089402107300388, 1e-14);
    }

    #[test]
    fn test_beta() {
        assert_almost_eq!(super::beta(0.5, 0.5), 3.141592653589793238463, 1e-15);
        assert_almost_eq!(super::beta(1.0, 0.5), 2.0, 1e-14);
        assert_almost_eq!(super::beta(2.5, 0.5), 1.17809724509617246442, 1e-15);
        assert_almost_eq!(super::beta(0.5, 1.0), 2.0, 1e-14);
        assert_almost_eq!(super::beta(1.0, 1.0), 1.0, 1e-15);
        assert_almost_eq!(super::beta(2.5, 1.0), 0.4, 1e-14);
        assert_almost_eq!(super::beta(0.5, 2.5), 1.17809724509617246442, 1e-15);
        assert_almost_eq!(super::beta(1.0, 2.5), 0.4, 1e-14);
        assert_almost_eq!(super::beta(2.5, 2.5), 0.073631077818510779026, 1e-15);
    }

    #[test]
    fn test_beta_inc() {
        assert_almost_eq!(super::beta_inc(0.5, 0.5, 0.5), 1.570796326794896619231, 1e-14);
        assert_almost_eq!(super::beta_inc(0.5, 0.5, 1.0), 3.141592653589793238463, 1e-15);
        assert_almost_eq!(super::beta_inc(1.0, 0.5, 0.5), 0.5857864376269049511983, 1e-15);
        assert_almost_eq!(super::beta_inc(1.0, 0.5, 1.0), 2.0, 1e-14);
        assert_almost_eq!(super::beta_inc(2.5, 0.5, 0.5), 0.0890486225480862322117, 1e-16);
        assert_almost_eq!(super::beta_inc(2.5, 0.5, 1.0), 1.17809724509617246442, 1e-15);
        assert_almost_eq!(super::beta_inc(0.5, 1.0, 0.5), 1.414213562373095048802, 1e-14);
        assert_almost_eq!(super::beta_inc(0.5, 1.0, 1.0), 2.0, 1e-14);
        assert_almost_eq!(super::beta_inc(1.0, 1.0, 0.5), 0.5, 1e-15);
        assert_almost_eq!(super::beta_inc(1.0, 1.0, 1.0), 1.0, 1e-15);
        assert_eq!(super::beta_inc(2.5, 1.0, 0.5), 0.0707106781186547524401);
        assert_almost_eq!(super::beta_inc(2.5, 1.0, 1.0), 0.4, 1e-14);
        assert_almost_eq!(super::beta_inc(0.5, 2.5, 0.5), 1.08904862254808623221, 1e-15);
        assert_almost_eq!(super::beta_inc(0.5, 2.5, 1.0), 1.17809724509617246442, 1e-15);
        assert_almost_eq!(super::beta_inc(1.0, 2.5, 0.5), 0.32928932188134524756, 1e-14);
        assert_almost_eq!(super::beta_inc(1.0, 2.5, 1.0), 0.4, 1e-14);
        assert_almost_eq!(super::beta_inc(2.5, 2.5, 0.5), 0.03681553890925538951323, 1e-15);
        assert_almost_eq!(super::beta_inc(2.5, 2.5, 1.0), 0.073631077818510779026, 1e-15);
    }

    #[test]
    fn test_beta_reg() {
        assert_almost_eq!(super::beta_reg(0.5, 0.5, 0.5), 0.5, 1e-15);
        assert_eq!(super::beta_reg(0.5, 0.5, 1.0), 1.0);
        assert_almost_eq!(super::beta_reg(1.0, 0.5, 0.5), 0.292893218813452475599, 1e-15);
        assert_eq!(super::beta_reg(1.0, 0.5, 1.0), 1.0);
        assert_almost_eq!(super::beta_reg(2.5, 0.5, 0.5), 0.07558681842161243795, 1e-16);
        assert_eq!(super::beta_reg(2.5, 0.5, 1.0), 1.0);
        assert_almost_eq!(super::beta_reg(0.5, 1.0, 0.5), 0.7071067811865475244, 1e-15);
        assert_eq!(super::beta_reg(0.5, 1.0, 1.0), 1.0);
        assert_almost_eq!(super::beta_reg(1.0, 1.0, 0.5), 0.5, 1e-15);
        assert_eq!(super::beta_reg(1.0, 1.0, 1.0), 1.0);
        assert_almost_eq!(super::beta_reg(2.5, 1.0, 0.5), 0.1767766952966368811, 1e-15);
        assert_eq!(super::beta_reg(2.5, 1.0, 1.0), 1.0);
        assert_eq!(super::beta_reg(0.5, 2.5, 0.5), 0.92441318157838756205);
        assert_eq!(super::beta_reg(0.5, 2.5, 1.0), 1.0);
        assert_almost_eq!(super::beta_reg(1.0, 2.5, 0.5), 0.8232233047033631189, 1e-15);
        assert_eq!(super::beta_reg(1.0, 2.5, 1.0), 1.0);
        assert_almost_eq!(super::beta_reg(2.5, 2.5, 0.5), 0.5, 1e-15);
        assert_eq!(super::beta_reg(2.5, 2.5, 1.0), 1.0);
    }

    #[test]
    #[should_panic]
    fn test_beta_reg_neg() {
        super::beta_reg(0.5, 0.5, -1.0);
    }

    #[test]
    #[should_panic]
    fn test_beta_reg_over_one() {
        super::beta_reg(0.5, 0.5, 2.5);
    }
}
<|endoftext|>


<commit_before>use std::sync::RwLock;
use std::sync::atomic::{AtomicU32, Ordering};
use std::collections::BTreeMap;

use rocksdb::{DB, Writable};
use abra::{Term};

use key_builder::KeyBuilder;

#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
pub struct TermRef(u32);

impl TermRef {
    pub fn ord(&self) -> u32 {
        self.0
    }
}

pub struct TermDictionary {
    next_term_ref: AtomicU32,
    terms: RwLock<BTreeMap<Vec<u8>, TermRef>>,
}

impl TermDictionary {
    pub fn new(db: &DB) -> TermDictionary {
        // Next term ref
        db.put(b".next_term_ref", b"1");

        TermDictionary {
            next_term_ref: AtomicU32::new(1),
            terms: RwLock::new(BTreeMap::new()),
        }
    }

    pub fn open(db: &DB) -> TermDictionary {
        let next_term_ref = match db.get(b".next_term_ref") {
            Ok(Some(next_term_ref)) => {
                next_term_ref.to_utf8().unwrap().parse::<u32>().unwrap()
            }
            Ok(None) => 1,  // TODO: error
            Err(_) => 1,  // TODO: error
        };

        TermDictionary {
            next_term_ref: AtomicU32::new(next_term_ref),
            terms: RwLock::new(BTreeMap::new()),  // TODO read this
        }
    }

    pub fn get(&self, term_bytes: &Vec<u8>) -> Option<TermRef> {
        self.terms.read().unwrap().get(term_bytes).cloned()
    }

    pub fn get_or_create(&mut self, db: &DB, term: &Term) -> TermRef {
        let term_bytes = term.to_bytes();

        if let Some(term_ref) = self.get(&term_bytes) {
            return term_ref;
        }

        // Term doesn't exist in the term dictionary

        // Increment next_term_ref
        let next_term_ref = self.next_term_ref.fetch_add(1, Ordering::SeqCst);
        db.put(b".next_term_ref", (next_term_ref + 1).to_string().as_bytes());

        // Create term ref
        let term_ref = TermRef(next_term_ref);

        // Get exclusive lock to term dictionary
        let mut terms = self.terms.write().unwrap();

        // It's possible that another thread has written the term to the dictionary
        // since we checked earlier. If this is the case, We should forget about
        // writing our TermRef and use the one that has been inserted already.
        if let Some(term_ref) = terms.get(&term_bytes) {
            return *term_ref;
        }

        // Write it to the on-disk term dictionary
        let mut kb = KeyBuilder::term_dict_mapping(&term_bytes);
        db.put(kb.key(), next_term_ref.to_string().as_bytes());

        // Write it to the term dictionary
        terms.insert(term_bytes, term_ref);

        term_ref
    }
}
<commit_msg>Load term dictionary on open<commit_after>use std::str;
use std::sync::RwLock;
use std::sync::atomic::{AtomicU32, Ordering};
use std::collections::BTreeMap;

use rocksdb::{DB, Writable, IteratorMode, Direction};
use abra::Term;

use key_builder::KeyBuilder;

#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
pub struct TermRef(u32);

impl TermRef {
    pub fn ord(&self) -> u32 {
        self.0
    }
}

pub struct TermDictionary {
    next_term_ref: AtomicU32,
    terms: RwLock<BTreeMap<Vec<u8>, TermRef>>,
}

impl TermDictionary {
    pub fn new(db: &DB) -> TermDictionary {
        // Next term ref
        db.put(b".next_term_ref", b"1");

        TermDictionary {
            next_term_ref: AtomicU32::new(1),
            terms: RwLock::new(BTreeMap::new()),
        }
    }

    pub fn open(db: &DB) -> TermDictionary {
        let next_term_ref = match db.get(b".next_term_ref") {
            Ok(Some(next_term_ref)) => {
                next_term_ref.to_utf8().unwrap().parse::<u32>().unwrap()
            }
            Ok(None) => 1,  // TODO: error
            Err(_) => 1,  // TODO: error
        };

        // Read dictionary
        let mut terms = BTreeMap::new();
        for (k, v) in db.iterator(IteratorMode::From(b"t", Direction::Forward)) {
            if k[0] != b't' {
                break;
            }

            let term_ref = TermRef(str::from_utf8(&v).unwrap().parse::<u32>().unwrap());
            terms.insert(k[1..].to_vec(), term_ref);
        }

        TermDictionary {
            next_term_ref: AtomicU32::new(next_term_ref),
            terms: RwLock::new(terms),
        }
    }

    pub fn get(&self, term_bytes: &Vec<u8>) -> Option<TermRef> {
        self.terms.read().unwrap().get(term_bytes).cloned()
    }

    pub fn get_or_create(&mut self, db: &DB, term: &Term) -> TermRef {
        let term_bytes = term.to_bytes();

        if let Some(term_ref) = self.get(&term_bytes) {
            return term_ref;
        }

        // Term doesn't exist in the term dictionary

        // Increment next_term_ref
        let next_term_ref = self.next_term_ref.fetch_add(1, Ordering::SeqCst);
        db.put(b".next_term_ref", (next_term_ref + 1).to_string().as_bytes());

        // Create term ref
        let term_ref = TermRef(next_term_ref);

        // Get exclusive lock to term dictionary
        let mut terms = self.terms.write().unwrap();

        // It's possible that another thread has written the term to the dictionary
        // since we checked earlier. If this is the case, We should forget about
        // writing our TermRef and use the one that has been inserted already.
        if let Some(term_ref) = terms.get(&term_bytes) {
            return *term_ref;
        }

        // Write it to the on-disk term dictionary
        let mut kb = KeyBuilder::term_dict_mapping(&term_bytes);
        db.put(kb.key(), next_term_ref.to_string().as_bytes());

        // Write it to the term dictionary
        terms.insert(term_bytes, term_ref);

        term_ref
    }
}
<|endoftext|>


<commit_before>extern crate gfx;
extern crate gfx_graphics;
extern crate glutin_window;
extern crate graphics;
extern crate image as im;
extern crate piston;

use gfx::format::{DepthStencil, Formatted, Srgba8};
use gfx::memory::Typed;
use gfx_graphics::{Gfx2d, Texture, TextureContext, TextureSettings, Wrap};
use glutin_window::{GlutinWindow, OpenGL};
use piston::event_loop::*;
use piston::input::*;
use piston::window::{OpenGLWindow, Window, WindowSettings};
use std::path::Path;

fn main() {
    println!("Press S to change the texture wrap mode for the s coordinate");
    println!("Press T to change the texture wrap mode for the t coordinate");

    let opengl = OpenGL::V3_2;
    let samples = 4;
    let (w, h) = (640, 480);
    let mut window: GlutinWindow = WindowSettings::new("gfx_graphics: texture_wrap", [w, h])
        .exit_on_esc(true)
        .samples(samples)
        .graphics_api(opengl)
        .build()
        .unwrap();
    let (mut device, mut factory) =
        gfx_device_gl::create(|s| window.get_proc_address(s) as *const std::os::raw::c_void);

    // Set up wrap modes
    let wrap_modes = [
        Wrap::ClampToEdge,
        Wrap::ClampToBorder,
        Wrap::Repeat,
        Wrap::MirroredRepeat,
    ];
    let mut ix_s = 0;
    let mut ix_t = 0;
    let mut texture_settings = TextureSettings::new();
    texture_settings.set_border_color([0.0, 0.0, 0.0, 1.0]);

    // Set up texture
    let path = Path::new("./assets/rust.png");
    let img = match im::open(path) {
        Ok(img) => img,
        Err(e) => {
            panic!("Could not load '{:?}': {:?}", path.file_name().unwrap(), e);
        }
    };
    let img = match img {
        im::DynamicImage::ImageRgba8(img) => img,
        x => x.to_rgba(),
    };
    let mut texture_context = TextureContext {
        factory: factory.clone(),
        encoder: factory.create_command_buffer().into(),
    };
    let mut rust_logo = Texture::from_image(&mut texture_context, &img, &texture_settings).unwrap();

    let mut encoder = factory.create_command_buffer().into();
    let draw_size = window.draw_size();
    let dim = (
        draw_size.width as u16,
        draw_size.height as u16,
        1,
        (samples as gfx::texture::NumSamples).into(),
    );
    let color_format = <Srgba8 as Formatted>::get_format();
    let depth_format = <DepthStencil as Formatted>::get_format();
    let (output_color, output_stencil) =
        gfx_device_gl::create_main_targets_raw(dim, color_format.0, depth_format.0);
    let output_color = Typed::new(output_color);
    let output_stencil = Typed::new(output_stencil);
    let mut g2d = Gfx2d::new(opengl, &mut factory);
    let mut events = Events::new(EventSettings::new().lazy(true));
    while let Some(e) = events.next(&mut window) {
        if let Some(args) = e.render_args() {
            use graphics::*;
            g2d.draw(
                &mut encoder,
                &output_color,
                &output_stencil,
                args.viewport(),
                |_c, g| {
                    clear([1.0; 4], g);
                    let points = [[0.5, 0.5], [-0.5, 0.5], [-0.5, -0.5], [0.5, -0.5]];
                    // (0, 1, 2) and (0, 2, 3)
                    let uvs = [
                        [4.0, 0.0],
                        [0.0, 0.0],
                        [0.0, 4.0],
                        [4.0, 0.0],
                        [0.0, 4.0],
                        [4.0, 4.0],
                    ];
                    let mut verts = [[0.0, 0.0]; 6];
                    let indices_points: [usize; 6] = [0, 1, 2, 0, 2, 3];
                    for (ixv, &ixp) in (0..6).zip(indices_points.into_iter()) {
                        verts[ixv] = points[ixp];
                    }
                    g.tri_list_uv(&DrawState::new_alpha(), &[1.0; 4], &rust_logo, |f| {
                        f(&verts, &uvs)
                    });
                },
            );
            encoder.flush(&mut device);
        }

        if let Some(Button::Keyboard(Key::S)) = e.press_args() {
            ix_s = (ix_s + 1) % wrap_modes.len();
            texture_settings.set_wrap_s(wrap_modes[ix_s]);
            rust_logo = Texture::from_image(&mut texture_context, &img, &texture_settings).unwrap();
            println!(
                "Changed texture wrap mode for s coordinate to: {:?}",
                wrap_modes[ix_s]
            );
        }

        if let Some(Button::Keyboard(Key::T)) = e.press_args() {
            ix_t = (ix_t + 1) % wrap_modes.len();
            texture_settings.set_wrap_t(wrap_modes[ix_t]);
            rust_logo = Texture::from_image(&mut texture_context, &img, &texture_settings).unwrap();
            println!(
                "Changed texture wrap mode for t coordinate to: {:?}",
                wrap_modes[ix_t]
            );
        }
    }
}
<commit_msg>Rename s t coordinates to u v<commit_after>extern crate gfx;
extern crate gfx_graphics;
extern crate glutin_window;
extern crate graphics;
extern crate image as im;
extern crate piston;

use gfx::format::{DepthStencil, Formatted, Srgba8};
use gfx::memory::Typed;
use gfx_graphics::{Gfx2d, Texture, TextureContext, TextureSettings, Wrap};
use glutin_window::{GlutinWindow, OpenGL};
use piston::event_loop::*;
use piston::input::*;
use piston::window::{OpenGLWindow, Window, WindowSettings};
use std::path::Path;

fn main() {
    println!("Press U to change the texture wrap mode for the u coordinate");
    println!("Press V to change the texture wrap mode for the v coordinate");

    let opengl = OpenGL::V3_2;
    let samples = 4;
    let (w, h) = (640, 480);
    let mut window: GlutinWindow = WindowSettings::new("gfx_graphics: texture_wrap", [w, h])
        .exit_on_esc(true)
        .samples(samples)
        .graphics_api(opengl)
        .build()
        .unwrap();
    let (mut device, mut factory) =
        gfx_device_gl::create(|s| window.get_proc_address(s) as *const std::os::raw::c_void);

    // Set up wrap modes
    let wrap_modes = [
        Wrap::ClampToEdge,
        Wrap::ClampToBorder,
        Wrap::Repeat,
        Wrap::MirroredRepeat,
    ];
    let mut ix_u = 0;
    let mut ix_v = 0;
    let mut texture_settings = TextureSettings::new();
    texture_settings.set_border_color([0.0, 0.0, 0.0, 1.0]);

    // Set up texture
    let path = Path::new("./assets/rust.png");
    let img = match im::open(path) {
        Ok(img) => img,
        Err(e) => {
            panic!("Could not load '{:?}': {:?}", path.file_name().unwrap(), e);
        }
    };
    let img = match img {
        im::DynamicImage::ImageRgba8(img) => img,
        x => x.to_rgba(),
    };
    let mut texture_context = TextureContext {
        factory: factory.clone(),
        encoder: factory.create_command_buffer().into(),
    };
    let mut rust_logo = Texture::from_image(&mut texture_context, &img, &texture_settings).unwrap();

    let mut encoder = factory.create_command_buffer().into();
    let draw_size = window.draw_size();
    let dim = (
        draw_size.width as u16,
        draw_size.height as u16,
        1,
        (samples as gfx::texture::NumSamples).into(),
    );
    let color_format = <Srgba8 as Formatted>::get_format();
    let depth_format = <DepthStencil as Formatted>::get_format();
    let (output_color, output_stencil) =
        gfx_device_gl::create_main_targets_raw(dim, color_format.0, depth_format.0);
    let output_color = Typed::new(output_color);
    let output_stencil = Typed::new(output_stencil);
    let mut g2d = Gfx2d::new(opengl, &mut factory);
    let mut events = Events::new(EventSettings::new().lazy(true));
    while let Some(e) = events.next(&mut window) {
        if let Some(args) = e.render_args() {
            use graphics::*;
            g2d.draw(
                &mut encoder,
                &output_color,
                &output_stencil,
                args.viewport(),
                |_c, g| {
                    clear([1.0; 4], g);
                    let points = [[0.5, 0.5], [-0.5, 0.5], [-0.5, -0.5], [0.5, -0.5]];
                    // (0, 1, 2) and (0, 2, 3)
                    let uvs = [
                        [4.0, 0.0],
                        [0.0, 0.0],
                        [0.0, 4.0],
                        [4.0, 0.0],
                        [0.0, 4.0],
                        [4.0, 4.0],
                    ];
                    let mut verts = [[0.0, 0.0]; 6];
                    let indices_points: [usize; 6] = [0, 1, 2, 0, 2, 3];
                    for (ixv, &ixp) in (0..6).zip(indices_points.into_iter()) {
                        verts[ixv] = points[ixp];
                    }
                    g.tri_list_uv(&DrawState::new_alpha(), &[1.0; 4], &rust_logo, |f| {
                        f(&verts, &uvs)
                    });
                },
            );
            encoder.flush(&mut device);
        }

        if let Some(Button::Keyboard(Key::U)) = e.press_args() {
            ix_u = (ix_u + 1) % wrap_modes.len();
            texture_settings.set_wrap_u(wrap_modes[ix_u]);
            rust_logo = Texture::from_image(&mut texture_context, &img, &texture_settings).unwrap();
            println!(
                "Changed texture wrap mode for u coordinate to: {:?}",
                wrap_modes[ix_u]
            );
        }

        if let Some(Button::Keyboard(Key::V)) = e.press_args() {
            ix_v = (ix_v + 1) % wrap_modes.len();
            texture_settings.set_wrap_v(wrap_modes[ix_v]);
            rust_logo = Texture::from_image(&mut texture_context, &img, &texture_settings).unwrap();
            println!(
                "Changed texture wrap mode for v coordinate to: {:?}",
                wrap_modes[ix_v]
            );
        }
    }
}
<|endoftext|>


<commit_before>// #![feature(test)]

extern crate rand;
extern crate time;
extern crate test;
extern crate getopts;
extern crate timely;
extern crate graph_map;
extern crate differential_dataflow;

use std::num;
use std::collections::HashMap;

use rand::{Rng, SeedableRng, StdRng};

use differential_dataflow::collection_trace::index::{Index, OrdIndex};

fn main() {
    for i in 25..28 {
        test_index(i);
    }
    // test_hash();
}

fn test_index(log_size: usize) {

    let mut index = OrdIndex::new();
    let mut hash = HashMap::new();

    let seed: &[_] = &[1, 2, 3, 4];
    let mut rng: StdRng = SeedableRng::from_seed(seed);

    let mut tally = 0;

    let mut vec = vec![];
    let mut remaining = 1 << log_size;
    while remaining > 0 {
        for _ in 0.. (1 << (log_size - 2)) {
            vec.push(((rng.next_u64()),(rng.next_u64())));
        }
        vec.sort();
        remaining -= vec.len();
        let start = time::precise_time_ns();
        index.for_each(&mut vec, |k,v| { *v = *k });
        tally += time::precise_time_ns() - start;
        vec.clear();
    }

    println!("loaded index 2e{}:\t{:.2e} ns", log_size, tally as f64);

    let start = time::precise_time_ns();

    for i in 0..(1 << log_size) {
        hash.insert((i,i),(i,i));
    }

    println!("loaded hash 2e{}:\t{:.2e} ns", log_size, (time::precise_time_ns() - start) as f64);

    for query in 0..log_size {

        let mut index_tally = 0;
        let mut hash_tally = 0;

        for _ in 0..10 {
            for _ in 0..(1 << query) {
                vec.push(((rng.next_u64()),(rng.next_u64())));
            }
            vec.sort();
            let start = time::precise_time_ns();
            index.find_each(&mut vec, |k,v| { *v = *k });
            vec.clear();
            index_tally += time::precise_time_ns() - start;

            let start = time::precise_time_ns();
            for i in 0..(1 << query) {
                assert!(hash.get(&(i,i)).unwrap() == &(i,i));
            }
            hash_tally += time::precise_time_ns() - start;

        }

        println!("\t2e{}:\t{}\t{:2.3}x\t{} ns", query, (index_tally / 10) >> query, index_tally as f64 / hash_tally as f64, (index_tally as i64 - hash_tally as i64) / 10);
    }
}

fn _test_hash() {
    let start = time::precise_time_ns();
    // let mut index = OrdIndex::new();
    let mut hash = HashMap::new();

    let seed: &[_] = &[1, 2, 3, 4];
    let mut rng: StdRng = SeedableRng::from_seed(seed);

    for i in 0..10_000 {

        let mut key = (0u64, 0u64);

        for _ in 0..1_000 {

            key.0 += rng.gen_range(0, 1000);
            key.1 += rng.gen_range(0, 1000);
            // key.2 += rng.gen_range(0, 1000);

            hash.entry(key.clone()).or_insert(key.clone());
        }
    }

    println!("loaded in {}ns avg", (time::precise_time_ns() - start) / 10_000_000);
    let start = time::precise_time_ns();

    let seed: &[_] = &[1, 2, 3, 4];
    let mut rng: StdRng = SeedableRng::from_seed(seed);

    let mut vec = vec![];
    for i in 0..100 {
        let mut key = (0u64, 0u64);
        for _ in 0..1000 {
            key.0 += rng.gen_range(0, 1000);
            key.1 += rng.gen_range(0, 1000);
            vec.push(key.clone());
        }
    }
    vec.sort();

    let start = time::precise_time_ns();
    for k in &vec { assert!(hash.get(k).unwrap() == k); }

    println!("read in {}ns avg", (time::precise_time_ns() - start) / 100_000);
}
<commit_msg>dataflog stuffs<commit_after>// #![feature(test)]

extern crate rand;
extern crate time;
// extern crate test;
extern crate getopts;
extern crate timely;
extern crate graph_map;
extern crate differential_dataflow;

use std::num;
use std::collections::HashMap;

use rand::{Rng, SeedableRng, StdRng};

use differential_dataflow::collection_trace::index::{Index, OrdIndex};

fn main() {
    for i in 25..28 {
        test_index(i);
    }
    // test_hash();
}

fn test_index(log_size: usize) {

    let mut index = OrdIndex::new();
    let mut hash = HashMap::new();

    let seed: &[_] = &[1, 2, 3, 4];
    let mut rng: StdRng = SeedableRng::from_seed(seed);

    let mut tally = 0;

    let mut vec = vec![];
    let mut remaining = 1 << log_size;
    while remaining > 0 {
        for _ in 0.. (1 << (log_size - 2)) {
            vec.push(((rng.next_u64()),(rng.next_u64())));
        }
        vec.sort();
        remaining -= vec.len();
        let start = time::precise_time_ns();
        index.for_each(&mut vec, |k,v| { *v = *k });
        tally += time::precise_time_ns() - start;
        vec.clear();
    }

    println!("loaded index 2e{}:\t{:.2e} ns", log_size, tally as f64);

    let start = time::precise_time_ns();

    for i in 0..(1 << log_size) {
        hash.insert((i,i),(i,i));
    }

    println!("loaded hash 2e{}:\t{:.2e} ns", log_size, (time::precise_time_ns() - start) as f64);

    for query in 0..log_size {

        let mut index_tally = 0;
        let mut hash_tally = 0;

        for _ in 0..10 {
            for _ in 0..(1 << query) {
                vec.push(((rng.next_u64()),(rng.next_u64())));
            }
            vec.sort();
            let start = time::precise_time_ns();
            index.find_each(&mut vec, |k,v| { *v = *k });
            vec.clear();
            index_tally += time::precise_time_ns() - start;

            let start = time::precise_time_ns();
            for i in 0..(1 << query) {
                assert!(hash.get(&(i,i)).unwrap() == &(i,i));
            }
            hash_tally += time::precise_time_ns() - start;

        }

        println!("\t2e{}:\t{}\t{:2.3}x\t{} ns", query, (index_tally / 10) >> query, index_tally as f64 / hash_tally as f64, (index_tally as i64 - hash_tally as i64) / 10);
    }
}

fn _test_hash() {
    let start = time::precise_time_ns();
    // let mut index = OrdIndex::new();
    let mut hash = HashMap::new();

    let seed: &[_] = &[1, 2, 3, 4];
    let mut rng: StdRng = SeedableRng::from_seed(seed);

    for i in 0..10_000 {

        let mut key = (0u64, 0u64);

        for _ in 0..1_000 {

            key.0 += rng.gen_range(0, 1000);
            key.1 += rng.gen_range(0, 1000);
            // key.2 += rng.gen_range(0, 1000);

            hash.entry(key.clone()).or_insert(key.clone());
        }
    }

    println!("loaded in {}ns avg", (time::precise_time_ns() - start) / 10_000_000);
    let start = time::precise_time_ns();

    let seed: &[_] = &[1, 2, 3, 4];
    let mut rng: StdRng = SeedableRng::from_seed(seed);

    let mut vec = vec![];
    for i in 0..100 {
        let mut key = (0u64, 0u64);
        for _ in 0..1000 {
            key.0 += rng.gen_range(0, 1000);
            key.1 += rng.gen_range(0, 1000);
            vec.push(key.clone());
        }
    }
    vec.sort();

    let start = time::precise_time_ns();
    for k in &vec { assert!(hash.get(k).unwrap() == k); }

    println!("read in {}ns avg", (time::precise_time_ns() - start) / 100_000);
}
<|endoftext|>


<commit_before>use std::sync::mpsc::Sender;
use std::rc::Rc;

use action::ActionCommand;
use super::{config, Context, Event};

pub struct Dispatcher {
    contexts: Vec<Context>,
    output_channel: Sender<ActionCommand>
}

impl Dispatcher {
    pub fn new(contexts: Vec<config::Context>, action_output_channel: Sender<ActionCommand>) -> Dispatcher {
        let contexts = contexts.into_iter().map(|ctx| Context::from(ctx)).collect::<Vec<Context>>();
        Dispatcher {
            contexts: contexts,
            output_channel: action_output_channel
        }
    }

    pub fn dispatch(&mut self, event: Event) {
        match event {
            Event::Message(event) => {
                let event = Rc::new(event);
                for context in self.contexts.iter_mut() {
                    context.on_message(event.clone());
                }
            },
            Event::Timer(ref event) => {
                for context in self.contexts.iter_mut() {
                    context.on_timer(event);
                }
            }
        }
    }
}
<commit_msg>dispatcher: forward commands to the outside<commit_after>use std::sync::mpsc::Sender;
use std::rc::Rc;

use action::ActionCommand;
use super::{config, Context, Event, Message, TimerEvent};

pub struct Dispatcher {
    contexts: Vec<Context>,
    output_channel: Sender<ActionCommand>
}

impl Dispatcher {
    pub fn new(contexts: Vec<config::Context>, action_output_channel: Sender<ActionCommand>) -> Dispatcher {
        let contexts = contexts.into_iter().map(|ctx| Context::from(ctx)).collect::<Vec<Context>>();
        Dispatcher {
            contexts: contexts,
            output_channel: action_output_channel
        }
    }

    pub fn dispatch(&mut self, event: Event) {
        let mut commands = Vec::new();
        match event {
            Event::Message(event) => {
                let event = Rc::new(event);
                self.on_message(&mut commands, event);
            },
            Event::Timer(ref event) => {
                self.on_timer(&mut commands, event);
            }
        };

        for i in commands.into_iter() {
            self.output_channel.send(i);
        }
    }

    fn on_message(&mut self, commands: &mut Vec<ActionCommand>, event: Rc<Message>) {
        for context in self.contexts.iter_mut() {
            if let Some(result) = context.on_message(event.clone()) {
                for i in result.into_iter() {
                    commands.push(i);
                }
            }
        }
    }

    fn on_timer(&mut self, commands: &mut Vec<ActionCommand>, event: &TimerEvent) {
        for context in self.contexts.iter_mut() {
            if let Some(result) = context.on_timer(event) {
                for i in result.into_iter() {
                    commands.push(i);
                }
            }
        }
    }
}
<|endoftext|>