<commit_before>use std::fmt;
use std::mem;
use std::ptr;
use std::slice;
use std::iter;
use std::io::{self, Write};
use std::cmp;
use std::rt::heap;
use std::cell::Cell;
use std::marker::PhantomData;
use std::intrinsics;

// A chunk in the vector
struct Chunk<T> {
    // Previous chunk
    prev: *mut Chunk<T>,
    // Next chunk
    next: *mut Chunk<T>,
    // Count of items
    len: usize,
    // Capacity
    cap: usize,
    // Items follow in memory
    items: [T; 0]
}

pub struct MonoVec<T> {
    head: Cell<*mut Chunk<T>>,
    tail: Cell<*mut Chunk<T>>,
    _ph: PhantomData<T>
}

unsafe impl<T: Send> Send for MonoVec<T> {}

impl<T> Chunk<T> {
    fn array_size(len: usize) -> usize {
        len.checked_mul(mem::size_of::<T>()).unwrap()
    }

    fn mem_size(len: usize) -> usize {
        mem::size_of::<Self>().checked_add(Self::array_size(len)).unwrap()
    }

    fn new(cap: usize) -> *mut Self {
        unsafe {
            let res = heap::allocate(Self::mem_size(cap),
                                     mem::align_of::<Self>()) as *mut Self;
            if res.is_null() {
                panic!("MonoVec: failed to allocate chunk!")
            }
            ptr::write(&mut (*res).prev, ptr::null_mut());
            ptr::write(&mut (*res).next, ptr::null_mut());
            ptr::write(&mut (*res).len, 0);
            ptr::write(&mut (*res).cap, cap);
            res
        }
    }
}

impl<T> MonoVec<T> {
    pub fn new() -> Self {
        Self::with_capacity(8)
    }

    pub fn with_capacity(cap: usize) -> Self {
        let head = Chunk::new(cmp::max(cap, 1));
        MonoVec {
            head: Cell::new(head),
            tail: Cell::new(head),
            _ph: PhantomData
        }
    }

    // FIXME: track total len in header to make this O(1)?
    pub fn len(&self) -> usize {
        let mut len = 0;
        let mut cur = self.head.get();

        while !cur.is_null() {
            unsafe {
                len += (*cur).len;
                cur = (*cur).next;
            }
        }
        len
    }

    // Reserves space for at least `len` more contiguous elements, returning
    // a pointer to the space and the available capacity (which may be > `len`)
    #[inline(never)]
    pub fn reserve(&self, len: usize) -> (*mut T, usize) {
        unsafe {
            let tail = self.tail.get();
            let cap = (*tail).cap;
            if cap - (*tail).len < len {
                // Grow capacity exponentially to amortize cost of insertions
                let mut new_cap = cap.checked_mul(2).unwrap();
                while new_cap < len {
                    new_cap = new_cap.checked_mul(2).unwrap();
                }
                let new = Chunk::new(new_cap);

                (*new).prev = tail;
                (*tail).next = new;
                self.tail.set(new);
            }

            let tail = self.tail.get();
            let ptr = (*tail).items.as_mut_ptr().offset((*tail).len as isize);
            let cap = (*tail).cap - (*tail).len;
            (ptr, cap)
        }
    }

    // Adds to length of curent chunk.  Usually used after
    // writing into reserved space.
    pub unsafe fn add_len(&self, len: usize) {
        let tail = self.tail.get();
        (*tail).len += len;
    }

    // Shrinks length of allocation at (ptr, ptr + old_len) if possible
    pub unsafe fn shrink_len(&self, ptr: *mut T, old_len: usize, new_len: usize) {
        let tail = self.tail.get();
        if ptr.offset(old_len as isize) == (*tail).items.as_mut_ptr().offset((*tail).len as isize) {
            (*tail).len = (*tail).len - old_len + new_len;
        }
    }

    #[inline]
    pub fn push(&self, elem: T) -> &T {
        let (ptr, _) = self.reserve(1);
        unsafe {
            ptr::write(ptr, elem);
            self.add_len(1);
            &*ptr
        }
    }

    pub fn extend_as_slice<E: IntoIterator<Item=T>>(&self, elems: E) -> &[T]
            where E::IntoIter: ExactSizeIterator {
        let iter = elems.into_iter();
        let len = iter.len();
        let (ptr, _) = self.reserve(len);
        let mut cur = ptr;
        unsafe {
            for elem in iter {
                ptr::write(cur, elem);
                cur = cur.offset(1);
            }
            self.add_len(len);
            slice::from_raw_parts(ptr, len)
        }
    }

    pub fn clear(&mut self) {
        unsafe {
            loop {
                let chunk = self.head.get();
                self.head.set((*chunk).next);
                if intrinsics::needs_drop::<T>() {
                    let ptr = (*chunk).items.as_mut_ptr();
                    let end = ptr.offset((*chunk).len as isize);
                    while ptr < end {
                        intrinsics::drop_in_place(ptr);
                    }
                }
                if chunk == self.tail.get() {
                    break
                }
                heap::deallocate(chunk as *mut u8,
                                 mem::size_of::<Chunk<T>>() + (*chunk).len * mem::size_of::<T>(),
                                 mem::align_of::<Chunk<T>>());
            }
            let save = self.tail.get();
            self.head.set(save);
            (*save).len = 0;
        }
    }

    pub fn chunks(&self) -> Chunks<T> {
        Chunks {
            start: self.head.get(),
            end: self.tail.get(),
            _ph: PhantomData
        }
    }

    pub fn items(&self) -> Items<T> {
        #[inline(always)]
        fn id<T>(x: T) -> T { x }
        Items(self.chunks().flat_map(id))
    }
}

impl<'a, T: 'a> IntoIterator for &'a MonoVec<T> {
    type Item = &'a T;
    type IntoIter = Items<'a, T>;

    fn into_iter(self) -> Self::IntoIter {
        self.items()
    }
}

impl io::Write for MonoVec<u8> {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        let (ptr, len) = self.reserve(0);
        let len = cmp::min(len, buf.len());
        if len != 0 {
            unsafe {
                ptr::copy_nonoverlapping(buf.as_ptr(), ptr, len);
            }
        }
        Ok(len)
    }

    fn flush(&mut self) -> io::Result<()> {
        Ok(())
    }
}

impl<T> Drop for MonoVec<T> {
    fn drop(&mut self) {
        self.clear();
        let chunk = self.head.get();
        unsafe {
            heap::deallocate(chunk as *mut u8,
                             mem::size_of::<Chunk<T>>() + (*chunk).len * mem::size_of::<T>(),
                             mem::align_of::<Chunk<T>>());

        }
    }
}

pub struct Chunks<'a, T: 'a> {
    start: *mut Chunk<T>,
    end: *mut Chunk<T>,
    _ph: PhantomData<&'a [T]>
}

impl<'a, T> Iterator for Chunks<'a, T> {
    type Item = &'a [T];

    fn next(&mut self) -> Option<&'a [T]> {
        let chunk = self.start;
        if chunk.is_null() {
            None
        } else {
            unsafe {
                if chunk == self.end {
                    self.start = ptr::null_mut();
                    self.end = ptr::null_mut()
                } else {
                    self.start = (*chunk).next
                }
                Some(slice::from_raw_parts((*chunk).items.as_ptr(), (*chunk).len))
            }
        }
    }
}

unsafe impl <'a, T:Send> Send for Chunks<'a, T> {}
// FIXME: need to double check that this holds.
// It certainly doesn't for the vec itself.
unsafe impl <'a, T:Sync> Sync for Chunks<'a, T> {}

impl<'a, T> DoubleEndedIterator for Chunks<'a, T> {
    fn next_back(&mut self) -> Option<&'a [T]> {
        let chunk = self.end;
        if chunk.is_null() {
            None
        } else {
            unsafe {
                if chunk == self.start {
                    self.start = ptr::null_mut();
                    self.end = ptr::null_mut()
                } else {
                    self.end = (*chunk).prev
                }
                Some(slice::from_raw_parts((*chunk).items.as_ptr(), (*chunk).len))
            }
        }
    }
}

// Wrapper to hide ugly adapter type
pub struct Items<'a, T: 'a>(iter::FlatMap<Chunks<'a, T>, &'a [T], fn(&'a [T]) -> &'a [T]>);

impl<'a, T: 'a> Iterator for Items<'a, T> {
    type Item = &'a T;
    fn next(&mut self) -> Option<&'a T> {
        self.0.next()
    }
}

impl<'a, T: 'a> DoubleEndedIterator for Items<'a, T> {
    fn next_back(&mut self) -> Option<&'a T> {
        self.0.next_back()
    }
}

impl<T: fmt::Debug> fmt::Debug for MonoVec<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let mut need_comma = false;
        try!(write!(f, "["));
        for elem in self {
            if need_comma {
                try!(write!(f, ", "));
            }
            try!(elem.fmt(f));
            need_comma = true;
        }
        write!(f, "]")
    }
}
<commit_msg>Allow mutable/move iteration of MonoVec<commit_after>use std::fmt;
use std::mem;
use std::ptr;
use std::slice;
use std::iter;
use std::io::{self, Write};
use std::cmp;
use std::rt::heap;
use std::cell::Cell;
use std::marker::PhantomData;
use std::intrinsics;

// A chunk in the vector
struct Chunk<T> {
    // Previous chunk
    prev: *mut Chunk<T>,
    // Next chunk
    next: *mut Chunk<T>,
    // Count of items
    len: usize,
    // Capacity
    cap: usize,
    // Items follow in memory
    items: [T; 0]
}

pub struct MonoVec<T> {
    head: Cell<*mut Chunk<T>>,
    tail: Cell<*mut Chunk<T>>,
    _ph: PhantomData<T>
}

unsafe impl<T: Send> Send for MonoVec<T> {}

impl<T> Chunk<T> {
    fn array_size(len: usize) -> usize {
        len.checked_mul(mem::size_of::<T>()).unwrap()
    }

    fn mem_size(len: usize) -> usize {
        mem::size_of::<Self>().checked_add(Self::array_size(len)).unwrap()
    }

    fn new(cap: usize) -> *mut Self {
        unsafe {
            let res = heap::allocate(Self::mem_size(cap),
                                     mem::align_of::<Self>()) as *mut Self;
            if res.is_null() {
                panic!("MonoVec: failed to allocate chunk!")
            }
            ptr::write(&mut (*res).prev, ptr::null_mut());
            ptr::write(&mut (*res).next, ptr::null_mut());
            ptr::write(&mut (*res).len, 0);
            ptr::write(&mut (*res).cap, cap);
            res
        }
    }
}

impl<T> MonoVec<T> {
    pub fn new() -> Self {
        Self::with_capacity(8)
    }

    pub fn with_capacity(cap: usize) -> Self {
        let head = Chunk::new(cmp::max(cap, 1));
        MonoVec {
            head: Cell::new(head),
            tail: Cell::new(head),
            _ph: PhantomData
        }
    }

    // FIXME: track total len in header to make this O(1)?
    pub fn len(&self) -> usize {
        let mut len = 0;
        let mut cur = self.head.get();

        while !cur.is_null() {
            unsafe {
                len += (*cur).len;
                cur = (*cur).next;
            }
        }
        len
    }

    // Reserves space for at least `len` more contiguous elements, returning
    // a pointer to the space and the available capacity (which may be > `len`)
    #[inline(never)]
    pub fn reserve(&self, len: usize) -> (*mut T, usize) {
        unsafe {
            let tail = self.tail.get();
            let cap = (*tail).cap;
            if cap - (*tail).len < len {
                // Grow capacity exponentially to amortize cost of insertions
                let mut new_cap = cap.checked_mul(2).unwrap();
                while new_cap < len {
                    new_cap = new_cap.checked_mul(2).unwrap();
                }
                let new = Chunk::new(new_cap);

                (*new).prev = tail;
                (*tail).next = new;
                self.tail.set(new);
            }

            let tail = self.tail.get();
            let ptr = (*tail).items.as_mut_ptr().offset((*tail).len as isize);
            let cap = (*tail).cap - (*tail).len;
            (ptr, cap)
        }
    }

    // Adds to length of curent chunk.  Usually used after
    // writing into reserved space.
    pub unsafe fn add_len(&self, len: usize) {
        let tail = self.tail.get();
        (*tail).len += len;
    }

    // Shrinks length of allocation at (ptr, ptr + old_len) if possible
    pub unsafe fn shrink_len(&self, ptr: *mut T, old_len: usize, new_len: usize) {
        let tail = self.tail.get();
        if ptr.offset(old_len as isize) == (*tail).items.as_mut_ptr().offset((*tail).len as isize) {
            (*tail).len = (*tail).len - old_len + new_len;
        }
    }

    #[inline]
    pub fn push(&self, elem: T) -> &T {
        let (ptr, _) = self.reserve(1);
        unsafe {
            ptr::write(ptr, elem);
            self.add_len(1);
            &*ptr
        }
    }

    pub fn extend_as_slice<E: IntoIterator<Item=T>>(&self, elems: E) -> &[T]
            where E::IntoIter: ExactSizeIterator {
        let iter = elems.into_iter();
        let len = iter.len();
        let (ptr, _) = self.reserve(len);
        let mut cur = ptr;
        unsafe {
            for elem in iter {
                ptr::write(cur, elem);
                cur = cur.offset(1);
            }
            self.add_len(len);
            slice::from_raw_parts(ptr, len)
        }
    }

    pub fn clear(&mut self) {
        unsafe {
            loop {
                let chunk = self.head.get();
                self.head.set((*chunk).next);
                if intrinsics::needs_drop::<T>() {
                    let ptr = (*chunk).items.as_mut_ptr();
                    let end = ptr.offset((*chunk).len as isize);
                    while ptr < end {
                        intrinsics::drop_in_place(ptr);
                    }
                }
                if chunk == self.tail.get() {
                    break
                }
                heap::deallocate(chunk as *mut u8,
                                 mem::size_of::<Chunk<T>>() + (*chunk).len * mem::size_of::<T>(),
                                 mem::align_of::<Chunk<T>>());
            }
            let save = self.tail.get();
            self.head.set(save);
            (*save).len = 0;
        }
    }

    pub fn chunks(&self) -> Chunks<T> {
        Chunks {
            start: self.head.get(),
            end: self.tail.get(),
            _ph: PhantomData
        }
    }

    pub fn chunks_mut(&mut self) -> ChunksMut<T> {
        ChunksMut {
            start: self.head.get(),
            end: self.tail.get(),
            _ph: PhantomData
        }
    }

    pub fn iter(&self) -> Iter<T> {
        #[inline(always)]
        fn id<T>(x: T) -> T { x }
        Iter(self.chunks().flat_map(id))
    }

    pub fn iter_mut(&mut self) -> IterMut<T> {
        #[inline(always)]
        fn id<T>(x: T) -> T { x }
        IterMut(self.chunks_mut().flat_map(id))
    }
}

impl<'a, T: 'a> IntoIterator for &'a MonoVec<T> {
    type Item = &'a T;
    type IntoIter = Iter<'a, T>;

    fn into_iter(self) -> Self::IntoIter {
        self.iter()
    }
}

impl<'a, T: 'a> IntoIterator for &'a mut MonoVec<T> {
    type Item = &'a mut T;
    type IntoIter = IterMut<'a, T>;

    fn into_iter(self) -> Self::IntoIter {
        self.iter_mut()
    }
}

impl<T> IntoIterator for MonoVec<T> {
    type Item = T;
    type IntoIter = IntoIter<T>;

    fn into_iter(self) -> Self::IntoIter {
        unsafe {
            let start = self.head.get();
            let end = self.tail.get();
            mem::forget(self);
            IntoIter {
                start: start,
                end: end,
                front: (*start).items.as_mut_ptr(),
                _ph: PhantomData
            }
        }
    }
}

impl<T: fmt::Debug> fmt::Debug for MonoVec<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let mut need_comma = false;
        try!(write!(f, "["));
        for elem in self {
            if need_comma {
                try!(write!(f, ", "));
            }
            try!(elem.fmt(f));
            need_comma = true;
        }
        write!(f, "]")
    }
}

impl io::Write for MonoVec<u8> {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        let (ptr, len) = self.reserve(0);
        let len = cmp::min(len, buf.len());
        if len != 0 {
            unsafe {
                ptr::copy_nonoverlapping(buf.as_ptr(), ptr, len);
            }
        }
        Ok(len)
    }

    fn flush(&mut self) -> io::Result<()> {
        Ok(())
    }
}

impl<T> Drop for MonoVec<T> {
    fn drop(&mut self) {
        self.clear();
        let chunk = self.head.get();
        unsafe {
            heap::deallocate(chunk as *mut u8,
                             mem::size_of::<Chunk<T>>() + (*chunk).len * mem::size_of::<T>(),
                             mem::align_of::<Chunk<T>>());

        }
    }
}

pub struct Chunks<'a, T: 'a> {
    start: *mut Chunk<T>,
    end: *mut Chunk<T>,
    _ph: PhantomData<&'a [T]>
}

impl<'a, T> Iterator for Chunks<'a, T> {
    type Item = &'a [T];

    fn next(&mut self) -> Option<&'a [T]> {
        let chunk = self.start;
        if chunk.is_null() {
            None
        } else {
            unsafe {
                if chunk == self.end {
                    self.start = ptr::null_mut();
                    self.end = ptr::null_mut()
                } else {
                    self.start = (*chunk).next
                }
                Some(slice::from_raw_parts((*chunk).items.as_ptr(), (*chunk).len))
            }
        }
    }
}

unsafe impl <'a, T:Send> Send for Chunks<'a, T> {}
unsafe impl <'a, T:Sync> Sync for Chunks<'a, T> {}

impl<'a, T> DoubleEndedIterator for Chunks<'a, T> {
    fn next_back(&mut self) -> Option<&'a [T]> {
        let chunk = self.end;
        if chunk.is_null() {
            None
        } else {
            unsafe {
                if chunk == self.start {
                    self.start = ptr::null_mut();
                    self.end = ptr::null_mut()
                } else {
                    self.end = (*chunk).prev
                }
                Some(slice::from_raw_parts((*chunk).items.as_ptr(), (*chunk).len))
            }
        }
    }
}

pub struct ChunksMut<'a, T: 'a> {
    start: *mut Chunk<T>,
    end: *mut Chunk<T>,
    _ph: PhantomData<&'a mut [T]>
}

impl<'a, T> Iterator for ChunksMut<'a, T> {
    type Item = &'a mut [T];

    fn next(&mut self) -> Option<&'a mut [T]> {
        let chunk = self.start;
        if chunk.is_null() {
            None
        } else {
            unsafe {
                if chunk == self.end {
                    self.start = ptr::null_mut();
                    self.end = ptr::null_mut()
                } else {
                    self.start = (*chunk).next
                }
                Some(slice::from_raw_parts_mut((*chunk).items.as_mut_ptr(), (*chunk).len))
            }
        }
    }
}

unsafe impl <'a, T:Send> Send for ChunksMut<'a, T> {}
unsafe impl <'a, T:Sync> Sync for ChunksMut<'a, T> {}

impl<'a, T> DoubleEndedIterator for ChunksMut<'a, T> {
    fn next_back(&mut self) -> Option<&'a mut [T]> {
        let chunk = self.end;
        if chunk.is_null() {
            None
        } else {
            unsafe {
                if chunk == self.start {
                    self.start = ptr::null_mut();
                    self.end = ptr::null_mut()
                } else {
                    self.end = (*chunk).prev
                }
                Some(slice::from_raw_parts_mut((*chunk).items.as_mut_ptr(), (*chunk).len))
            }
        }
    }
}

// Wrapper to hide ugly adapter type
pub struct Iter<'a, T: 'a>(iter::FlatMap<Chunks<'a, T>, &'a [T], fn(&'a [T]) -> &'a [T]>);

impl<'a, T: 'a> Iterator for Iter<'a, T> {
    type Item = &'a T;
    fn next(&mut self) -> Option<&'a T> {
        self.0.next()
    }
}

impl<'a, T: 'a> DoubleEndedIterator for Iter<'a, T> {
    fn next_back(&mut self) -> Option<&'a T> {
        self.0.next_back()
    }
}

// Wrapper to hide ugly adapter type
pub struct IterMut<'a, T: 'a>(iter::FlatMap<ChunksMut<'a, T>, &'a mut [T],
                              fn(&'a mut [T]) -> &'a mut [T]>);

impl<'a, T: 'a> Iterator for IterMut<'a, T> {
    type Item = &'a mut T;
    fn next(&mut self) -> Option<&'a mut T> {
        self.0.next()
    }
}

impl<'a, T: 'a> DoubleEndedIterator for IterMut<'a, T> {
    fn next_back(&mut self) -> Option<&'a mut T> {
        self.0.next_back()
    }
}

pub struct IntoIter<T> {
    start: *mut Chunk<T>,
    end: *mut Chunk<T>,
    front: *mut T,
    _ph: PhantomData<T>
}

impl<T> Iterator for IntoIter<T> {
    type Item = T;

    fn next(&mut self) -> Option<T> {
        loop {
            unsafe {
                let chunk = self.start;
                let back = (*chunk).items.as_mut_ptr().offset((*chunk).len as isize);
                if self.front == back {
                    if self.start == self.end {
                        return None
                    }
                    self.start = (*chunk).next;
                    heap::deallocate(chunk as *mut u8,
                                     mem::size_of::<Chunk<T>>() + (*chunk).cap * mem::size_of::<T>(),
                                     mem::min_align_of::<Chunk<T>>());
                    self.front = (*self.start).items.as_mut_ptr();
                    continue;
                }
                let ptr = self.front;
                self.front = self.front.offset(1);

                return Some(ptr::read(ptr))
            }
        }
    }
}

unsafe impl <T: Send> Send for IntoIter<T> {}
unsafe impl <T: Sync> Sync for IntoIter<T> {}

impl<T> DoubleEndedIterator for IntoIter<T> {
    fn next_back(&mut self) -> Option<T> {
        loop {
            unsafe {
                let chunk = self.end;
                let back = (*chunk).items.as_mut_ptr().offset((*chunk).len as isize);
                if back == self.front {
                    if chunk == self.start {
                        return None
                    }
                    self.end = (*chunk).prev;
                    heap::deallocate(
                        chunk as *mut u8,
                        mem::size_of::<Chunk<T>>() + (*chunk).cap * mem::size_of::<T>(),
                        mem::min_align_of::<Chunk<T>>());
                    continue;
                }
                (*chunk).len -= 1;
                let ptr = (*chunk).items.as_mut_ptr().offset((*chunk).len as isize);
                return Some(ptr::read(ptr))
            }
        }
    }
}

impl<T> Drop for IntoIter<T> {
    fn drop(&mut self) {
        while let Some(_) = self.next() {}
        debug_assert!(self.start == self.end);
        unsafe {
            heap::deallocate(self.start as *mut u8,
                             mem::size_of::<Chunk<T>>() + (*self.start).cap * mem::size_of::<T>(),
                             mem::min_align_of::<Chunk<T>>());
        }
    }
}
<|endoftext|>


<commit_before>use std::rc::Rc;
use nes::bus::{AddressValidator, AddressBus, BusKind, DeviceKind, Address};
use nes::system::{Region, SystemState, System};
use nes::memory::MemoryBlock;

pub struct PpuState {
    current_tick: u64,
    regs: [u8;8],
    vblank: bool,
    sprite_zero_hit: bool,
    sprite_overflow: bool,
    last_write: u8,

    scroll_latch: bool,
    scroll_x: i32,
    scroll_y: i32,

    addr_latch: bool,
    data_addr: u16,
    data_read_buffer: u8,

    oam_addr: u8,
    oam_data: [u8; 256],

    current_frame: i32,
    current_line: i32,
    stage: Stage,

    palette_data: [u8; 32],
}

impl Default for PpuState {
    fn default() -> PpuState {
        PpuState {
            current_tick: Default::default(),
            regs: Default::default(),
            vblank: Default::default(),
            sprite_zero_hit: Default::default(),
            sprite_overflow: Default::default(),
            last_write: Default::default(),

            scroll_latch: Default::default(),
            scroll_x: Default::default(),
            scroll_y: Default::default(),

            addr_latch: Default::default(),
            data_addr: Default::default(),
            data_read_buffer: Default::default(),

            oam_addr: Default::default(),
            oam_data: [0; 256],

            current_frame: Default::default(),
            current_line: Default::default(),
            stage: Stage::Dot(0,0),

            palette_data: Default::default(),
        }
    }
}

impl PpuState {
    fn is_nmi_enabled(&self) -> bool { self.regs[0] & 0x80 != 0 }
    fn is_ext_bg(&self) -> bool { self.regs[0] & 0x40 != 0 }
    fn is_tall_sprites(&self) -> bool { self.regs[0] & 0x20 != 0 }

    fn background_pattern_table(&self) -> u16 {
        if self.regs[0] & 0x10 != 0 { 0x1000 } else { 0x0000 }
    }

    fn sprite_pattern_table(&self) -> u16 {
        if self.regs[0] & 0x08 != 0 { 0x1000 } else { 0x0000 }
    }

    fn vram_inc(&self) -> u16 {
        if self.regs[0] & 0x04 != 0 { 32 } else { 1 }
    }

    fn base_nametable(&self) -> u16 {
        match self.regs[0] & 3 {
            0 => 0x2000,
            1 => 0x2400,
            2 => 0x2800,
            3 => 0x2c00,
            _ => unreachable!()
        }
    }

    fn is_blue_emph(&self) -> bool { self.regs[1] & 0x80 != 0 }
    fn is_green_emph(&self) -> bool { self.regs[1] & 0x40 != 0 }
    fn is_red_emph(&self) -> bool { self.regs[1] & 0x20 != 0 }
    fn is_sprites_enabled(&self) -> bool { self.regs[1] & 0x10 != 0 }
    fn is_background_enabled(&self) -> bool { self.regs[1] & 0x08 != 0 }
    fn is_left_sprites(&self) -> bool { self.regs[1] & 0x04 != 0 }
    fn is_left_baclground(&self) -> bool { self.regs[1] & 0x02 != 0 }
    fn is_grayscale(&self) -> bool { self.regs[1] & 0x01 != 0 }

    fn ppu_status(&self) -> u8 {
        let mut value = self.last_write & 0x1f;
        if self.sprite_overflow { value |= 0x20; }
        if self.sprite_zero_hit { value |= 0x40; }
        if self.vblank { value |= 0x80; }
        value
    }

    fn oam_address(&self) -> u8 { self.regs[3] }
}

enum Stage {
    Vblank(i32, u32),
    Hblank(i32, u32),
    Dot(i32, u32),
    Prerender(i32, u32),
}

impl Stage {
    fn increment(&self) -> Stage {
        match *self {
            Stage::Prerender(s, d) => {
                if d == 341 {
                    Stage::Dot(0, 0)
                } else {
                    Stage::Prerender(s, d + 1)
                }
            },
            Stage::Vblank(s, d) => {
                if d == 341 {
                    if s == 260 {
                        Stage::Prerender(261, 0)
                    } else {
                        Stage::Vblank(s + 1, 0)
                    }
                } else {
                    Stage::Vblank(s, d + 1)
                }
            },
            Stage::Hblank(s, d) => {
                if d == 341 {
                    if s == 239 {
                        Stage::Vblank(s + 1, 0)
                    } else {
                        Stage::Hblank(s + 1, 0)
                    }
                } else {
                    Stage::Hblank(s, d + 1)
                }
            },
            Stage::Dot(s, d) => {
                if d == 255 {
                    Stage::Hblank(s, d + 1)
                } else {
                    Stage::Dot(s, d + 1)
                }
            },
        }
    }
}

impl Default for Stage {
    fn default() -> Stage {
        Stage::Dot(0,0)
    }
}

pub struct Ppu {
    region: Region,
    pub mem: MemoryBlock,
    bus: AddressBus,
}

impl Ppu {
    pub fn new(region: Region, state: &mut SystemState) -> Ppu {
        let ppu = Ppu {
            region: region,
            bus: AddressBus::new(BusKind::Ppu, state, 0),
            mem: MemoryBlock::new(2, &mut state.mem),
        };

        ppu
    }

    pub fn register_read<T>(&mut self, state: &mut SystemState, device: DeviceKind, addr: T) where T: AddressValidator {
        self.bus.register_read(state, device, addr);
    }

    pub fn register_write<T>(&mut self, state: &mut SystemState, device: DeviceKind, addr: T) where T: AddressValidator {
        self.bus.register_write(state, device, addr);
    }

    pub fn peek(&self, bus: BusKind, system: &System, state: &SystemState, address: u16) -> u8 {
        match address {
            0 => state.ppu.last_write,
            1 => state.ppu.last_write,
            2 => state.ppu.ppu_status(),
            3 => state.ppu.oam_addr, //OAMADDR
            4 => state.ppu.oam_data[state.ppu.oam_addr as usize], //OANDATA
            5 => state.ppu.last_write,
            6 => state.ppu.last_write,
            7 => { //PPUDATA
                let addr = state.ppu.data_addr;
                let result = if addr & 0x3f00 == 0x3f00 {
                    state.ppu.palette_data[(addr & 0x1f) as usize]
                } else {
                    state.ppu.data_read_buffer
                };
                result
            }
            4014 => 0,
            _ => unreachable!(),
        }
    }
    pub fn read(&self, bus: BusKind, system: &System, state: &mut SystemState, address: u16) -> u8 {
        match address {
            0 => state.ppu.last_write,
            1 => state.ppu.last_write,
            2 => {
                state.ppu.addr_latch = false;
                state.ppu.scroll_latch = false;
                let status = state.ppu.ppu_status();
                state.ppu.vblank = false;
                status
            }, //PPUSTATUS
            3 => state.ppu.oam_addr, //OAMADDR
            4 => state.ppu.oam_data[state.ppu.oam_addr as usize], //OANDATA
            5 => state.ppu.last_write,
            6 => state.ppu.last_write,
            7 => { //PPUDATA
                let addr = state.ppu.data_addr;
                let result = if addr & 0x3f00 == 0x3f00 {
                    state.ppu.palette_data[(addr & 0x1f) as usize]
                } else {
                    state.ppu.data_read_buffer
                };
                state.ppu.data_read_buffer = self.bus.read(system, state, addr);
                result
            }
            4014 => 0,
            _ => unreachable!(),
        }
    }

    pub fn write(&self, bus: BusKind, system: &System, state: &mut SystemState, address: u16, value: u8) {
        match address {
            0 => state.ppu.regs[0] = value, //PPUCTRL
            1 => state.ppu.regs[1] = value, //PPUMASK
            2 => state.ppu.regs[2] = value,
            3 => state.ppu.oam_addr = value, //OAMADDR
            4 => state.ppu.oam_data[state.ppu.oam_addr as usize] = value, //OAMDATA
            5 => { //PPUSCROLL
                if state.ppu.scroll_latch {
                    state.ppu.scroll_y = value as i32;
                } else {
                    state.ppu.scroll_x = value as i32;
                }
                state.ppu.scroll_latch = !state.ppu.scroll_latch;

            },
            6 => { //PPUADDR
                if state.ppu.addr_latch {
                    state.ppu.data_addr &= 0xff00;
                    state.ppu.data_addr |= value as u16
                } else {
                    state.ppu.data_addr &= 0x00ff;
                    state.ppu.data_addr |= (value as u16) << 8;
                }
                state.ppu.addr_latch = !state.ppu.addr_latch;
            },
            7 => { //PPUDATA
                let addr = state.ppu.data_addr;
                self.bus.write(system, state, addr, value);
                if addr & 0x3f00 == 0x3f00 {
                    state.ppu.palette_data[(addr & 0x1f) as usize] = value;
                }
                state.ppu.data_addr += state.ppu.vram_inc();
            },
            4014 => { //OAMDMA
                state.cpu.oam_dma_req(value);
            },
            _ => unreachable!(),
        }

        if address < 8 { state.ppu.last_write = value; }
    }

    pub fn tick(&self, system: &System, state: &mut SystemState) {
        state.ppu.current_tick += 1;
        match state.ppu.stage {
            Stage::Vblank(241,1) => {
                state.ppu.vblank = true;
                if state.ppu.is_nmi_enabled() {
                    state.cpu.nmi_req();
                }
            },
            Stage::Prerender(261, 1) => {
                state.ppu.vblank = false;
            },
            _ => {}
        }
        state.ppu.stage = state.ppu.stage.increment();
    }
}
<commit_msg>Add loopy ppu addr updating<commit_after>use std::rc::Rc;
use nes::bus::{AddressValidator, AddressBus, BusKind, DeviceKind, Address};
use nes::system::{Region, SystemState, System};
use nes::memory::MemoryBlock;

pub struct PpuState {
    current_tick: u64,
    regs: [u8;8],
    vblank: bool,
    sprite_zero_hit: bool,
    sprite_overflow: bool,
    last_write: u8,

    write_latch: bool,

    data_read_buffer: u8,

    vram_addr: u16,
    vram_addr_temp: u16,
    vram_fine_x: u16,

    oam_addr: u8,
    oam_data: [u8; 256],

    current_frame: i32,
    current_line: i32,
    stage: Stage,

    palette_data: [u8; 32],
}

impl Default for PpuState {
    fn default() -> PpuState {
        PpuState {
            current_tick: Default::default(),
            regs: Default::default(),
            vblank: Default::default(),
            sprite_zero_hit: Default::default(),
            sprite_overflow: Default::default(),
            last_write: Default::default(),

            write_latch: Default::default(),
            data_read_buffer: Default::default(),

            vram_addr: Default::default(),
            vram_addr_temp: Default::default(),
            vram_fine_x: Default::default(),

            oam_addr: Default::default(),
            oam_data: [0; 256],

            current_frame: Default::default(),
            current_line: Default::default(),
            stage: Stage::Dot(0,0),

            palette_data: Default::default(),
        }
    }
}

impl PpuState {
    fn is_nmi_enabled(&self) -> bool { self.regs[0] & 0x80 != 0 }
    fn is_ext_bg(&self) -> bool { self.regs[0] & 0x40 != 0 }
    fn is_tall_sprites(&self) -> bool { self.regs[0] & 0x20 != 0 }

    fn background_pattern_table(&self) -> u16 {
        if self.regs[0] & 0x10 != 0 { 0x1000 } else { 0x0000 }
    }

    fn sprite_pattern_table(&self) -> u16 {
        if self.regs[0] & 0x08 != 0 { 0x1000 } else { 0x0000 }
    }

    fn vram_inc(&self) -> u16 {
        if self.regs[0] & 0x04 != 0 { 32 } else { 1 }
    }

    fn base_nametable(&self) -> u16 {
        match self.regs[0] & 3 {
            0 => 0x000,
            1 => 0x400,
            2 => 0x800,
            3 => 0xc00,
            _ => unreachable!()
        }
    }

    fn is_blue_emph(&self) -> bool { self.regs[1] & 0x80 != 0 }
    fn is_green_emph(&self) -> bool { self.regs[1] & 0x40 != 0 }
    fn is_red_emph(&self) -> bool { self.regs[1] & 0x20 != 0 }
    fn is_sprites_enabled(&self) -> bool { self.regs[1] & 0x10 != 0 }
    fn is_background_enabled(&self) -> bool { self.regs[1] & 0x08 != 0 }
    fn is_left_sprites(&self) -> bool { self.regs[1] & 0x04 != 0 }
    fn is_left_baclground(&self) -> bool { self.regs[1] & 0x02 != 0 }
    fn is_grayscale(&self) -> bool { self.regs[1] & 0x01 != 0 }

    fn ppu_status(&self) -> u8 {
        let mut value = self.last_write & 0x1f;
        if self.sprite_overflow { value |= 0x20; }
        if self.sprite_zero_hit { value |= 0x40; }
        if self.vblank { value |= 0x80; }
        value
    }

    fn oam_address(&self) -> u8 { self.regs[3] }
}

enum Stage {
    Vblank(i32, u32),
    Hblank(i32, u32),
    Dot(i32, u32),
    Prerender(i32, u32),
}

impl Stage {
    fn increment(&self) -> Stage {
        match *self {
            Stage::Prerender(s, d) => {
                if d == 341 {
                    Stage::Dot(0, 0)
                } else {
                    Stage::Prerender(s, d + 1)
                }
            },
            Stage::Vblank(s, d) => {
                if d == 341 {
                    if s == 260 {
                        Stage::Prerender(261, 0)
                    } else {
                        Stage::Vblank(s + 1, 0)
                    }
                } else {
                    Stage::Vblank(s, d + 1)
                }
            },
            Stage::Hblank(s, d) => {
                if d == 341 {
                    if s == 239 {
                        Stage::Vblank(s + 1, 0)
                    } else {
                        Stage::Hblank(s + 1, 0)
                    }
                } else {
                    Stage::Hblank(s, d + 1)
                }
            },
            Stage::Dot(s, d) => {
                if d == 255 {
                    Stage::Hblank(s, d + 1)
                } else {
                    Stage::Dot(s, d + 1)
                }
            },
        }
    }
}

impl Default for Stage {
    fn default() -> Stage {
        Stage::Dot(0,0)
    }
}

pub struct Ppu {
    region: Region,
    pub mem: MemoryBlock,
    bus: AddressBus,
}

impl Ppu {
    pub fn new(region: Region, state: &mut SystemState) -> Ppu {
        let ppu = Ppu {
            region: region,
            bus: AddressBus::new(BusKind::Ppu, state, 0),
            mem: MemoryBlock::new(2, &mut state.mem),
        };

        ppu
    }

    pub fn register_read<T>(&mut self, state: &mut SystemState, device: DeviceKind, addr: T) where T: AddressValidator {
        self.bus.register_read(state, device, addr);
    }

    pub fn register_write<T>(&mut self, state: &mut SystemState, device: DeviceKind, addr: T) where T: AddressValidator {
        self.bus.register_write(state, device, addr);
    }

    pub fn peek(&self, bus: BusKind, system: &System, state: &SystemState, address: u16) -> u8 {
        match address {
            0 => state.ppu.last_write,
            1 => state.ppu.last_write,
            2 => state.ppu.ppu_status(),
            3 => state.ppu.oam_addr, //OAMADDR
            4 => state.ppu.oam_data[state.ppu.oam_addr as usize], //OANDATA
            5 => state.ppu.last_write,
            6 => state.ppu.last_write,
            7 => { //PPUDATA
                let addr = state.ppu.vram_addr;
                let result = if addr & 0x3f00 == 0x3f00 {
                    state.ppu.palette_data[(addr & 0x1f) as usize]
                } else {
                    state.ppu.data_read_buffer
                };
                result
            }
            4014 => 0,
            _ => unreachable!(),
        }
    }
    pub fn read(&self, bus: BusKind, system: &System, state: &mut SystemState, address: u16) -> u8 {
        match address {
            0 => state.ppu.last_write,
            1 => state.ppu.last_write,
            2 => {
                state.ppu.write_latch = false;
                let status = state.ppu.ppu_status();
                state.ppu.vblank = false;
                status
            }, //PPUSTATUS
            3 => state.ppu.oam_addr, //OAMADDR
            4 => state.ppu.oam_data[state.ppu.oam_addr as usize], //OANDATA
            5 => state.ppu.last_write,
            6 => state.ppu.last_write,
            7 => { //PPUDATA
                let addr = state.ppu.vram_addr;
                let result = if addr & 0x3f00 == 0x3f00 {
                    state.ppu.palette_data[(addr & 0x1f) as usize]
                } else {
                    state.ppu.data_read_buffer
                };
                state.ppu.data_read_buffer = self.bus.read(system, state, addr);
                state.ppu.vram_addr += state.ppu.vram_inc();
                result
            }
            4014 => 0,
            _ => unreachable!(),
        }
    }

    pub fn write(&self, bus: BusKind, system: &System, state: &mut SystemState, address: u16, value: u8) {
        match address {
            0 => {
                state.ppu.regs[0] = value;
                state.ppu.vram_addr_temp &= 0xc00;
                state.ppu.vram_addr_temp |= state.ppu.base_nametable();
            }, //PPUCTRL
            1 => state.ppu.regs[1] = value, //PPUMASK
            2 => state.ppu.regs[2] = value,
            3 => state.ppu.oam_addr = value, //OAMADDR
            4 => state.ppu.oam_data[state.ppu.oam_addr as usize] = value, //OAMDATA
            5 => { //PPUSCROLL
                if state.ppu.write_latch {
                    let value = value as u16;
                    state.ppu.vram_addr_temp &= 0xfc1f;
                    state.ppu.vram_addr_temp |= (value & 0xff07) << 2;
                    state.ppu.vram_addr_temp &= 0x0fff;
                    state.ppu.vram_addr_temp |= (value & 0x07) << 12;
                } else {
                    state.ppu.vram_addr_temp &= 0xffe0;
                    state.ppu.vram_addr_temp |= (value >> 3) as u16;
                    state.ppu.vram_fine_x = (value & 0x07) as u16;
                }
                state.ppu.write_latch = !state.ppu.write_latch;

            },
            6 => { //PPUADDR
                if state.ppu.write_latch {
                    state.ppu.vram_addr_temp &= 0xff00;
                    state.ppu.vram_addr_temp |= value as u16;
                    state.ppu.vram_addr = state.ppu.vram_addr_temp;
                } else {
                    state.ppu.vram_addr_temp &= 0x00ff;
                    state.ppu.vram_addr_temp |= ((value & 0x7f) as u16) << 8;
                }
                state.ppu.write_latch = !state.ppu.write_latch;
            },
            7 => { //PPUDATA
                let addr = state.ppu.vram_addr;
                self.bus.write(system, state, addr, value);
                if addr & 0x3f00 == 0x3f00 {
                    state.ppu.palette_data[(addr & 0x1f) as usize] = value;
                }
                state.ppu.vram_addr += state.ppu.vram_inc();
            },
            4014 => { //OAMDMA
                state.cpu.oam_dma_req(value);
            },
            _ => unreachable!(),
        }

        if address < 8 { state.ppu.last_write = value; }
    }

    pub fn tick(&self, system: &System, state: &mut SystemState) {
        state.ppu.current_tick += 1;
        match state.ppu.stage {
            Stage::Vblank(241,1) => {
                state.ppu.vblank = true;
                if state.ppu.is_nmi_enabled() {
                    state.cpu.nmi_req();
                }
            },
            Stage::Prerender(261, 1) => {
                state.ppu.vblank = false;
            },
            _ => {}
        }
        state.ppu.stage = state.ppu.stage.increment();
    }

    fn x_increment(&self, mut addr: u16) -> u16  {
        if addr & 0x001f == 31 {
            addr &= !0x001f;
            addr ^= 0x0400;
        } else {
            addr += 1;
        }
        addr
    }

    fn y_increment(&self, mut addr: u16 ) -> u16 {
        if (addr & 0x7000) != 0x7000 {
            addr += 0x1000;
        } else {
            addr &= !0x7000;
            let mut y = (addr & 0x03e0) >> 5;
            if y == 29 {
                y = 0;
                addr ^= 0x0800;
            } else if y == 31{
                y = 0;
            } else {
                y += 1;
            }

            addr = (addr & !0x03e0) | (y << 5);
        }
        addr
    }
}
<|endoftext|>


<commit_before>//! The neural network struct. See the module level documentation for usage.

use std::ops::Range;
use std::io;

use utils::Stack;
use file;
use gene::*;
use gene::GeneExtras::*;

const BIAS_GENE_VALUE: f64 = 1.0;

#[derive(Clone, Debug, PartialEq)]
pub struct Network {
    // size should be the length of the genome minus one, don't forget
    pub size: usize,
    pub genome: Vec<Gene>
}

impl Network {
    /// Evaluates the neural network with the given inputs, returning a vector of outputs. The encoding can
    /// encode recurrent connections and bias inputs, so an internal state is used. It is important to run
    /// the clear_state method before calling evaluate again, unless it is desired to allow data
    /// carry over from the previous evaluation, for example if the network is being used as a real
    /// time controller.
    ///
    /// If too little inputs are given, the empty inputs will have a value of zero. If too many
    /// inputs are given, the extras are discarded.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use cge::Network;
    ///
    /// // Load a neural network
    /// let mut network = Network::load_from_file("neural_network.ann").unwrap();
    ///
    /// // Get the output of the neural network the the specified inputs
    /// let result = network.evaluate(&vec![1.0, 1.0]);
    ///
    /// // Get the output of the neural network with no inputs
    /// let result = network.evaluate(&Vec::new());
    ///
    /// // Get the output of the neural network with too many inputs (extras aren't used)
    /// let result = network.evaluate(&vec![1.0, 1.0, 1.0]);
    ///
    /// // Let's say adder.ann is a file with a neural network with recurrent connections, used for
    /// // adding numbers together.
    /// let mut adder = Network::load_from_file("adder.ann").unwrap();
    ///
    /// // result_one will be 1.0
    /// let result_one = adder.evaluate(&vec![1.0]);
    ///
    /// // result_two will be 3.0
    /// let result_two = adder.evaluate(&vec![2.0]);
    ///
    /// // result_three will be 5.0
    /// let result_three = adder.evaluate(&vec![2.0]);
    ///
    /// // If this behavior is not desired, call the clear_state method between evaluations:
    /// let result_one = adder.evaluate(&vec![1.0]);
    ///
    /// adder.clear_state();
    ///
    /// // The 1.0 from the previous call is gone, so result_two will be 2.0
    /// let result_two = adder.evaluate(&vec![2.0]);
    /// ```
    pub fn evaluate(&mut self, inputs: &Vec<f64>) -> Vec<f64> {
        // Set inputs
        for gene in &mut self.genome {
            if let Input(ref mut current_value) = gene.variant {
                *current_value = match inputs.get(gene.id) {
                    Some(v) => *v,
                    None => 0.0
                }
            }
        }

        let size = self.size;
        self.evaluate_slice(0..size, true)
    }

    /// Clears the internal state of the neural network.
    pub fn clear_state(&mut self) {
        for gene in &mut self.genome {
            match gene.variant {
                Input(ref mut current_value) => {
                    *current_value = 0.0;
                },
                Neuron(ref mut current_value, _) => {
                    *current_value = 0.0;
                }
                _ => {}
            }
        }
    }

    /// Saves the neural network to a file. Returns an empty tuple on success, or an io error.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use cge::Network;
    ///
    /// // Create a neural network
    /// let network = Network {
    ///     size: 0,
    ///     genome: Vec::new()
    /// };
    ///
    /// // Save network to neural_network.ann
    /// network.save_to_file("neural_network.ann");
    /// ```
    pub fn save_to_file(&self, path: &str) -> io::Result<()> {
        file::write_network(self, path)
    }

    /// Loads a neural network from a file. No guarantees are made about the validity of the
    /// genome. Returns the network, or an io error. If the file is in a bad format,
    /// io::ErrorKind::InvalidData is returned.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use cge::Network;
    ///
    /// // Loads a network from the file neural_network.ann
    /// let mut network = Network::load_from_file("neural_network.ann").unwrap();
    /// ```
    pub fn load_from_file(path: &str) -> io::Result<Network> {
        file::read_network(path)
    }

    // Returns the output of sub-linear genome in the given range
    fn evaluate_slice(&mut self, range: Range<usize>, neuron_update: bool) -> Vec<f64> {
        let mut gene_index = range.end;
        // Initialize a stack for evaluating the neural network
        let mut stack = Stack::new();

        // Iterate backwards over the specified slice
        while gene_index >= range.start {
            let variant = self.genome[gene_index].variant.clone();

            // For debugging: uncomment these print statements
            // Perhaps add it as an option to help users
            // println!("{:?}", variant);

            match variant {
                Input(_) => {
                    // If the gene is an input, push its value multiplied by the inputs weight onto
                    // the stack
                    let (weight, _, value) = self.genome[gene_index].ref_input().unwrap();
                    stack.push(weight * value);
                },
                Neuron(_, _) => {
                    // If the gene is a neuron, pop a number (the neurons input count) of inputs
                    // off the stack, and push their sum multiplied by the neurons weight onto the
                    // stack
                    let (weight, _, value, inputs) = self.genome[gene_index].ref_mut_neuron().unwrap();
                    let new_value = stack.pop(*inputs).unwrap().iter().fold(0.0, |acc, i| acc + i);

                    if neuron_update {
                        *value = new_value;
                    }

                    stack.push(*weight * new_value);
                },
                Forward => {
                    // This is inefficient because it can run the neuron evaluation code multiple
                    // times
                    // TODO: Turn current value of neurons into a struct with a flag representing
                    // whether the neuron has been evaluated this network evaluation. Reset this
                    // flag after every network evaluation.

                    // If the gene is a forward jumper, evaluate the subnetwork starting at the
                    // neuron with id of the jumper, and push the result multiplied by the jumpers
                    // weight onto the stack
                    let weight = self.genome[gene_index].weight;
                    let id = self.genome[gene_index].id;
                    let subnetwork_range = self.get_subnetwork_index(id).unwrap();

                    let result = self.evaluate_slice(subnetwork_range, false);
                    // println!("{:?}", result);
                    stack.push(weight * result[0]);
                },
                Recurrent => {
                    // If the gene is a recurrent jumper, push the previous value of the neuron
                    // with the id of the jumper multiplied by the jumpers weight onto the stack
                    let gene = &self.genome[gene_index];
                    let neuron = &self.genome[self.get_neuron_index(gene.id).unwrap()];

                    if let Neuron(ref current_value, _) = neuron.variant {
                        stack.push(gene.weight * *current_value);
                    }
                },
                Bias => {
                    // If the gene is a bias input, push the bias constant multiplied by the genes
                    // weight onto the stack
                    let gene = &self.genome[gene_index];
                    stack.push(gene.weight * BIAS_GENE_VALUE);
                }
            }

            if gene_index == range.start {
                break;
            }

            gene_index -= 1;
            // println!("{:?}", stack.data);
        }

        stack.data
    }

    /// Returns the start and end index of the subnetwork starting at the neuron with the given id,
    /// or None if it does not exist.
    pub fn get_subnetwork_index(&self, id: usize) -> Option<Range<usize>> {
        let start = match self.get_neuron_index(id) {
            Some(i) => i,
            None => return None
        };

        let mut end = start;
        let mut sum = 0;

        // Iterate through genes after the start index, modifying the sum each step
        // I could use an iterator here, but it would be messy
        for gene in &self.genome[start..self.size] {
            match gene.variant {
                Neuron(_, ref inputs) => {
                    sum += 1 - *inputs as i32;
                },
                _ => {
                    sum += 1;
                }
            }

            if sum == 1 {
                break;
            }

            end += 1;
        }

        if sum != 1 {
            None
        } else {
            Some(Range {
                start: start,
                end: end
            })
        }
    }

    /// Returns the index of the neuron with the given id, or None if it does not exist.
    pub fn get_neuron_index(&self, id: usize) -> Option<usize> {
        let mut result = None;

        for (i, gene) in self.genome.iter().enumerate() {
            if let Neuron(_, _) = gene.variant {
                if gene.id == id {
                    result = Some(i);
                }
            }
        }

        result
    }
}
<commit_msg>Fix docs<commit_after>//! The neural network struct.

use std::ops::Range;
use std::io;

use utils::Stack;
use file;
use gene::*;
use gene::GeneExtras::*;

const BIAS_GENE_VALUE: f64 = 1.0;

#[derive(Clone, Debug, PartialEq)]
pub struct Network {
    // size should be the length of the genome minus one, don't forget
    pub size: usize,
    pub genome: Vec<Gene>
}

impl Network {
    /// Evaluates the neural network with the given inputs, returning a vector of outputs. The encoding can
    /// encode recurrent connections and bias inputs, so an internal state is used. It is important to run
    /// the clear_state method before calling evaluate again, unless it is desired to allow data
    /// carry over from the previous evaluation, for example if the network is being used as a real
    /// time controller.
    ///
    /// If too little inputs are given, the empty inputs will have a value of zero. If too many
    /// inputs are given, the extras are discarded.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use cge::Network;
    ///
    /// // Load a neural network
    /// let mut network = Network::load_from_file("neural_network.ann").unwrap();
    ///
    /// // Get the output of the neural network the the specified inputs
    /// let result = network.evaluate(&vec![1.0, 1.0]);
    ///
    /// // Get the output of the neural network with no inputs
    /// let result = network.evaluate(&Vec::new());
    ///
    /// // Get the output of the neural network with too many inputs (extras aren't used)
    /// let result = network.evaluate(&vec![1.0, 1.0, 1.0]);
    ///
    /// // Let's say adder.ann is a file with a neural network with recurrent connections, used for
    /// // adding numbers together.
    /// let mut adder = Network::load_from_file("adder.ann").unwrap();
    ///
    /// // result_one will be 1.0
    /// let result_one = adder.evaluate(&vec![1.0]);
    ///
    /// // result_two will be 3.0
    /// let result_two = adder.evaluate(&vec![2.0]);
    ///
    /// // result_three will be 5.0
    /// let result_three = adder.evaluate(&vec![2.0]);
    ///
    /// // If this behavior is not desired, call the clear_state method between evaluations:
    /// let result_one = adder.evaluate(&vec![1.0]);
    ///
    /// adder.clear_state();
    ///
    /// // The 1.0 from the previous call is gone, so result_two will be 2.0
    /// let result_two = adder.evaluate(&vec![2.0]);
    /// ```
    pub fn evaluate(&mut self, inputs: &Vec<f64>) -> Vec<f64> {
        // Set inputs
        for gene in &mut self.genome {
            if let Input(ref mut current_value) = gene.variant {
                *current_value = match inputs.get(gene.id) {
                    Some(v) => *v,
                    None => 0.0
                }
            }
        }

        let size = self.size;
        self.evaluate_slice(0..size, true)
    }

    /// Clears the internal state of the neural network.
    pub fn clear_state(&mut self) {
        for gene in &mut self.genome {
            match gene.variant {
                Input(ref mut current_value) => {
                    *current_value = 0.0;
                },
                Neuron(ref mut current_value, _) => {
                    *current_value = 0.0;
                }
                _ => {}
            }
        }
    }

    /// Saves the neural network to a file. Returns an empty tuple on success, or an io error.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use cge::Network;
    ///
    /// // Create a neural network
    /// let network = Network {
    ///     size: 0,
    ///     genome: Vec::new()
    /// };
    ///
    /// // Save network to neural_network.ann
    /// network.save_to_file("neural_network.ann");
    /// ```
    pub fn save_to_file(&self, path: &str) -> io::Result<()> {
        file::write_network(self, path)
    }

    /// Loads a neural network from a file. No guarantees are made about the validity of the
    /// genome. Returns the network, or an io error. If the file is in a bad format,
    /// io::ErrorKind::InvalidData is returned.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use cge::Network;
    ///
    /// // Loads a network from the file neural_network.ann
    /// let mut network = Network::load_from_file("neural_network.ann").unwrap();
    /// ```
    pub fn load_from_file(path: &str) -> io::Result<Network> {
        file::read_network(path)
    }

    // Returns the output of sub-linear genome in the given range
    fn evaluate_slice(&mut self, range: Range<usize>, neuron_update: bool) -> Vec<f64> {
        let mut gene_index = range.end;
        // Initialize a stack for evaluating the neural network
        let mut stack = Stack::new();

        // Iterate backwards over the specified slice
        while gene_index >= range.start {
            let variant = self.genome[gene_index].variant.clone();

            // For debugging: uncomment these print statements
            // Perhaps add it as an option to help users
            // println!("{:?}", variant);

            match variant {
                Input(_) => {
                    // If the gene is an input, push its value multiplied by the inputs weight onto
                    // the stack
                    let (weight, _, value) = self.genome[gene_index].ref_input().unwrap();
                    stack.push(weight * value);
                },
                Neuron(_, _) => {
                    // If the gene is a neuron, pop a number (the neurons input count) of inputs
                    // off the stack, and push their sum multiplied by the neurons weight onto the
                    // stack
                    let (weight, _, value, inputs) = self.genome[gene_index].ref_mut_neuron().unwrap();
                    let new_value = stack.pop(*inputs).unwrap().iter().fold(0.0, |acc, i| acc + i);

                    if neuron_update {
                        *value = new_value;
                    }

                    stack.push(*weight * new_value);
                },
                Forward => {
                    // This is inefficient because it can run the neuron evaluation code multiple
                    // times
                    // TODO: Turn current value of neurons into a struct with a flag representing
                    // whether the neuron has been evaluated this network evaluation. Reset this
                    // flag after every network evaluation.

                    // If the gene is a forward jumper, evaluate the subnetwork starting at the
                    // neuron with id of the jumper, and push the result multiplied by the jumpers
                    // weight onto the stack
                    let weight = self.genome[gene_index].weight;
                    let id = self.genome[gene_index].id;
                    let subnetwork_range = self.get_subnetwork_index(id).unwrap();

                    let result = self.evaluate_slice(subnetwork_range, false);
                    // println!("{:?}", result);
                    stack.push(weight * result[0]);
                },
                Recurrent => {
                    // If the gene is a recurrent jumper, push the previous value of the neuron
                    // with the id of the jumper multiplied by the jumpers weight onto the stack
                    let gene = &self.genome[gene_index];
                    let neuron = &self.genome[self.get_neuron_index(gene.id).unwrap()];

                    if let Neuron(ref current_value, _) = neuron.variant {
                        stack.push(gene.weight * *current_value);
                    }
                },
                Bias => {
                    // If the gene is a bias input, push the bias constant multiplied by the genes
                    // weight onto the stack
                    let gene = &self.genome[gene_index];
                    stack.push(gene.weight * BIAS_GENE_VALUE);
                }
            }

            if gene_index == range.start {
                break;
            }

            gene_index -= 1;
            // println!("{:?}", stack.data);
        }

        stack.data
    }

    /// Returns the start and end index of the subnetwork starting at the neuron with the given id,
    /// or None if it does not exist.
    pub fn get_subnetwork_index(&self, id: usize) -> Option<Range<usize>> {
        let start = match self.get_neuron_index(id) {
            Some(i) => i,
            None => return None
        };

        let mut end = start;
        let mut sum = 0;

        // Iterate through genes after the start index, modifying the sum each step
        // I could use an iterator here, but it would be messy
        for gene in &self.genome[start..self.size] {
            match gene.variant {
                Neuron(_, ref inputs) => {
                    sum += 1 - *inputs as i32;
                },
                _ => {
                    sum += 1;
                }
            }

            if sum == 1 {
                break;
            }

            end += 1;
        }

        if sum != 1 {
            None
        } else {
            Some(Range {
                start: start,
                end: end
            })
        }
    }

    /// Returns the index of the neuron with the given id, or None if it does not exist.
    pub fn get_neuron_index(&self, id: usize) -> Option<usize> {
        let mut result = None;

        for (i, gene) in self.genome.iter().enumerate() {
            if let Neuron(_, _) = gene.variant {
                if gene.id == id {
                    result = Some(i);
                }
            }
        }

        result
    }
}
<|endoftext|>


<commit_before>use decoders::RawImage;
use decoders::cfa::CFA;
use imageops::*;
use std::cmp;

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct OpDemosaic {
  cfa: String,
}

impl OpDemosaic {
  pub fn new(img: &RawImage) -> OpDemosaic {
    OpDemosaic{
      cfa: img.cropped_cfa().to_string(),
    }
  }
}

impl<'a> ImageOp<'a> for OpDemosaic {
  fn name(&self) -> &str {"demosaic"}
  fn run(&self, pipeline: &mut PipelineGlobals, inid: BufHash, outid: BufHash) {
    let buf = pipeline.cache.get(inid).unwrap();

    let (scale, nwidth, nheight) = if pipeline.maxwidth == 0 || pipeline.maxheight == 0 {
      (1.0, buf.width, buf.height)
    } else {
      // Do the calculations manually to avoid off-by-one errors from floating point rounding
      let xscale = (buf.width as f32) / (pipeline.maxwidth as f32);
      let yscale = (buf.height as f32) / (pipeline.maxheight as f32);
      if yscale > xscale {
        (yscale, ((buf.width as f32)/yscale) as usize, pipeline.maxheight)
      } else {
        (xscale, pipeline.maxwidth, ((buf.height as f32)/xscale) as usize)
      }
    };

    let cfa = CFA::new(&self.cfa);
    let minscale = match cfa.width {
      2  => 2.0,  // RGGB/RGBE bayer
      6  => 3.0,  // x-trans is 6 wide but has all colors in every 3x3 block
      8  => 2.0,  // Canon pro 70 has a 8x2 patern that has all four colors every 2x2 block
      12 => 12.0, // some crazy sensor I haven't actually encountered, use full block
      _  => 2.0,  // default
    };

    if scale <= 1.0 && buf.colors == 4 {
      // We want full size and the image is already 4 color, pass it through
      pipeline.cache.alias(inid, outid);
    } else if buf.colors == 4 {
      // Scale down a 4 colour image
      let buf = scale_down(&buf, nwidth, nheight);
      pipeline.cache.put(outid, buf, 1);
    } else if scale >= minscale {
      // We're scaling down enough that each pixel has all four colors under it so do the
      // demosaic and scale down in one go
      let buf = scaled(cfa, &buf, nwidth, nheight);
      pipeline.cache.put(outid, buf, 1);
    } else {
      // We're in a close to full scale output that needs full demosaic and possibly
      // minimal scale down
      let fullsize = full(cfa, &buf);
      let buf = if scale > 1.0 {
        scale_down(&fullsize, nwidth, nheight)
      } else {
        fullsize
      };
      pipeline.cache.put(outid, buf, 1);
    }
  }
}

pub fn full(cfa: CFA, buf: &OpBuffer) -> OpBuffer {
  let mut out = OpBuffer::new(buf.width, buf.height, 4);

  // First we set the colors we already have
  out.mutate_lines(&(|line: &mut [f32], row| {
    for (col, (pixout, pixin)) in line.chunks_mut(4).zip(buf.data[buf.width*row..].chunks(1)).enumerate() {
      let color = cfa.color_at(row, col);
      pixout[color] = pixin[0] as f32;
    }
  }));

  // Now we go around the image setting the unset colors to the average of the
  // surrounding pixels
  out.mutate_lines(&(|line: &mut [f32], row| {
    for col in 0..buf.width {
      let mut sums: [f32; 4] = [0.0;4];
      let mut counts: [u32; 4] = [0; 4];
      let color = cfa.color_at(row, col);

      for y in (cmp::max(0,(row as isize)-1) as usize) .. cmp::min(buf.height, row+2) {
        for x in (cmp::max(0,(col as isize)-1) as usize) .. cmp::min(buf.width, col+2) {
          let c = cfa.color_at(y, x);
          if c != color {
            sums[c] += buf.data[y*buf.width+x] as f32;
            counts[c] += 1;
          }
        }
      }

      for c in 0..4 {
        if c != color && counts[c] > 0 {
          line[col*4+c] = sums[c] / (counts[c] as f32);
        }
      }
    }
  }));

  out
}

fn calc_skips(idx: usize, idxmax: usize, skip: f32) -> (usize, usize, f32, f32) {
  let from = (idx as f32)*skip;
  let fromback = from.floor();
  let fromfactor = 1.0 - (from-fromback).fract();

  let to = ((idx+1) as f32)*skip;
  let toforward = (idxmax as f32).min(to.ceil());
  let tofactor = (toforward-to).fract();

  (fromback as usize, toforward as usize, fromfactor, tofactor)
}

pub fn scaled(cfa: CFA, buf: &OpBuffer, nwidth: usize, nheight: usize) -> OpBuffer {
  let mut out = OpBuffer::new(nwidth, nheight, 4);

  let rowskip = (buf.width as f32) / (nwidth as f32);
  let colskip = (buf.height as f32) / (nheight as f32);

  // Go around the image averaging blocks of pixels
  out.mutate_lines(&(|line: &mut [f32], row| {
    for col in 0..nwidth {
      let mut sums: [f32; 4] = [0.0;4];
      let mut counts: [f32; 4] = [0.0;4];
      let (fromrow, torow, topfactor, bottomfactor) = calc_skips(row, buf.height, rowskip);
      for y in fromrow..torow {
        let (fromcol, tocol, leftfactor, rightfactor) = calc_skips(col, buf.width, colskip);
        for x in fromcol..tocol {
          let factor = {
            (if y == fromrow {topfactor} else if y == torow {bottomfactor} else {1.0}) *
            (if x == fromcol {leftfactor} else if x == tocol {rightfactor} else {1.0})
          };

          let c = cfa.color_at(y, x);
          sums[c] += (buf.data[y*buf.width+x] as f32) * factor;
          counts[c] += factor;
        }
      }

      for c in 0..4 {
        if counts[c] > 0.0 {
          line[col*4+c] = sums[c] / counts[c];
        }
      }
    }
  }));

  out
}

pub fn scale_down(buf: &OpBuffer, nwidth: usize, nheight: usize) -> OpBuffer {
  let mut out = OpBuffer::new(nwidth, nheight, buf.colors);
  let rowskip = (buf.width as f32) / (nwidth as f32);
  let colskip = (buf.height as f32) / (nheight as f32);

  // Go around the image averaging blocks of pixels
  out.mutate_lines(&(|line: &mut [f32], row| {
    for col in 0..nwidth {
      let mut sums: [f32; 4] = [0.0;4];
      let mut counts: [f32; 4] = [0.0;4];
      let (fromrow, torow, topfactor, bottomfactor) = calc_skips(row, buf.height, rowskip);
      for y in fromrow..torow {
        let (fromcol, tocol, leftfactor, rightfactor) = calc_skips(col, buf.width, colskip);
        for x in fromcol..tocol {
          let factor = {
            (if y == fromrow {topfactor} else if y == torow {bottomfactor} else {1.0}) *
            (if x == fromcol {leftfactor} else if x == tocol {rightfactor} else {1.0})
          };

          for c in 0..buf.colors {
            sums[c] += buf.data[(y*buf.width+x)*buf.colors + c] * factor;
            counts[c] += factor;
          }
        }
      }

      for c in 0..buf.colors {
        if counts[c] > 0.0 {
          line[col*buf.colors+c] = sums[c] / counts[c];
        }
      }
    }
  }));

  out
}
<commit_msg>demosaic: speed up scale_down() by assuming cpp=4<commit_after>use decoders::RawImage;
use decoders::cfa::CFA;
use imageops::*;
use std::cmp;

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct OpDemosaic {
  cfa: String,
}

impl OpDemosaic {
  pub fn new(img: &RawImage) -> OpDemosaic {
    OpDemosaic{
      cfa: img.cropped_cfa().to_string(),
    }
  }
}

impl<'a> ImageOp<'a> for OpDemosaic {
  fn name(&self) -> &str {"demosaic"}
  fn run(&self, pipeline: &mut PipelineGlobals, inid: BufHash, outid: BufHash) {
    let buf = pipeline.cache.get(inid).unwrap();

    let (scale, nwidth, nheight) = if pipeline.maxwidth == 0 || pipeline.maxheight == 0 {
      (1.0, buf.width, buf.height)
    } else {
      // Do the calculations manually to avoid off-by-one errors from floating point rounding
      let xscale = (buf.width as f32) / (pipeline.maxwidth as f32);
      let yscale = (buf.height as f32) / (pipeline.maxheight as f32);
      if yscale > xscale {
        (yscale, ((buf.width as f32)/yscale) as usize, pipeline.maxheight)
      } else {
        (xscale, pipeline.maxwidth, ((buf.height as f32)/xscale) as usize)
      }
    };

    let cfa = CFA::new(&self.cfa);
    let minscale = match cfa.width {
      2  => 2.0,  // RGGB/RGBE bayer
      6  => 3.0,  // x-trans is 6 wide but has all colors in every 3x3 block
      8  => 2.0,  // Canon pro 70 has a 8x2 patern that has all four colors every 2x2 block
      12 => 12.0, // some crazy sensor I haven't actually encountered, use full block
      _  => 2.0,  // default
    };

    if scale <= 1.0 && buf.colors == 4 {
      // We want full size and the image is already 4 color, pass it through
      pipeline.cache.alias(inid, outid);
    } else if buf.colors == 4 {
      // Scale down a 4 colour image
      let buf = scale_down(&buf, nwidth, nheight);
      pipeline.cache.put(outid, buf, 1);
    } else if scale >= minscale {
      // We're scaling down enough that each pixel has all four colors under it so do the
      // demosaic and scale down in one go
      let buf = scaled(cfa, &buf, nwidth, nheight);
      pipeline.cache.put(outid, buf, 1);
    } else {
      // We're in a close to full scale output that needs full demosaic and possibly
      // minimal scale down
      let fullsize = full(cfa, &buf);
      let buf = if scale > 1.0 {
        scale_down(&fullsize, nwidth, nheight)
      } else {
        fullsize
      };
      pipeline.cache.put(outid, buf, 1);
    }
  }
}

pub fn full(cfa: CFA, buf: &OpBuffer) -> OpBuffer {
  let mut out = OpBuffer::new(buf.width, buf.height, 4);

  // First we set the colors we already have
  out.mutate_lines(&(|line: &mut [f32], row| {
    for (col, (pixout, pixin)) in line.chunks_mut(4).zip(buf.data[buf.width*row..].chunks(1)).enumerate() {
      let color = cfa.color_at(row, col);
      pixout[color] = pixin[0] as f32;
    }
  }));

  // Now we go around the image setting the unset colors to the average of the
  // surrounding pixels
  out.mutate_lines(&(|line: &mut [f32], row| {
    for col in 0..buf.width {
      let mut sums: [f32; 4] = [0.0;4];
      let mut counts: [u32; 4] = [0; 4];
      let color = cfa.color_at(row, col);

      for y in (cmp::max(0,(row as isize)-1) as usize) .. cmp::min(buf.height, row+2) {
        for x in (cmp::max(0,(col as isize)-1) as usize) .. cmp::min(buf.width, col+2) {
          let c = cfa.color_at(y, x);
          if c != color {
            sums[c] += buf.data[y*buf.width+x] as f32;
            counts[c] += 1;
          }
        }
      }

      for c in 0..4 {
        if c != color && counts[c] > 0 {
          line[col*4+c] = sums[c] / (counts[c] as f32);
        }
      }
    }
  }));

  out
}

fn calc_skips(idx: usize, idxmax: usize, skip: f32) -> (usize, usize, f32, f32) {
  let from = (idx as f32)*skip;
  let fromback = from.floor();
  let fromfactor = 1.0 - (from-fromback).fract();

  let to = ((idx+1) as f32)*skip;
  let toforward = (idxmax as f32).min(to.ceil());
  let tofactor = (toforward-to).fract();

  (fromback as usize, toforward as usize, fromfactor, tofactor)
}

pub fn scaled(cfa: CFA, buf: &OpBuffer, nwidth: usize, nheight: usize) -> OpBuffer {
  let mut out = OpBuffer::new(nwidth, nheight, 4);

  let rowskip = (buf.width as f32) / (nwidth as f32);
  let colskip = (buf.height as f32) / (nheight as f32);

  // Go around the image averaging blocks of pixels
  out.mutate_lines(&(|line: &mut [f32], row| {
    for col in 0..nwidth {
      let mut sums: [f32; 4] = [0.0;4];
      let mut counts: [f32; 4] = [0.0;4];
      let (fromrow, torow, topfactor, bottomfactor) = calc_skips(row, buf.height, rowskip);
      for y in fromrow..torow {
        let (fromcol, tocol, leftfactor, rightfactor) = calc_skips(col, buf.width, colskip);
        for x in fromcol..tocol {
          let factor = {
            (if y == fromrow {topfactor} else if y == torow {bottomfactor} else {1.0}) *
            (if x == fromcol {leftfactor} else if x == tocol {rightfactor} else {1.0})
          };

          let c = cfa.color_at(y, x);
          sums[c] += (buf.data[y*buf.width+x] as f32) * factor;
          counts[c] += factor;
        }
      }

      for c in 0..4 {
        if counts[c] > 0.0 {
          line[col*4+c] = sums[c] / counts[c];
        }
      }
    }
  }));

  out
}

pub fn scale_down(buf: &OpBuffer, nwidth: usize, nheight: usize) -> OpBuffer {
  assert_eq!(buf.colors, 4); // When we're scaling down we're always at 4 cpp

  let mut out = OpBuffer::new(nwidth, nheight, 4);
  let rowskip = (buf.width as f32) / (nwidth as f32);
  let colskip = (buf.height as f32) / (nheight as f32);

  // Go around the image averaging blocks of pixels
  out.mutate_lines(&(|line: &mut [f32], row| {
    for col in 0..nwidth {
      let mut sums: [f32; 4] = [0.0;4];
      let mut counts: [f32; 4] = [0.0;4];
      let (fromrow, torow, topfactor, bottomfactor) = calc_skips(row, buf.height, rowskip);
      for y in fromrow..torow {
        let (fromcol, tocol, leftfactor, rightfactor) = calc_skips(col, buf.width, colskip);
        for x in fromcol..tocol {
          let factor = {
            (if y == fromrow {topfactor} else if y == torow {bottomfactor} else {1.0}) *
            (if x == fromcol {leftfactor} else if x == tocol {rightfactor} else {1.0})
          };

          for c in 0..4 {
            sums[c] += buf.data[(y*buf.width+x)*4 + c] * factor;
            counts[c] += factor;
          }
        }
      }

      for c in 0..4 {
        if counts[c] > 0.0 {
          line[col*4+c] = sums[c] / counts[c];
        }
      }
    }
  }));

  out
}
<|endoftext|>


<commit_before>// Zinc, the bare metal stack for rust.
// Copyright 2014 Vladimir "farcaller" Pouzanov <farcaller@gmail.com>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Basic multitasking interface.

use core::mem::size_of;
use core::intrinsics::abort;

use hal::cortex_m3::{sched, systick};
use os::syscall::syscall;
use hal::stack;

/// Task takes one argument, which is u32
pub type Task = fn(u32);

mod current_stack_offset {
  /// Currently allocated stack memory, growing down, starting at __STACK_BASE.
  static mut CurrentStackOffset: u32 = 0;

  pub fn get() -> u32 {
    unsafe { CurrentStackOffset }
  }

  pub fn set(val: u32) {
    unsafe { CurrentStackOffset = val };
  }
}

/// Bytes to reserve in privileged stack based on stack size at the time of task::setup() call.
static ReservedPivilegedStackSize: u32 = 256;

/// Maximum number of tasks.
static MaxTasksCount: uint = 4;

mod defined_tasks_count {
  use core::intrinsics::abort;

  /// Total defined tasks count.
  static mut DefinedTasksCount: uint = 0;

  pub fn get() -> uint {
    unsafe { DefinedTasksCount }
  }

  pub fn increase() {
    unsafe {
      DefinedTasksCount += 1;
      if DefinedTasksCount > super::MaxTasksCount {
        abort();
      }
    }
  }
}

/// Task descriptor, provides task stack pointer.
pub struct TaskDescriptor {
  pub stack_start: u32,
  pub stack_end: u32,
}

struct TasksCollection {
  pub current_task: uint,
  pub tasks: [TaskDescriptor, ..MaxTasksCount],
}

static mut Tasks: TasksCollection = TasksCollection {
  current_task: 0,
  tasks: [TaskDescriptor { stack_start: 0, stack_end: 0 }, ..MaxTasksCount]
};

impl TasksCollection {
  fn current_task<'a>(&'a mut self) -> &'a mut TaskDescriptor {
    &mut self.tasks[self.current_task]
  }

  fn next_task(&mut self) {
    loop {
      self.current_task += 1;
      if self.current_task == defined_tasks_count::get() {
        self.current_task = 0;
      }
      if self.current_task().valid() {
        break;
      }
    }
  }

  fn add_task(&mut self, t: TaskDescriptor) {
    self.tasks[defined_tasks_count::get()] = t;
    defined_tasks_count::increase();
  }
}

/// Initialize and start task manager.
///
/// This function keeps main stack intact. It starts the task scheduler and
/// never returns.
///
/// t should point to initial task.
#[inline(never)]
pub fn setup(t: Task, stack_size: u32) {
  systick::setup(::hal::cortex_m3::systick::CALIBRATED, true);

  let current_stack = sched::get_current_stack_pointer();
  // User tasks start at this current stack size + reserved size aligned by 4
  // bytes.
  let task_stack_base: u32 = (current_stack as u32 - ReservedPivilegedStackSize) & !3;
  current_stack_offset::set(task_stack_base);

  let td = define_task(t, 0, stack_size, true);

  td.load();

  systick::enable();
  sched::switch_context();

  unsafe { abort() };
}

#[inline(never)]
pub fn define_task(t: Task, arg: u32, stack_size: u32, initial: bool) -> TaskDescriptor {
  systick::disable_irq();
  let task_base = current_stack_offset::get();
  let task_stack_size: u32 = (
    stack_size +
    8*4 +  // hw saved regs
    8*4 +  // sw saved regs
    8*4    // scratch pad for __morestack failure. see note on morestack below.
  ) & !0b1111;
  current_stack_offset::set(task_base - task_stack_size);

  let td = TaskDescriptor::new(t, arg, task_base, stack_size, initial);
  unsafe { Tasks.add_task(td) };

  systick::enable_irq();
  td
}

impl TaskDescriptor {
  /// Creates a new TaskDescriptor for given task, arg and stack base.
  ///
  /// This function initializes task stack with hw saved registers.
  #[inline(never)]
  pub fn new(t: Task, arg: u32, stack_base: u32, stack_size: u32, initial: bool) -> TaskDescriptor {
    let state = sched::SavedState::new(t, arg);

    let mut stack_top: u32 = stack_base - size_of::<sched::SavedState>() as u32;
    unsafe { *(stack_top as *mut sched::SavedState) = state };
    if !initial {
      stack_top -= 8*4;
    }

    TaskDescriptor {
      stack_start: stack_top,
      stack_end: stack_base - stack_size,
    }
  }

  pub fn load(&self) {
    sched::set_task_stack_pointer(self.stack_start);
    stack::set_stack_limit(self.stack_end);
  }

  pub fn save(&mut self) {
    self.stack_start = sched::get_task_stack_pointer();
  }

  pub fn valid(&self) -> bool {
    self.stack_end != 0
  }

  pub fn invalidate(&mut self) {
    self.stack_end = 0;
  }
}

#[inline(always)]
pub unsafe fn task_scheduler() {
  stack::set_stack_limit(stack::stack_base() - ReservedPivilegedStackSize);
  Tasks.current_task().save();
  Tasks.next_task();
  Tasks.current_task().load();
}

// TODO(farcaller): this should not actually use stack!
// At the time of the call of syscall(), the stack is overflown by 4, we still
// have 12 bytes in reserve and 2*8*4 to save the frame in pendsv after kill.
#[no_split_stack]
pub fn morestack() {
  let psp = sched::get_task_stack_pointer();
  let sp = sched::get_current_stack_pointer();
  if psp == sp {
    unsafe { syscall(kill_current_task, 0) };
  } else {
    unsafe { abort() };
  }
}

#[inline(never)]
#[no_mangle]
#[no_split_stack]
pub fn kill_current_task(_: u32) {
  unsafe { Tasks.current_task().invalidate() };
  sched::switch_context();
}
<commit_msg>os::task: Add support for blocking<commit_after>// Zinc, the bare metal stack for rust.
// Copyright 2014 Vladimir "farcaller" Pouzanov <farcaller@gmail.com>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Basic multitasking interface.

use core::mem::size_of;
use core::intrinsics::abort;

use hal::cortex_m3::{sched, systick};
use hal::cortex_m3::sched::NoInterrupts;
use os::syscall::syscall;
use hal::stack;

/// Task takes one argument, which is u32
pub type Task = fn(u32);

mod current_stack_offset {
  /// Currently allocated stack memory, growing down, starting at __STACK_BASE.
  static mut CurrentStackOffset: u32 = 0;

  pub fn get() -> u32 {
    unsafe { CurrentStackOffset }
  }

  pub fn set(val: u32) {
    unsafe { CurrentStackOffset = val };
  }
}

/// Bytes to reserve in privileged stack based on stack size at the time of task::setup() call.
static ReservedPivilegedStackSize: u32 = 256;

/// Maximum number of tasks.
static MaxTasksCount: uint = 4;

mod defined_tasks_count {
  use core::intrinsics::abort;

  /// Total defined tasks count.
  static mut DefinedTasksCount: uint = 0;

  pub fn get() -> uint {
    unsafe { DefinedTasksCount }
  }

  pub fn increase() {
    unsafe {
      DefinedTasksCount += 1;
      if DefinedTasksCount > super::MaxTasksCount {
        abort();
      }
    }
  }
}

pub enum Status {
  Runnable,
  Blocked
}

/// Task descriptor, provides task stack pointer.
pub struct TaskDescriptor {
  pub stack_start: u32,
  pub stack_end: u32,
  pub status: Status
}

impl TaskDescriptor {
  pub fn block(&mut self, _: NoInterrupts) {
    self.status = Blocked;
    sched::switch_context();
  }
  pub fn unblock(&mut self, _: &NoInterrupts) { self.status = Runnable; }
}

struct TasksCollection {
  pub current_task: uint,
  pub tasks: [TaskDescriptor, ..MaxTasksCount],
}

pub static mut Tasks: TasksCollection = TasksCollection {
  current_task: 0,
  tasks: [TaskDescriptor { stack_start: 0, stack_end: 0, status: Runnable }, ..MaxTasksCount]
};

impl TasksCollection {
  pub fn current_task<'a>(&'a mut self) -> &'a mut TaskDescriptor {
    &mut self.tasks[self.current_task]
  }

  fn next_task(&mut self) {
    loop {
      self.current_task += 1;
      if self.current_task == defined_tasks_count::get() {
        self.current_task = 0;
      }
      match self.current_task() {
        &task if !task.valid()                 => {}
        &TaskDescriptor {status: Runnable, ..} => break,
        _                                      => {}
      }
    }
  }

  fn add_task(&mut self, t: TaskDescriptor) {
    self.tasks[defined_tasks_count::get()] = t;
    defined_tasks_count::increase();
  }
}

/// Initialize and start task manager.
///
/// This function keeps main stack intact. It starts the task scheduler and
/// never returns.
///
/// t should point to initial task.
#[inline(never)]
pub fn setup(t: Task, stack_size: u32) {
  systick::setup(::hal::cortex_m3::systick::CALIBRATED, true);

  let current_stack = sched::get_current_stack_pointer();
  // User tasks start at this current stack size + reserved size aligned by 4
  // bytes.
  let task_stack_base: u32 = (current_stack as u32 - ReservedPivilegedStackSize) & !3;
  current_stack_offset::set(task_stack_base);

  let td = define_task(t, 0, stack_size, true);

  td.load();

  systick::enable();
  sched::switch_context();

  unsafe { abort() };
}

#[inline(never)]
pub fn define_task(t: Task, arg: u32, stack_size: u32, initial: bool) -> TaskDescriptor {
  systick::disable_irq();
  let task_base = current_stack_offset::get();
  let task_stack_size: u32 = (
    stack_size +
    8*4 +  // hw saved regs
    8*4 +  // sw saved regs
    8*4    // scratch pad for __morestack failure. see note on morestack below.
  ) & !0b1111;
  current_stack_offset::set(task_base - task_stack_size);

  let td = TaskDescriptor::new(t, arg, task_base, stack_size, initial);
  unsafe { Tasks.add_task(td) };

  systick::enable_irq();
  td
}

impl TaskDescriptor {
  /// Creates a new TaskDescriptor for given task, arg and stack base.
  ///
  /// This function initializes task stack with hw saved registers.
  #[inline(never)]
  pub fn new(t: Task, arg: u32, stack_base: u32, stack_size: u32, initial: bool) -> TaskDescriptor {
    let state = sched::SavedState::new(t, arg);

    let mut stack_top: u32 = stack_base - size_of::<sched::SavedState>() as u32;
    unsafe { *(stack_top as *mut sched::SavedState) = state };
    if !initial {
      stack_top -= 8*4;
    }

    TaskDescriptor {
      stack_start: stack_top,
      stack_end: stack_base - stack_size,
      status: Runnable,
    }
  }

  pub fn load(&self) {
    sched::set_task_stack_pointer(self.stack_start);
    stack::set_stack_limit(self.stack_end);
  }

  pub fn save(&mut self) {
    self.stack_start = sched::get_task_stack_pointer();
  }

  pub fn valid(&self) -> bool {
    self.stack_end != 0
  }

  pub fn invalidate(&mut self) {
    self.stack_end = 0;
  }
}

#[inline(always)]
pub unsafe fn task_scheduler() {
  stack::set_stack_limit(stack::stack_base() - ReservedPivilegedStackSize);
  Tasks.current_task().save();
  Tasks.next_task();
  Tasks.current_task().load();
}

// TODO(farcaller): this should not actually use stack!
// At the time of the call of syscall(), the stack is overflown by 4, we still
// have 12 bytes in reserve and 2*8*4 to save the frame in pendsv after kill.
#[no_split_stack]
pub fn morestack() {
  let psp = sched::get_task_stack_pointer();
  let sp = sched::get_current_stack_pointer();
  if psp == sp {
    unsafe { syscall(kill_current_task, 0) };
  } else {
    unsafe { abort() };
  }
}

#[inline(never)]
#[no_mangle]
#[no_split_stack]
pub fn kill_current_task(_: u32) {
  unsafe { Tasks.current_task().invalidate() };
  sched::switch_context();
}
<|endoftext|>


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

use std::ascii::OwnedAsciiExt;
use std::collections::HashSet;

// Returns true if the sentence uses all 26 letters in the English
// alphabet at least once.
fn is_pangram(sentence: &str) -> bool {
    sentence.to_string().into_ascii_lower().chars()
        .filter(|&c| c >= 'a' && c <= 'z')
        .collect::<HashSet<char>>().len() == 26
}

#[cfg(not(test))]
fn main() {
    let test_sentences = ["The quick brown fox jumps over the lazy dog.",
                          "The quick brown frog jumps over the lazy dog."];
    for &sentence in test_sentences.iter() {
        println!("\"{}\" {} a pangram", sentence,
                 if is_pangram(sentence) { "is" } else { "is not" });
    }
}

#[test]
fn test_empty() {
    assert_eq!(is_pangram(""), false);
}

#[test]
fn test_one_letter() {
    assert_eq!(is_pangram("A"), false);
}

#[test]
fn test_pangram() {
    assert_eq!(is_pangram("The quick brown fox jumps over the lazy dog"),
               true);
}

#[test]
fn test_non_pangram() {
    assert_eq!(is_pangram("The quick brown fox jumps over the lurking dog"),
               false);
}

#[test]
fn test_pangram_unicode() {
    assert_eq!(is_pangram("The quick brown fox (狐狸) jumps over the lazy dog"),
               true);
}

#[test]
fn test_non_pangram_unicode() {
    assert_eq!(is_pangram("The quick brown 狐狸 jumps over the lazy dog"),
               false);
}
<commit_msg>Used map() in pangram instead of allocating a new string<commit_after>// Implements http://rosettacode.org/wiki/Pangram_checker

use std::collections::HashSet;

// Returns true if the sentence uses all 26 letters in the English
// alphabet at least once.
fn is_pangram(sentence: &str) -> bool {
    sentence.chars().map(|c| c.to_lowercase())
        .filter(|&c| c >= 'a' && c <= 'z')
        .collect::<HashSet<char>>().len() == 26
}

#[cfg(not(test))]
fn main() {
    let test_sentences = ["The quick brown fox jumps over the lazy dog.",
                          "The quick brown frog jumps over the lazy dog."];
    for &sentence in test_sentences.iter() {
        println!("\"{}\" {} a pangram", sentence,
                 if is_pangram(sentence) { "is" } else { "is not" });
    }
}

#[test]
fn test_empty() {
    assert_eq!(is_pangram(""), false);
}

#[test]
fn test_one_letter() {
    assert_eq!(is_pangram("A"), false);
}

#[test]
fn test_pangram() {
    assert_eq!(is_pangram("The quick brown fox jumps over the lazy dog"),
               true);
}

#[test]
fn test_non_pangram() {
    assert_eq!(is_pangram("The quick brown fox jumps over the lurking dog"),
               false);
}

#[test]
fn test_pangram_unicode() {
    assert_eq!(is_pangram("The quick brown fox (狐狸) jumps over the lazy dog"),
               true);
}

#[test]
fn test_non_pangram_unicode() {
    assert_eq!(is_pangram("The quick brown 狐狸 jumps over the lazy dog"),
               false);
}
<|endoftext|>