<commit_before>use error::{Error, Result, UnsupportedFeature};
use parser::Component;

pub struct Upsampler {
    components: Vec<UpsamplerComponent>,
}

struct UpsamplerComponent {
    upsampler: Box<Upsample + Sync>,
    width: usize,
    height: usize,
    row_stride: usize,
}

impl Upsampler {
    pub fn new(components: &[Component], output_width: u16, output_height: u16) -> Result<Upsampler> {
        let h_max = components.iter().map(|c| c.horizontal_sampling_factor).max().unwrap();
        let v_max = components.iter().map(|c| c.vertical_sampling_factor).max().unwrap();
        let mut upsampler_components = Vec::with_capacity(components.len());

        for component in components {
            let upsampler = try!(choose_upsampler((component.horizontal_sampling_factor,
                                                   component.vertical_sampling_factor),
                                                  (h_max, v_max),
                                                  output_width,
                                                  output_height));
            upsampler_components.push(UpsamplerComponent {
                upsampler: upsampler,
                width: component.size.width as usize,
                height: component.size.height as usize,
                row_stride: component.block_size.width as usize * 8,
            });
        }

        Ok(Upsampler {
            components: upsampler_components,
        })
    }

    pub fn upsample_and_interleave_row(&self, component_data: &[Vec<u8>], row: usize, output_width: usize, output: &mut [u8]) {
        let component_count = component_data.len();
        let mut line_buffer = vec![0u8; output_width + 1];

        debug_assert_eq!(component_count, self.components.len());

        for (i, component) in self.components.iter().enumerate() {
            component.upsampler.upsample_row(&component_data[i],
                                             component.width,
                                             component.height,
                                             component.row_stride,
                                             row,
                                             output_width,
                                             &mut line_buffer);
            for x in 0 .. output_width {
                output[x * component_count + i] = line_buffer[x];
            }
        }
    }
}

struct UpsamplerH1V1;
struct UpsamplerH2V1;
struct UpsamplerH1V2;
struct UpsamplerH2V2;

fn choose_upsampler(sampling_factors: (u8, u8),
                    max_sampling_factors: (u8, u8),
                    output_width: u16,
                    output_height: u16) -> Result<Box<Upsample + Sync>> {
    let h1 = sampling_factors.0 == max_sampling_factors.0 || output_width == 1;
    let v1 = sampling_factors.1 == max_sampling_factors.1 || output_height == 1;
    let h2 = sampling_factors.0 * 2 == max_sampling_factors.0;
    let v2 = sampling_factors.1 * 2 == max_sampling_factors.1;

    if h1 && v1 {
        Ok(Box::new(UpsamplerH1V1))
    }
    else if h2 && v1 {
        Ok(Box::new(UpsamplerH2V1))
    }
    else if h1 && v2 {
        Ok(Box::new(UpsamplerH1V2))
    }
    else if h2 && v2 {
        Ok(Box::new(UpsamplerH2V2))
    }
    else {
        if max_sampling_factors.0 % sampling_factors.0 != 0 || max_sampling_factors.1 % sampling_factors.1 != 0 {
            Err(Error::Unsupported(UnsupportedFeature::NonIntegerSubsamplingRatio))
        }
        else {
            Err(Error::Unsupported(UnsupportedFeature::SubsamplingRatio))
        }
    }
}

trait Upsample {
    fn upsample_row(&self,
                    input: &[u8],
                    input_width: usize,
                    input_height: usize,
                    row_stride: usize,
                    row: usize,
                    output_width: usize,
                    output: &mut [u8]);
}

impl Upsample for UpsamplerH1V1 {
    fn upsample_row(&self,
                    input: &[u8],
                    _input_width: usize,
                    _input_height: usize,
                    row_stride: usize,
                    row: usize,
                    output_width: usize,
                    output: &mut [u8]) {
        let input = &input[row * row_stride ..];

        for i in 0 .. output_width {
            output[i] = input[i];
        }
    }
}

impl Upsample for UpsamplerH2V1 {
    fn upsample_row(&self,
                    input: &[u8],
                    input_width: usize,
                    _input_height: usize,
                    row_stride: usize,
                    row: usize,
                    _output_width: usize,
                    output: &mut [u8]) {
        let input = &input[row * row_stride ..];

        if input_width == 1 {
            output[0] = input[0];
            output[1] = input[0];
            return;
        }

        output[0] = input[0];
        output[1] = ((input[0] as u32 * 3 + input[1] as u32 + 2) >> 2) as u8;

        for i in 1 .. input_width - 1 {
            let sample = 3 * input[i] as u32 + 2;
            output[i * 2]     = ((sample + input[i - 1] as u32) >> 2) as u8;
            output[i * 2 + 1] = ((sample + input[i + 1] as u32) >> 2) as u8;
        }

        output[(input_width - 1) * 2] = ((input[input_width - 1] as u32 * 3 + input[input_width - 2] as u32 + 2) >> 2) as u8;
        output[(input_width - 1) * 2 + 1] = input[input_width - 1];
    }
}

impl Upsample for UpsamplerH1V2 {
    fn upsample_row(&self,
                    input: &[u8],
                    _input_width: usize,
                    input_height: usize,
                    row_stride: usize,
                    row: usize,
                    output_width: usize,
                    output: &mut [u8]) {
        let row_near = row as f32 / 2.0;
        // If row_near's fractional is 0.0 we want row_far to be the previous row and if it's 0.5 we
        // want it to be the next row.
        let row_far = (row_near + row_near.fract() * 3.0 - 0.25).min((input_height - 1) as f32);

        let input_near = &input[row_near as usize * row_stride ..];
        let input_far = &input[row_far as usize * row_stride ..];

        for i in 0 .. output_width {
            output[i] = ((3 * input_near[i] as u32 + input_far[i] as u32 + 2) >> 2) as u8;
        }
    }
}

impl Upsample for UpsamplerH2V2 {
    fn upsample_row(&self,
                    input: &[u8],
                    input_width: usize,
                    input_height: usize,
                    row_stride: usize,
                    row: usize,
                    _output_width: usize,
                    output: &mut [u8]) {
        let row_near = row as f32 / 2.0;
        // If row_near's fractional is 0.0 we want row_far to be the previous row and if it's 0.5 we
        // want it to be the next row.
        let row_far = (row_near + row_near.fract() * 3.0 - 0.25).min((input_height - 1) as f32);

        let input_near = &input[row_near as usize * row_stride ..];
        let input_far = &input[row_far as usize * row_stride ..];

        if input_width == 1 {
            let value = ((3 * input_near[0] as u32 + input_far[0] as u32 + 2) >> 2) as u8;
            output[0] = value;
            output[1] = value;
            return;
        }

        let mut t1 = 3 * input_near[0] as u32 + input_far[0] as u32;
        output[0] = ((t1 + 2) >> 2) as u8;

        for i in 1 .. input_width {
            let t0 = t1;
            t1 = 3 * input_near[i] as u32 + input_far[i] as u32;

            output[i * 2 - 1] = ((3 * t0 + t1 + 8) >> 4) as u8;
            output[i * 2]     = ((3 * t1 + t0 + 8) >> 4) as u8;
        }

        output[input_width * 2 - 1] = ((t1 + 2) >> 2) as u8;
    }
}
<commit_msg>Adds UpsamplerGeneric<commit_after>use error::{Error, Result, UnsupportedFeature};
use parser::Component;

pub struct Upsampler {
    components: Vec<UpsamplerComponent>,
    line_buffer_size: usize
}

struct UpsamplerComponent {
    upsampler: Box<Upsample + Sync>,
    width: usize,
    height: usize,
    row_stride: usize,
}

impl Upsampler {
    pub fn new(components: &[Component], output_width: u16, output_height: u16) -> Result<Upsampler> {
        let h_max = components.iter().map(|c| c.horizontal_sampling_factor).max().unwrap();
        let v_max = components.iter().map(|c| c.vertical_sampling_factor).max().unwrap();
        let mut upsampler_components = Vec::with_capacity(components.len());

        for component in components {
            let upsampler = try!(choose_upsampler((component.horizontal_sampling_factor,
                                                   component.vertical_sampling_factor),
                                                  (h_max, v_max),
                                                  output_width,
                                                  output_height));
            upsampler_components.push(UpsamplerComponent {
                upsampler: upsampler,
                width: component.size.width as usize,
                height: component.size.height as usize,
                row_stride: component.block_size.width as usize * 8,
            });
        }

        let buffer_size = components.iter().map(|c| c.size.width).max().unwrap() as usize * h_max as usize;

        Ok(Upsampler {
            components: upsampler_components,
            line_buffer_size: buffer_size
        })
    }

    pub fn upsample_and_interleave_row(&self, component_data: &[Vec<u8>], row: usize, output_width: usize, output: &mut [u8]) {
        let component_count = component_data.len();
        let mut line_buffer = vec![0u8; self.line_buffer_size];

        debug_assert_eq!(component_count, self.components.len());

        for (i, component) in self.components.iter().enumerate() {
            component.upsampler.upsample_row(&component_data[i],
                                             component.width,
                                             component.height,
                                             component.row_stride,
                                             row,
                                             output_width,
                                             &mut line_buffer);
            for x in 0 .. output_width {
                output[x * component_count + i] = line_buffer[x];
            }
        }
    }
}

struct UpsamplerH1V1;
struct UpsamplerH2V1;
struct UpsamplerH1V2;
struct UpsamplerH2V2;

struct UpsamplerGeneric {
    horizontal_scaling_factor: u8,
    vertical_scaling_factor: u8
}

fn choose_upsampler(sampling_factors: (u8, u8),
                    max_sampling_factors: (u8, u8),
                    output_width: u16,
                    output_height: u16) -> Result<Box<Upsample + Sync>> {
    let h1 = sampling_factors.0 == max_sampling_factors.0 || output_width == 1;
    let v1 = sampling_factors.1 == max_sampling_factors.1 || output_height == 1;
    let h2 = sampling_factors.0 * 2 == max_sampling_factors.0;
    let v2 = sampling_factors.1 * 2 == max_sampling_factors.1;

    if h1 && v1 {
        Ok(Box::new(UpsamplerH1V1))
    }
    else if h2 && v1 {
        Ok(Box::new(UpsamplerH2V1))
    }
    else if h1 && v2 {
        Ok(Box::new(UpsamplerH1V2))
    }
    else if h2 && v2 {
        Ok(Box::new(UpsamplerH2V2))
    }
    else {
        if max_sampling_factors.0 % sampling_factors.0 != 0 || max_sampling_factors.1 % sampling_factors.1 != 0 {
            Err(Error::Unsupported(UnsupportedFeature::NonIntegerSubsamplingRatio))
        }
        else {
            Ok(Box::new(UpsamplerGeneric {
                horizontal_scaling_factor: max_sampling_factors.0 / sampling_factors.0,
                vertical_scaling_factor: max_sampling_factors.1 / sampling_factors.1
            }))
        }
    }
}

trait Upsample {
    fn upsample_row(&self,
                    input: &[u8],
                    input_width: usize,
                    input_height: usize,
                    row_stride: usize,
                    row: usize,
                    output_width: usize,
                    output: &mut [u8]);
}

impl Upsample for UpsamplerH1V1 {
    fn upsample_row(&self,
                    input: &[u8],
                    _input_width: usize,
                    _input_height: usize,
                    row_stride: usize,
                    row: usize,
                    output_width: usize,
                    output: &mut [u8]) {
        let input = &input[row * row_stride ..];

        for i in 0 .. output_width {
            output[i] = input[i];
        }
    }
}

impl Upsample for UpsamplerH2V1 {
    fn upsample_row(&self,
                    input: &[u8],
                    input_width: usize,
                    _input_height: usize,
                    row_stride: usize,
                    row: usize,
                    _output_width: usize,
                    output: &mut [u8]) {
        let input = &input[row * row_stride ..];

        if input_width == 1 {
            output[0] = input[0];
            output[1] = input[0];
            return;
        }

        output[0] = input[0];
        output[1] = ((input[0] as u32 * 3 + input[1] as u32 + 2) >> 2) as u8;

        for i in 1 .. input_width - 1 {
            let sample = 3 * input[i] as u32 + 2;
            output[i * 2]     = ((sample + input[i - 1] as u32) >> 2) as u8;
            output[i * 2 + 1] = ((sample + input[i + 1] as u32) >> 2) as u8;
        }

        output[(input_width - 1) * 2] = ((input[input_width - 1] as u32 * 3 + input[input_width - 2] as u32 + 2) >> 2) as u8;
        output[(input_width - 1) * 2 + 1] = input[input_width - 1];
    }
}

impl Upsample for UpsamplerH1V2 {
    fn upsample_row(&self,
                    input: &[u8],
                    _input_width: usize,
                    input_height: usize,
                    row_stride: usize,
                    row: usize,
                    output_width: usize,
                    output: &mut [u8]) {
        let row_near = row as f32 / 2.0;
        // If row_near's fractional is 0.0 we want row_far to be the previous row and if it's 0.5 we
        // want it to be the next row.
        let row_far = (row_near + row_near.fract() * 3.0 - 0.25).min((input_height - 1) as f32);

        let input_near = &input[row_near as usize * row_stride ..];
        let input_far = &input[row_far as usize * row_stride ..];

        for i in 0 .. output_width {
            output[i] = ((3 * input_near[i] as u32 + input_far[i] as u32 + 2) >> 2) as u8;
        }
    }
}

impl Upsample for UpsamplerH2V2 {
    fn upsample_row(&self,
                    input: &[u8],
                    input_width: usize,
                    input_height: usize,
                    row_stride: usize,
                    row: usize,
                    _output_width: usize,
                    output: &mut [u8]) {
        let row_near = row as f32 / 2.0;
        // If row_near's fractional is 0.0 we want row_far to be the previous row and if it's 0.5 we
        // want it to be the next row.
        let row_far = (row_near + row_near.fract() * 3.0 - 0.25).min((input_height - 1) as f32);

        let input_near = &input[row_near as usize * row_stride ..];
        let input_far = &input[row_far as usize * row_stride ..];

        if input_width == 1 {
            let value = ((3 * input_near[0] as u32 + input_far[0] as u32 + 2) >> 2) as u8;
            output[0] = value;
            output[1] = value;
            return;
        }

        let mut t1 = 3 * input_near[0] as u32 + input_far[0] as u32;
        output[0] = ((t1 + 2) >> 2) as u8;

        for i in 1 .. input_width {
            let t0 = t1;
            t1 = 3 * input_near[i] as u32 + input_far[i] as u32;

            output[i * 2 - 1] = ((3 * t0 + t1 + 8) >> 4) as u8;
            output[i * 2]     = ((3 * t1 + t0 + 8) >> 4) as u8;
        }

        output[input_width * 2 - 1] = ((t1 + 2) >> 2) as u8;
    }
}

impl Upsample for UpsamplerGeneric {
    // Uses nearest neighbor sampling
    fn upsample_row(&self,
                    input: &[u8],
                    input_width: usize,
                    _input_height: usize,
                    row_stride: usize,
                    row: usize,
                    _output_width: usize,
                    output: &mut [u8]) {
        let mut index = 0;
        let start = (row / self.vertical_scaling_factor as usize) * row_stride;
        let input = &input[start..(start + input_width)];
        for val in input {
            for _ in 0..self.horizontal_scaling_factor {
                output[index] = *val;
                index += 1;
            }
        }
    }
}
<|endoftext|>


<commit_before>use std::marker::PhantomData;

use ffi::cairo_user_data_key_t;

/// A key for indexing user data in various cairo types.
///
/// Some types like [`Surface`] have `get_user_data`, `set_user_data`, and `remove_user_data`
/// methods that take `&'static UserDataKey`, where the address of that reference is significant.
///
/// To reliably have a stable address, the expected usage is to define a `static` item:
///
/// ```
/// use cairo::UserDataKey;
/// static FOO: UserDataKey<String> = UserDataKey::new();
///
/// # fn foo(surface: &cairo::Surface) {
/// surface.get_user_data(&FOO)
/// # ; }
pub struct UserDataKey<T> {
    pub(crate) ffi: cairo_user_data_key_t,
    marker: PhantomData<*const T>,
}

unsafe impl<T> Sync for UserDataKey<T> {}

impl<T> UserDataKey<T> {
    pub const fn new() -> Self {
        UserDataKey {
            ffi: cairo_user_data_key_t { unused: 0 },
            marker: PhantomData,
        }
    }
}

// In a safe API for user data we can’t make `get_user_data`
// transfer full ownership of the value to the caller (e.g. by returning `Box<T>`)
// because `self` still has a pointer to that value
// and `get_user_data` could be called again with the same key.
//
// We also can’t return a `&T` reference that borrows from `self`
// because the value could be removed with `remove_user_data` or replaced with `set_user_data`
// while the borrow still needs to be valid.
// (Borrowing with `&mut self` would not help as `Self` can be itself reference-counted.)
//
// Therefore the value must be reference-counted.
//
// We use `Rc` over `Arc` because the types implementing these methods are `!Send` and `!Sync`.
// See <https://github.com/gtk-rs/cairo/issues/256>

macro_rules! user_data_methods {
    ($ffi_get_user_data: path, $ffi_set_user_data: path,) => {
        /// Attach user data to `self` for the given `key`.
        pub fn set_user_data<T: 'static>(&self, key: &'static crate::UserDataKey<T>,
                                         value: std::rc::Rc<T>)
        {
            unsafe extern "C" fn destructor<T>(ptr: *mut libc::c_void) {
                let ptr: *const T = ptr as _;
                drop(std::rc::Rc::from_raw(ptr))
            }
            // Safety:
            //
            // The destructor’s cast and `from_raw` are symetric
            // with the `into_raw` and cast below.
            // They both transfer ownership of one strong reference:
            // neither of them touches the reference count.
            let ptr: *const T = std::rc::Rc::into_raw(value);
            let ptr = ptr as *mut T as *mut libc::c_void;
            let result = unsafe {
                $ffi_set_user_data(self.to_raw_none(), &key.ffi, ptr, Some(destructor::<T>))
            };
            Status::from(result).ensure_valid()
        }

        /// Return the user data previously attached to `self` with the given `key`, if any.
        pub fn get_user_data<T: 'static>(&self, key: &'static crate::UserDataKey<T>)
                                         -> Option<std::rc::Rc<T>>
        {
            // Safety:
            //
            // `Rc::from_raw` would normally take ownership of a strong reference for this pointer.
            // But `self` still has a copy of that pointer and `get_user_data` can be called again
            // with the same key.
            // We use `ManuallyDrop` to avoid running the destructor of that first `Rc`,
            // and return a cloned one (which increments the reference count).
            //
            // If `ffi_get_user_data` returns a non-null pointer,
            // there was a previous call to `ffi_set_user_data` with a key with the same address.
            // Either:
            //
            // * This was a call to a Rust `Self::set_user_data` method.
            //   Because that method takes a `&'static` reference,
            //   the key used then must live at that address until the end of the process.
            //   Because `UserDataKey<T>` has a non-zero size regardless of `T`,
            //   no other `UserDataKey<U>` value can have the same address.
            //   Therefore the `T` type was the same then at it is now and `cast` is type-safe.
            //
            // * Or, it is technically possible that the `set` call was to the C function directly,
            //   with a `cairo_user_data_key_t` in heap-allocated memory that was then freed,
            //   then `Box::new(UserDataKey::new()).leak()` was used to create a `&'static`
            //   that happens to have the same address because the allocator for `Box`
            //   reused that memory region.
            //   Since this involves a C (or FFI) call *and* is so far out of “typical” use
            //   of the user data functionality, we consider this a misuse of an unsafe API.
            unsafe {
                let ptr = $ffi_get_user_data(self.to_raw_none(), &key.ffi);
                let ptr: *mut T = std::ptr::NonNull::new(ptr)?.cast().as_ptr();
                let rc = std::mem::ManuallyDrop::new(std::rc::Rc::from_raw(ptr));
                Some(std::rc::Rc::clone(&rc))
            }
        }

        /// Unattach from `self` the user data associated with `key`, if any.
        /// If there is no other `Rc` strong reference, the data is destroyed.
        pub fn remove_user_data<T: 'static>(&self, key: &'static crate::UserDataKey<T>) {
            let result = unsafe {
                $ffi_set_user_data(self.to_raw_none(), &key.ffi, std::ptr::null_mut(), None)
            };
            Status::from(result).ensure_valid()
        }
    };
}
<commit_msg>Add get_user_data_ptr<commit_after>use std::marker::PhantomData;

use ffi::cairo_user_data_key_t;

/// A key for indexing user data in various cairo types.
///
/// Some types like [`Surface`] have `get_user_data`, `set_user_data`, and `remove_user_data`
/// methods that take `&'static UserDataKey`, where the address of that reference is significant.
///
/// To reliably have a stable address, the expected usage is to define a `static` item:
///
/// ```
/// use cairo::UserDataKey;
/// static FOO: UserDataKey<String> = UserDataKey::new();
///
/// # fn foo(surface: &cairo::Surface) {
/// surface.get_user_data(&FOO)
/// # ; }
pub struct UserDataKey<T> {
    pub(crate) ffi: cairo_user_data_key_t,
    marker: PhantomData<*const T>,
}

unsafe impl<T> Sync for UserDataKey<T> {}

impl<T> UserDataKey<T> {
    pub const fn new() -> Self {
        UserDataKey {
            ffi: cairo_user_data_key_t { unused: 0 },
            marker: PhantomData,
        }
    }
}

// In a safe API for user data we can’t make `get_user_data`
// transfer full ownership of the value to the caller (e.g. by returning `Box<T>`)
// because `self` still has a pointer to that value
// and `get_user_data` could be called again with the same key.
//
// We also can’t return a `&T` reference that borrows from `self`
// because the value could be removed with `remove_user_data` or replaced with `set_user_data`
// while the borrow still needs to be valid.
// (Borrowing with `&mut self` would not help as `Self` can be itself reference-counted.)
//
// Therefore the value must be reference-counted.
//
// We use `Rc` over `Arc` because the types implementing these methods are `!Send` and `!Sync`.
// See <https://github.com/gtk-rs/cairo/issues/256>

macro_rules! user_data_methods {
    ($ffi_get_user_data: path, $ffi_set_user_data: path,) => {
        /// Attach user data to `self` for the given `key`.
        pub fn set_user_data<T: 'static>(&self, key: &'static crate::UserDataKey<T>,
                                         value: std::rc::Rc<T>)
        {
            unsafe extern "C" fn destructor<T>(ptr: *mut libc::c_void) {
                let ptr: *const T = ptr as _;
                drop(std::rc::Rc::from_raw(ptr))
            }
            // Safety:
            //
            // The destructor’s cast and `from_raw` are symetric
            // with the `into_raw` and cast below.
            // They both transfer ownership of one strong reference:
            // neither of them touches the reference count.
            let ptr: *const T = std::rc::Rc::into_raw(value);
            let ptr = ptr as *mut T as *mut libc::c_void;
            let result = unsafe {
                $ffi_set_user_data(self.to_raw_none(), &key.ffi, ptr, Some(destructor::<T>))
            };
            Status::from(result).ensure_valid()
        }

        /// Return the user data previously attached to `self` with the given `key`, if any.
        pub fn get_user_data<T: 'static>(&self, key: &'static crate::UserDataKey<T>)
                                         -> Option<std::rc::Rc<T>>
        {
            let ptr = self.get_user_data_ptr(key)?.as_ptr();

            // Safety:
            //
            // `Rc::from_raw` would normally take ownership of a strong reference for this pointer.
            // But `self` still has a copy of that pointer and `get_user_data` can be called again
            // with the same key.
            // We use `ManuallyDrop` to avoid running the destructor of that first `Rc`,
            // and return a cloned one (which increments the reference count).
            unsafe {
                let rc = std::mem::ManuallyDrop::new(std::rc::Rc::from_raw(ptr));
                Some(std::rc::Rc::clone(&rc))
            }
        }

        /// Return the user data previously attached to `self` with the given `key`, if any,
        /// without incrementing the reference count.
        ///
        /// The pointer is valid when it is returned from this method,
        /// until the cairo object that `self` represents is destroyed
        /// or `remove_user_data` or `set_user_data` is called with the same key.
        pub fn get_user_data_ptr<T: 'static>(&self, key: &'static crate::UserDataKey<T>)
                                             -> Option<std::ptr::NonNull<T>>
        {
            // Safety:
            //
            // If `ffi_get_user_data` returns a non-null pointer,
            // there was a previous call to `ffi_set_user_data` with a key with the same address.
            // Either:
            //
            // * This was a call to a Rust `Self::set_user_data` method.
            //   Because that method takes a `&'static` reference,
            //   the key used then must live at that address until the end of the process.
            //   Because `UserDataKey<T>` has a non-zero size regardless of `T`,
            //   no other `UserDataKey<U>` value can have the same address.
            //   Therefore the `T` type was the same then at it is now and `cast` is type-safe.
            //
            // * Or, it is technically possible that the `set` call was to the C function directly,
            //   with a `cairo_user_data_key_t` in heap-allocated memory that was then freed,
            //   then `Box::new(UserDataKey::new()).leak()` was used to create a `&'static`
            //   that happens to have the same address because the allocator for `Box`
            //   reused that memory region.
            //   Since this involves a C (or FFI) call *and* is so far out of “typical” use
            //   of the user data functionality, we consider this a misuse of an unsafe API.
            unsafe {
                let ptr = $ffi_get_user_data(self.to_raw_none(), &key.ffi);
                Some(std::ptr::NonNull::new(ptr)?.cast())
            }
        }

        /// Unattach from `self` the user data associated with `key`, if any.
        /// If there is no other `Rc` strong reference, the data is destroyed.
        pub fn remove_user_data<T: 'static>(&self, key: &'static crate::UserDataKey<T>) {
            let result = unsafe {
                $ffi_set_user_data(self.to_raw_none(), &key.ffi, std::ptr::null_mut(), None)
            };
            Status::from(result).ensure_valid()
        }
    };
}
<|endoftext|>


<commit_before>macro_rules! id_gen {
    ($func_name:ident, $id_name:ident, $ids_name:ident) => {
        static $id_name: std::sync::atomic::AtomicUsize = std::sync::atomic::AtomicUsize::new(0);
        lazy_static::lazy_static! {
            static ref $ids_name: std::sync::Mutex<std::collections::HashSet<usize>> =
                std::sync::Mutex::new(std::collections::HashSet::new());
        }

        fn $func_name() -> usize {
            let mut ids = $ids_name.lock().unwrap();
            if ids.len() == usize::MAX {
                panic!("Out of ids");
            }

            let id = loop {
                let new_id = $id_name.fetch_update(
                    std::sync::atomic::Ordering::SeqCst,
                    std::sync::atomic::Ordering::SeqCst,
                    |mut id| {
                        while ids.iter().any(|k| *k == id) {
                            id += 1;
                        }
                        Some(id)
                    },
                );
                if let Ok(id) = new_id {
                    break id;
                }
            };

            ids.insert(id);
            id
        }
    };
}

pub(crate) use id_gen;
<commit_msg>utils: correctly increment ids on first call<commit_after>macro_rules! id_gen {
    ($func_name:ident, $id_name:ident, $ids_name:ident) => {
        static $id_name: std::sync::atomic::AtomicUsize = std::sync::atomic::AtomicUsize::new(0);
        lazy_static::lazy_static! {
            static ref $ids_name: std::sync::Mutex<std::collections::HashSet<usize>> =
                std::sync::Mutex::new(std::collections::HashSet::new());
        }

        fn $func_name() -> usize {
            let mut ids = $ids_name.lock().unwrap();
            if ids.len() == usize::MAX {
                panic!("Out of ids");
            }

            let id = loop {
                let new_id = $id_name.fetch_update(
                    std::sync::atomic::Ordering::SeqCst,
                    std::sync::atomic::Ordering::SeqCst,
                    |mut id| {
                        while ids.iter().any(|k| *k == id) {
                            id += 1;
                        }
                        id += 1;
                        Some(id)
                    },
                );
                if let Ok(id) = new_id {
                    break id;
                }
            };

            ids.insert(id);
            id
        }
    };
}

pub(crate) use id_gen;
<|endoftext|>


<commit_before>// Implements http://rosettacode.org/wiki/Wireworld

use std::mem;
use std::time::duration::Duration;
use std::old_io::timer::sleep;

// Use VT100 cursor control sequences to animate in-place
const ANIMATE: bool = true;

#[derive(Copy, Clone)]
enum Cell {
    Empty(char),
    Head,
    Tail,
    Conductor,
}
impl Cell {
    fn from_char(c: char) -> Cell {
        match c {
            '.' => Cell::Conductor,
            'H' => Cell::Head,
            't' => Cell::Tail,
            c => Cell::Empty(c),
        }
    }
    fn to_char(&self) -> char {
        match *self {
            Cell::Conductor => '.',
            Cell::Head => 'H',
            Cell::Tail => 't',
            Cell::Empty(c) => c,
        }
    }
}

fn next_world(input: &[Cell], output: &mut [Cell], w: usize, h: usize) {
    for i in 0..(w*h) {
        match input[i] {
            Cell::Empty(c)  => output[i] = Cell::Empty(c),
            Cell::Tail      => output[i] = Cell::Conductor,
            Cell::Head      => output[i] = Cell::Tail,
            Cell::Conductor => {
                let nc = vec![
                    input.get(i-w-1), input.get(i-w), input.get(i-w+1),
                    input.get(i-1),                   input.get(i+1),
                    input.get(i+w-1), input.get(i+w), input.get(i+w+1)
                ].iter().fold(0, |sum, &o| {
                    if let Some(&Cell::Head) = o { sum + 1 } else { sum }
                });
                output[i] = if nc == 1 || nc == 2 { Cell::Head } else { Cell::Conductor };
            }
        }
    }
}

#[cfg(not(test))]
fn main() {
    let (w, h) = (14usize, 7usize);
    let mut world: Vec<Cell> = "
+-----------+
|tH.........|
|.   .      |
|   ...     |
|.   .      |
|Ht.. ......|
+-----------+
".chars().map(|c| Cell::from_char(c)).collect();
    let mut next: Vec<Cell> = world.clone();

    loop {
        for i in 0..(w*h) {
            print!("{}", world[i].to_char());
        }
        next_world(&world, &mut next, 14, 7);
        mem::swap(&mut world, &mut next);

        if ANIMATE {
            print!("\x1b[{}A", 7);
            print!("\x1b[{}D", 14);
            sleep(Duration::milliseconds(100));
        }
    }
}

#[test]
fn test() {
    let (w, h) = (14usize, 7usize);
    let mut world: Vec<Cell> = "
+-----------+
|tH.........|
|.   .      |
|   ...     |
|.   .      |
|Ht.. ......|
+-----------+
".chars().map(|c| Cell::from_char(c)).collect();
    let mut next: Vec<Cell> = world.clone();

    for _ in 0..10 {
        next_world(&world, &mut next, 14, 7);
        mem::swap(&mut world, &mut next);
    }

    let result: String = world.iter().map(|c| c.to_char()).collect();
    let correct = "
+-----------+
|.tH.tH.tH.t|
|H   t      |
|   HHH     |
|H   .      |
|t.tH ......|
+-----------+
";
    assert_eq!(result, correct);
}
<commit_msg>Rustup Wireworld implementation<commit_after>#![feature(std_misc, thread_sleep)]

// Implements http://rosettacode.org/wiki/Wireworld

use std::mem;
use std::time::duration::Duration;
use std::thread::sleep;

// Use VT100 cursor control sequences to animate in-place
const ANIMATE: bool = true;

#[derive(Copy, Clone)]
enum Cell {
    Empty(char),
    Head,
    Tail,
    Conductor,
}
impl Cell {
    fn from_char(c: char) -> Cell {
        match c {
            '.' => Cell::Conductor,
            'H' => Cell::Head,
            't' => Cell::Tail,
            c => Cell::Empty(c),
        }
    }
    fn to_char(&self) -> char {
        match *self {
            Cell::Conductor => '.',
            Cell::Head => 'H',
            Cell::Tail => 't',
            Cell::Empty(c) => c,
        }
    }
}

fn next_world(input: &[Cell], output: &mut [Cell], w: usize, h: usize) {
    for i in 0..(w*h) {
        match input[i] {
            Cell::Empty(c)  => output[i] = Cell::Empty(c),
            Cell::Tail      => output[i] = Cell::Conductor,
            Cell::Head      => output[i] = Cell::Tail,
            Cell::Conductor => {
                let nc = vec![
                    input.get(i-w-1), input.get(i-w), input.get(i-w+1),
                    input.get(i-1),                   input.get(i+1),
                    input.get(i+w-1), input.get(i+w), input.get(i+w+1)
                ].iter().fold(0, |sum, &o| {
                    if let Some(&Cell::Head) = o { sum + 1 } else { sum }
                });
                output[i] = if nc == 1 || nc == 2 { Cell::Head } else { Cell::Conductor };
            }
        }
    }
}

#[cfg(not(test))]
fn main() {
    let (w, h) = (14usize, 7usize);
    let mut world: Vec<Cell> = "
+-----------+
|tH.........|
|.   .      |
|   ...     |
|.   .      |
|Ht.. ......|
+-----------+
".chars().map(|c| Cell::from_char(c)).collect();
    let mut next: Vec<Cell> = world.clone();

    loop {
        for i in 0..(w*h) {
            print!("{}", world[i].to_char());
        }
        print!("\n");
        next_world(&world, &mut next, 14, 7);
        mem::swap(&mut world, &mut next);

        if ANIMATE {
            print!("\x1b[{}A", 8);
            print!("\x1b[{}D", 14);
            sleep(Duration::milliseconds(100));
        }
    }
}

#[test]
fn test() {
    let (w, h) = (14usize, 7usize);
    let mut world: Vec<Cell> = "
+-----------+
|tH.........|
|.   .      |
|   ...     |
|.   .      |
|Ht.. ......|
+-----------+
".chars().map(|c| Cell::from_char(c)).collect();
    let mut next: Vec<Cell> = world.clone();

    for _ in 0..10 {
        next_world(&world, &mut next, 14, 7);
        mem::swap(&mut world, &mut next);
    }

    let result: String = world.iter().map(|c| c.to_char()).collect();
    let correct = "
+-----------+
|.tH.tH.tH.t|
|H   t      |
|   HHH     |
|H   .      |
|t.tH ......|
+-----------+
";
    assert_eq!(result, correct);
}
<|endoftext|>


<commit_before>// Copyright 2013-2014 The CGMath Developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Points are fixed positions in affine space with no length or direction. This
//! disinguishes them from vectors, which have a length and direction, but do
//! not have a fixed position.

use std::fmt;
use std::mem;
use std::ops::*;

use approx::ApproxEq;
use array::{Array1, FixedArray};
use num::{BaseNum, BaseFloat, one, zero};
use vector::*;

/// A point in 2-dimensional space.
#[derive(PartialEq, Copy, Clone, Hash, RustcEncodable, RustcDecodable)]
pub struct Point2<S> { pub x: S, pub y: S }

/// A point in 3-dimensional space.
#[derive(PartialEq, Copy, Clone, Hash, RustcEncodable, RustcDecodable)]
pub struct Point3<S> { pub x: S, pub y: S, pub z: S }

impl<S: BaseNum> Point2<S> {
    #[inline]
    pub fn new(x: S, y: S) -> Point2<S> {
        Point2 { x: x, y: y }
    }
}

impl<S: BaseNum> Point3<S> {
    #[inline]
    pub fn new(x: S, y: S, z: S) -> Point3<S> {
        Point3 { x: x, y: y, z: z }
    }
}

impl<S: BaseNum> Point3<S> {
    #[inline]
    pub fn from_homogeneous(v: &Vector4<S>) -> Point3<S> {
        let e = v.truncate().mul_s(one::<S>() / v.w);
        Point3::new(e.x, e.y, e.z)  //FIXME
    }

    #[inline]
    pub fn to_homogeneous(&self) -> Vector4<S> {
        Vector4::new(self.x, self.y, self.z, one())
    }
}

/// Specifies the numeric operations for point types.
pub trait Point<S: BaseNum, V: Vector<S>>: Array1<S> + Clone {
    /// Create a point at the origin.
    fn origin() -> Self;

    /// Create a point from a vector.
    fn from_vec(v: &V) -> Self;
    /// Convert a point to a vector.
    fn to_vec(&self) -> V;

    /// Multiply each component by a scalar, returning the new point.
    fn mul_s(&self, s: S) -> Self;
    /// Divide each component by a scalar, returning the new point.
    fn div_s(&self, s: S) -> Self;
    /// Subtract a scalar from each component, returning the new point.
    fn rem_s(&self, s: S) -> Self;

    /// Add a vector to this point, returning the new point.
    fn add_v(&self, v: &V) -> Self;
    /// Subtract another point from this one, returning a new vector.
    fn sub_p(&self, p: &Self) -> V;

    /// Multiply each component by a scalar, in-place.
    fn mul_self_s(&mut self, s: S);
    /// Divide each component by a scalar, in-place.
    fn div_self_s(&mut self, s: S);
    /// Take the remainder of each component by a scalar, in-place.
    fn rem_self_s(&mut self, s: S);

    /// Add a vector to this point, in-place.
    fn add_self_v(&mut self, v: &V);

    /// This is a weird one, but its useful for plane calculations.
    fn dot(&self, v: &V) -> S;

    fn min(&self, p: &Self) -> Self;

    fn max(&self, p: &Self) -> Self;
}

impl<S> FixedArray<[S; 2]> for Point2<S> {
    #[inline]
    fn into_fixed(self) -> [S; 2] {
        match self { Point2 { x, y } => [x, y] }
    }

    #[inline]
    fn as_fixed<'a>(&'a self) -> &'a [S; 2] {
        unsafe { mem::transmute(self) }
    }

    #[inline]
    fn as_mut_fixed<'a>(&'a mut self) -> &'a mut [S; 2] {
        unsafe { mem::transmute(self) }
    }

    #[inline]
    fn from_fixed(_v: [S; 2]) -> Point2<S> {
        // match v { [x, y] => Point2 { x: x, y: y } }
        panic!("Unimplemented, pending a fix for rust-lang/rust#16418");
    }

    #[inline]
    fn from_fixed_ref<'a>(v: &'a [S; 2]) -> &'a Point2<S> {
        unsafe { mem::transmute(v) }
    }

    #[inline]
    fn from_fixed_mut<'a>(v: &'a mut [S; 2]) -> &'a mut Point2<S> {
        unsafe { mem::transmute(v) }
    }
}

impl<S: BaseNum> Index<usize> for Point2<S> {
    type Output = S;
    #[inline]
    fn index<'a>(&'a self, i: &usize) -> &'a S {
        &self.as_fixed()[*i]
    }
}

impl<S: BaseNum> IndexMut<usize> for Point2<S> {
    #[inline]
    fn index_mut<'a>(&'a mut self, i: &usize) -> &'a mut S {
        &mut self.as_mut_fixed()[*i]
    }
}

impl<S: BaseNum> Array1<S> for Point2<S> {
    #[inline]
    fn map<F>(&mut self, mut op: F) -> Point2<S> where F: FnMut(S) -> S {
        self.x = op(self.x);
        self.y = op(self.y);
        *self
    }
}

impl<S: BaseNum> Point<S, Vector2<S>> for Point2<S> {
    #[inline]
    fn origin() -> Point2<S> {
        Point2::new(zero(), zero())
    }

    #[inline]
    fn from_vec(v: &Vector2<S>) -> Point2<S> {
        Point2::new(v.x, v.y)
    }

    #[inline]
    fn to_vec(&self) -> Vector2<S> {
        Vector2::new(self.x,
                     self.y)
    }

    #[inline]
    fn mul_s(&self, s: S) -> Point2<S> {
        Point2::new(self.x * s,
                    self.y * s)
    }

    #[inline]
    fn div_s(&self, s: S) -> Point2<S> {
        Point2::new(self.x / s,
                    self.y / s)
    }

    #[inline]
    fn rem_s(&self, s: S) -> Point2<S> {
        Point2::new(self.x % s,
                    self.y % s)
    }

    #[inline]
    fn add_v(&self, v: &Vector2<S>) -> Point2<S> {
        Point2::new(self.x + v.x,
                    self.y + v.y)
    }

    #[inline]
    fn sub_p(&self, p: &Point2<S>) -> Vector2<S> {
        Vector2::new(self.x - p.x,
                     self.y - p.y)
    }

    #[inline]
    fn mul_self_s(&mut self, s: S) {
        self.x = self.x * s;
        self.y = self.y * s;
    }

    #[inline]
    fn div_self_s(&mut self, s: S) {
        self.x = self.x / s;
        self.y = self.y / s;
    }

    #[inline]
    fn rem_self_s(&mut self, s: S) {
        self.x = self.x % s;
        self.y = self.y % s;
    }

    #[inline]
    fn add_self_v(&mut self, v: &Vector2<S>) {
        self.x = self.x + v.x;
        self.y = self.y + v.y;
    }

    #[inline]
    fn dot(&self, v: &Vector2<S>) -> S {
        self.x * v.x +
        self.y * v.y
    }

    #[inline]
    fn min(&self, p: &Point2<S>) -> Point2<S> {
        Point2::new(self.x.partial_min(p.x),
                    self.y.partial_min(p.y))
    }

    #[inline]
    fn max(&self, p: &Point2<S>) -> Point2<S> {
        Point2::new(self.x.partial_max(p.x),
                    self.y.partial_max(p.y))
    }
}

impl<S: BaseFloat> ApproxEq<S> for Point2<S> {
    #[inline]
    fn approx_eq_eps(&self, other: &Point2<S>, epsilon: &S) -> bool {
        self.x.approx_eq_eps(&other.x, epsilon) &&
        self.y.approx_eq_eps(&other.y, epsilon)
    }
}

impl<S> FixedArray<[S; 3]> for Point3<S> {
    #[inline]
    fn into_fixed(self) -> [S; 3] {
        match self { Point3 { x, y, z } => [x, y, z] }
    }

    #[inline]
    fn as_fixed<'a>(&'a self) -> &'a [S; 3] {
        unsafe { mem::transmute(self) }
    }

    #[inline]
    fn as_mut_fixed<'a>(&'a mut self) -> &'a mut [S; 3] {
        unsafe { mem::transmute(self) }
    }

    #[inline]
    fn from_fixed(_v: [S; 3]) -> Point3<S> {
        // match v { [x, y, z] => Point3 { x: x, y: y, z: z } }
        panic!("Unimplemented, pending a fix for rust-lang/rust#16418")
    }

    #[inline]
    fn from_fixed_ref<'a>(v: &'a [S; 3]) -> &'a Point3<S> {
        unsafe { mem::transmute(v) }
    }

    #[inline]
    fn from_fixed_mut<'a>(v: &'a mut [S; 3]) -> &'a mut Point3<S> {
        unsafe { mem::transmute(v) }
    }
}

impl<S: BaseNum> Index<usize> for Point3<S> {
    type Output = S;

    #[inline]
    fn index<'a>(&'a self, i: &usize) -> &'a S {
        &self.as_fixed()[*i]
    }
}

impl<S: BaseNum> IndexMut<usize> for Point3<S> {
    #[inline]
    fn index_mut<'a>(&'a mut self, i: &usize) -> &'a mut S {
        &mut self.as_mut_fixed()[*i]
    }
}

impl<S: BaseNum> Array1<S> for Point3<S> {
    #[inline]
    fn map<F>(&mut self, mut op: F) -> Point3<S> where F: FnMut(S) -> S {
        self.x = op(self.x);
        self.y = op(self.y);
        self.z = op(self.z);
        *self
    }
}

impl<S: BaseNum> Point<S, Vector3<S>> for Point3<S> {
    #[inline]
    fn origin() -> Point3<S> {
        Point3::new(zero(), zero(), zero())
    }

    #[inline]
    fn from_vec(v: &Vector3<S>) -> Point3<S> {
        Point3::new(v.x, v.y, v.z)
    }

    #[inline]
    fn to_vec(&self) -> Vector3<S> {
        Vector3::new(self.x,
                     self.y,
                     self.z)
    }

    #[inline]
    fn mul_s(&self, s: S) -> Point3<S> {
        Point3::new(self.x * s,
                    self.y * s,
                    self.z * s)
    }

    #[inline]
    fn div_s(&self, s: S) -> Point3<S> {
        Point3::new(self.x / s,
                    self.y / s,
                    self.z / s)
    }

    #[inline]
    fn rem_s(&self, s: S) -> Point3<S> {
        Point3::new(self.x % s,
                    self.y % s,
                    self.z % s)
    }

    #[inline]
    fn add_v(&self, v: &Vector3<S>) -> Point3<S> {
        Point3::new(self.x + v.x,
                    self.y + v.y,
                    self.z + v.z)
    }

    #[inline]
    fn sub_p(&self, p: &Point3<S>) -> Vector3<S> {
        Vector3::new(self.x - p.x,
                     self.y - p.y,
                     self.z - p.z)
    }

    #[inline]
    fn mul_self_s(&mut self, s: S) {
        self.x = self.x * s;
        self.y = self.y * s;
        self.z = self.z * s;
    }

    #[inline]
    fn div_self_s(&mut self, s: S) {
        self.x = self.x / s;
        self.y = self.y / s;
        self.z = self.z / s;
    }

    #[inline]
    fn rem_self_s(&mut self, s: S) {
        self.x = self.x % s;
        self.y = self.y % s;
        self.z = self.z % s;
    }

    #[inline]
    fn add_self_v(&mut self, v: &Vector3<S>) {
        self.x = self.x + v.x;
        self.y = self.y + v.y;
        self.z = self.z + v.z;
    }

    #[inline]
    fn dot(&self, v: &Vector3<S>) -> S {
        self.x * v.x +
        self.y * v.y +
        self.z * v.z
    }

    #[inline]
    fn min(&self, p: &Point3<S>) -> Point3<S> {
        Point3::new(self.x.partial_min(p.x),
                    self.y.partial_min(p.y),
                    self.z.partial_min(p.z))
    }

    #[inline]
    fn max(&self, p: &Point3<S>) -> Point3<S> {
        Point3::new(self.x.partial_max(p.x),
                    self.y.partial_max(p.y),
                    self.z.partial_max(p.z))
    }
}

impl<S: BaseFloat> ApproxEq<S> for Point3<S> {
    #[inline]
    fn approx_eq_eps(&self, other: &Point3<S>, epsilon: &S) -> bool {
        self.x.approx_eq_eps(&other.x, epsilon) &&
        self.y.approx_eq_eps(&other.y, epsilon) &&
        self.z.approx_eq_eps(&other.z, epsilon)
    }
}

impl<S: BaseNum> fmt::Debug for Point2<S> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "[{:?}, {:?}]", self.x, self.y)
    }
}

impl<S: BaseNum> fmt::Debug for Point3<S> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "[{:?}, {:?}, {:?}]", self.x, self.y, self.z)
    }
}
<commit_msg>Points derive Eq.<commit_after>// Copyright 2013-2014 The CGMath Developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Points are fixed positions in affine space with no length or direction. This
//! disinguishes them from vectors, which have a length and direction, but do
//! not have a fixed position.

use std::fmt;
use std::mem;
use std::ops::*;

use approx::ApproxEq;
use array::{Array1, FixedArray};
use num::{BaseNum, BaseFloat, one, zero};
use vector::*;

/// A point in 2-dimensional space.
#[derive(PartialEq, Eq, Copy, Clone, Hash, RustcEncodable, RustcDecodable)]
pub struct Point2<S> { pub x: S, pub y: S }

/// A point in 3-dimensional space.
#[derive(PartialEq, Eq, Copy, Clone, Hash, RustcEncodable, RustcDecodable)]
pub struct Point3<S> { pub x: S, pub y: S, pub z: S }

impl<S: BaseNum> Point2<S> {
    #[inline]
    pub fn new(x: S, y: S) -> Point2<S> {
        Point2 { x: x, y: y }
    }
}

impl<S: BaseNum> Point3<S> {
    #[inline]
    pub fn new(x: S, y: S, z: S) -> Point3<S> {
        Point3 { x: x, y: y, z: z }
    }
}

impl<S: BaseNum> Point3<S> {
    #[inline]
    pub fn from_homogeneous(v: &Vector4<S>) -> Point3<S> {
        let e = v.truncate().mul_s(one::<S>() / v.w);
        Point3::new(e.x, e.y, e.z)  //FIXME
    }

    #[inline]
    pub fn to_homogeneous(&self) -> Vector4<S> {
        Vector4::new(self.x, self.y, self.z, one())
    }
}

/// Specifies the numeric operations for point types.
pub trait Point<S: BaseNum, V: Vector<S>>: Array1<S> + Clone {
    /// Create a point at the origin.
    fn origin() -> Self;

    /// Create a point from a vector.
    fn from_vec(v: &V) -> Self;
    /// Convert a point to a vector.
    fn to_vec(&self) -> V;

    /// Multiply each component by a scalar, returning the new point.
    fn mul_s(&self, s: S) -> Self;
    /// Divide each component by a scalar, returning the new point.
    fn div_s(&self, s: S) -> Self;
    /// Subtract a scalar from each component, returning the new point.
    fn rem_s(&self, s: S) -> Self;

    /// Add a vector to this point, returning the new point.
    fn add_v(&self, v: &V) -> Self;
    /// Subtract another point from this one, returning a new vector.
    fn sub_p(&self, p: &Self) -> V;

    /// Multiply each component by a scalar, in-place.
    fn mul_self_s(&mut self, s: S);
    /// Divide each component by a scalar, in-place.
    fn div_self_s(&mut self, s: S);
    /// Take the remainder of each component by a scalar, in-place.
    fn rem_self_s(&mut self, s: S);

    /// Add a vector to this point, in-place.
    fn add_self_v(&mut self, v: &V);

    /// This is a weird one, but its useful for plane calculations.
    fn dot(&self, v: &V) -> S;

    fn min(&self, p: &Self) -> Self;

    fn max(&self, p: &Self) -> Self;
}

impl<S> FixedArray<[S; 2]> for Point2<S> {
    #[inline]
    fn into_fixed(self) -> [S; 2] {
        match self { Point2 { x, y } => [x, y] }
    }

    #[inline]
    fn as_fixed<'a>(&'a self) -> &'a [S; 2] {
        unsafe { mem::transmute(self) }
    }

    #[inline]
    fn as_mut_fixed<'a>(&'a mut self) -> &'a mut [S; 2] {
        unsafe { mem::transmute(self) }
    }

    #[inline]
    fn from_fixed(_v: [S; 2]) -> Point2<S> {
        // match v { [x, y] => Point2 { x: x, y: y } }
        panic!("Unimplemented, pending a fix for rust-lang/rust#16418");
    }

    #[inline]
    fn from_fixed_ref<'a>(v: &'a [S; 2]) -> &'a Point2<S> {
        unsafe { mem::transmute(v) }
    }

    #[inline]
    fn from_fixed_mut<'a>(v: &'a mut [S; 2]) -> &'a mut Point2<S> {
        unsafe { mem::transmute(v) }
    }
}

impl<S: BaseNum> Index<usize> for Point2<S> {
    type Output = S;
    #[inline]
    fn index<'a>(&'a self, i: &usize) -> &'a S {
        &self.as_fixed()[*i]
    }
}

impl<S: BaseNum> IndexMut<usize> for Point2<S> {
    #[inline]
    fn index_mut<'a>(&'a mut self, i: &usize) -> &'a mut S {
        &mut self.as_mut_fixed()[*i]
    }
}

impl<S: BaseNum> Array1<S> for Point2<S> {
    #[inline]
    fn map<F>(&mut self, mut op: F) -> Point2<S> where F: FnMut(S) -> S {
        self.x = op(self.x);
        self.y = op(self.y);
        *self
    }
}

impl<S: BaseNum> Point<S, Vector2<S>> for Point2<S> {
    #[inline]
    fn origin() -> Point2<S> {
        Point2::new(zero(), zero())
    }

    #[inline]
    fn from_vec(v: &Vector2<S>) -> Point2<S> {
        Point2::new(v.x, v.y)
    }

    #[inline]
    fn to_vec(&self) -> Vector2<S> {
        Vector2::new(self.x,
                     self.y)
    }

    #[inline]
    fn mul_s(&self, s: S) -> Point2<S> {
        Point2::new(self.x * s,
                    self.y * s)
    }

    #[inline]
    fn div_s(&self, s: S) -> Point2<S> {
        Point2::new(self.x / s,
                    self.y / s)
    }

    #[inline]
    fn rem_s(&self, s: S) -> Point2<S> {
        Point2::new(self.x % s,
                    self.y % s)
    }

    #[inline]
    fn add_v(&self, v: &Vector2<S>) -> Point2<S> {
        Point2::new(self.x + v.x,
                    self.y + v.y)
    }

    #[inline]
    fn sub_p(&self, p: &Point2<S>) -> Vector2<S> {
        Vector2::new(self.x - p.x,
                     self.y - p.y)
    }

    #[inline]
    fn mul_self_s(&mut self, s: S) {
        self.x = self.x * s;
        self.y = self.y * s;
    }

    #[inline]
    fn div_self_s(&mut self, s: S) {
        self.x = self.x / s;
        self.y = self.y / s;
    }

    #[inline]
    fn rem_self_s(&mut self, s: S) {
        self.x = self.x % s;
        self.y = self.y % s;
    }

    #[inline]
    fn add_self_v(&mut self, v: &Vector2<S>) {
        self.x = self.x + v.x;
        self.y = self.y + v.y;
    }

    #[inline]
    fn dot(&self, v: &Vector2<S>) -> S {
        self.x * v.x +
        self.y * v.y
    }

    #[inline]
    fn min(&self, p: &Point2<S>) -> Point2<S> {
        Point2::new(self.x.partial_min(p.x),
                    self.y.partial_min(p.y))
    }

    #[inline]
    fn max(&self, p: &Point2<S>) -> Point2<S> {
        Point2::new(self.x.partial_max(p.x),
                    self.y.partial_max(p.y))
    }
}

impl<S: BaseFloat> ApproxEq<S> for Point2<S> {
    #[inline]
    fn approx_eq_eps(&self, other: &Point2<S>, epsilon: &S) -> bool {
        self.x.approx_eq_eps(&other.x, epsilon) &&
        self.y.approx_eq_eps(&other.y, epsilon)
    }
}

impl<S> FixedArray<[S; 3]> for Point3<S> {
    #[inline]
    fn into_fixed(self) -> [S; 3] {
        match self { Point3 { x, y, z } => [x, y, z] }
    }

    #[inline]
    fn as_fixed<'a>(&'a self) -> &'a [S; 3] {
        unsafe { mem::transmute(self) }
    }

    #[inline]
    fn as_mut_fixed<'a>(&'a mut self) -> &'a mut [S; 3] {
        unsafe { mem::transmute(self) }
    }

    #[inline]
    fn from_fixed(_v: [S; 3]) -> Point3<S> {
        // match v { [x, y, z] => Point3 { x: x, y: y, z: z } }
        panic!("Unimplemented, pending a fix for rust-lang/rust#16418")
    }

    #[inline]
    fn from_fixed_ref<'a>(v: &'a [S; 3]) -> &'a Point3<S> {
        unsafe { mem::transmute(v) }
    }

    #[inline]
    fn from_fixed_mut<'a>(v: &'a mut [S; 3]) -> &'a mut Point3<S> {
        unsafe { mem::transmute(v) }
    }
}

impl<S: BaseNum> Index<usize> for Point3<S> {
    type Output = S;

    #[inline]
    fn index<'a>(&'a self, i: &usize) -> &'a S {
        &self.as_fixed()[*i]
    }
}

impl<S: BaseNum> IndexMut<usize> for Point3<S> {
    #[inline]
    fn index_mut<'a>(&'a mut self, i: &usize) -> &'a mut S {
        &mut self.as_mut_fixed()[*i]
    }
}

impl<S: BaseNum> Array1<S> for Point3<S> {
    #[inline]
    fn map<F>(&mut self, mut op: F) -> Point3<S> where F: FnMut(S) -> S {
        self.x = op(self.x);
        self.y = op(self.y);
        self.z = op(self.z);
        *self
    }
}

impl<S: BaseNum> Point<S, Vector3<S>> for Point3<S> {
    #[inline]
    fn origin() -> Point3<S> {
        Point3::new(zero(), zero(), zero())
    }

    #[inline]
    fn from_vec(v: &Vector3<S>) -> Point3<S> {
        Point3::new(v.x, v.y, v.z)
    }

    #[inline]
    fn to_vec(&self) -> Vector3<S> {
        Vector3::new(self.x,
                     self.y,
                     self.z)
    }

    #[inline]
    fn mul_s(&self, s: S) -> Point3<S> {
        Point3::new(self.x * s,
                    self.y * s,
                    self.z * s)
    }

    #[inline]
    fn div_s(&self, s: S) -> Point3<S> {
        Point3::new(self.x / s,
                    self.y / s,
                    self.z / s)
    }

    #[inline]
    fn rem_s(&self, s: S) -> Point3<S> {
        Point3::new(self.x % s,
                    self.y % s,
                    self.z % s)
    }

    #[inline]
    fn add_v(&self, v: &Vector3<S>) -> Point3<S> {
        Point3::new(self.x + v.x,
                    self.y + v.y,
                    self.z + v.z)
    }

    #[inline]
    fn sub_p(&self, p: &Point3<S>) -> Vector3<S> {
        Vector3::new(self.x - p.x,
                     self.y - p.y,
                     self.z - p.z)
    }

    #[inline]
    fn mul_self_s(&mut self, s: S) {
        self.x = self.x * s;
        self.y = self.y * s;
        self.z = self.z * s;
    }

    #[inline]
    fn div_self_s(&mut self, s: S) {
        self.x = self.x / s;
        self.y = self.y / s;
        self.z = self.z / s;
    }

    #[inline]
    fn rem_self_s(&mut self, s: S) {
        self.x = self.x % s;
        self.y = self.y % s;
        self.z = self.z % s;
    }

    #[inline]
    fn add_self_v(&mut self, v: &Vector3<S>) {
        self.x = self.x + v.x;
        self.y = self.y + v.y;
        self.z = self.z + v.z;
    }

    #[inline]
    fn dot(&self, v: &Vector3<S>) -> S {
        self.x * v.x +
        self.y * v.y +
        self.z * v.z
    }

    #[inline]
    fn min(&self, p: &Point3<S>) -> Point3<S> {
        Point3::new(self.x.partial_min(p.x),
                    self.y.partial_min(p.y),
                    self.z.partial_min(p.z))
    }

    #[inline]
    fn max(&self, p: &Point3<S>) -> Point3<S> {
        Point3::new(self.x.partial_max(p.x),
                    self.y.partial_max(p.y),
                    self.z.partial_max(p.z))
    }
}

impl<S: BaseFloat> ApproxEq<S> for Point3<S> {
    #[inline]
    fn approx_eq_eps(&self, other: &Point3<S>, epsilon: &S) -> bool {
        self.x.approx_eq_eps(&other.x, epsilon) &&
        self.y.approx_eq_eps(&other.y, epsilon) &&
        self.z.approx_eq_eps(&other.z, epsilon)
    }
}

impl<S: BaseNum> fmt::Debug for Point2<S> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "[{:?}, {:?}]", self.x, self.y)
    }
}

impl<S: BaseNum> fmt::Debug for Point3<S> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "[{:?}, {:?}, {:?}]", self.x, self.y, self.z)
    }
}
<|endoftext|>


<commit_before>import cast = unsafe::reinterpret_cast;
import comm;
import option::{some, none};
import option = option::t;
import ptr;

export task;
export joinable_task;
export sleep;
export yield;
export task_notification;
export join;
export unsupervise;
export pin;
export unpin;
export set_min_stack;
export spawn;
export spawn_notify;
export spawn_joinable;
export task_result;
export tr_success;
export tr_failure;
export get_task_id;
export spawn2;
export spawn_notify2;
export spawn_joinable2;

native "rust" mod rustrt {
    fn task_sleep(time_in_us: uint);
    fn task_yield();
    fn task_join(t: task_id) -> int;
    fn unsupervise();
    fn pin_task();
    fn unpin_task();
    fn get_task_id() -> task_id;

    type rust_chan;

    fn set_min_stack(stack_size: uint);

    fn new_task() -> task_id;
    fn drop_task(task: *rust_task);
    fn get_task_pointer(id: task_id) -> *rust_task;

    fn migrate_alloc(alloc: *u8, target: task_id);
    fn start_task(id: task_id, closure: *u8);
}

type rust_task =
    {id: task,
     mutable notify_enabled: u32,
     mutable notify_chan: comm::chan<task_notification>,
     mutable stack_ptr: *u8};

resource rust_task_ptr(task: *rust_task) { rustrt::drop_task(task); }

type task = int;
type task_id = task;
type joinable_task = (task_id, comm::port<task_notification>);

fn get_task_id() -> task_id { rustrt::get_task_id() }

/**
 * Hints the scheduler to yield this task for a specified ammount of time.
 *
 * arg: time_in_us maximum number of microseconds to yield control for
 */
fn sleep(time_in_us: uint) { ret rustrt::task_sleep(time_in_us); }

fn yield() { ret rustrt::task_yield(); }

tag task_result { tr_success; tr_failure; }

tag task_notification { exit(task, task_result); }

fn join(task_port: (task_id, comm::port<task_notification>)) -> task_result {
    let (id, port) = task_port;
    alt comm::recv::<task_notification>(port) {
      exit(_id, res) {
        if _id == id {
            ret res
        } else { fail #fmt["join received id %d, expected %d", _id, id] }
      }
    }
}

fn join_id(t: task_id) -> task_result {
    alt rustrt::task_join(t) { 0 { tr_success } _ { tr_failure } }
}

fn unsupervise() { ret rustrt::unsupervise(); }

fn pin() { rustrt::pin_task(); }

fn unpin() { rustrt::unpin_task(); }

fn set_min_stack(stack_size: uint) { rustrt::set_min_stack(stack_size); }

fn spawn2<~T>(-data: T, f: fn#(T)) -> task {
    spawn_inner2(data, f, none)
}

fn spawn_notify2<~T>(-data: T, f: fn#(T),
                         notify: comm::chan<task_notification>) -> task {
    spawn_inner2(data, f, some(notify))
}

fn spawn_joinable2<~T>(-data: T, f: fn#(T)) -> joinable_task {
    let p = comm::port::<task_notification>();
    let id = spawn_notify2(data, f, comm::chan::<task_notification>(p));
    ret (id, p);
}

// FIXME: To transition from the unsafe spawn that spawns a shared closure to
// the safe spawn that spawns a bare function we're going to write
// barefunc-spawn on top of unsafe-spawn.  Sadly, bind does not work reliably
// enough to suite our needs (#1034, probably others yet to be discovered), so
// we're going to copy the bootstrap data into a unique pointer, cast it to an
// unsafe pointer then wrap up the bare function and the unsafe pointer in a
// shared closure to spawn.
//
// After the transition this should all be rewritten.

fn spawn_inner2<~T>(-data: T, f: fn#(T),
                    notify: option<comm::chan<task_notification>>)
    -> task_id {

    fn wrapper<~T>(-data: *u8, f: fn#(T)) {
        let data: ~T = unsafe::reinterpret_cast(data);
        f(*data);
    }

    let data = ~data;
    let dataptr: *u8 = unsafe::reinterpret_cast(data);
    unsafe::leak(data);
    let wrapped = bind wrapper(dataptr, f);
    ret spawn_inner(wrapped, notify);
}

fn spawn(-thunk: fn()) -> task { spawn_inner(thunk, none) }

fn spawn_notify(-thunk: fn(), notify: comm::chan<task_notification>) -> task {
    spawn_inner(thunk, some(notify))
}

fn spawn_joinable(-thunk: fn()) -> joinable_task {
    let p = comm::port::<task_notification>();
    let id = spawn_notify(thunk, comm::chan::<task_notification>(p));
    ret (id, p);
}

// FIXME: make this a fn~ once those are supported.
fn spawn_inner(-thunk: fn(), notify: option<comm::chan<task_notification>>) ->
   task_id unsafe {
    let id = rustrt::new_task();

    let raw_thunk: {code: u32, env: u32} = cast(thunk);

    // set up the task pointer
    let task_ptr <- rust_task_ptr(rustrt::get_task_pointer(id));

    assert (ptr::null() != (**task_ptr).stack_ptr);

    // copy the thunk from our stack to the new stack
    let sp: uint = cast((**task_ptr).stack_ptr);
    let ptrsize = sys::size_of::<*u8>();
    let thunkfn: *mutable uint = cast(sp - ptrsize * 2u);
    let thunkenv: *mutable uint = cast(sp - ptrsize);
    *thunkfn = cast(raw_thunk.code);;
    *thunkenv = cast(raw_thunk.env);;
    // align the stack to 16 bytes
    (**task_ptr).stack_ptr = cast(sp - ptrsize * 4u);

    // set up notifications if they are enabled.
    alt notify {
      some(c) {
        (**task_ptr).notify_enabled = 1u32;;
        (**task_ptr).notify_chan = c;
      }
      none { }
    }

    // give the thunk environment's allocation to the new task
    rustrt::migrate_alloc(cast(raw_thunk.env), id);
    rustrt::start_task(id, cast(thunkfn));
    // don't cleanup the thunk in this task
    unsafe::leak(thunk);
    ret id;
}

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
<commit_msg>Stop exporting unsafe spawn functions<commit_after>import cast = unsafe::reinterpret_cast;
import comm;
import option::{some, none};
import option = option::t;
import ptr;

export task;
export joinable_task;
export sleep;
export yield;
export task_notification;
export join;
export unsupervise;
export pin;
export unpin;
export set_min_stack;
export task_result;
export tr_success;
export tr_failure;
export get_task_id;
export spawn2;
export spawn_notify2;
export spawn_joinable2;

native "rust" mod rustrt {
    fn task_sleep(time_in_us: uint);
    fn task_yield();
    fn task_join(t: task_id) -> int;
    fn unsupervise();
    fn pin_task();
    fn unpin_task();
    fn get_task_id() -> task_id;

    type rust_chan;

    fn set_min_stack(stack_size: uint);

    fn new_task() -> task_id;
    fn drop_task(task: *rust_task);
    fn get_task_pointer(id: task_id) -> *rust_task;

    fn migrate_alloc(alloc: *u8, target: task_id);
    fn start_task(id: task_id, closure: *u8);
}

type rust_task =
    {id: task,
     mutable notify_enabled: u32,
     mutable notify_chan: comm::chan<task_notification>,
     mutable stack_ptr: *u8};

resource rust_task_ptr(task: *rust_task) { rustrt::drop_task(task); }

type task = int;
type task_id = task;
type joinable_task = (task_id, comm::port<task_notification>);

fn get_task_id() -> task_id { rustrt::get_task_id() }

/**
 * Hints the scheduler to yield this task for a specified ammount of time.
 *
 * arg: time_in_us maximum number of microseconds to yield control for
 */
fn sleep(time_in_us: uint) { ret rustrt::task_sleep(time_in_us); }

fn yield() { ret rustrt::task_yield(); }

tag task_result { tr_success; tr_failure; }

tag task_notification { exit(task, task_result); }

fn join(task_port: (task_id, comm::port<task_notification>)) -> task_result {
    let (id, port) = task_port;
    alt comm::recv::<task_notification>(port) {
      exit(_id, res) {
        if _id == id {
            ret res
        } else { fail #fmt["join received id %d, expected %d", _id, id] }
      }
    }
}

fn join_id(t: task_id) -> task_result {
    alt rustrt::task_join(t) { 0 { tr_success } _ { tr_failure } }
}

fn unsupervise() { ret rustrt::unsupervise(); }

fn pin() { rustrt::pin_task(); }

fn unpin() { rustrt::unpin_task(); }

fn set_min_stack(stack_size: uint) { rustrt::set_min_stack(stack_size); }

fn spawn2<~T>(-data: T, f: fn#(T)) -> task {
    spawn_inner2(data, f, none)
}

fn spawn_notify2<~T>(-data: T, f: fn#(T),
                         notify: comm::chan<task_notification>) -> task {
    spawn_inner2(data, f, some(notify))
}

fn spawn_joinable2<~T>(-data: T, f: fn#(T)) -> joinable_task {
    let p = comm::port::<task_notification>();
    let id = spawn_notify2(data, f, comm::chan::<task_notification>(p));
    ret (id, p);
}

// FIXME: To transition from the unsafe spawn that spawns a shared closure to
// the safe spawn that spawns a bare function we're going to write
// barefunc-spawn on top of unsafe-spawn.  Sadly, bind does not work reliably
// enough to suite our needs (#1034, probably others yet to be discovered), so
// we're going to copy the bootstrap data into a unique pointer, cast it to an
// unsafe pointer then wrap up the bare function and the unsafe pointer in a
// shared closure to spawn.
//
// After the transition this should all be rewritten.

fn spawn_inner2<~T>(-data: T, f: fn#(T),
                    notify: option<comm::chan<task_notification>>)
    -> task_id {

    fn wrapper<~T>(-data: *u8, f: fn#(T)) {
        let data: ~T = unsafe::reinterpret_cast(data);
        f(*data);
    }

    let data = ~data;
    let dataptr: *u8 = unsafe::reinterpret_cast(data);
    unsafe::leak(data);
    let wrapped = bind wrapper(dataptr, f);
    ret spawn_inner(wrapped, notify);
}

fn spawn(-thunk: fn()) -> task { spawn_inner(thunk, none) }

fn spawn_notify(-thunk: fn(), notify: comm::chan<task_notification>) -> task {
    spawn_inner(thunk, some(notify))
}

fn spawn_joinable(-thunk: fn()) -> joinable_task {
    let p = comm::port::<task_notification>();
    let id = spawn_notify(thunk, comm::chan::<task_notification>(p));
    ret (id, p);
}

// FIXME: make this a fn~ once those are supported.
fn spawn_inner(-thunk: fn(), notify: option<comm::chan<task_notification>>) ->
   task_id unsafe {
    let id = rustrt::new_task();

    let raw_thunk: {code: u32, env: u32} = cast(thunk);

    // set up the task pointer
    let task_ptr <- rust_task_ptr(rustrt::get_task_pointer(id));

    assert (ptr::null() != (**task_ptr).stack_ptr);

    // copy the thunk from our stack to the new stack
    let sp: uint = cast((**task_ptr).stack_ptr);
    let ptrsize = sys::size_of::<*u8>();
    let thunkfn: *mutable uint = cast(sp - ptrsize * 2u);
    let thunkenv: *mutable uint = cast(sp - ptrsize);
    *thunkfn = cast(raw_thunk.code);;
    *thunkenv = cast(raw_thunk.env);;
    // align the stack to 16 bytes
    (**task_ptr).stack_ptr = cast(sp - ptrsize * 4u);

    // set up notifications if they are enabled.
    alt notify {
      some(c) {
        (**task_ptr).notify_enabled = 1u32;;
        (**task_ptr).notify_chan = c;
      }
      none { }
    }

    // give the thunk environment's allocation to the new task
    rustrt::migrate_alloc(cast(raw_thunk.env), id);
    rustrt::start_task(id, cast(thunkfn));
    // don't cleanup the thunk in this task
    unsafe::leak(thunk);
    ret id;
}

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
<|endoftext|>


<commit_before>
pure fn id<@T>(x: T) -> T { x }

fn unreachable() -> ! {
    fail "Internal error: entered unreachable code";
}

/* FIXME (issue #141):  See test/run-pass/constrained-type.rs.  Uncomment
 * the constraint once fixed. */
type rational = {num: int, den: int}; // : int::positive(*.den);

// : int::positive(*.den);
pure fn rational_leq(x: rational, y: rational) -> bool {
    // NB: Uses the fact that rationals have positive denominators WLOG:

    x.num * y.den <= y.num * x.den
}

pure fn orb(a: bool, b: bool) -> bool { a || b }
// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
<commit_msg>stdlib: Add a void type<commit_after>
pure fn id<@T>(x: T) -> T { x }

fn unreachable() -> ! {
    fail "Internal error: entered unreachable code";
}

/* FIXME (issue #141):  See test/run-pass/constrained-type.rs.  Uncomment
 * the constraint once fixed. */
type rational = {num: int, den: int}; // : int::positive(*.den);

// : int::positive(*.den);
pure fn rational_leq(x: rational, y: rational) -> bool {
    // NB: Uses the fact that rationals have positive denominators WLOG:

    x.num * y.den <= y.num * x.den
}

pure fn orb(a: bool, b: bool) -> bool { a || b }

tag void {
    void(@void);
}

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
<|endoftext|>


<commit_before>use std::str::FromStr;
use ::token::parse_expressions;
use ::token::{Expression, Token};

#[derive(PartialEq,Debug)]
pub struct Regex {
    pub pattern: String
}

impl Regex {
    pub fn from(pattern: &str) -> Regex {
        Regex {
            pattern: pattern.to_owned()
        }
    }

    pub fn is_match(&self, text: &str) -> bool {
        let expressions = parse_expressions(&self.pattern).unwrap();

        let mut regex_i = 0;
        let mut text_i = 0;

        while regex_i < expressions.len() {
            let mut options = Self::ways_to_grab_text(&text[text_i..], &expressions[regex_i]);

            if options.len() == 0 {
                text_i += 1;

                if text_i >= text.len() {
                    return false;
                }

                continue;
            }

            let chosen_option = options.pop().unwrap();

            text_i += chosen_option;
            regex_i += 1;
        }

        true
    }

    fn ways_to_grab_text(text: &str, expr: &Expression) -> Vec<usize> {
        let mut valid_offsets = Vec::<usize>::new();

        match expr {
            &Expression::Token(ref token, ref multiplicity) => {
                if multiplicity.minimum == None ||
                    multiplicity.minimum == Some(0) {
                    valid_offsets.push(0); //it is an option to do nothing with this expr
                }

                match token {
                    &Token::Literal(value) => {
                        let mut offset = 0;

                        for c in text.chars() {
                            if value != c {
                                break;
                            }

                            offset += 1;

                            match multiplicity.minimum {
                                Some(min) => {
                                    if min < offset { continue; }
                                },
                                None => ()
                            }

                            match multiplicity.maximum {
                                Some(max) => {
                                    if max > offset { continue; }
                                },
                                None => ()
                            }

                            valid_offsets.push(offset);
                        }
                    },
                    _ => ()
                }
            },
            _ => ()
        }

        valid_offsets
    }

    pub fn first(&self, text: &str) -> Option<(usize, usize)> {
        if text.contains(&self.pattern) {
            Some((1, 2))
        } else {
            None
        }
    }
}

#[cfg(test)]
mod regex_spec {
    use super::Regex;

    #[test]
    fn matches_simple_examples() {
        assert!(Regex::from("ab?c").is_match("zac"));
        assert!(Regex::from("ab?c").is_match("abbbc"));
    }

    #[test]
    fn does_not_match() {
        assert!(!Regex::from("ab?c").is_match("z"));
    }
}
<commit_msg>add tests for backtracking<commit_after>use std::str::FromStr;
use ::token::parse_expressions;
use ::token::{Expression, Token};

#[derive(PartialEq,Debug)]
pub struct Regex {
    pub pattern: String
}

impl Regex {
    pub fn from(pattern: &str) -> Regex {
        Regex {
            pattern: pattern.to_owned()
        }
    }

    pub fn is_match(&self, text: &str) -> bool {
        let expressions = parse_expressions(&self.pattern).unwrap();

        let mut regex_i = 0;
        let mut text_i = 0;

        while regex_i < expressions.len() {
            let mut options = Self::ways_to_grab_text(&text[text_i..], &expressions[regex_i]);

            if options.len() == 0 {
                text_i += 1;

                if text_i >= text.len() {
                    return false;
                }

                continue;
            }

            let chosen_option = options.pop().unwrap();

            text_i += chosen_option;
            regex_i += 1;
        }

        true
    }

    fn ways_to_grab_text(text: &str, expr: &Expression) -> Vec<usize> {
        let mut valid_offsets = Vec::<usize>::new();

        match expr {
            &Expression::Token(ref token, ref multiplicity) => {
                if multiplicity.minimum == None ||
                    multiplicity.minimum == Some(0) {
                    valid_offsets.push(0); //it is an option to do nothing with this expr
                }

                match token {
                    &Token::Literal(value) => {
                        let mut offset = 0;

                        for c in text.chars() {
                            if value != c {
                                break;
                            }

                            offset += 1;

                            match multiplicity.minimum {
                                Some(min) => {
                                    if min < offset { continue; }
                                },
                                None => ()
                            }

                            match multiplicity.maximum {
                                Some(max) => {
                                    if max > offset { continue; }
                                },
                                None => ()
                            }

                            valid_offsets.push(offset);
                        }
                    },
                    _ => ()
                }
            },
            _ => ()
        }

        valid_offsets
    }

    pub fn first(&self, text: &str) -> Option<(usize, usize)> {
        if text.contains(&self.pattern) {
            Some((1, 2))
        } else {
            None
        }
    }
}

#[cfg(test)]
mod regex_spec {
    use super::Regex;

    #[test]
    fn matches_simple_examples() {
        assert!(Regex::from("ab?c").is_match("zac"));
        assert!(Regex::from("ab?c").is_match("abbbc"));
        assert!(Regex::from("a?").is_match(""));
        assert!(Regex::from("a+").is_match("a"));
    }

    #[test]
    fn does_not_match() {
        assert!(!Regex::from("ab?c").is_match("z"));
        assert!(!Regex::from("a+").is_match(""));
    }

    #[test]
    fn backtracks_to_find_match() {
        assert!(Regex::from("[bc]?c").is_match("cb"));
    }
}
<|endoftext|>


<commit_before>use std::path::Path;

use cache::{Cache, Get};
use resource::{Load, Reload};

/// The scene type.
///
/// This type gathers all the required objects a scene needs to correctly handle and render all
/// visual effects.
pub struct Scene<'a> {
  /// Cache.
  cache: Cache<'a>
}

impl<'a> Scene<'a> {
  pub fn new<P>(root: P) -> Self where P: AsRef<Path>{
    Scene {
      cache: Cache::new(root),
    }
  }

  pub fn get_id<T>(&mut self, name: &str, args: <T as Load>::Args) -> Option<<Cache<'a> as Get<T>>::Id> where Cache<'a>: Get<T>, T: Reload {
    self.cache.get_id(name, args)
  }

  pub fn get_by_id<T>(&mut self, id: &<Cache<'a> as Get<T>>::Id) -> Option<&T> where Cache<'a>: Get<T>, T: Reload {
    self.cache.get_by_id(id)
  }

  pub fn get<T>(&mut self, name: &str, args: <T as Load>::Args) -> Option<&T> where Cache<'a>: Get<T>, T: Reload {
    self.cache.get(name, args)
  }
}

#[macro_export]
macro_rules! get_id {
  ($scene:ident, $name:expr) => {
    $scene.get_id($name, ())
  };

  ($scene:ident, $name:expr, $($arg:expr),*) => {
    $scene.get_id($name, ($($arg),*))
  }
}
<commit_msg>Added get!.<commit_after>use std::path::Path;

use cache::{Cache, Get};
use resource::{Load, Reload};

/// The scene type.
///
/// This type gathers all the required objects a scene needs to correctly handle and render all
/// visual effects.
pub struct Scene<'a> {
  /// Cache.
  cache: Cache<'a>
}

impl<'a> Scene<'a> {
  pub fn new<P>(root: P) -> Self where P: AsRef<Path>{
    Scene {
      cache: Cache::new(root),
    }
  }

  pub fn get_id<T>(&mut self, name: &str, args: <T as Load>::Args) -> Option<<Cache<'a> as Get<T>>::Id> where Cache<'a>: Get<T>, T: Reload {
    self.cache.get_id(name, args)
  }

  pub fn get_by_id<T>(&mut self, id: &<Cache<'a> as Get<T>>::Id) -> Option<&T> where Cache<'a>: Get<T>, T: Reload {
    self.cache.get_by_id(id)
  }

  pub fn get<T>(&mut self, name: &str, args: <T as Load>::Args) -> Option<&T> where Cache<'a>: Get<T>, T: Reload {
    self.cache.get(name, args)
  }
}

#[macro_export]
macro_rules! get_id {
  ($scene:ident, $name:expr) => {
    $scene.get_id($name, ())
  };

  ($scene:ident, $name:expr, $($arg:expr),*) => {
    $scene.get_id($name, ($($arg),*))
  }
}

#[macro_export]
macro_rules! get {
  ($scene:ident, $name:expr) => {
    $scene.get($name, ())
  };

  ($scene:ident, $name:expr, $($arg:expr),*) => {
    $scene.get($name, ($($arg),*))
  }
}
<|endoftext|>


<commit_before>use std::error;
use std::fmt;
use std::path::Path;

use geometry::{Intersectable, Transformable};
use color::Color;
use ray::Ray;
use intersection::Intersection;
use lights::PointLight;
use config;
use config::Object;
use mesh_loader::MeshLoader;
use geometry::{Sphere, Plane, Mesh};
use math::{Point3, Vector3};
use material::Material;

#[derive(Debug, Clone)]
pub struct SceneConfigLoadError;

impl fmt::Display for SceneConfigLoadError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "failed to load scene from config")
    }
}

impl error::Error for SceneConfigLoadError {
    fn description(&self) -> &str {
        "failed to load scene from config"
    }

    fn cause(&self) -> Option<&error::Error> {
        None
    }
}

pub struct Scene {
    pub objects: Vec<Box<Intersectable>>,
    pub lights: Vec<Box<PointLight>>,
    pub clear_color: Color,
}

impl Scene {
    pub fn new(objects: Vec<Box<Intersectable>>,
               lights: Vec<Box<PointLight>>,
               clear_color: Color)
               -> Scene {
        Scene {
            objects: objects,
            lights: lights,
            clear_color: clear_color,
        }
    }

    pub fn new_from_config(scene: &config::Scene,
                           materials: &Vec<Material>,
                           mesh_loader: &MeshLoader,
                           fallback_material: Material)
                           -> Result<Scene, SceneConfigLoadError> {
        let mut objects: Vec<Box<Intersectable>> = vec![];

        scene.objects.iter().for_each(|object| match object {
                                          &Object::Sphere { radius,
                                                            ref transforms,
                                                            material_id } => {
            let material = match material_id {
                None => fallback_material,
                Some(id) => {
                    assert!(id >= 0 && id < materials.len(), "Invalid material_id");
                    materials[id]
                }
            };
            let mut sphere = Box::new(Sphere::new(Point3::at_origin(), radius, material));
            Self::apply_transforms(sphere.as_mut() as &mut Transformable, transforms);
            objects.push(sphere as Box<Intersectable>);
        }
                                          &Object::Plane { normal,
                                                           ref transforms,
                                                           material_id } => {
            let mut plane = Box::new(Plane::new(Point3::at_origin(),
                                                Vector3::new_from_slice(normal),
                                                fallback_material));
            Self::apply_transforms(plane.as_mut() as &mut Transformable, transforms);
            objects.push(plane as Box<Intersectable>);
        }
                                          &Object::Mesh { ref path, ref transforms } => {
            let mut meshes = mesh_loader.load(Path::new(&path), &fallback_material);
            for mesh in meshes.iter_mut() {
                Self::apply_transforms(mesh.as_mut() as &mut Transformable, transforms);
            }
            let mut intersectables =
                meshes.into_iter().map(|mesh| mesh as Box<Intersectable>).collect();

            objects.append(&mut intersectables);
        }
                                      });

        let lights = scene.lights
            .iter()
            .map(|light| match *light {
                     config::Light::PointLight { origin, color, intensity } => {
                         Box::new(PointLight::new(Point3::new_from_slice(origin),
                                                  Color::new_from_slice(color),
                                                  intensity))
                     }
                 })
            .collect();

        Ok(Self::new(objects, lights, Color::new_from_slice(scene.clear_color)))
    }

    fn apply_transforms(shape: &mut Transformable, transforms: &Option<Vec<config::Transform>>) {
        if let &Some(ref transforms_to_apply) = transforms {
            for transform in transforms_to_apply {
                transform.perform(shape);
            }
        }
    }

    pub fn intersect(&self, ray: Ray, cull: bool) -> Option<Intersection> {
        let mut closest_intersection: Option<Intersection> = None;

        for shape in self.objects.iter() {
            if let Some(intersection) = shape.intersect(ray, cull) {
                if let Some(closest) = closest_intersection {
                    if intersection.t < closest.t {
                        closest_intersection = Some(intersection)
                    }
                } else {
                    closest_intersection = Some(intersection)
                }
            }
        }

        return closest_intersection;
    }

    pub fn first_intersection(&self, ray: Ray, cull: bool, distance: f64) -> Option<Intersection> {
        for object in self.objects.iter() {
            if let Some(hit) = object.intersect(ray, cull) {
                if hit.t < distance {
                    return Some(hit);
                }
            }
        }

        None
    }
}
<commit_msg>[Config] Support materials for plane<commit_after>use std::error;
use std::fmt;
use std::path::Path;

use geometry::{Intersectable, Transformable};
use color::Color;
use ray::Ray;
use intersection::Intersection;
use lights::PointLight;
use config;
use config::Object;
use mesh_loader::MeshLoader;
use geometry::{Sphere, Plane};
use math::{Point3, Vector3};
use material::Material;

#[derive(Debug, Clone)]
pub struct SceneConfigLoadError;

impl fmt::Display for SceneConfigLoadError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "failed to load scene from config")
    }
}

impl error::Error for SceneConfigLoadError {
    fn description(&self) -> &str {
        "failed to load scene from config"
    }

    fn cause(&self) -> Option<&error::Error> {
        None
    }
}

pub struct Scene {
    pub objects: Vec<Box<Intersectable>>,
    pub lights: Vec<Box<PointLight>>,
    pub clear_color: Color,
}

impl Scene {
    pub fn new(objects: Vec<Box<Intersectable>>,
               lights: Vec<Box<PointLight>>,
               clear_color: Color)
               -> Scene {
        Scene {
            objects: objects,
            lights: lights,
            clear_color: clear_color,
        }
    }

    pub fn new_from_config(scene: &config::Scene,
                           materials: &Vec<Material>,
                           mesh_loader: &MeshLoader,
                           fallback_material: Material)
                           -> Result<Scene, SceneConfigLoadError> {
        let mut objects: Vec<Box<Intersectable>> = vec![];

        scene.objects.iter().for_each(|object| match object {
                                          &Object::Sphere { radius,
                                                            ref transforms,
                                                            material_id } => {
            let material = match material_id {
                None => fallback_material,
                Some(id) => {
                    assert!(id < materials.len(), "Invalid material_id");
                    materials[id]
                }
            };
            let mut sphere = Box::new(Sphere::new(Point3::at_origin(), radius, material));
            Self::apply_transforms(sphere.as_mut() as &mut Transformable, transforms);
            objects.push(sphere as Box<Intersectable>);
        }
                                          &Object::Plane { normal,
                                                           ref transforms,
                                                           material_id } => {
            let material = match material_id {
                None => fallback_material,
                Some(id) => {
                    assert!(id < materials.len(), "Invalid material_id");
                    materials[id]
                }
            };
            let mut plane = Box::new(Plane::new(Point3::at_origin(),
                                                Vector3::new_from_slice(normal),
                                                material));
            Self::apply_transforms(plane.as_mut() as &mut Transformable, transforms);
            objects.push(plane as Box<Intersectable>);
        }
                                          &Object::Mesh { ref path, ref transforms } => {
            let mut meshes = mesh_loader.load(Path::new(&path), &fallback_material);
            for mesh in meshes.iter_mut() {
                Self::apply_transforms(mesh.as_mut() as &mut Transformable, transforms);
            }
            let mut intersectables =
                meshes.into_iter().map(|mesh| mesh as Box<Intersectable>).collect();

            objects.append(&mut intersectables);
        }
                                      });

        let lights = scene.lights
            .iter()
            .map(|light| match *light {
                     config::Light::PointLight { origin, color, intensity } => {
                         Box::new(PointLight::new(Point3::new_from_slice(origin),
                                                  Color::new_from_slice(color),
                                                  intensity))
                     }
                 })
            .collect();

        Ok(Self::new(objects, lights, Color::new_from_slice(scene.clear_color)))
    }

    fn apply_transforms(shape: &mut Transformable, transforms: &Option<Vec<config::Transform>>) {
        if let &Some(ref transforms_to_apply) = transforms {
            for transform in transforms_to_apply {
                transform.perform(shape);
            }
        }
    }

    pub fn intersect(&self, ray: Ray, cull: bool) -> Option<Intersection> {
        let mut closest_intersection: Option<Intersection> = None;

        for shape in self.objects.iter() {
            if let Some(intersection) = shape.intersect(ray, cull) {
                if let Some(closest) = closest_intersection {
                    if intersection.t < closest.t {
                        closest_intersection = Some(intersection)
                    }
                } else {
                    closest_intersection = Some(intersection)
                }
            }
        }

        return closest_intersection;
    }

    pub fn first_intersection(&self, ray: Ray, cull: bool, distance: f64) -> Option<Intersection> {
        for object in self.objects.iter() {
            if let Some(hit) = object.intersect(ray, cull) {
                if hit.t < distance {
                    return Some(hit);
                }
            }
        }

        None
    }
}
<|endoftext|>