<commit_before>//! Basic block allocator implementation
//!
//! (c) 2015 Rick Richardson <rick.richardson@gmail.com>
//!
//!
//!

use mmap::{MemoryMap, MapOption};
use std::mem;
use std::u32;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::slice;
use std::error::Error;
use std::fmt::{self, Display};
use std::marker::PhantomData;

/// Allocator
/// Provides fixed-sized buffers from a pre-allocated arena specified at creation
/// Current limitations: Max number of buffers it can produce is u32::MAX - 1
/// Multiple allocators may be in use at any time, but their buffers may not be
/// used interchangibly :)
///
/// Note : This allocator will only produce blocks in sizes of powers of two, but
/// the usable buffer space is going to be 4 bytes smaller than the requested size
/// so if you need the full power of 2 space, request the next power of 2
///
/// Implementation
/// This keeps track of the next available buffer in the slab using a Double CAS Treiber Stack
/// Since Rust atomics don't actually support a double CAS yet, I am simulating it by
/// CAS'ing on a single 64 bit value that is actually a [u32; 2], where the lower bits
/// are the counter, and the higher order bits is the next offset
///
/// # Example
/// ```
/// use block_allocator::Allocator;
///
/// //reserve 100 usable blocks of size 512 (-4) bytes
/// let myalloc = Allocator::new(512, 100).unwrap();
/// let ptr = myalloc.alloc_raw().unwrap();
///
/// //do stuff
///
/// myalloc.free_raw(ptr);
/// ```
///
pub struct Allocator<'a> {
head : AtomicUsize,
     block_size : u32,
     region : MemoryMap,
     num_blocks : u32,
     _phantom: PhantomData<&'a u8>
}

impl<'a> Allocator<'a> {

    /// Constructs a new Block Allocator
    pub fn new(block_size: u32, num_blocks: u32) -> Result<Allocator<'a>, AllocError> {
        // for now this can only work on 64 bit platforms
        // it would be nice to have atomics other than register sizes
        assert!(mem::size_of::<isize>() >= mem::size_of::<u64>());
        assert!(num_blocks < u32::MAX); //we can support u32::MAX - 1 entries
        assert!(block_size >= mem::size_of::<u32>() as u32);
        assert!(num_blocks > 0);
        assert!(block_size.is_power_of_two());
        let rgn = match MemoryMap::new(block_size as usize * num_blocks as usize,
                &[MapOption::MapReadable, MapOption::MapWritable]) {
            Ok(r) => r,
            Err(e) => return Err(AllocError::MemoryMapFail(format!("{}", e)))
        };

        unsafe {
            let p = rgn.data();

            for i in 0 .. num_blocks {
                let cell = p.offset(block_size as isize * i as isize) as *mut u32;
                *cell = i + 1;
            }
            let cell = p.offset( (num_blocks - 1) as isize * block_size as isize) as *mut u32;
            *cell = u32::MAX; //sentinel value indicating end of list
        }
        Ok(Allocator {
            head : AtomicUsize::new(0),
            block_size : block_size,
            num_blocks : num_blocks,
            region : rgn,
            _phantom: PhantomData
        })

    }

    /// Acquire the next free buffer from the allocator's slab
    pub fn alloc(&self) -> Result<&'a mut [u8], AllocError> { unsafe {
        self.alloc_raw().map(|a|
            slice::from_raw_parts_mut(a, self.block_size as usize)
        )
    }}

    /// Free the buffer back into the allocator's slab
    pub fn free(&self, buf: &'a mut [u8]) -> Result<(), AllocError> {
        self.free_raw(buf.as_mut_ptr())
    }

    /// Acquire the next buffer as a raw `std::u8` pointer from the allocator's slab
    pub fn alloc_raw(&self) -> Result<*mut u8, AllocError> {

        let mut hd = self.head.load(Ordering::Acquire);
        let hd_ary : &[u32 ;2] = unsafe { mem::transmute(&hd) };
        let mut offset = hd_ary[0]; //top 32 bits are the offset to the start of the free list
        //println!("alloc - Loaded head {} | {}", hd_ary[0], hd_ary[1]);
        if offset == u32::MAX {
            return Err(AllocError::NoMemory);
        }

        loop {

            offset = self.get_next_offset(hd_ary[0]);
            let counter = hd_ary[1];
            let newhd_ary = [offset, counter.wrapping_add(1)];
            //println!("alloc - Setting newhd to {} | {}",  offset, counter.wrapping_add(1));
            let oldhead = hd;
            hd = self.head.compare_and_swap(hd, unsafe { mem::transmute(newhd_ary) }, Ordering::SeqCst);
            if hd == oldhead {
                return Ok(self.get_cell(hd_ary[0]))
            }
            if hd_ary[0] == u32::MAX {
                return Err(AllocError::NoMemory);
            }
        }
    }

    /// Free a raw (previously alloc'd pointer) back into the allocator's slab
    pub fn free_raw(&self, item : *mut u8) -> Result<(), AllocError> { unsafe {

        if item.is_null() {
            return Err(AllocError::BadArgument("Null".to_string()));
        }

        let cell = item.offset(-(mem::size_of::<u32>() as isize));

        let cell_addr : usize = mem::transmute(cell);
        let start_addr : usize = mem::transmute(self.region.data());
        let end_addr : usize = mem::transmute(self.region.data().offset((self.block_size * self.num_blocks) as isize));

        if (cell_addr < start_addr) || (cell_addr > end_addr) {
            return Err(AllocError::BadArgument("Out of bounds".to_string()));
        }

        //ensure that the ptr falls on the alignment of the block_size
        if (cell_addr & (self.block_size as usize - 1)) != 0 {
            return Err(AllocError::BadArgument("Misaligned value".to_string()));
        }

        let newoffset = (cell_addr - start_addr) as u32 / self.block_size;
        let mut hd = self.head.load(Ordering::Acquire);
        let hd_ary : &[u32; 2] = mem::transmute(&hd);
        //println!("free  - Loaded head {} | {}", hd_ary[0], hd_ary[1]);

        loop {
            let counter = hd_ary[1];
            //println!("free  - Setting newhd to {} | {}",  newoffset, counter.wrapping_add(1));
            let newhd_ary = [newoffset,  counter.wrapping_add(1)];

            let oldhead = hd;
            let oldhd_ary : &[u32; 2] = mem::transmute(&oldhead);
            //println!("free  - Setting cell to {}", oldhd_ary[0]);
            *(cell as *mut u32) = oldhd_ary[0];

            hd = self.head.compare_and_swap(hd, mem::transmute(newhd_ary), Ordering::SeqCst);
            if hd == oldhead {
                break;
            }
        }

        Ok(())
    }}

    #[inline(always)]
    fn get_next_offset(&self, index : u32) -> u32 { unsafe {
        let cell = self.region.data().offset(index as isize * self.block_size as isize) as *const u32;
        *cell
    }}

    #[inline(always)]
    fn get_cell(&self, index : u32) -> *mut u8 { unsafe {
        self.region.data().offset((index as isize * self.block_size as isize) + mem::size_of::<u32>() as isize)
    }}
}

unsafe impl<'a> Send for Allocator<'a> {}
unsafe impl<'a> Sync for Allocator<'a> {}

#[inline]
fn _next_pow_of_2(mut n : u32) -> u32
{
    n -= 1;
    n |= n >> 1;
    n |= n >> 2;
    n |= n >> 4;
    n |= n >> 8;
    n |= n >> 16;
    n += 1;
    n
}

#[derive(Debug)]
pub enum AllocError {
    BadArgument(String),
    MemoryMapFail(String),
    NoMemory,
}

impl Display for AllocError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &AllocError::BadArgument(ref s) => write!(f, "Bad Argument : {}", s),
            &AllocError::MemoryMapFail(ref s) => write!(f, "Memory Map Failure : {}", s),
            &AllocError::NoMemory => write!(f, "Out of memory")
        }
    }
}

impl Error for AllocError {
    fn description(&self) -> &str {
        match self {
            &AllocError::BadArgument(_) => "Bad Argument",
            &AllocError::MemoryMapFail(_) => "Memory Map Failure",
            &AllocError::NoMemory => "Out of memory"
        }
    }

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

#[cfg(test)]
mod tests {
    use super::*;
    use std::thread;
    use std::sync::Arc;
    use test::Bencher;
    use std::mem;
#[test]
    fn basic() {
        let myalloc = Allocator::new(256, 100).unwrap();
        let ptr = myalloc.alloc_raw().unwrap();
        myalloc.free_raw(ptr);
    }

#[test]
    fn max_cap() {
        let myalloc = Allocator::new(256, 10).unwrap();
        for _ in 0..10 {
            let _ = myalloc.alloc_raw().unwrap();
        }
        let ptr = myalloc.alloc_raw();
        assert!(ptr.is_err());
    }

#[test]
    fn sizing() { unsafe {
        let myalloc = Allocator::new(256, 10).unwrap();
        let a = myalloc.alloc_raw().unwrap();
        let b = myalloc.alloc_raw().unwrap();
        let a1 : usize = mem::transmute(a);
        let b1 : usize = mem::transmute(b);
        let diff = b1 - a1;
        println!("block_size: {}", diff);
        assert!(diff >= 256);
    } }

#[test]
    fn up_down() {
        let myalloc = Allocator::new(256, 10).unwrap();
        let ptrs : Vec<*mut u8> = (0..10).map(|_| myalloc.alloc_raw().unwrap()).collect();

        let ptr = myalloc.alloc_raw();
        assert!(ptr.is_err());

        for p in ptrs.iter() {
            myalloc.free_raw(*p);
        }

        let ptrs : Vec<*mut u8> = (0..10).map(|_| myalloc.alloc_raw().unwrap()).collect();

        let ptr = myalloc.alloc_raw();
        assert!(ptr.is_err());

        for p in ptrs.iter() {
            myalloc.free_raw(*p);
        }

        let ptr = myalloc.alloc_raw();
        assert!(ptr.is_ok());
    }
#[test]
    fn concurrency() {
        let myalloc = Arc::new(Allocator::new(256, 1000).unwrap());

        let threads : Vec<thread::JoinHandle<()>> = (0..10).map(|_| {
            let ma = myalloc.clone();
            thread::spawn(move || {
                for _ in 0 .. 100000 {
                    let p = ma.alloc_raw().unwrap();
                    ma.free_raw(p);
                    let p = ma.alloc_raw().unwrap();
                    ma.free_raw(p);
                    let p = ma.alloc_raw().unwrap();
                    ma.free_raw(p);
                    let p = ma.alloc_raw().unwrap();
                    ma.free_raw(p);
                    }
        })}).collect();

        for t in threads {
            t.join().unwrap();
        }

        //we should be back to 0 at this point, so this should succeed
        let _ : Vec<*mut u8> = (0..1000).map(|_| myalloc.alloc_raw().unwrap()).collect();
        // then this should fail
        let ptr = myalloc.alloc_raw();
        assert!(ptr.is_err());
    }

#[bench]
    fn speedtest(b: &mut Bencher) {
        let myalloc = Arc::new(Allocator::new(256, 1000).unwrap());
        b.iter(||{
                let p = myalloc.alloc_raw().unwrap();
                myalloc.free_raw(p);
                });
    }

#[bench]
    fn concurrent_speed(b: &mut Bencher) {
        let myalloc = Arc::new(Allocator::new(256, 1000).unwrap());
        b.iter(||{
            let threads : Vec<thread::JoinHandle<()>> = (0..20).map(|_| {
                let ma = myalloc.clone();
                thread::spawn(move || {
                    for _ in 0 .. 1000 {
                        let p = ma.alloc_raw().unwrap();
                        ma.free_raw(p);
                        let p = ma.alloc_raw().unwrap();
                        ma.free_raw(p);
                        let p = ma.alloc_raw().unwrap();
                        ma.free_raw(p);
                        let p = ma.alloc_raw().unwrap();
                        ma.free_raw(p);
                        }
            })}).collect();

            for t in threads {
                t.join().unwrap();
            }
       });
   }
}

<commit_msg>added sanity check for the length of a free'd slice<commit_after>//! Basic block allocator implementation
//!
//! (c) 2015 Rick Richardson <rick.richardson@gmail.com>
//!
//!
//!

use mmap::{MemoryMap, MapOption};
use std::mem;
use std::u32;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::slice;
use std::error::Error;
use std::fmt::{self, Display};
use std::marker::PhantomData;

/// Allocator
/// Provides fixed-sized buffers from a pre-allocated arena specified at creation
/// Current limitations: Max number of buffers it can produce is u32::MAX - 1
/// Multiple allocators may be in use at any time, but their buffers may not be
/// used interchangibly :)
///
/// Note : This allocator will only produce blocks in sizes of powers of two, but
/// the usable buffer space is going to be 4 bytes smaller than the requested size
/// so if you need the full power of 2 space, request the next power of 2
///
/// Implementation
/// This keeps track of the next available buffer in the slab using a Double CAS Treiber Stack
/// Since Rust atomics don't actually support a double CAS yet, I am simulating it by
/// CAS'ing on a single 64 bit value that is actually a [u32; 2], where the lower bits
/// are the counter, and the higher order bits is the next offset
///
/// # Example
/// ```
/// use block_allocator::Allocator;
///
/// //reserve 100 usable blocks of size 512 (-4) bytes
/// let myalloc = Allocator::new(512, 100).unwrap();
/// let ptr = myalloc.alloc_raw().unwrap();
///
/// //do stuff
///
/// myalloc.free_raw(ptr);
/// ```
///
pub struct Allocator<'a> {
head : AtomicUsize,
     block_size : u32,
     region : MemoryMap,
     num_blocks : u32,
     _phantom: PhantomData<&'a u8>
}

impl<'a> Allocator<'a> {

    /// Constructs a new Block Allocator
    pub fn new(block_size: u32, num_blocks: u32) -> Result<Allocator<'a>, AllocError> {
        // for now this can only work on 64 bit platforms
        // it would be nice to have atomics other than register sizes
        assert!(mem::size_of::<isize>() >= mem::size_of::<u64>());
        assert!(num_blocks < u32::MAX); //we can support u32::MAX - 1 entries
        assert!(block_size >= mem::size_of::<u32>() as u32);
        assert!(num_blocks > 0);
        assert!(block_size.is_power_of_two());
        let rgn = match MemoryMap::new(block_size as usize * num_blocks as usize,
                &[MapOption::MapReadable, MapOption::MapWritable]) {
            Ok(r) => r,
            Err(e) => return Err(AllocError::MemoryMapFail(format!("{}", e)))
        };

        unsafe {
            let p = rgn.data();

            for i in 0 .. num_blocks {
                let cell = p.offset(block_size as isize * i as isize) as *mut u32;
                *cell = i + 1;
            }
            let cell = p.offset( (num_blocks - 1) as isize * block_size as isize) as *mut u32;
            *cell = u32::MAX; //sentinel value indicating end of list
        }
        Ok(Allocator {
            head : AtomicUsize::new(0),
            block_size : block_size,
            num_blocks : num_blocks,
            region : rgn,
            _phantom: PhantomData
        })

    }

    /// Acquire the next free buffer from the allocator's slab
    pub fn alloc(&self) -> Result<&'a mut [u8], AllocError> { unsafe {
        self.alloc_raw().map(|a|
            slice::from_raw_parts_mut(a, self.block_size as usize)
        )
    }}

    /// Free the buffer back into the allocator's slab
    pub fn free(&self, buf: &'a mut [u8]) -> Result<(), AllocError> {
        if buf.len() as u32 != self.block_size {
          return Err(AllocError::BadArgument("Slice != allocator's block_size".to_string()));
        }
        self.free_raw(buf.as_mut_ptr())
    }

    /// Acquire the next buffer as a raw `std::u8` pointer from the allocator's slab
    pub fn alloc_raw(&self) -> Result<*mut u8, AllocError> {

        let mut hd = self.head.load(Ordering::Acquire);
        let hd_ary : &[u32 ;2] = unsafe { mem::transmute(&hd) };
        let mut offset = hd_ary[0]; //top 32 bits are the offset to the start of the free list
        //println!("alloc - Loaded head {} | {}", hd_ary[0], hd_ary[1]);
        if offset == u32::MAX {
            return Err(AllocError::NoMemory);
        }

        loop {

            offset = self.get_next_offset(hd_ary[0]);
            let counter = hd_ary[1];
            let newhd_ary = [offset, counter.wrapping_add(1)];
            //println!("alloc - Setting newhd to {} | {}",  offset, counter.wrapping_add(1));
            let oldhead = hd;
            hd = self.head.compare_and_swap(hd, unsafe { mem::transmute(newhd_ary) }, Ordering::SeqCst);
            if hd == oldhead {
                return Ok(self.get_cell(hd_ary[0]))
            }
            if hd_ary[0] == u32::MAX {
                return Err(AllocError::NoMemory);
            }
        }
    }

    /// Free a raw (previously alloc'd pointer) back into the allocator's slab
    pub fn free_raw(&self, item : *mut u8) -> Result<(), AllocError> { unsafe {

        if item.is_null() {
            return Err(AllocError::BadArgument("Null".to_string()));
        }

        let cell = item.offset(-(mem::size_of::<u32>() as isize));

        let cell_addr : usize = mem::transmute(cell);
        let start_addr : usize = mem::transmute(self.region.data());
        let end_addr : usize = mem::transmute(self.region.data().offset((self.block_size * self.num_blocks) as isize));

        if (cell_addr < start_addr) || (cell_addr > end_addr) {
            return Err(AllocError::BadArgument("Out of bounds".to_string()));
        }

        //ensure that the ptr falls on the alignment of the block_size
        if (cell_addr & (self.block_size as usize - 1)) != 0 {
            return Err(AllocError::BadArgument("Misaligned value".to_string()));
        }

        let newoffset = (cell_addr - start_addr) as u32 / self.block_size;
        let mut hd = self.head.load(Ordering::Acquire);
        let hd_ary : &[u32; 2] = mem::transmute(&hd);
        //println!("free  - Loaded head {} | {}", hd_ary[0], hd_ary[1]);

        loop {
            let counter = hd_ary[1];
            //println!("free  - Setting newhd to {} | {}",  newoffset, counter.wrapping_add(1));
            let newhd_ary = [newoffset,  counter.wrapping_add(1)];

            let oldhead = hd;
            let oldhd_ary : &[u32; 2] = mem::transmute(&oldhead);
            //println!("free  - Setting cell to {}", oldhd_ary[0]);
            *(cell as *mut u32) = oldhd_ary[0];

            hd = self.head.compare_and_swap(hd, mem::transmute(newhd_ary), Ordering::SeqCst);
            if hd == oldhead {
                break;
            }
        }

        Ok(())
    }}

    #[inline(always)]
    fn get_next_offset(&self, index : u32) -> u32 { unsafe {
        let cell = self.region.data().offset(index as isize * self.block_size as isize) as *const u32;
        *cell
    }}

    #[inline(always)]
    fn get_cell(&self, index : u32) -> *mut u8 { unsafe {
        self.region.data().offset((index as isize * self.block_size as isize) + mem::size_of::<u32>() as isize)
    }}
}

unsafe impl<'a> Send for Allocator<'a> {}
unsafe impl<'a> Sync for Allocator<'a> {}

#[inline]
fn _next_pow_of_2(mut n : u32) -> u32
{
    n -= 1;
    n |= n >> 1;
    n |= n >> 2;
    n |= n >> 4;
    n |= n >> 8;
    n |= n >> 16;
    n += 1;
    n
}

#[derive(Debug)]
pub enum AllocError {
    BadArgument(String),
    MemoryMapFail(String),
    NoMemory,
}

impl Display for AllocError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &AllocError::BadArgument(ref s) => write!(f, "Bad Argument : {}", s),
            &AllocError::MemoryMapFail(ref s) => write!(f, "Memory Map Failure : {}", s),
            &AllocError::NoMemory => write!(f, "Out of memory")
        }
    }
}

impl Error for AllocError {
    fn description(&self) -> &str {
        match self {
            &AllocError::BadArgument(_) => "Bad Argument",
            &AllocError::MemoryMapFail(_) => "Memory Map Failure",
            &AllocError::NoMemory => "Out of memory"
        }
    }

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

#[cfg(test)]
mod tests {
    use super::*;
    use std::thread;
    use std::sync::Arc;
    use test::Bencher;
    use std::mem;
#[test]
    fn basic() {
        let myalloc = Allocator::new(256, 100).unwrap();
        let ptr = myalloc.alloc_raw().unwrap();
        myalloc.free_raw(ptr);
    }

#[test]
    fn max_cap() {
        let myalloc = Allocator::new(256, 10).unwrap();
        for _ in 0..10 {
            let _ = myalloc.alloc_raw().unwrap();
        }
        let ptr = myalloc.alloc_raw();
        assert!(ptr.is_err());
    }

#[test]
    fn sizing() { unsafe {
        let myalloc = Allocator::new(256, 10).unwrap();
        let a = myalloc.alloc_raw().unwrap();
        let b = myalloc.alloc_raw().unwrap();
        let a1 : usize = mem::transmute(a);
        let b1 : usize = mem::transmute(b);
        let diff = b1 - a1;
        println!("block_size: {}", diff);
        assert!(diff >= 256);
    } }

#[test]
    fn up_down() {
        let myalloc = Allocator::new(256, 10).unwrap();
        let ptrs : Vec<*mut u8> = (0..10).map(|_| myalloc.alloc_raw().unwrap()).collect();

        let ptr = myalloc.alloc_raw();
        assert!(ptr.is_err());

        for p in ptrs.iter() {
            myalloc.free_raw(*p);
        }

        let ptrs : Vec<*mut u8> = (0..10).map(|_| myalloc.alloc_raw().unwrap()).collect();

        let ptr = myalloc.alloc_raw();
        assert!(ptr.is_err());

        for p in ptrs.iter() {
            myalloc.free_raw(*p);
        }

        let ptr = myalloc.alloc_raw();
        assert!(ptr.is_ok());
    }
#[test]
    fn concurrency() {
        let myalloc = Arc::new(Allocator::new(256, 1000).unwrap());

        let threads : Vec<thread::JoinHandle<()>> = (0..10).map(|_| {
            let ma = myalloc.clone();
            thread::spawn(move || {
                for _ in 0 .. 100000 {
                    let p = ma.alloc_raw().unwrap();
                    ma.free_raw(p);
                    let p = ma.alloc_raw().unwrap();
                    ma.free_raw(p);
                    let p = ma.alloc_raw().unwrap();
                    ma.free_raw(p);
                    let p = ma.alloc_raw().unwrap();
                    ma.free_raw(p);
                    }
        })}).collect();

        for t in threads {
            t.join().unwrap();
        }

        //we should be back to 0 at this point, so this should succeed
        let _ : Vec<*mut u8> = (0..1000).map(|_| myalloc.alloc_raw().unwrap()).collect();
        // then this should fail
        let ptr = myalloc.alloc_raw();
        assert!(ptr.is_err());
    }

#[bench]
    fn speedtest(b: &mut Bencher) {
        let myalloc = Arc::new(Allocator::new(256, 1000).unwrap());
        b.iter(||{
                let p = myalloc.alloc_raw().unwrap();
                myalloc.free_raw(p);
                });
    }

#[bench]
    fn concurrent_speed(b: &mut Bencher) {
        let myalloc = Arc::new(Allocator::new(256, 1000).unwrap());
        b.iter(||{
            let threads : Vec<thread::JoinHandle<()>> = (0..20).map(|_| {
                let ma = myalloc.clone();
                thread::spawn(move || {
                    for _ in 0 .. 1000 {
                        let p = ma.alloc_raw().unwrap();
                        ma.free_raw(p);
                        let p = ma.alloc_raw().unwrap();
                        ma.free_raw(p);
                        let p = ma.alloc_raw().unwrap();
                        ma.free_raw(p);
                        let p = ma.alloc_raw().unwrap();
                        ma.free_raw(p);
                        }
            })}).collect();

            for t in threads {
                t.join().unwrap();
            }
       });
   }
}

<|endoftext|>


<commit_before>use std::f32::consts;
use super::*;
use ::{Vector, Point2f};
use colour::Colourf;

pub struct LambertianReflection {
    r: Colourf,
}

impl BxDF for LambertianReflection {
    fn f(&self, wo: &Vector, wi: &Vector) -> Colourf {
        self.r * consts::FRAC_1_PI
    }

    fn get_type(&self) -> BxDFType {
        BSDF_DIFFUSE | BSDF_REFLECTION
    }
}
<commit_msg>Add constructor for LambertianReflection<commit_after>use std::f32::consts;
use super::*;
use ::{Vector, Point2f};
use colour::Colourf;

pub struct LambertianReflection {
    r: Colourf,
}

impl LambertianReflection {
    pub fn new(r: Colourf) -> LambertianReflection {
        LambertianReflection { r: r }
    }
}

impl BxDF for LambertianReflection {
    fn f(&self, wo: &Vector, wi: &Vector) -> Colourf {
        self.r * consts::FRAC_1_PI
    }

    fn get_type(&self) -> BxDFType {
        BSDF_DIFFUSE | BSDF_REFLECTION
    }
}
<|endoftext|>


<commit_before>#![crate_name = "sam4l"]
#![crate_type = "rlib"]
#![feature(asm,core_intrinsics,concat_idents,const_fn)]
#![no_std]

extern crate common;
extern crate hil;
extern crate process;

mod helpers;

pub mod chip;
pub mod ast;
pub mod dma;
pub mod i2c;
pub mod spi;
pub mod nvic;
pub mod pm;
pub mod gpio;
pub mod usart;
pub mod scif;
pub mod adc;

unsafe extern "C" fn unhandled_interrupt() {
    panic!("Unhandled Interrupt");
}

extern {
    // _estack is not really a function, but it makes the types work
    // You should never actually invoke it!!
    fn _estack();

    // Defined in src/main/main.rs
    fn main();

    // Defined in src/arch/cortex-m4/ctx_switch.S
    fn SVC_Handler();

    static mut _szero : u32;
    static mut _ezero : u32;
    static mut _etext : u32;
    static mut _srelocate : u32;
    static mut _erelocate : u32;
}

#[link_section=".vectors"]
pub static ISR_VECTOR: [Option<unsafe extern fn()>; 96] = [
    // First 16 are defined in the Cortex M4 user guide section 2.3.4

    /* Stack top */     Option::Some(_estack),
    /* Reset */         Option::Some(reset_handler),
    /* NMI */           Option::Some(unhandled_interrupt),
    /* Hard Fault */    Option::Some(unhandled_interrupt),
    /* MemManage */     Option::Some(unhandled_interrupt),
    /* BusFault */      Option::Some(unhandled_interrupt),
    /* UsageFault*/     Option::Some(unhandled_interrupt),
    None, None, None, None,
    /* SVC */           Option::Some(SVC_Handler),
    /* DebugMon */      Option::Some(unhandled_interrupt),
    None,
    /* PendSV */        Option::Some(unhandled_interrupt),
    /* SysTick */       Option::Some(unhandled_interrupt),

    // Perhipheral vectors are defined by Atmel in the SAM4L datasheet section
    // 4.7.
    /* HFLASHC */       Option::Some(unhandled_interrupt),
    /* PDCA0 */         Option::Some(dma::PDCA_0_Handler),
    /* PDCA1 */         Option::Some(dma::PDCA_1_Handler),
    /* PDCA2 */         Option::Some(dma::PDCA_2_Handler),
    /* PDCA3..PDCA15 */ None, None, None, None, None, None, None, None, None,
                        None, None, None, None,
    /* CRCCU */         Option::Some(unhandled_interrupt),
    /* USBC */          Option::Some(unhandled_interrupt),
    /* PEVC_TR */       Option::Some(unhandled_interrupt),
    /* PEVC_OV */       Option::Some(unhandled_interrupt),
    /* AESA */          Option::Some(unhandled_interrupt),
    /* PM */            Option::Some(unhandled_interrupt),
    /* SCIF */          Option::Some(unhandled_interrupt),
    /* FREQM */         Option::Some(unhandled_interrupt),
    /* GPIO0 */         Option::Some(gpio::GPIO_0_Handler),
    /* GPIO1 */         Option::Some(gpio::GPIO_1_Handler),
    /* GPIO2 */         Option::Some(gpio::GPIO_2_Handler),
    /* GPIO3 */         Option::Some(gpio::GPIO_3_Handler),
    /* GPIO4 */         Option::Some(gpio::GPIO_4_Handler),
    /* GPIO5 */         Option::Some(gpio::GPIO_5_Handler),
    /* GPIO6 */         Option::Some(gpio::GPIO_6_Handler),
    /* GPIO7 */         Option::Some(gpio::GPIO_7_Handler),
    /* GPIO8 */         Option::Some(gpio::GPIO_8_Handler),
    /* GPIO9 */         Option::Some(gpio::GPIO_9_Handler),
    /* GPIO10 */        Option::Some(gpio::GPIO_10_Handler),
    /* GPIO11 */        Option::Some(gpio::GPIO_11_Handler),
    /* BPM */           Option::Some(unhandled_interrupt),
    /* BSCIF */         Option::Some(unhandled_interrupt),
    /* AST_ALARM */     Option::Some(ast::AST_ALARM_Handler),
    /* AST_PER */       Option::Some(unhandled_interrupt),
    /* AST_OVF */       Option::Some(unhandled_interrupt),
    /* AST_READY */     Option::Some(unhandled_interrupt),
    /* AST_CLKREADY */  Option::Some(unhandled_interrupt),
    /* WDT */           Option::Some(unhandled_interrupt),
    /* EIC1 */          Option::Some(unhandled_interrupt),
    /* EIC2 */          Option::Some(unhandled_interrupt),
    /* EIC3 */          Option::Some(unhandled_interrupt),
    /* EIC4 */          Option::Some(unhandled_interrupt),
    /* EIC5 */          Option::Some(unhandled_interrupt),
    /* EIC6 */          Option::Some(unhandled_interrupt),
    /* EIC7 */          Option::Some(unhandled_interrupt),
    /* EIC8 */          Option::Some(unhandled_interrupt),
    /* IISC */          Option::Some(unhandled_interrupt),
    /* SPI */           Option::Some(unhandled_interrupt),
    /* TC00 */          Option::Some(unhandled_interrupt),
    /* TC01 */          Option::Some(unhandled_interrupt),
    /* TC02 */          Option::Some(unhandled_interrupt),
    /* TC10 */          Option::Some(unhandled_interrupt),
    /* TC11 */          Option::Some(unhandled_interrupt),
    /* TC12 */          Option::Some(unhandled_interrupt),
    /* TWIM0 */         Option::Some(unhandled_interrupt),
    /* TWIS0 */         Option::Some(unhandled_interrupt),
    /* TWIM1 */         Option::Some(unhandled_interrupt),
    /* TWIS1 */         Option::Some(unhandled_interrupt),
    /* USART0 */        Option::Some(unhandled_interrupt),
    /* USART1 */        Option::Some(unhandled_interrupt),
    /* USART2 */        Option::Some(unhandled_interrupt),
    /* USART3 */        Option::Some(usart::USART3_Handler),
    /* ADCIFE */        Option::Some(adc::ADCIFE_Handler),
    /* DACC */          Option::Some(unhandled_interrupt),
    /* ACIFC */         Option::Some(unhandled_interrupt),
    /* ABDACB */        Option::Some(unhandled_interrupt),
    /* TRNG */          Option::Some(unhandled_interrupt),
    /* PARC */          Option::Some(unhandled_interrupt),
    /* CATB */          Option::Some(unhandled_interrupt),
    None,
    /* TWIM2 */         Option::Some(unhandled_interrupt),
    /* TWIM3 */         Option::Some(unhandled_interrupt),
    /* LCDCA */         Option::Some(unhandled_interrupt),
];

unsafe extern "C" fn reset_handler() {

    // Relocate data segment.
    // Assumes data starts right after text segment as specified by the linker
    // file.
    let mut pdest  = &mut _srelocate as *mut u32;
    let pend  = &mut _erelocate as *mut u32;
    let mut psrc = &_etext as *const u32;

    if psrc != pdest {
        while (pdest as *const u32) < pend {
            *pdest = *psrc;
            pdest = pdest.offset(1);
            psrc = psrc.offset(1);
        }
    }

    // Clear the zero segment (BSS)
    let pzero = &_ezero as *const u32;
    pdest = &mut _szero as *mut u32;

    while (pdest as *const u32) < pzero {
        *pdest = 0;
        pdest = pdest.offset(1);
    }

    main();
}

<commit_msg>Add a real HardFault handler that prints context<commit_after>#![crate_name = "sam4l"]
#![crate_type = "rlib"]
#![feature(asm,core_intrinsics,concat_idents,const_fn)]
#![no_std]

extern crate common;
extern crate hil;
extern crate process;

mod helpers;

pub mod chip;
pub mod ast;
pub mod dma;
pub mod i2c;
pub mod spi;
pub mod nvic;
pub mod pm;
pub mod gpio;
pub mod usart;
pub mod scif;
pub mod adc;

unsafe extern "C" fn unhandled_interrupt() {
    // HACK: See comment at function definition
    hard_fault_handler_helper(0 as *const u32, true);

    panic!("Unhandled Interrupt");
}

extern {
    // _estack is not really a function, but it makes the types work
    // You should never actually invoke it!!
    fn _estack();

    // Defined in src/main/main.rs
    fn main();

    // Defined in src/arch/cortex-m4/ctx_switch.S
    fn SVC_Handler();

    static mut _szero : u32;
    static mut _ezero : u32;
    static mut _etext : u32;
    static mut _srelocate : u32;
    static mut _erelocate : u32;
}

#[link_section=".vectors"]
pub static ISR_VECTOR: [Option<unsafe extern fn()>; 96] = [
    // First 16 are defined in the Cortex M4 user guide section 2.3.4

    /* Stack top */     Option::Some(_estack),
    /* Reset */         Option::Some(reset_handler),
    /* NMI */           Option::Some(unhandled_interrupt),
    /* Hard Fault */    Option::Some(hard_fault_handler),
    /* MemManage */     Option::Some(unhandled_interrupt),
    /* BusFault */      Option::Some(unhandled_interrupt),
    /* UsageFault*/     Option::Some(unhandled_interrupt),
    None, None, None, None,
    /* SVC */           Option::Some(SVC_Handler),
    /* DebugMon */      Option::Some(unhandled_interrupt),
    None,
    /* PendSV */        Option::Some(unhandled_interrupt),
    /* SysTick */       Option::Some(unhandled_interrupt),

    // Perhipheral vectors are defined by Atmel in the SAM4L datasheet section
    // 4.7.
    /* HFLASHC */       Option::Some(unhandled_interrupt),
    /* PDCA0 */         Option::Some(dma::PDCA_0_Handler),
    /* PDCA1 */         Option::Some(dma::PDCA_1_Handler),
    /* PDCA2 */         Option::Some(dma::PDCA_2_Handler),
    /* PDCA3..PDCA15 */ None, None, None, None, None, None, None, None, None,
                        None, None, None, None,
    /* CRCCU */         Option::Some(unhandled_interrupt),
    /* USBC */          Option::Some(unhandled_interrupt),
    /* PEVC_TR */       Option::Some(unhandled_interrupt),
    /* PEVC_OV */       Option::Some(unhandled_interrupt),
    /* AESA */          Option::Some(unhandled_interrupt),
    /* PM */            Option::Some(unhandled_interrupt),
    /* SCIF */          Option::Some(unhandled_interrupt),
    /* FREQM */         Option::Some(unhandled_interrupt),
    /* GPIO0 */         Option::Some(gpio::GPIO_0_Handler),
    /* GPIO1 */         Option::Some(gpio::GPIO_1_Handler),
    /* GPIO2 */         Option::Some(gpio::GPIO_2_Handler),
    /* GPIO3 */         Option::Some(gpio::GPIO_3_Handler),
    /* GPIO4 */         Option::Some(gpio::GPIO_4_Handler),
    /* GPIO5 */         Option::Some(gpio::GPIO_5_Handler),
    /* GPIO6 */         Option::Some(gpio::GPIO_6_Handler),
    /* GPIO7 */         Option::Some(gpio::GPIO_7_Handler),
    /* GPIO8 */         Option::Some(gpio::GPIO_8_Handler),
    /* GPIO9 */         Option::Some(gpio::GPIO_9_Handler),
    /* GPIO10 */        Option::Some(gpio::GPIO_10_Handler),
    /* GPIO11 */        Option::Some(gpio::GPIO_11_Handler),
    /* BPM */           Option::Some(unhandled_interrupt),
    /* BSCIF */         Option::Some(unhandled_interrupt),
    /* AST_ALARM */     Option::Some(ast::AST_ALARM_Handler),
    /* AST_PER */       Option::Some(unhandled_interrupt),
    /* AST_OVF */       Option::Some(unhandled_interrupt),
    /* AST_READY */     Option::Some(unhandled_interrupt),
    /* AST_CLKREADY */  Option::Some(unhandled_interrupt),
    /* WDT */           Option::Some(unhandled_interrupt),
    /* EIC1 */          Option::Some(unhandled_interrupt),
    /* EIC2 */          Option::Some(unhandled_interrupt),
    /* EIC3 */          Option::Some(unhandled_interrupt),
    /* EIC4 */          Option::Some(unhandled_interrupt),
    /* EIC5 */          Option::Some(unhandled_interrupt),
    /* EIC6 */          Option::Some(unhandled_interrupt),
    /* EIC7 */          Option::Some(unhandled_interrupt),
    /* EIC8 */          Option::Some(unhandled_interrupt),
    /* IISC */          Option::Some(unhandled_interrupt),
    /* SPI */           Option::Some(unhandled_interrupt),
    /* TC00 */          Option::Some(unhandled_interrupt),
    /* TC01 */          Option::Some(unhandled_interrupt),
    /* TC02 */          Option::Some(unhandled_interrupt),
    /* TC10 */          Option::Some(unhandled_interrupt),
    /* TC11 */          Option::Some(unhandled_interrupt),
    /* TC12 */          Option::Some(unhandled_interrupt),
    /* TWIM0 */         Option::Some(unhandled_interrupt),
    /* TWIS0 */         Option::Some(unhandled_interrupt),
    /* TWIM1 */         Option::Some(unhandled_interrupt),
    /* TWIS1 */         Option::Some(unhandled_interrupt),
    /* USART0 */        Option::Some(unhandled_interrupt),
    /* USART1 */        Option::Some(unhandled_interrupt),
    /* USART2 */        Option::Some(unhandled_interrupt),
    /* USART3 */        Option::Some(usart::USART3_Handler),
    /* ADCIFE */        Option::Some(adc::ADCIFE_Handler),
    /* DACC */          Option::Some(unhandled_interrupt),
    /* ACIFC */         Option::Some(unhandled_interrupt),
    /* ABDACB */        Option::Some(unhandled_interrupt),
    /* TRNG */          Option::Some(unhandled_interrupt),
    /* PARC */          Option::Some(unhandled_interrupt),
    /* CATB */          Option::Some(unhandled_interrupt),
    None,
    /* TWIM2 */         Option::Some(unhandled_interrupt),
    /* TWIM3 */         Option::Some(unhandled_interrupt),
    /* LCDCA */         Option::Some(unhandled_interrupt),
];

unsafe extern "C" fn reset_handler() {

    // Relocate data segment.
    // Assumes data starts right after text segment as specified by the linker
    // file.
    let mut pdest  = &mut _srelocate as *mut u32;
    let pend  = &mut _erelocate as *mut u32;
    let mut psrc = &_etext as *const u32;

    if psrc != pdest {
        while (pdest as *const u32) < pend {
            *pdest = *psrc;
            pdest = pdest.offset(1);
            psrc = psrc.offset(1);
        }
    }

    // Clear the zero segment (BSS)
    let pzero = &_ezero as *const u32;
    pdest = &mut _szero as *mut u32;

    while (pdest as *const u32) < pzero {
        *pdest = 0;
        pdest = pdest.offset(1);
    }

    main();
}

unsafe extern "C" fn hard_fault_handler() {
    asm!(
        "tst    lr, #4                      \n\
         ite    eq                          \n\
         mrseq  r0, msp                     \n\
         mrsne  r0, psp                     \n\
         movs   r1, #0                      \n\
         b      hard_fault_handler_helper   "
        :::: "volatile");
}

/* Okay, so this is a cascade of hacks. The fundamental issue is that there's
 * no way to convince rust to preserve a function called only from assembly
 * currently, that's waiting on:
 *   https://github.com/mahkoh/rfcs/blob/used/text/0000-used.md
 *   https://github.com/rust-lang/rfcs/pull/1459
 *
 * Because of limitations in rust's current LTO implementation (referenced in
 * the above issues), the *only* way to keep this function around is for
 * something to actually call it. Now this is where LTO gets annoyingly smart,
 * if it can reason about the parameters passed to the function from the only
 * caller, (i.e. if preserve_hack is always true), then it will rip out the
 * body of the if statement. So, this function actually takes two arguments,
 * we just read the second one using assembly so that the compiler can't see it.
 * Ugh.
 */
#[export_name = "hard_fault_handler_helper"]
#[inline(never)]
unsafe extern "C" fn  hard_fault_handler_helper(faulting_stack: *const u32, preserve_hack :bool) {
    let flag: bool;

    asm!("cmp r1, #0\n\
          ite eq\n\
          moveq r2, #1\n\
          movne r2, #0\n\
          "
         : "={r2}"(flag)                        /* output operands */
         : "preserve_hack"(preserve_hack)       /* input operands */
         : "r2"                                 /* clobbers */
         :                                      /* options */
         );

    if flag {
        let stacked_r0  = *faulting_stack;
        let stacked_r1  = *faulting_stack+4;
        let stacked_r2  = *faulting_stack+8;
        let stacked_r3  = *faulting_stack+12;
        let stacked_r12 = *faulting_stack+16;
        let stacked_lr  = *faulting_stack+20;
        let stacked_pc  = *faulting_stack+24;
        let stacked_prs = *faulting_stack+28;

        panic!("HardFault.\n\
               \tr0  0x{:x}\n\
               \tr1  0x{:x}\n\
               \tr2  0x{:x}\n\
               \tr3  0x{:x}\n\
               \tr12 0x{:x}\n\
               \tlr  0x{:x}\n\
               \tpc  0x{:x}\n\
               \tprs 0x{:x}\n\
               ", stacked_r0, stacked_r1, stacked_r2, stacked_r3,
               stacked_r12, stacked_lr, stacked_pc, stacked_prs);
    }
}

<|endoftext|>


<commit_before>use std::thread;
use std::sync::mpsc;

#[cfg(test)]
extern crate time;

#[cfg(test)]
fn mark_time(i:usize, bounds: (usize, usize), s_time: time::PreciseTime){
    println!("Thread: {}, Bounds:({}, {}), time: {}", i, bounds.0, bounds.1, s_time.to(time::PreciseTime::now()));
}

pub fn to_concurrent_on_section<T, SeqF>(seq_fun: SeqF,
            min_num: usize, max_num: usize, threads: usize, from_zero_speed_factor: usize) -> Vec<T>
            where
                T: Clone + Send + 'static,
                SeqF: Send + Sync + Copy + 'static + Fn(usize, usize) -> Vec<T>, {

    let mut res_vec:  Vec<Vec<T>> = vec![vec![]; threads];
    let (start_seg_end, seg_size) = match min_num{
        0 => {
            let seg_size = (max_num)/(threads*from_zero_speed_factor);
            (max_num - seg_size*(threads-1), seg_size)
        },
        _ => {
            let range = max_num - min_num;
            let seg_size = range/threads;
            (min_num + seg_size + range%threads, seg_size)
        },
    };

    let (tx, rx) = mpsc::channel();

    #[cfg(test)]
    let start = time::PreciseTime::now();
    { //First section.
        let (tx, min, max) = (tx.clone(), min_num, start_seg_end);
        thread::spawn( move || {
            let to_send = match max-min{
                0 => vec![],
                _ => seq_fun(min, max),
            };

            #[cfg(test)]
            mark_time(0, (min, max), start);

            tx.send((0, to_send)).unwrap();
        });
    }
    for i in 1..threads{
        let (tx, min, max) = (tx.clone(), start_seg_end + seg_size*(i-1),
                                start_seg_end + seg_size*i);
        thread::spawn( move || {
            let to_send = match max-min{
                0 => vec![],
                _ => seq_fun(min, max),
            };

            #[cfg(test)]
            mark_time(i, (min, max), start);

            tx.send((i, to_send)).unwrap();
        });
    }

    for _ in 0..threads{
        let (i, p_sec) = match rx.recv(){
            Ok(mes) => mes,
            Err(e) => panic!(e.to_string()),
        };
        res_vec[i] = p_sec;
    }
    res_vec.concat()
}
<commit_msg>printing in tests without nocapture...<commit_after>use std::thread;
use std::sync::mpsc;

// #[cfg(test)]
// extern crate time;
//
// #[cfg(test)]
// fn mark_time(i:usize, bounds: (usize, usize), s_time: time::PreciseTime){
//     #[cfg(test)]
//     println!("Thread: {}, Bounds:({}, {}), time: {}", i, bounds.0, bounds.1, s_time.to(time::PreciseTime::now()));
// }

pub fn to_concurrent_on_section<T, SeqF>(seq_fun: SeqF,
            min_num: usize, max_num: usize, threads: usize, from_zero_speed_factor: usize) -> Vec<T>
            where
                T: Clone + Send + 'static,
                SeqF: Send + Sync + Copy + 'static + Fn(usize, usize) -> Vec<T>, {

    let mut res_vec:  Vec<Vec<T>> = vec![vec![]; threads];
    let (start_seg_end, seg_size) = match min_num{
        0 => {
            let seg_size = (max_num)/(threads*from_zero_speed_factor);
            (max_num - seg_size*(threads-1), seg_size)
        },
        _ => {
            let range = max_num - min_num;
            let seg_size = range/threads;
            (min_num + seg_size + range%threads, seg_size)
        },
    };

    let (tx, rx) = mpsc::channel();
    //
    // #[cfg(test)]
    // let start = time::PreciseTime::now();
    { //First section.
        let (tx, min, max) = (tx.clone(), min_num, start_seg_end);
        thread::spawn( move || {
            let to_send = match max-min{
                0 => vec![],
                _ => seq_fun(min, max),
            };
            //
            // #[cfg(test)]
            // mark_time(0, (min, max), start);
            //
            // tx.send((0, to_send)).unwrap();
        });
    }
    for i in 1..threads{
        let (tx, min, max) = (tx.clone(), start_seg_end + seg_size*(i-1),
                                start_seg_end + seg_size*i);
        thread::spawn( move || {
            let to_send = match max-min{
                0 => vec![],
                _ => seq_fun(min, max),
            };
            //
            // #[cfg(test)]
            // mark_time(i, (min, max), start);

            tx.send((i, to_send)).unwrap();
        });
    }

    for _ in 0..threads{
        let (i, p_sec) = match rx.recv(){
            Ok(mes) => mes,
            Err(e) => panic!(e.to_string()),
        };
        res_vec[i] = p_sec;
    }
    res_vec.concat()
}
<|endoftext|>


<commit_before>use oppai_field::field::{euclidean, wave_diag, Field, Pos};
use oppai_field::player::Player;
use std::{
  collections::HashSet,
  ops::Index,
  sync::atomic::{AtomicBool, Ordering},
};

#[derive(Debug, Clone)]
struct Trajectory {
  points: Vec<Pos>,
  hash: u64,
}

impl Trajectory {
  pub fn new(points: Vec<Pos>, hash: u64) -> Trajectory {
    Trajectory { points, hash }
  }

  pub fn points(&self) -> &Vec<Pos> {
    &self.points
  }

  pub fn hash(&self) -> u64 {
    self.hash
  }

  pub fn len(&self) -> usize {
    self.points.len()
  }
}

pub struct TrajectoriesPruning {
  rebuild_trajectories: bool,
  cur_trajectories: Vec<Trajectory>,
  enemy_trajectories: Vec<Trajectory>,
  moves: Vec<Pos>,
}

impl TrajectoriesPruning {
  fn add_trajectory(field: &Field, trajectories: &mut Vec<Trajectory>, points: &[Pos], player: Player) {
    for &pos in points {
      if !field.cell(pos).is_bound() || field.number_near_groups(pos, player) < 2 {
        return;
      }
    }
    let zobrist = field.zobrist();
    let mut hash = 0u64;
    for &pos in points {
      hash ^= zobrist.get_hash(pos);
    }
    for trajectory in trajectories.iter() {
      if trajectory.hash() == hash {
        return;
      }
    }
    let trajectory = Trajectory::new(points.to_vec(), hash);
    trajectories.push(trajectory);
  }

  fn next_moves(
    field: &Field,
    start_pos: Pos,
    player: Player,
    empty_board: &mut Vec<u32>,
    marks: &mut Vec<Pos>,
  ) -> Vec<Pos> {
    let mut moves = Vec::new();
    wave_diag(field.width(), start_pos, |pos| {
      if empty_board[pos] != 0 {
        return false;
      }
      empty_board[pos] = 1;
      let cell = field.cell(pos);
      if cell.is_players_point(player) {
        marks.push(pos);
        true
      } else {
        if cell.is_putting_allowed() && !cell.is_players_empty_base(player) {
          moves.push(pos);
        } else {
          marks.push(pos);
        }
        false
      }
    });
    for &pos in &moves {
      empty_board[pos] = 0;
    }
    moves
  }

  fn build_trajectories_rec(
    field: &mut Field,
    trajectories: &mut Vec<Trajectory>,
    player: Player,
    cur_depth: u32,
    depth: u32,
    empty_board: &mut Vec<u32>,
    last_pos: Pos,
    moves: Vec<Pos>,
    should_stop: &AtomicBool,
  ) {
    for pos in moves {
      if should_stop.load(Ordering::Relaxed) {
        break;
      }
      if field.number_near_points(pos, player) >= 3 {
        continue;
      }
      let cell = field.cell(pos);
      if cell.is_players_empty_base(player.next()) {
        field.put_point(pos, player);
        if field.get_delta_score(player) > 0 {
          TrajectoriesPruning::add_trajectory(
            field,
            trajectories,
            field
              .points_seq()
              .index(field.moves_count() - cur_depth as usize..field.moves_count()),
            player,
          );
        }
        field.undo();
      } else {
        field.put_point(pos, player);
        if field.get_delta_score(player) > 0 {
          TrajectoriesPruning::add_trajectory(
            field,
            trajectories,
            field
              .points_seq()
              .index(field.moves_count() - cur_depth as usize..field.moves_count()),
            player,
          );
        } else if depth > 0 {
          let mut marks = Vec::new();
          let mut next_moves = TrajectoriesPruning::next_moves(field, pos, player, empty_board, &mut marks);
          if last_pos != 0 {
            next_moves.retain(|&next_pos| euclidean(field.width(), last_pos, next_pos) > 2);
          }
          TrajectoriesPruning::build_trajectories_rec(
            field,
            trajectories,
            player,
            cur_depth + 1,
            depth - 1,
            empty_board,
            pos,
            next_moves,
            should_stop,
          );
          for mark_pos in marks {
            empty_board[mark_pos] = 0;
          }
        }
        field.undo();
      }
    }
  }

  fn build_trajectories(
    field: &mut Field,
    player: Player,
    depth: u32,
    empty_board: &mut Vec<u32>,
    should_stop: &AtomicBool,
  ) -> Vec<Trajectory> {
    let mut trajectories = Vec::new();

    if depth == 0 {
      return trajectories;
    }

    let mut marks = Vec::new();
    for pos in field.points_seq().clone() {
      if field.cell(pos).get_player() != player {
        continue;
      }

      if should_stop.load(Ordering::Relaxed) {
        break;
      }

      let moves = TrajectoriesPruning::next_moves(field, pos, player, empty_board, &mut marks);

      TrajectoriesPruning::build_trajectories_rec(
        field,
        &mut trajectories,
        player,
        1,
        depth - 1,
        empty_board,
        0,
        moves,
        should_stop,
      );
    }

    for pos in marks {
      empty_board[pos] = 0;
    }

    trajectories
  }

  fn project(trajectories: &[Trajectory], empty_board: &mut Vec<u32>) {
    for &pos in trajectories.iter().flat_map(|trajectory| trajectory.points().iter()) {
      empty_board[pos] += 1;
    }
  }

  fn project_length(trajectories: &[Trajectory], empty_board: &mut Vec<u32>) {
    for trajectory in trajectories {
      let len = trajectory.len() as u32;
      for &pos in trajectory.points() {
        if empty_board[pos] == 0 || empty_board[pos] > len {
          empty_board[pos] = len;
        }
      }
    }
  }

  fn deproject(trajectories: &[Trajectory], empty_board: &mut Vec<u32>) {
    for &pos in trajectories.iter().flat_map(|trajectory| trajectory.points().iter()) {
      empty_board[pos] = 0;
    }
  }

  fn exclude_unnecessary_trajectories(trajectories: &mut Vec<Trajectory>, empty_board: &mut Vec<u32>) -> bool {
    let mut need_exclude = false;
    trajectories.retain(|trajectory| {
      let single_count = trajectory.points().iter().filter(|&&pos| empty_board[pos] == 1).count();
      if single_count > 1 {
        for &pos in trajectory.points() {
          empty_board[pos] -= 1;
        }
        need_exclude = true;
        false
      } else {
        true
      }
    });
    need_exclude
  }

  fn calculate_moves(
    trajectories1: &mut Vec<Trajectory>,
    trajectories2: &mut Vec<Trajectory>,
    empty_board: &mut Vec<u32>,
  ) -> Vec<Pos> {
    TrajectoriesPruning::project(trajectories1, empty_board);
    TrajectoriesPruning::project(trajectories2, empty_board);
    while TrajectoriesPruning::exclude_unnecessary_trajectories(trajectories1, empty_board)
      || TrajectoriesPruning::exclude_unnecessary_trajectories(trajectories2, empty_board)
    {}
    let mut result_set = HashSet::new();
    for &pos in trajectories1
      .iter()
      .chain(trajectories2.iter())
      .flat_map(|trajectory| trajectory.points().iter())
    {
      result_set.insert(pos);
    }
    let mut result = result_set.into_iter().collect::<Vec<Pos>>();
    result.sort_unstable_by(|&pos1, &pos2| empty_board[pos2].cmp(&empty_board[pos1]));
    TrajectoriesPruning::deproject(trajectories1, empty_board);
    TrajectoriesPruning::deproject(trajectories2, empty_board);
    TrajectoriesPruning::project_length(trajectories1, empty_board);
    TrajectoriesPruning::project_length(trajectories2, empty_board);
    result.sort_by(|&pos1, &pos2| empty_board[pos1].cmp(&empty_board[pos2]));
    TrajectoriesPruning::deproject(trajectories1, empty_board);
    TrajectoriesPruning::deproject(trajectories2, empty_board);
    result
  }

  #[inline]
  pub fn empty(rebuild_trajectories: bool) -> TrajectoriesPruning {
    TrajectoriesPruning {
      rebuild_trajectories,
      cur_trajectories: Vec::with_capacity(0),
      enemy_trajectories: Vec::with_capacity(0),
      moves: Vec::with_capacity(0),
    }
  }

  pub fn new(
    rebuild_trajectories: bool,
    field: &mut Field,
    player: Player,
    depth: u32,
    empty_board: &mut Vec<u32>,
    should_stop: &AtomicBool,
  ) -> TrajectoriesPruning {
    if depth == 0 {
      return TrajectoriesPruning::empty(rebuild_trajectories);
    }
    let mut cur_trajectories =
      TrajectoriesPruning::build_trajectories(field, player, (depth + 1) / 2, empty_board, should_stop);
    if should_stop.load(Ordering::Relaxed) {
      return TrajectoriesPruning::empty(rebuild_trajectories);
    }
    let mut enemy_trajectories =
      TrajectoriesPruning::build_trajectories(field, player.next(), depth / 2, empty_board, should_stop);
    if should_stop.load(Ordering::Relaxed) {
      return TrajectoriesPruning::empty(rebuild_trajectories);
    }
    let moves = TrajectoriesPruning::calculate_moves(&mut cur_trajectories, &mut enemy_trajectories, empty_board);
    TrajectoriesPruning {
      rebuild_trajectories,
      cur_trajectories,
      enemy_trajectories,
      moves,
    }
  }

  fn last_pos_trajectory(field: &Field, player: Player, depth: u32, last_pos: Pos) -> Option<Trajectory> {
    let mut points = Vec::with_capacity(4);
    let mut hash = 0;
    for &pos in &field.directions(last_pos) {
      if field.cell(pos).is_putting_allowed() {
        let mut neighbors_count = 0;
        for &neighbor in &field.directions(pos) {
          if field.cell(neighbor).is_players_point(player) {
            neighbors_count += 1;
          }
        }
        if neighbors_count < 3 {
          points.push(pos);
          hash ^= field.zobrist().get_hash(pos);
        }
      } else if !field.cell(pos).is_players_point(player) {
        return None;
      }
    }
    if points.len() as u32 <= (depth + 1) / 2 {
      Some(Trajectory::new(points, hash))
    } else {
      None
    }
  }

  pub fn next(
    &self,
    field: &mut Field,
    player: Player,
    depth: u32,
    empty_board: &mut Vec<u32>,
    last_pos: Pos,
    should_stop: &AtomicBool,
  ) -> TrajectoriesPruning {
    if depth == 0 {
      return TrajectoriesPruning::empty(self.rebuild_trajectories);
    }
    let mut cur_trajectories = if self.rebuild_trajectories {
      TrajectoriesPruning::build_trajectories(field, player, (depth + 1) / 2, empty_board, should_stop)
    } else {
      self
        .enemy_trajectories
        .iter()
        .filter(|trajectory| {
          trajectory
            .points()
            .iter()
            .all(|&pos| field.cell(pos).is_putting_allowed())
        })
        .cloned()
        .chain(TrajectoriesPruning::last_pos_trajectory(field, player, depth, last_pos).into_iter())
        .collect()
    };
    if should_stop.load(Ordering::Relaxed) {
      return TrajectoriesPruning::empty(self.rebuild_trajectories);
    }
    let enemy_depth = depth / 2;
    let mut enemy_trajectories = if enemy_depth > 0 {
      self
        .cur_trajectories
        .iter()
        .filter_map(|trajectory| {
          let len = trajectory.len() as u32;
          let contains_pos = trajectory.points().contains(&last_pos);
          if (len <= enemy_depth || len == enemy_depth + 1 && contains_pos)
            && trajectory
              .points()
              .iter()
              .all(|&pos| field.cell(pos).is_putting_allowed() || pos == last_pos)
          {
            let new_trajectory = if contains_pos {
              if len == 1 {
                return None;
              }
              Trajectory::new(
                trajectory
                  .points
                  .iter()
                  .cloned()
                  .filter(|&pos| pos != last_pos)
                  .collect(),
                trajectory.hash() ^ field.zobrist().get_hash(last_pos),
              )
            } else {
              trajectory.clone()
            };
            Some(new_trajectory)
          } else {
            None
          }
        })
        .collect()
    } else {
      Vec::new()
    };
    if should_stop.load(Ordering::Relaxed) {
      return TrajectoriesPruning::empty(self.rebuild_trajectories);
    }
    let moves = TrajectoriesPruning::calculate_moves(&mut cur_trajectories, &mut enemy_trajectories, empty_board);
    TrajectoriesPruning {
      rebuild_trajectories: self.rebuild_trajectories,
      cur_trajectories,
      enemy_trajectories,
      moves,
    }
  }

  pub fn dec_and_swap(&self, depth: u32, empty_board: &mut Vec<u32>, should_stop: &AtomicBool) -> TrajectoriesPruning {
    if depth == 0 {
      return TrajectoriesPruning::empty(self.rebuild_trajectories);
    }
    let mut cur_trajectories = self.enemy_trajectories.clone();
    let enemy_depth = depth / 2;
    let mut enemy_trajectories = if enemy_depth > 0 {
      self
        .cur_trajectories
        .iter()
        .filter(|trajectory| trajectory.len() as u32 <= enemy_depth)
        .cloned()
        .collect()
    } else {
      Vec::new()
    };
    if should_stop.load(Ordering::Relaxed) {
      return TrajectoriesPruning::empty(self.rebuild_trajectories);
    }
    let moves = TrajectoriesPruning::calculate_moves(&mut cur_trajectories, &mut enemy_trajectories, empty_board);
    TrajectoriesPruning {
      rebuild_trajectories: self.rebuild_trajectories,
      cur_trajectories,
      enemy_trajectories,
      moves,
    }
  }

  pub fn inc(
    &self,
    field: &mut Field,
    player: Player,
    depth: u32,
    empty_board: &mut Vec<u32>,
    should_stop: &AtomicBool,
  ) -> TrajectoriesPruning {
    let (mut cur_trajectories, mut enemy_trajectories) = if depth % 2 == 0 {
      let enemy_trajectories =
        TrajectoriesPruning::build_trajectories(field, player.next(), depth / 2, empty_board, should_stop);
      if should_stop.load(Ordering::Relaxed) {
        return TrajectoriesPruning::empty(self.rebuild_trajectories);
      }
      (self.cur_trajectories.clone(), enemy_trajectories)
    } else {
      let cur_trajectories =
        TrajectoriesPruning::build_trajectories(field, player, (depth + 1) / 2, empty_board, should_stop);
      if should_stop.load(Ordering::Relaxed) {
        return TrajectoriesPruning::empty(self.rebuild_trajectories);
      }
      (cur_trajectories, self.enemy_trajectories.clone())
    };
    if should_stop.load(Ordering::Relaxed) {
      return TrajectoriesPruning::empty(self.rebuild_trajectories);
    }
    let moves = TrajectoriesPruning::calculate_moves(&mut cur_trajectories, &mut enemy_trajectories, empty_board);
    TrajectoriesPruning {
      rebuild_trajectories: self.rebuild_trajectories,
      cur_trajectories,
      enemy_trajectories,
      moves,
    }
  }

  pub fn moves(&self) -> &Vec<Pos> {
    &self.moves
  }

  pub fn moves_mut(&mut self) -> &mut Vec<Pos> {
    &mut self.moves
  }
}
<commit_msg>Mark less cells.<commit_after>use oppai_field::field::{euclidean, wave_diag, Field, Pos};
use oppai_field::player::Player;
use std::{
  collections::HashSet,
  ops::Index,
  sync::atomic::{AtomicBool, Ordering},
};

#[derive(Debug, Clone)]
struct Trajectory {
  points: Vec<Pos>,
  hash: u64,
}

impl Trajectory {
  pub fn new(points: Vec<Pos>, hash: u64) -> Trajectory {
    Trajectory { points, hash }
  }

  pub fn points(&self) -> &Vec<Pos> {
    &self.points
  }

  pub fn hash(&self) -> u64 {
    self.hash
  }

  pub fn len(&self) -> usize {
    self.points.len()
  }
}

pub struct TrajectoriesPruning {
  rebuild_trajectories: bool,
  cur_trajectories: Vec<Trajectory>,
  enemy_trajectories: Vec<Trajectory>,
  moves: Vec<Pos>,
}

impl TrajectoriesPruning {
  fn add_trajectory(field: &Field, trajectories: &mut Vec<Trajectory>, points: &[Pos], player: Player) {
    for &pos in points {
      if !field.cell(pos).is_bound() || field.number_near_groups(pos, player) < 2 {
        return;
      }
    }
    let zobrist = field.zobrist();
    let mut hash = 0u64;
    for &pos in points {
      hash ^= zobrist.get_hash(pos);
    }
    for trajectory in trajectories.iter() {
      if trajectory.hash() == hash {
        return;
      }
    }
    let trajectory = Trajectory::new(points.to_vec(), hash);
    trajectories.push(trajectory);
  }

  fn next_moves(
    field: &Field,
    start_pos: Pos,
    player: Player,
    empty_board: &mut Vec<u32>,
    marks: &mut Vec<Pos>,
  ) -> Vec<Pos> {
    let mut moves = Vec::new();
    wave_diag(field.width(), start_pos, |pos| {
      if empty_board[pos] != 0 {
        return false;
      }
      let cell = field.cell(pos);
      if cell.is_players_point(player) {
        empty_board[pos] = 1;
        marks.push(pos);
        true
      } else {
        if cell.is_putting_allowed() && !cell.is_players_empty_base(player) {
          empty_board[pos] = 1;
          moves.push(pos);
        }
        false
      }
    });
    for &pos in &moves {
      empty_board[pos] = 0;
    }
    moves
  }

  fn build_trajectories_rec(
    field: &mut Field,
    trajectories: &mut Vec<Trajectory>,
    player: Player,
    cur_depth: u32,
    depth: u32,
    empty_board: &mut Vec<u32>,
    last_pos: Pos,
    moves: Vec<Pos>,
    should_stop: &AtomicBool,
  ) {
    for pos in moves {
      if should_stop.load(Ordering::Relaxed) {
        break;
      }
      if field.number_near_points(pos, player) >= 3 {
        continue;
      }
      let cell = field.cell(pos);
      if cell.is_players_empty_base(player.next()) {
        field.put_point(pos, player);
        if field.get_delta_score(player) > 0 {
          TrajectoriesPruning::add_trajectory(
            field,
            trajectories,
            field
              .points_seq()
              .index(field.moves_count() - cur_depth as usize..field.moves_count()),
            player,
          );
        }
        field.undo();
      } else {
        field.put_point(pos, player);
        if field.get_delta_score(player) > 0 {
          TrajectoriesPruning::add_trajectory(
            field,
            trajectories,
            field
              .points_seq()
              .index(field.moves_count() - cur_depth as usize..field.moves_count()),
            player,
          );
        } else if depth > 0 {
          let mut marks = Vec::new();
          let mut next_moves = TrajectoriesPruning::next_moves(field, pos, player, empty_board, &mut marks);
          if last_pos != 0 {
            next_moves.retain(|&next_pos| euclidean(field.width(), last_pos, next_pos) > 2);
          }
          TrajectoriesPruning::build_trajectories_rec(
            field,
            trajectories,
            player,
            cur_depth + 1,
            depth - 1,
            empty_board,
            pos,
            next_moves,
            should_stop,
          );
          for mark_pos in marks {
            empty_board[mark_pos] = 0;
          }
        }
        field.undo();
      }
    }
  }

  fn build_trajectories(
    field: &mut Field,
    player: Player,
    depth: u32,
    empty_board: &mut Vec<u32>,
    should_stop: &AtomicBool,
  ) -> Vec<Trajectory> {
    let mut trajectories = Vec::new();

    if depth == 0 {
      return trajectories;
    }

    let mut marks = Vec::new();
    for pos in field.points_seq().clone() {
      if field.cell(pos).get_player() != player {
        continue;
      }

      if should_stop.load(Ordering::Relaxed) {
        break;
      }

      let moves = TrajectoriesPruning::next_moves(field, pos, player, empty_board, &mut marks);

      TrajectoriesPruning::build_trajectories_rec(
        field,
        &mut trajectories,
        player,
        1,
        depth - 1,
        empty_board,
        0,
        moves,
        should_stop,
      );
    }

    for pos in marks {
      empty_board[pos] = 0;
    }

    trajectories
  }

  fn project(trajectories: &[Trajectory], empty_board: &mut Vec<u32>) {
    for &pos in trajectories.iter().flat_map(|trajectory| trajectory.points().iter()) {
      empty_board[pos] += 1;
    }
  }

  fn project_length(trajectories: &[Trajectory], empty_board: &mut Vec<u32>) {
    for trajectory in trajectories {
      let len = trajectory.len() as u32;
      for &pos in trajectory.points() {
        if empty_board[pos] == 0 || empty_board[pos] > len {
          empty_board[pos] = len;
        }
      }
    }
  }

  fn deproject(trajectories: &[Trajectory], empty_board: &mut Vec<u32>) {
    for &pos in trajectories.iter().flat_map(|trajectory| trajectory.points().iter()) {
      empty_board[pos] = 0;
    }
  }

  fn exclude_unnecessary_trajectories(trajectories: &mut Vec<Trajectory>, empty_board: &mut Vec<u32>) -> bool {
    let mut need_exclude = false;
    trajectories.retain(|trajectory| {
      let single_count = trajectory.points().iter().filter(|&&pos| empty_board[pos] == 1).count();
      if single_count > 1 {
        for &pos in trajectory.points() {
          empty_board[pos] -= 1;
        }
        need_exclude = true;
        false
      } else {
        true
      }
    });
    need_exclude
  }

  fn calculate_moves(
    trajectories1: &mut Vec<Trajectory>,
    trajectories2: &mut Vec<Trajectory>,
    empty_board: &mut Vec<u32>,
  ) -> Vec<Pos> {
    TrajectoriesPruning::project(trajectories1, empty_board);
    TrajectoriesPruning::project(trajectories2, empty_board);
    while TrajectoriesPruning::exclude_unnecessary_trajectories(trajectories1, empty_board)
      || TrajectoriesPruning::exclude_unnecessary_trajectories(trajectories2, empty_board)
    {}
    let mut result_set = HashSet::new();
    for &pos in trajectories1
      .iter()
      .chain(trajectories2.iter())
      .flat_map(|trajectory| trajectory.points().iter())
    {
      result_set.insert(pos);
    }
    let mut result = result_set.into_iter().collect::<Vec<Pos>>();
    result.sort_unstable_by(|&pos1, &pos2| empty_board[pos2].cmp(&empty_board[pos1]));
    TrajectoriesPruning::deproject(trajectories1, empty_board);
    TrajectoriesPruning::deproject(trajectories2, empty_board);
    TrajectoriesPruning::project_length(trajectories1, empty_board);
    TrajectoriesPruning::project_length(trajectories2, empty_board);
    result.sort_by(|&pos1, &pos2| empty_board[pos1].cmp(&empty_board[pos2]));
    TrajectoriesPruning::deproject(trajectories1, empty_board);
    TrajectoriesPruning::deproject(trajectories2, empty_board);
    result
  }

  #[inline]
  pub fn empty(rebuild_trajectories: bool) -> TrajectoriesPruning {
    TrajectoriesPruning {
      rebuild_trajectories,
      cur_trajectories: Vec::with_capacity(0),
      enemy_trajectories: Vec::with_capacity(0),
      moves: Vec::with_capacity(0),
    }
  }

  pub fn new(
    rebuild_trajectories: bool,
    field: &mut Field,
    player: Player,
    depth: u32,
    empty_board: &mut Vec<u32>,
    should_stop: &AtomicBool,
  ) -> TrajectoriesPruning {
    if depth == 0 {
      return TrajectoriesPruning::empty(rebuild_trajectories);
    }
    let mut cur_trajectories =
      TrajectoriesPruning::build_trajectories(field, player, (depth + 1) / 2, empty_board, should_stop);
    if should_stop.load(Ordering::Relaxed) {
      return TrajectoriesPruning::empty(rebuild_trajectories);
    }
    let mut enemy_trajectories =
      TrajectoriesPruning::build_trajectories(field, player.next(), depth / 2, empty_board, should_stop);
    if should_stop.load(Ordering::Relaxed) {
      return TrajectoriesPruning::empty(rebuild_trajectories);
    }
    let moves = TrajectoriesPruning::calculate_moves(&mut cur_trajectories, &mut enemy_trajectories, empty_board);
    TrajectoriesPruning {
      rebuild_trajectories,
      cur_trajectories,
      enemy_trajectories,
      moves,
    }
  }

  fn last_pos_trajectory(field: &Field, player: Player, depth: u32, last_pos: Pos) -> Option<Trajectory> {
    let mut points = Vec::with_capacity(4);
    let mut hash = 0;
    for &pos in &field.directions(last_pos) {
      if field.cell(pos).is_putting_allowed() {
        let mut neighbors_count = 0;
        for &neighbor in &field.directions(pos) {
          if field.cell(neighbor).is_players_point(player) {
            neighbors_count += 1;
          }
        }
        if neighbors_count < 3 {
          points.push(pos);
          hash ^= field.zobrist().get_hash(pos);
        }
      } else if !field.cell(pos).is_players_point(player) {
        return None;
      }
    }
    if points.len() as u32 <= (depth + 1) / 2 {
      Some(Trajectory::new(points, hash))
    } else {
      None
    }
  }

  pub fn next(
    &self,
    field: &mut Field,
    player: Player,
    depth: u32,
    empty_board: &mut Vec<u32>,
    last_pos: Pos,
    should_stop: &AtomicBool,
  ) -> TrajectoriesPruning {
    if depth == 0 {
      return TrajectoriesPruning::empty(self.rebuild_trajectories);
    }
    let mut cur_trajectories = if self.rebuild_trajectories {
      TrajectoriesPruning::build_trajectories(field, player, (depth + 1) / 2, empty_board, should_stop)
    } else {
      self
        .enemy_trajectories
        .iter()
        .filter(|trajectory| {
          trajectory
            .points()
            .iter()
            .all(|&pos| field.cell(pos).is_putting_allowed())
        })
        .cloned()
        .chain(TrajectoriesPruning::last_pos_trajectory(field, player, depth, last_pos).into_iter())
        .collect()
    };
    if should_stop.load(Ordering::Relaxed) {
      return TrajectoriesPruning::empty(self.rebuild_trajectories);
    }
    let enemy_depth = depth / 2;
    let mut enemy_trajectories = if enemy_depth > 0 {
      self
        .cur_trajectories
        .iter()
        .filter_map(|trajectory| {
          let len = trajectory.len() as u32;
          let contains_pos = trajectory.points().contains(&last_pos);
          if (len <= enemy_depth || len == enemy_depth + 1 && contains_pos)
            && trajectory
              .points()
              .iter()
              .all(|&pos| field.cell(pos).is_putting_allowed() || pos == last_pos)
          {
            let new_trajectory = if contains_pos {
              if len == 1 {
                return None;
              }
              Trajectory::new(
                trajectory
                  .points
                  .iter()
                  .cloned()
                  .filter(|&pos| pos != last_pos)
                  .collect(),
                trajectory.hash() ^ field.zobrist().get_hash(last_pos),
              )
            } else {
              trajectory.clone()
            };
            Some(new_trajectory)
          } else {
            None
          }
        })
        .collect()
    } else {
      Vec::new()
    };
    if should_stop.load(Ordering::Relaxed) {
      return TrajectoriesPruning::empty(self.rebuild_trajectories);
    }
    let moves = TrajectoriesPruning::calculate_moves(&mut cur_trajectories, &mut enemy_trajectories, empty_board);
    TrajectoriesPruning {
      rebuild_trajectories: self.rebuild_trajectories,
      cur_trajectories,
      enemy_trajectories,
      moves,
    }
  }

  pub fn dec_and_swap(&self, depth: u32, empty_board: &mut Vec<u32>, should_stop: &AtomicBool) -> TrajectoriesPruning {
    if depth == 0 {
      return TrajectoriesPruning::empty(self.rebuild_trajectories);
    }
    let mut cur_trajectories = self.enemy_trajectories.clone();
    let enemy_depth = depth / 2;
    let mut enemy_trajectories = if enemy_depth > 0 {
      self
        .cur_trajectories
        .iter()
        .filter(|trajectory| trajectory.len() as u32 <= enemy_depth)
        .cloned()
        .collect()
    } else {
      Vec::new()
    };
    if should_stop.load(Ordering::Relaxed) {
      return TrajectoriesPruning::empty(self.rebuild_trajectories);
    }
    let moves = TrajectoriesPruning::calculate_moves(&mut cur_trajectories, &mut enemy_trajectories, empty_board);
    TrajectoriesPruning {
      rebuild_trajectories: self.rebuild_trajectories,
      cur_trajectories,
      enemy_trajectories,
      moves,
    }
  }

  pub fn inc(
    &self,
    field: &mut Field,
    player: Player,
    depth: u32,
    empty_board: &mut Vec<u32>,
    should_stop: &AtomicBool,
  ) -> TrajectoriesPruning {
    let (mut cur_trajectories, mut enemy_trajectories) = if depth % 2 == 0 {
      let enemy_trajectories =
        TrajectoriesPruning::build_trajectories(field, player.next(), depth / 2, empty_board, should_stop);
      if should_stop.load(Ordering::Relaxed) {
        return TrajectoriesPruning::empty(self.rebuild_trajectories);
      }
      (self.cur_trajectories.clone(), enemy_trajectories)
    } else {
      let cur_trajectories =
        TrajectoriesPruning::build_trajectories(field, player, (depth + 1) / 2, empty_board, should_stop);
      if should_stop.load(Ordering::Relaxed) {
        return TrajectoriesPruning::empty(self.rebuild_trajectories);
      }
      (cur_trajectories, self.enemy_trajectories.clone())
    };
    if should_stop.load(Ordering::Relaxed) {
      return TrajectoriesPruning::empty(self.rebuild_trajectories);
    }
    let moves = TrajectoriesPruning::calculate_moves(&mut cur_trajectories, &mut enemy_trajectories, empty_board);
    TrajectoriesPruning {
      rebuild_trajectories: self.rebuild_trajectories,
      cur_trajectories,
      enemy_trajectories,
      moves,
    }
  }

  pub fn moves(&self) -> &Vec<Pos> {
    &self.moves
  }

  pub fn moves_mut(&mut self) -> &mut Vec<Pos> {
    &mut self.moves
  }
}
<|endoftext|>


<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/. */

extern crate mozangle;
extern crate webrender;

use mozangle::shaders::{BuiltInResources, Output, ShaderSpec, ShaderValidator};

// from glslang
const FRAGMENT_SHADER: u32 = 0x8B30;
const VERTEX_SHADER: u32 = 0x8B31;

struct Shader {
    name: &'static str,
    features: &'static [&'static str],
}

const SHADER_PREFIX: &str = "#define WR_MAX_VERTEX_TEXTURE_WIDTH 1024\n";

const CLIP_FEATURES: &[&str] = &["TRANSFORM"];
const CACHE_FEATURES: &[&str] = &[""];
const PRIM_FEATURES: &[&str] = &["", "TRANSFORM"];

const SHADERS: &[Shader] = &[
    // Clip mask shaders
    Shader {
        name: "cs_clip_rectangle",
        features: CLIP_FEATURES,
    },
    Shader {
        name: "cs_clip_image",
        features: CLIP_FEATURES,
    },
    Shader {
        name: "cs_clip_box_shadow",
        features: CLIP_FEATURES,
    },
    Shader {
        name: "cs_clip_line",
        features: CLIP_FEATURES,
    },
    // Cache shaders
    Shader {
        name: "cs_blur",
        features: CACHE_FEATURES,
    },
    Shader {
        name: "cs_border_segment",
        features: CACHE_FEATURES,
    },
    // Prim shaders
    Shader {
        name: "ps_split_composite",
        features: PRIM_FEATURES,
    },
    Shader {
        name: "ps_text_run",
        features: PRIM_FEATURES,
    },
    // Brush shaders
    Shader {
        name: "brush_yuv_image",
        features: &["", "YUV_NV12", "YUV_PLANAR", "YUV_INTERLEAVED", "YUV_NV12,TEXTURE_RECT"],
    },
    Shader {
        name: "brush_solid",
        features: &[],
    },
    Shader {
        name: "brush_image",
        features: &["", "ALPHA_PASS"],
    },
    Shader {
        name: "brush_blend",
        features: &[],
    },
    Shader {
        name: "brush_mix_blend",
        features: &[],
    },
    Shader {
        name: "brush_radial_gradient",
        features: &[ "DITHERING" ],
    },
    Shader {
        name: "brush_linear_gradient",
        features: &[],
    },
];

const VERSION_STRING: &str = "#version 300 es\n";

#[test]
fn validate_shaders() {
    mozangle::shaders::initialize().unwrap();

    let resources = BuiltInResources::default();
    let vs_validator =
        ShaderValidator::new(VERTEX_SHADER, ShaderSpec::Gles3, Output::Essl, &resources).unwrap();

    let fs_validator =
        ShaderValidator::new(FRAGMENT_SHADER, ShaderSpec::Gles3, Output::Essl, &resources).unwrap();

    for shader in SHADERS {
        for config in shader.features {
            let mut features = String::new();
            features.push_str(SHADER_PREFIX);

            for feature in config.split(",") {
                features.push_str(&format!("#define WR_FEATURE_{}", feature));
            }

            let (vs, fs) =
                webrender::build_shader_strings(VERSION_STRING, &features, shader.name, &None);

            validate(&vs_validator, shader.name, vs);
            validate(&fs_validator, shader.name, fs);
        }
    }
}

fn validate(validator: &ShaderValidator, name: &str, source: String) {
    // Check for each `switch` to have a `default`, see
    // https://github.com/servo/webrender/wiki/Driver-issues#lack-of-default-case-in-a-switch
    assert_eq!(source.matches("switch").count(), source.matches("default:").count(),
        "Shader '{}' doesn't have all `switch` covered with `default` cases", name);
    // Run Angle validator
    match validator.compile_and_translate(&[&source]) {
        Ok(_) => {
            println!("Shader translated succesfully: {}", name);
        }
        Err(_) => {
            panic!(
                "Shader compilation failed: {}\n{}",
                name,
                validator.info_log()
            );
        }
    }
}
<commit_msg>Auto merge of #2873 - zakorgy:angle-validator-fix, 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/. */

extern crate mozangle;
extern crate webrender;

use mozangle::shaders::{BuiltInResources, Output, ShaderSpec, ShaderValidator};

// from glslang
const FRAGMENT_SHADER: u32 = 0x8B30;
const VERTEX_SHADER: u32 = 0x8B31;

struct Shader {
    name: &'static str,
    features: &'static [&'static str],
}

const SHADER_PREFIX: &str = "#define WR_MAX_VERTEX_TEXTURE_WIDTH 1024\n";

const BRUSH_FEATURES: &[&str] = &["", "ALPHA_PASS"];
const CLIP_FEATURES: &[&str] = &["TRANSFORM"];
const CACHE_FEATURES: &[&str] = &[""];
const GRADIENT_FEATURES: &[&str] = &[ "", "DITHERING", "ALPHA_PASS", "DITHERING,ALPHA_PASS" ];
const PRIM_FEATURES: &[&str] = &[""];

const SHADERS: &[Shader] = &[
    // Clip mask shaders
    Shader {
        name: "cs_clip_rectangle",
        features: CLIP_FEATURES,
    },
    Shader {
        name: "cs_clip_image",
        features: CLIP_FEATURES,
    },
    Shader {
        name: "cs_clip_box_shadow",
        features: CLIP_FEATURES,
    },
    Shader {
        name: "cs_clip_line",
        features: CLIP_FEATURES,
    },
    // Cache shaders
    Shader {
        name: "cs_blur",
        features: &[ "ALPHA_TARGET", "COLOR_TARGET" ],
    },
    Shader {
        name: "cs_border_segment",
        features: CACHE_FEATURES,
    },
    // Prim shaders
    Shader {
        name: "ps_split_composite",
        features: PRIM_FEATURES,
    },
    Shader {
        name: "ps_text_run",
        features: &[ "", "GLYPH_TRANSFORM" ],
    },
    // Brush shaders
    Shader {
        name: "brush_yuv_image",
        features: &[
            "",
            "YUV_NV12",
            "YUV_PLANAR",
            "YUV_INTERLEAVED",
            "TEXTURE_2D,YUV_NV12",
            "YUV_NV12,ALPHA_PASS",
        ],
    },
    Shader {
        name: "brush_solid",
        features: BRUSH_FEATURES,
    },
    Shader {
        name: "brush_image",
        features: BRUSH_FEATURES,
    },
    Shader {
        name: "brush_blend",
        features: BRUSH_FEATURES,
    },
    Shader {
        name: "brush_mix_blend",
        features: BRUSH_FEATURES,
    },
    Shader {
        name: "brush_radial_gradient",
        features: GRADIENT_FEATURES,
    },
    Shader {
        name: "brush_linear_gradient",
        features: GRADIENT_FEATURES,
    },
];

const VERSION_STRING: &str = "#version 300 es\n";

#[test]
fn validate_shaders() {
    mozangle::shaders::initialize().unwrap();

    let resources = BuiltInResources::default();
    let vs_validator =
        ShaderValidator::new(VERTEX_SHADER, ShaderSpec::Gles3, Output::Essl, &resources).unwrap();

    let fs_validator =
        ShaderValidator::new(FRAGMENT_SHADER, ShaderSpec::Gles3, Output::Essl, &resources).unwrap();

    for shader in SHADERS {
        for config in shader.features {
            let mut features = String::new();
            features.push_str(SHADER_PREFIX);

            for feature in config.split(",") {
                features.push_str(&format!("#define WR_FEATURE_{}\n", feature));
            }

            let (vs, fs) =
                webrender::build_shader_strings(VERSION_STRING, &features, shader.name, &None);

            validate(&vs_validator, shader.name, vs);
            validate(&fs_validator, shader.name, fs);
        }
    }
}

fn validate(validator: &ShaderValidator, name: &str, source: String) {
    // Check for each `switch` to have a `default`, see
    // https://github.com/servo/webrender/wiki/Driver-issues#lack-of-default-case-in-a-switch
    assert_eq!(source.matches("switch").count(), source.matches("default:").count(),
        "Shader '{}' doesn't have all `switch` covered with `default` cases", name);
    // Run Angle validator
    match validator.compile_and_translate(&[&source]) {
        Ok(_) => {
            println!("Shader translated succesfully: {}", name);
        }
        Err(_) => {
            panic!(
                "Shader compilation failed: {}\n{}",
                name,
                validator.info_log()
            );
        }
    }
}
<|endoftext|>


<commit_before>extern crate roadrunner;
extern crate tokio_core;
extern crate hyper;
extern crate serde_json;
extern crate base64;
extern crate mime;
extern crate env_logger;

#[macro_use]
extern crate serde_derive;

use roadrunner::RestClient;
use roadrunner::RestClientMethods;
use hyper::status::StatusCode;
use serde_json::Value;

mod httpbin;

fn setup() {
   let _ = env_logger::init();
}

#[derive(Serialize, Deserialize, Debug, PartialEq)]
struct Address {
    street: String,
    city: String,
}

#[test]
fn rest_client_delete_test() {
    setup();

    let mut core = tokio_core::reactor::Core::new().unwrap();

    let url = httpbin::to_full_http_url("/delete");
    let response = RestClient::delete(&url)
        .execute_on(&mut core)
        .unwrap();

    println!("{:?}", response);

    assert_eq!(*response.status(), StatusCode::Ok);

    let json_value = response.content().as_value().unwrap();
    assert_eq!(Value::String(url),
    json_value["url"]);
}

#[test]
fn rest_client_json_body_typed_patch_test() {
    setup();

    let mut core = tokio_core::reactor::Core::new().unwrap();

    let original_typed = Address {
        street: "135 College View Ave.".to_owned(),
        city: "Greenville".to_owned(),
    };

    let response = RestClient::patch(&httpbin::to_full_http_url("/patch"))
        .json_body_typed(&original_typed)
        .execute_on(&mut core)
        .unwrap();

    println!("{:?}", response);

    assert_eq!(*response.status(), StatusCode::Ok);

    let json_value = response.content().as_value().unwrap();
    assert_eq!(Value::String("application/json".to_owned()), json_value["headers"]["Content-Type"]);

    let data_str = json_value["data"].as_str().unwrap();

    println!("data_str : {:?}", data_str);

    let response_typed: Address = serde_json::from_str(data_str).unwrap();
    assert_eq!(original_typed, response_typed);
}

#[test]
fn rest_client_json_body_typed_put_test() {
    setup();

    let mut core = tokio_core::reactor::Core::new().unwrap();

    let original_typed = Address {
        street: "135 College View Ave.".to_owned(),
        city: "Greenville".to_owned(),
    };

    let response = RestClient::put(&httpbin::to_full_http_url("/put"))
        .json_body_typed(&original_typed)
        .execute_on(&mut core)
        .unwrap();

    println!("{:?}", response);

    assert_eq!(*response.status(), StatusCode::Ok);

    let json_value = response.content().as_value().unwrap();
    assert_eq!(Value::String("application/json".to_owned()), json_value["headers"]["Content-Type"]);

    let data_str = json_value["data"].as_str().unwrap();

    println!("data_str : {:?}", data_str);

    let response_typed: Address = serde_json::from_str(data_str).unwrap();
    assert_eq!(original_typed, response_typed);
}

#[test]
fn rest_client_options_test() {
    setup();

    let mut core = tokio_core::reactor::Core::new().unwrap();

    let response = RestClient::options(&httpbin::to_full_http_url("/headers"))
        .execute_on(&mut core)
        .unwrap();

    println!("{:?}", response);

    assert_eq!(*response.status(), StatusCode::Ok);

    let allow_methods = response.headers().get::<hyper::header::Allow>().unwrap().as_slice();
    let mut iterator = allow_methods.iter();
    assert_eq!(Some(&hyper::Method::Head), iterator.next());
    assert_eq!(Some(&hyper::Method::Get), iterator.next());
    assert_eq!(Some(&hyper::Method::Options), iterator.next());
    assert_eq!(None, iterator.next());
}

#[test]
fn rest_client_json_body_typed_post_test() {
    setup();

    let mut core = tokio_core::reactor::Core::new().unwrap();

    let original_typed = Address {
        street: "135 College View Ave.".to_owned(),
        city: "Greenville".to_owned(),
    };

    let response = RestClient::post(&httpbin::to_full_http_url("/post"))
        .json_body_typed(&original_typed)
        .execute_on(&mut core)
        .unwrap();

    println!("{:?}", response);

    assert_eq!(*response.status(), StatusCode::Ok);

    let json_value = response.content().as_value().unwrap();
    assert_eq!(Value::String("application/json".to_owned()), json_value["headers"]["Content-Type"]);

    let data_str = json_value["data"].as_str().unwrap();

    println!("data_str : {:?}", data_str);

    let response_typed: Address = serde_json::from_str(data_str).unwrap();
    assert_eq!(original_typed, response_typed);
}

#[test]
fn rest_client_json_body_str_post_test() {
    setup();

    let mut core = tokio_core::reactor::Core::new().unwrap();

    let json_str = r#"{ "hello": "world" }"#;

    let response = RestClient::post(&httpbin::to_full_http_url("/post"))
        .json_body_str(json_str.to_owned())
        .execute_on(&mut core)
        .unwrap();

    println!("{:?}", response);

    assert_eq!(*response.status(), StatusCode::Ok);

    let json_value = response.content().as_value().unwrap();
    assert_eq!(Value::String("application/json".to_owned()), json_value["headers"]["Content-Type"]);

    let data_str = json_value["data"].as_str().unwrap();

    println!("data_str : {:?}", data_str);

    let json_value_got_back: Value = serde_json::from_str(data_str).unwrap();
    println!("json value got back: {:?}", json_value_got_back);

    assert_eq!(Value::String("world".to_string()), json_value_got_back["hello"]);
}

#[test]
fn rest_client_form_field_post_test() {
    setup();

    let mut core = tokio_core::reactor::Core::new().unwrap();

    let response = RestClient::post(&httpbin::to_full_http_url("/post"))
        .query_param("question1", "hello")
        .form_field("foo", "bar1")
        .form_field("foo", "bar2")
        .execute_on(&mut core)
        .unwrap();

    println!("{:?}", response);

    assert_eq!(*response.status(), StatusCode::Ok);

    let json_value = response.content().as_value().unwrap();
    assert_eq!(Value::Array(vec![Value::String("bar1".to_string()),
                                 Value::String("bar2".to_owned())]), json_value["form"]["foo"]);
}
<commit_msg>Make a test more stable<commit_after>extern crate roadrunner;
extern crate tokio_core;
extern crate hyper;
extern crate serde_json;
extern crate base64;
extern crate mime;
extern crate env_logger;

#[macro_use]
extern crate serde_derive;

use roadrunner::RestClient;
use roadrunner::RestClientMethods;
use hyper::status::StatusCode;
use serde_json::Value;

mod httpbin;

fn setup() {
   let _ = env_logger::init();
}

#[derive(Serialize, Deserialize, Debug, PartialEq)]
struct Address {
    street: String,
    city: String,
}

#[test]
fn rest_client_delete_test() {
    setup();

    let mut core = tokio_core::reactor::Core::new().unwrap();

    let url = httpbin::to_full_http_url("/delete");
    let response = RestClient::delete(&url)
        .execute_on(&mut core)
        .unwrap();

    println!("{:?}", response);

    assert_eq!(*response.status(), StatusCode::Ok);

    let json_value = response.content().as_value().unwrap();
    assert_eq!(Value::String(url),
    json_value["url"]);
}

#[test]
fn rest_client_json_body_typed_patch_test() {
    setup();

    let mut core = tokio_core::reactor::Core::new().unwrap();

    let original_typed = Address {
        street: "135 College View Ave.".to_owned(),
        city: "Greenville".to_owned(),
    };

    let response = RestClient::patch(&httpbin::to_full_http_url("/patch"))
        .json_body_typed(&original_typed)
        .execute_on(&mut core)
        .unwrap();

    println!("{:?}", response);

    assert_eq!(*response.status(), StatusCode::Ok);

    let json_value = response.content().as_value().unwrap();
    assert_eq!(Value::String("application/json".to_owned()), json_value["headers"]["Content-Type"]);

    let data_str = json_value["data"].as_str().unwrap();

    println!("data_str : {:?}", data_str);

    let response_typed: Address = serde_json::from_str(data_str).unwrap();
    assert_eq!(original_typed, response_typed);
}

#[test]
fn rest_client_json_body_typed_put_test() {
    setup();

    let mut core = tokio_core::reactor::Core::new().unwrap();

    let original_typed = Address {
        street: "135 College View Ave.".to_owned(),
        city: "Greenville".to_owned(),
    };

    let response = RestClient::put(&httpbin::to_full_http_url("/put"))
        .json_body_typed(&original_typed)
        .execute_on(&mut core)
        .unwrap();

    println!("{:?}", response);

    assert_eq!(*response.status(), StatusCode::Ok);

    let json_value = response.content().as_value().unwrap();
    assert_eq!(Value::String("application/json".to_owned()), json_value["headers"]["Content-Type"]);

    let data_str = json_value["data"].as_str().unwrap();

    println!("data_str : {:?}", data_str);

    let response_typed: Address = serde_json::from_str(data_str).unwrap();
    assert_eq!(original_typed, response_typed);
}

#[test]
fn rest_client_options_test() {
    setup();

    let mut core = tokio_core::reactor::Core::new().unwrap();

    let response = RestClient::options(&httpbin::to_full_http_url("/headers"))
        .execute_on(&mut core)
        .unwrap();

    println!("{:?}", response);

    assert_eq!(*response.status(), StatusCode::Ok);

    let allow_methods = response.headers().get::<hyper::header::Allow>().unwrap().as_slice();
    let allow_set: std::collections::HashSet<&hyper::Method> = allow_methods.iter().collect();
    assert!(allow_set.contains(&hyper::Method::Head));
    assert!(allow_set.contains(&hyper::Method::Get));
    assert!(allow_set.contains(&hyper::Method::Options));
}

#[test]
fn rest_client_json_body_typed_post_test() {
    setup();

    let mut core = tokio_core::reactor::Core::new().unwrap();

    let original_typed = Address {
        street: "135 College View Ave.".to_owned(),
        city: "Greenville".to_owned(),
    };

    let response = RestClient::post(&httpbin::to_full_http_url("/post"))
        .json_body_typed(&original_typed)
        .execute_on(&mut core)
        .unwrap();

    println!("{:?}", response);

    assert_eq!(*response.status(), StatusCode::Ok);

    let json_value = response.content().as_value().unwrap();
    assert_eq!(Value::String("application/json".to_owned()), json_value["headers"]["Content-Type"]);

    let data_str = json_value["data"].as_str().unwrap();

    println!("data_str : {:?}", data_str);

    let response_typed: Address = serde_json::from_str(data_str).unwrap();
    assert_eq!(original_typed, response_typed);
}

#[test]
fn rest_client_json_body_str_post_test() {
    setup();

    let mut core = tokio_core::reactor::Core::new().unwrap();

    let json_str = r#"{ "hello": "world" }"#;

    let response = RestClient::post(&httpbin::to_full_http_url("/post"))
        .json_body_str(json_str.to_owned())
        .execute_on(&mut core)
        .unwrap();

    println!("{:?}", response);

    assert_eq!(*response.status(), StatusCode::Ok);

    let json_value = response.content().as_value().unwrap();
    assert_eq!(Value::String("application/json".to_owned()), json_value["headers"]["Content-Type"]);

    let data_str = json_value["data"].as_str().unwrap();

    println!("data_str : {:?}", data_str);

    let json_value_got_back: Value = serde_json::from_str(data_str).unwrap();
    println!("json value got back: {:?}", json_value_got_back);

    assert_eq!(Value::String("world".to_string()), json_value_got_back["hello"]);
}

#[test]
fn rest_client_form_field_post_test() {
    setup();

    let mut core = tokio_core::reactor::Core::new().unwrap();

    let response = RestClient::post(&httpbin::to_full_http_url("/post"))
        .query_param("question1", "hello")
        .form_field("foo", "bar1")
        .form_field("foo", "bar2")
        .execute_on(&mut core)
        .unwrap();

    println!("{:?}", response);

    assert_eq!(*response.status(), StatusCode::Ok);

    let json_value = response.content().as_value().unwrap();
    assert_eq!(Value::Array(vec![Value::String("bar1".to_string()),
                                 Value::String("bar2".to_owned())]), json_value["form"]["foo"]);
}
<|endoftext|>


<commit_before>use rules::re::Regex;

#[test]
fn chars() {
    let re = Regex::new(r"Apple");
    assert!(re.is_match("I have an Apple. Do you?"));
}
#[test]
fn whitespace_escapes() {
    let re = Regex::new(r"ping\ pong");
    assert!(re.is_match("Do you like ping pong? I do."));
}
#[test]
fn literals_ticks() {
    let re = Regex::new(r"'two apples'");
    assert!(re.is_match("Are there two apples? Really?"));
}
#[test]
fn literals_quotes() {
    let re = Regex::new(r#""two apples""#);
    assert!(re.is_match("Are there two apples? Really?"));
}
#[test]
fn literals_regular() {
    let re = Regex::new(r#"'2' and "3" and "4" and '5'"#);
    assert!(re.is_match("Well, 2and3and4and5 there."));
}
<commit_msg>Update is_match() tests to test for failure also<commit_after>use rules::re::Regex;

#[test]
fn chars() {
    let re = Regex::new(r"Apple");
    assert!( re.is_match("I have an Apple. Do you?"));
    assert!(!re.is_match("I have an Pear. Do you?"));
}
#[test]
fn whitespace_escapes() {
    let re = Regex::new(r"ping\ pong");
    assert!( re.is_match("Do you like ping pong? I do."));
    assert!(!re.is_match("Do you like golf? I do."));
}
#[test]
fn literals_ticks() {
    let re = Regex::new(r"'two apples'");
    assert!( re.is_match("Are there two apples? Really?"));
    assert!(!re.is_match("Are there two grapes? Really?"));
}
#[test]
fn literals_quotes() {
    let re = Regex::new(r#""two apples""#);
    assert!( re.is_match("Are there two apples? Really?"));
    assert!(!re.is_match("Are there two grapes? Really?"));
}
#[test]
fn literals_regular() {
    let re = Regex::new(r#"'2' and "3" and "4" and '5'"#);
    assert!( re.is_match("Well, 2and3and4and5 there."));
    assert!(!re.is_match("Well, 5and4and3and2 there."));
}
<|endoftext|>