<commit_before>use basetypes::*;

pub struct BoardGeometry {
    pub grid: [u8; 120],
    pub piece_deltas: [[i8; 8]; 5],
    pub piece_longrange: [bool; 5],
    pub attacks: [[u64; 64]; 5],
    pub blockers_and_beyond: [[u64; 64]; 5],
}

impl BoardGeometry {
    pub fn new() -> BoardGeometry {
        // We use 10x12 grid (8x8 with guarding markers, 2 at top and
        // bottom, 1 at the sides), so that we can detect out-of-board
        // movements. Each cell in the grid contains the corresponding
        // square number (from 0 to 63) or 0xff (the guarding marker).
        let mut grid = [0xffu8; 120];
        for i in 0..64 {
            grid[BoardGeometry::grid_index_from_square(i)] = i as u8;
        }

        // "piece_deltas" represent the change in the grid-index when
        // sliding a particular piece by one square in a particular
        // direction. We are not concerned with pawns here.
        let mut piece_deltas = [[0i8; 8]; 5];
        piece_deltas[QUEEN] = [-11, -10, -9, -1, 1, 9, 10, 11];
        piece_deltas[ROOK] = [0, -10, 0, -1, 1, 0, 10, 0];
        piece_deltas[BISHOP] = [-11, 0, -9, 0, 0, 9, 0, 11];
        piece_deltas[KNIGHT] = [-21, -19, -12, -8, 8, 12, 19, 21];
        piece_deltas[KING] = [-11, -10, -9, -1, 1, 9, 10, 11];

        // All pieces except knights and kings are long-range (They
        // can slide by more than one square). We are not concerned
        // with pawns here.
        let mut piece_longrange = [true; 5];
        piece_longrange[KNIGHT] = false;
        piece_longrange[KING] = false;

        let mut g = BoardGeometry {
            grid: grid,
            piece_deltas: piece_deltas,
            piece_longrange: piece_longrange,
            attacks: [[0u64; 64]; 5],
            blockers_and_beyond: [[0u64; 64]; 5],
        };

        // "attacks" and "blockers_and_beyond" fileds hold attack and
        // blockers bitsets for each piece on each possible square.
        // For example:
        //
        // g.attacks[QUEEN][D4]  g.blockers_and_beyond[QUEEN][D4]
        // . . . 1 . . . 1       . . . . . . . .
        // 1 . . 1 . . 1 .       . . . 1 . . 1 .
        // . 1 . 1 . 1 . .       . 1 . 1 . 1 . .
        // . . 1 1 1 . . .       . . 1 1 1 . . .
        // 1 1 1 Q 1 1 1 1       . 1 1 Q 1 1 1 .
        // . . 1 1 1 . . .       . . 1 1 1 . . .
        // . 1 . 1 . 1 . .       . 1 . 1 . 1 . .
        // 1 . . 1 . . 1 .       . . . . . . . .
        //
        // g.attacks[KNIGHT][D4] g.blockers_and_beyond[KNIGHT][D4]
        // . . . . . . . .       . . . . . . . .
        // . . . . . . . .       . . . . . . . .
        // . . 1 . 1 . . .       . . . . . . . .
        // . 1 . . . 1 . .       . . . . . . . .
        // . . . N . . . .       . . . N . . . .
        // . 1 . . . 1 . .       . . . . . . . .
        // . . 1 . 1 . . .       . . . . . . . .
        // . . . . . . . .       . . . . . . . .
        g.fill_attack_and_blockers_and_beyond_arrays();

        g
    }

    pub fn grid_index(&self, i: Square) -> usize {
        Self::grid_index_from_square(i)
    }

    #[inline(always)]
    fn grid_index_from_square(i: Square) -> usize {
        ((i / 8) * 10 + (i % 8) + 21)
    }

    fn fill_attack_and_blockers_and_beyond_arrays(&mut self) {
        for piece_type in 0..5 {
            for square in 0..64 {
                let mut attack = 0u64;
                let mut blockers = 0u64;
                for move_direction in 0..8 {
                    let delta = self.piece_deltas[piece_type][move_direction];
                    if delta != 0 {
                        let mut last_mask = 0u64;
                        let mut curr_grid_index = self.grid_index(square);
                        loop {
                            curr_grid_index = (curr_grid_index as i8 + delta) as usize;
                            let curr_square = self.grid[curr_grid_index];
                            if curr_square != 0xff {
                                last_mask = 1 << curr_square;
                                attack |= last_mask;
                                blockers |= last_mask;
                                if self.piece_longrange[piece_type] {
                                    continue;
                                }
                            }
                            blockers &= !last_mask;
                            break;
                        }
                    }
                }
                self.attacks[piece_type][square] = attack;
                self.blockers_and_beyond[piece_type][square] = blockers;
            }
        }
    }
}

// Attack (or blockers and beyond) array for all sliding pieces.
pub type SlidersArray = [[u64; 64]; 5];

// The StateInfo struct stores information needed to restore a Position
// object to its previous state when we retract a move. Whenever a move
// is made on the board (by calling Position::do_move), a StateInfo
// object must be passed as a parameter.

// struct StateInfo {
//   Key pawnKey, materialKey;
//   Value npMaterial[COLOR_NB];
//   int castlingRights, rule50, pliesFromNull;
//   Score psq;
//   Square epSquare;

//   Key key;
//   Bitboard checkersBB;
//   PieceType capturedType;
//   StateInfo* previous;
// };

pub type LinesArray = [[u64; 64]; 64];

// pub fn generate_behind_and_between_arrays() -> LinesArray {

// }

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

    #[test]
    fn test_attack_sets() {
        use basetypes::*;
        let g = BoardGeometry::new();
        let (att_sets, bl_sets) = (g.attacks, g.blockers_and_beyond);
        assert_eq!(att_sets[KING][0], 0b11 << 8 | 0b10);
        assert_eq!(bl_sets[KING][0], 0);
        assert_eq!(att_sets[ROOK][0],
                   0b11111110 | 1 << 8 | 1 << 16 | 1 << 24 | 1 << 32 | 1 << 40 | 1 << 48 | 1 << 56);
        assert_eq!(bl_sets[ROOK][0],
                   0b01111110 | 1 << 8 | 1 << 16 | 1 << 24 | 1 << 32 | 1 << 40 | 1 << 48 | 0 << 56);
    }

}
<commit_msg>Rename piece_delatas to piece_grid_delatas.<commit_after>use basetypes::*;

pub struct BoardGeometry {
    pub grid: [u8; 120],
    pub piece_grid_deltas: [[i8; 8]; 5],
    pub piece_longrange: [bool; 5],
    pub attacks: [[u64; 64]; 5],
    pub blockers_and_beyond: [[u64; 64]; 5],
}

impl BoardGeometry {
    pub fn new() -> BoardGeometry {
        // We use 10x12 grid (8x8 with guarding markers, 2 at top and
        // bottom, 1 at the sides), so that we can detect out-of-board
        // movements. Each cell in the grid contains the corresponding
        // square number (from 0 to 63) or 0xff (the guarding marker).
        let mut grid = [0xffu8; 120];
        for i in 0..64 {
            grid[BoardGeometry::grid_index_from_square(i)] = i as u8;
        }

        // "piece_deltas" represent the change in the grid-index when
        // sliding a particular piece by one square in a particular
        // direction. We are not concerned with pawns here.
        let mut piece_deltas = [[0i8; 8]; 5];
        piece_deltas[QUEEN] = [-11, -10, -9, -1, 1, 9, 10, 11];
        piece_deltas[ROOK] = [0, -10, 0, -1, 1, 0, 10, 0];
        piece_deltas[BISHOP] = [-11, 0, -9, 0, 0, 9, 0, 11];
        piece_deltas[KNIGHT] = [-21, -19, -12, -8, 8, 12, 19, 21];
        piece_deltas[KING] = [-11, -10, -9, -1, 1, 9, 10, 11];

        // All pieces except knights and kings are long-range (They
        // can slide by more than one square). We are not concerned
        // with pawns here.
        let mut piece_longrange = [true; 5];
        piece_longrange[KNIGHT] = false;
        piece_longrange[KING] = false;

        let mut g = BoardGeometry {
            grid: grid,
            piece_grid_deltas: piece_deltas,
            piece_longrange: piece_longrange,
            attacks: [[0u64; 64]; 5],
            blockers_and_beyond: [[0u64; 64]; 5],
        };

        // "attacks" and "blockers_and_beyond" fileds hold attack and
        // blockers bitsets for each piece on each possible square.
        // For example:
        //
        // g.attacks[QUEEN][D4]  g.blockers_and_beyond[QUEEN][D4]
        // . . . 1 . . . 1       . . . . . . . .
        // 1 . . 1 . . 1 .       . . . 1 . . 1 .
        // . 1 . 1 . 1 . .       . 1 . 1 . 1 . .
        // . . 1 1 1 . . .       . . 1 1 1 . . .
        // 1 1 1 Q 1 1 1 1       . 1 1 Q 1 1 1 .
        // . . 1 1 1 . . .       . . 1 1 1 . . .
        // . 1 . 1 . 1 . .       . 1 . 1 . 1 . .
        // 1 . . 1 . . 1 .       . . . . . . . .
        //
        // g.attacks[KNIGHT][D4] g.blockers_and_beyond[KNIGHT][D4]
        // . . . . . . . .       . . . . . . . .
        // . . . . . . . .       . . . . . . . .
        // . . 1 . 1 . . .       . . . . . . . .
        // . 1 . . . 1 . .       . . . . . . . .
        // . . . N . . . .       . . . N . . . .
        // . 1 . . . 1 . .       . . . . . . . .
        // . . 1 . 1 . . .       . . . . . . . .
        // . . . . . . . .       . . . . . . . .
        g.fill_attack_and_blockers_and_beyond_arrays();

        g
    }

    pub fn grid_index(&self, i: Square) -> usize {
        Self::grid_index_from_square(i)
    }

    #[inline(always)]
    fn grid_index_from_square(i: Square) -> usize {
        ((i / 8) * 10 + (i % 8) + 21)
    }

    fn fill_attack_and_blockers_and_beyond_arrays(&mut self) {
        for piece_type in 0..5 {
            for square in 0..64 {
                let mut attack = 0u64;
                let mut blockers = 0u64;
                for move_direction in 0..8 {
                    let delta = self.piece_grid_deltas[piece_type][move_direction];
                    if delta != 0 {
                        let mut last_mask = 0u64;
                        let mut curr_grid_index = self.grid_index(square);
                        loop {
                            curr_grid_index = (curr_grid_index as i8 + delta) as usize;
                            let curr_square = self.grid[curr_grid_index];
                            if curr_square != 0xff {
                                last_mask = 1 << curr_square;
                                attack |= last_mask;
                                blockers |= last_mask;
                                if self.piece_longrange[piece_type] {
                                    continue;
                                }
                            }
                            blockers &= !last_mask;
                            break;
                        }
                    }
                }
                self.attacks[piece_type][square] = attack;
                self.blockers_and_beyond[piece_type][square] = blockers;
            }
        }
    }
}

// Attack (or blockers and beyond) array for all sliding pieces.
pub type SlidersArray = [[u64; 64]; 5];

// The StateInfo struct stores information needed to restore a Position
// object to its previous state when we retract a move. Whenever a move
// is made on the board (by calling Position::do_move), a StateInfo
// object must be passed as a parameter.

// struct StateInfo {
//   Key pawnKey, materialKey;
//   Value npMaterial[COLOR_NB];
//   int castlingRights, rule50, pliesFromNull;
//   Score psq;
//   Square epSquare;

//   Key key;
//   Bitboard checkersBB;
//   PieceType capturedType;
//   StateInfo* previous;
// };

pub type LinesArray = [[u64; 64]; 64];

// pub fn generate_behind_and_between_arrays() -> LinesArray {

// }

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

    #[test]
    fn test_attack_sets() {
        use basetypes::*;
        let g = BoardGeometry::new();
        let (att_sets, bl_sets) = (g.attacks, g.blockers_and_beyond);
        assert_eq!(att_sets[KING][0], 0b11 << 8 | 0b10);
        assert_eq!(bl_sets[KING][0], 0);
        assert_eq!(att_sets[ROOK][0],
                   0b11111110 | 1 << 8 | 1 << 16 | 1 << 24 | 1 << 32 | 1 << 40 | 1 << 48 | 1 << 56);
        assert_eq!(bl_sets[ROOK][0],
                   0b01111110 | 1 << 8 | 1 << 16 | 1 << 24 | 1 << 32 | 1 << 40 | 1 << 48 | 0 << 56);
    }

}
<|endoftext|>


<commit_before>use std::mem;
use std::iter::range_inclusive;

use std::rand::{Rng, SeedableRng, Rand};

const DSFMT_LOW_MASK:   u64 = 0x000FFFFFFFFFFFFF;
const DSFMT_HIGH_CONST: u64 = 0x3FF0000000000000;

const DSFMT_F32_MANTISSA_MASK: u64 = 0x00000000007FFFFF;
const DSFMT_HIGH_CONST32:      u32 = 0x3F800000;

const DSFMT_MEXP:uint = 19937;
const DSFMT_N:   uint = ((DSFMT_MEXP - 128) / 104 + 1);
const DSFMT_N64: uint = (DSFMT_N * 2);
const DSFMT_SR:  uint = 12;

const DSFMT_POS1: uint = 117;
const DSFMT_SL1:  uint = 19;
const DSFMT_PCV1: u64  = 0x3d84e1ac0dc82880;
const DSFMT_PCV2: u64  = 0x0000000000000001;
const DSFMT_FIX1: u64  = 0x90014964b32f4329;
const DSFMT_FIX2: u64  = 0x3b8d12ac548a7c7a;
const DSFMT_MSK1: u64  = 0x000ffafffffffb3f;
const DSFMT_MSK2: u64  = 0x000ffdfffc90fffd;

const SSE2_SHUFF: u8 = 0x1b;
const SSE2_PARAMS_MASK: u64x2 = u64x2{x: DSFMT_MSK1, y: DSFMT_MSK2};

pub struct DSFMTRng{
    status: [u64x2, ..DSFMT_N + 1],
    idx: uint,
}

#[repr(C)]
#[simd]
#[deriving(Show)]
struct u32x4{
    x: u32,
    y: u32,
    z: u32,
    w: u32,
}

#[repr(C)]
#[simd]
#[deriving(Show)]
struct u64x2{
    x: u64,
    y: u64,
}

impl Index<uint, u64> for u64x2{
    #[inline(always)]
    fn index(&self, _rhs: &uint) -> &u64{
        match *_rhs{
            0 => &self.x,
            _ => &self.y,
        }
    }
}

impl IndexMut<uint, u64> for u64x2{
    #[inline(always)]
    fn index_mut(&mut self, _rhs: &uint) -> &mut u64{
        match *_rhs{
            0 => &mut self.x,
            _ => &mut self.y,
        }
    }
}

impl Index<uint, u32> for u32x4{
    #[inline(always)]
    fn index(&self, _rhs: &uint) -> &u32{
        match *_rhs{
            0 => &self.x,
            1 => &self.y,
            2 => &self.z,
            _ => &self.w,
        }
    }
}

impl IndexMut<uint, u32> for u32x4{
    #[inline(always)]
    fn index_mut(&mut self, _rhs: &uint) -> &mut u32{
        match *_rhs{
            0 => &mut self.x,
            1 => &mut self.y,
            2 => &mut self.z,
            _ => &mut self.w,
        }
    }
}

#[cfg(target_endian = "big")]
fn idxof(i: uint) -> uint {
    i ^ 1
}

#[cfg(target_endian = "little")]
fn idxof(i: uint) -> uint {
    i
}

//#[allow(unused)]
//#[inline(always)]
//fn do_recursion(r: &mut u64x2, a: u64x2, b: u64x2, lung: &mut u64x2){
//
//    let u64x2{x: t0, y: t1} = a;
//    let u64x2{x: l0, y: l1} = *lung;
//
//    lung[0] = (t0 << DSFMT_SL1) ^ (l1 >> 32) ^ (l1 << 32) ^ b[0];
//    lung[1] = (t1 << DSFMT_SL1) ^ (l0 >> 32) ^ (l0 << 32) ^ b[1];
//
//    r[0] = ((*lung)[0] >> DSFMT_SR) ^ ((*lung)[0] & DSFMT_MSK1) ^ t0;
//    r[1] = ((*lung)[1] >> DSFMT_SR) ^ ((*lung)[1] & DSFMT_MSK2) ^ t1;
//}

#[allow(unused)]
#[inline(always)]
fn do_recursion(r: &mut u64x2, a: u64x2, b: u64x2, u: &mut u64x2){
    let mut z = a;
    unsafe{asm!(
        "psllq  $4, $0\n\t
         pxor   $8, $0\n\t
         pshufd $3, $1, $1\n\t
         pxor   $0, $1\n\t
         movaps $1, $0\n\t
         movaps $1, $2\n\t
         pand   $6, $0\n\t
         psrlq  $5, $2\n\t
         pxor   $7, $2\n\t
         pxor   $0, $2\n\t
        "
        :"+x"(z), "+x"(*u), "=x"(*r)
        :"i"(SSE2_SHUFF), "i"(DSFMT_SL1), "i"(DSFMT_SR), "x"(SSE2_PARAMS_MASK), "m"(a), "x"(b)
    )};
}

impl DSFMTRng{
    /// Create a new unseeded DSFMTRng instance
    pub fn new_unseeded() -> DSFMTRng {
        DSFMTRng{status: [u64x2{x: 0, y: 0}, ..DSFMT_N + 1], idx: 0}
    }

    /// Initializes the internal state array to fit the IEEE 754 format.
    fn initial_mask(&mut self){
        for i in range(0, DSFMT_N * 2){
            let (n, m) = (i / 2, i % 2);
            self.status[n][m] = (self.status[n][m] & DSFMT_LOW_MASK) | DSFMT_HIGH_CONST;
        }
    }

    /// Certifies the period of 2^{SFMT_MEXP}-1.
    fn period_certification(&mut self) {
        let pcv: [u64, ..2] = [DSFMT_PCV1, DSFMT_PCV2];

        {
            let tmp = [self.status[DSFMT_N][0] ^ DSFMT_FIX1, self.status[DSFMT_N][1] ^ DSFMT_FIX2];
            let mut inner = (tmp[0] & pcv[0]) ^ (tmp[1] & pcv[1]);

            let mut i = 32u;
            while i > 0 {
                inner ^= inner >> i;
                i >>= 1;
            }
            inner &= 1;
            /* check OK */
            if inner == 1 {
                return;
            }
        }

        /* check NG, and modification */
        if (DSFMT_PCV2 & 1) == 1 {
            self.status[DSFMT_N][1] ^= 1;
        }
        else{
            for i in range_inclusive(1, 0){
                let mut work = 1u64;
                for _ in range(0i, 64){
                    if (work & pcv[i]) != 0 {
                        self.status[DSFMT_N][i] ^= work;
                        return;
                    }
                    work <<= 1;
                }
            }
        }
    }

    fn init(&mut self, seed: u32) {
        let psfmt: &mut [u32x4, ..DSFMT_N + 1] = unsafe{mem::transmute(&mut self.status)};
        let i = idxof(0);
        psfmt[i / 4][i % 4] = seed;

        for i in range(1u, 4 * (DSFMT_N + 1)){
            let idx1 = idxof(i);
            let idx2 = idxof(i - 1);
            psfmt[idx1 / 4][idx1 % 4] = 1812433253u32 * (psfmt[idx2 / 4][idx2 % 4] ^ (psfmt[idx2 / 4][idx2 % 4] >> 30)) + (i as u32);
        }

        self.initial_mask();
        self.period_certification();
        self.idx = DSFMT_N64;
    }

    #[inline]
    fn gen_rand_all(&mut self){
        let mut lung = self.status[DSFMT_N];
        {
            let a = self.status[0];
            let b = self.status[DSFMT_POS1];
            do_recursion(&mut self.status[0], a, b, &mut lung);
        }
        let mut i = 1u;
        while i < DSFMT_N - DSFMT_POS1 {
            let a = self.status[i];
            let b = self.status[i + DSFMT_POS1];
            do_recursion(&mut self.status[i], a, b, &mut lung);
            i += 1;
        }
        while i < DSFMT_N {
            let a = self.status[i];
            let b = self.status[i + DSFMT_POS1 - DSFMT_N];
            do_recursion(&mut self.status[i], a, b, &mut lung);
            i += 1;
        }
        self.status[DSFMT_N] = lung;
    }

    #[inline(always)]
    fn next(&mut self) -> u64 {
        if self.idx >= DSFMT_N64 {
            self.gen_rand_all();
            self.idx = 0;
        }

        let (n, m) = (self.idx / 2, self.idx % 2);
        self.idx += 1;

        self.status[n][m]
    }

    #[inline]
    pub fn genrand_close1_open2(&mut self) -> f64 {
        unsafe{mem::transmute(self.next())}
    }

    #[inline]
    pub fn genrand_open_open(&mut self) -> f64 {
        unsafe{mem::transmute::<u64, f64>(self.next() | 1u64) - 1.0f64}
    }
}

impl Rng for DSFMTRng {
    #[inline]
    fn next_u32(&mut self) -> u32 {
        (self.next() & 0xffffffffu64) as u32
    }

    #[inline]
    fn next_f32(&mut self) -> f32 {
        unsafe{mem::transmute::<u32, f32>(((self.next() & DSFMT_F32_MANTISSA_MASK)) as u32 | DSFMT_HIGH_CONST32) - 1.0}
    }

    #[inline]
    fn next_f64(&mut self) -> f64 {
        self.genrand_close1_open2() - 1.0
    }
}

impl SeedableRng<u32> for DSFMTRng {
    fn reseed(&mut self, seed: u32){
        self.init(seed);
    }

    fn from_seed(seed: u32) -> DSFMTRng {
        let mut rng = DSFMTRng::new_unseeded();
        rng.init(seed);
        rng
    }
}

impl Rand for DSFMTRng {
    fn rand<R: Rng>(other: &mut R) -> DSFMTRng {
        SeedableRng::from_seed(other.next_u32())
    }
}

<commit_msg>Implement Copy for the SIMD types.<commit_after>use std::mem;
use std::iter::range_inclusive;

use std::rand::{Rng, SeedableRng, Rand};

const DSFMT_LOW_MASK:   u64 = 0x000FFFFFFFFFFFFF;
const DSFMT_HIGH_CONST: u64 = 0x3FF0000000000000;

const DSFMT_F32_MANTISSA_MASK: u64 = 0x00000000007FFFFF;
const DSFMT_HIGH_CONST32:      u32 = 0x3F800000;

const DSFMT_MEXP:uint = 19937;
const DSFMT_N:   uint = ((DSFMT_MEXP - 128) / 104 + 1);
const DSFMT_N64: uint = (DSFMT_N * 2);
const DSFMT_SR:  uint = 12;

const DSFMT_POS1: uint = 117;
const DSFMT_SL1:  uint = 19;
const DSFMT_PCV1: u64  = 0x3d84e1ac0dc82880;
const DSFMT_PCV2: u64  = 0x0000000000000001;
const DSFMT_FIX1: u64  = 0x90014964b32f4329;
const DSFMT_FIX2: u64  = 0x3b8d12ac548a7c7a;
const DSFMT_MSK1: u64  = 0x000ffafffffffb3f;
const DSFMT_MSK2: u64  = 0x000ffdfffc90fffd;

const SSE2_SHUFF: u8 = 0x1b;
const SSE2_PARAMS_MASK: u64x2 = u64x2{x: DSFMT_MSK1, y: DSFMT_MSK2};

pub struct DSFMTRng{
    status: [u64x2, ..DSFMT_N + 1],
    idx: uint,
}

#[repr(C)]
#[simd]
#[deriving(Show, Copy)]
struct u32x4{
    x: u32,
    y: u32,
    z: u32,
    w: u32,
}

#[repr(C)]
#[simd]
#[deriving(Show, Copy)]
struct u64x2{
    x: u64,
    y: u64,
}

impl Index<uint, u64> for u64x2{
    #[inline(always)]
    fn index(&self, _rhs: &uint) -> &u64{
        match *_rhs{
            0 => &self.x,
            _ => &self.y,
        }
    }
}

impl IndexMut<uint, u64> for u64x2{
    #[inline(always)]
    fn index_mut(&mut self, _rhs: &uint) -> &mut u64{
        match *_rhs{
            0 => &mut self.x,
            _ => &mut self.y,
        }
    }
}

impl Index<uint, u32> for u32x4{
    #[inline(always)]
    fn index(&self, _rhs: &uint) -> &u32{
        match *_rhs{
            0 => &self.x,
            1 => &self.y,
            2 => &self.z,
            _ => &self.w,
        }
    }
}

impl IndexMut<uint, u32> for u32x4{
    #[inline(always)]
    fn index_mut(&mut self, _rhs: &uint) -> &mut u32{
        match *_rhs{
            0 => &mut self.x,
            1 => &mut self.y,
            2 => &mut self.z,
            _ => &mut self.w,
        }
    }
}

#[cfg(target_endian = "big")]
fn idxof(i: uint) -> uint {
    i ^ 1
}

#[cfg(target_endian = "little")]
fn idxof(i: uint) -> uint {
    i
}

//#[allow(unused)]
//#[inline(always)]
//fn do_recursion(r: &mut u64x2, a: u64x2, b: u64x2, lung: &mut u64x2){
//
//    let u64x2{x: t0, y: t1} = a;
//    let u64x2{x: l0, y: l1} = *lung;
//
//    lung[0] = (t0 << DSFMT_SL1) ^ (l1 >> 32) ^ (l1 << 32) ^ b[0];
//    lung[1] = (t1 << DSFMT_SL1) ^ (l0 >> 32) ^ (l0 << 32) ^ b[1];
//
//    r[0] = ((*lung)[0] >> DSFMT_SR) ^ ((*lung)[0] & DSFMT_MSK1) ^ t0;
//    r[1] = ((*lung)[1] >> DSFMT_SR) ^ ((*lung)[1] & DSFMT_MSK2) ^ t1;
//}

#[allow(unused)]
#[inline(always)]
fn do_recursion(r: &mut u64x2, a: u64x2, b: u64x2, u: &mut u64x2){
    let mut z = a;
    unsafe{asm!(
        "psllq  $4, $0\n\t
         pxor   $8, $0\n\t
         pshufd $3, $1, $1\n\t
         pxor   $0, $1\n\t
         movaps $1, $0\n\t
         movaps $1, $2\n\t
         pand   $6, $0\n\t
         psrlq  $5, $2\n\t
         pxor   $7, $2\n\t
         pxor   $0, $2\n\t
        "
        :"+x"(z), "+x"(*u), "=x"(*r)
        :"i"(SSE2_SHUFF), "i"(DSFMT_SL1), "i"(DSFMT_SR), "x"(SSE2_PARAMS_MASK), "m"(a), "x"(b)
    )};
}

impl DSFMTRng{
    /// Create a new unseeded DSFMTRng instance
    pub fn new_unseeded() -> DSFMTRng {
        DSFMTRng{status: [u64x2{x: 0, y: 0}, ..DSFMT_N + 1], idx: 0}
    }

    /// Initializes the internal state array to fit the IEEE 754 format.
    fn initial_mask(&mut self){
        for i in range(0, DSFMT_N * 2){
            let (n, m) = (i / 2, i % 2);
            self.status[n][m] = (self.status[n][m] & DSFMT_LOW_MASK) | DSFMT_HIGH_CONST;
        }
    }

    /// Certifies the period of 2^{SFMT_MEXP}-1.
    fn period_certification(&mut self) {
        let pcv: [u64, ..2] = [DSFMT_PCV1, DSFMT_PCV2];

        {
            let tmp = [self.status[DSFMT_N][0] ^ DSFMT_FIX1, self.status[DSFMT_N][1] ^ DSFMT_FIX2];
            let mut inner = (tmp[0] & pcv[0]) ^ (tmp[1] & pcv[1]);

            let mut i = 32u;
            while i > 0 {
                inner ^= inner >> i;
                i >>= 1;
            }
            inner &= 1;
            /* check OK */
            if inner == 1 {
                return;
            }
        }

        /* check NG, and modification */
        if (DSFMT_PCV2 & 1) == 1 {
            self.status[DSFMT_N][1] ^= 1;
        }
        else{
            for i in range_inclusive(1, 0){
                let mut work = 1u64;
                for _ in range(0i, 64){
                    if (work & pcv[i]) != 0 {
                        self.status[DSFMT_N][i] ^= work;
                        return;
                    }
                    work <<= 1;
                }
            }
        }
    }

    fn init(&mut self, seed: u32) {
        let psfmt: &mut [u32x4, ..DSFMT_N + 1] = unsafe{mem::transmute(&mut self.status)};
        let i = idxof(0);
        psfmt[i / 4][i % 4] = seed;

        for i in range(1u, 4 * (DSFMT_N + 1)){
            let idx1 = idxof(i);
            let idx2 = idxof(i - 1);
            psfmt[idx1 / 4][idx1 % 4] = 1812433253u32 * (psfmt[idx2 / 4][idx2 % 4] ^ (psfmt[idx2 / 4][idx2 % 4] >> 30)) + (i as u32);
        }

        self.initial_mask();
        self.period_certification();
        self.idx = DSFMT_N64;
    }

    #[inline]
    fn gen_rand_all(&mut self){
        let mut lung = self.status[DSFMT_N];
        {
            let a = self.status[0];
            let b = self.status[DSFMT_POS1];
            do_recursion(&mut self.status[0], a, b, &mut lung);
        }
        let mut i = 1u;
        while i < DSFMT_N - DSFMT_POS1 {
            let a = self.status[i];
            let b = self.status[i + DSFMT_POS1];
            do_recursion(&mut self.status[i], a, b, &mut lung);
            i += 1;
        }
        while i < DSFMT_N {
            let a = self.status[i];
            let b = self.status[i + DSFMT_POS1 - DSFMT_N];
            do_recursion(&mut self.status[i], a, b, &mut lung);
            i += 1;
        }
        self.status[DSFMT_N] = lung;
    }

    #[inline(always)]
    fn next(&mut self) -> u64 {
        if self.idx >= DSFMT_N64 {
            self.gen_rand_all();
            self.idx = 0;
        }

        let (n, m) = (self.idx / 2, self.idx % 2);
        self.idx += 1;

        self.status[n][m]
    }

    #[inline]
    pub fn genrand_close1_open2(&mut self) -> f64 {
        unsafe{mem::transmute(self.next())}
    }

    #[inline]
    pub fn genrand_open_open(&mut self) -> f64 {
        unsafe{mem::transmute::<u64, f64>(self.next() | 1u64) - 1.0f64}
    }
}

impl Rng for DSFMTRng {
    #[inline]
    fn next_u32(&mut self) -> u32 {
        (self.next() & 0xffffffffu64) as u32
    }

    #[inline]
    fn next_f32(&mut self) -> f32 {
        unsafe{mem::transmute::<u32, f32>(((self.next() & DSFMT_F32_MANTISSA_MASK)) as u32 | DSFMT_HIGH_CONST32) - 1.0}
    }

    #[inline]
    fn next_f64(&mut self) -> f64 {
        self.genrand_close1_open2() - 1.0
    }
}

impl SeedableRng<u32> for DSFMTRng {
    fn reseed(&mut self, seed: u32){
        self.init(seed);
    }

    fn from_seed(seed: u32) -> DSFMTRng {
        let mut rng = DSFMTRng::new_unseeded();
        rng.init(seed);
        rng
    }
}

impl Rand for DSFMTRng {
    fn rand<R: Rng>(other: &mut R) -> DSFMTRng {
        SeedableRng::from_seed(other.next_u32())
    }
}

<|endoftext|>


<commit_before>use super::neuron_state::NeuronState;
use super::neuron_config::NeuronConfig;
use super::{Num, SynapseId, NeuronId, Delay};

struct Neuron {
    state: NeuronState,
    config: NeuronConfig,
    i_ext: Num,
    i_inp: Num,

    // XXX: Have a list of `active` synapses, which are active
    // once a neuron fires on it. The `active` synapses track
    // themselves, once they become inactive. Use a similar
    // `decay` process as for STDP for the action potential,
    // so that the shape of the spike is less sharp. A high
    // decay rate can simulate the old behaviour.
    //
    // Spike-Time Dependent Plasticity
    //
    // when a neuron fires, we set this value to STDP_FIRE_RESET
    // (0.1 for example), and during every time-step we decay
    // it by STDP_DECAY e.g. 0.95.
    stdp: Num,

    // XXX: Rename to Connection and incoming/outgoing?
    pre_synapses: Vec<SynapseId>,
    post_synapses: Vec<SynapseId>,
}

struct Synapse {
    pre_neuron: NeuronId,
    post_neuron: NeuronId,
    delay: Delay,
    weight: Num,

    // efficiacy derivative used for STDP
    eff_d: Num, // ... learning parameters
}

pub struct Network {
    neurons: Vec<Neuron>,
    synapses: Vec<Synapse>,
    max_delay: Delay,
}

impl Network {
    pub fn new() -> Network {
        Network {
            neurons: Vec::new(),
            synapses: Vec::new(),
            max_delay: 0,
        }
    }

    pub fn n_neurons_of<F>(&mut self, n: usize, f: F) -> Vec<NeuronId>
        where F: Fn(usize) -> NeuronConfig
    {
        (0..n).map(|i| self.create_neuron(f(i))).collect()
    }

    pub fn save_state(&self) -> Vec<NeuronState> {
        self.neurons.iter().enumerate().map(|(_, n)| n.state).collect()
    }

    pub fn create_neuron(&mut self, config: NeuronConfig) -> NeuronId {
        let neuron = Neuron {
            state: NeuronState::new(),
            config: config,
            stdp: 0.0,
            i_ext: 0.0,
            i_inp: 0.0,
            pre_synapses: Vec::new(),
            post_synapses: Vec::new(),
        };
        let neuron_id = NeuronId::from(self.neurons.len());
        self.neurons.push(neuron);
        return neuron_id;
    }

    pub fn max_delay(&self) -> Delay {
        self.max_delay
    }

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

    pub fn connect_all(&mut self, a: &[NeuronId], b: &[NeuronId], delay: Delay, weight: Num) {
        for &i in a.iter() {
            for &o in b.iter() {
                let _ = self.connect(i, o, delay, weight);
            }
        }
    }

    /// Reset the input currents of all neurons
    pub fn reset_all_input_currents(&mut self) {
        for neuron in self.neurons.iter_mut() {
            neuron.i_inp = 0.0;
        }
    }

    /// Excite ```neuron_id``` with ```current```.
    pub fn set_external_input(&mut self, neuron_id: NeuronId, current: Num) {
        self.neurons[neuron_id.index()].i_ext = current;
    }

    /// The synapses ```firing_synapses``` fire. Update the network state.
    pub fn process_firing_synapses(&mut self, firing_synapses: &[SynapseId]) {
        for &syn_id in firing_synapses {
            let syn = &mut self.synapses[syn_id.index()];

            let pre_neuron_stdp = self.neurons[syn.pre_neuron.index()].stdp;
            let post_neuron = &mut self.neurons[syn.post_neuron.index()];
            let post_neuron_stdp = post_neuron.stdp;

            post_neuron.i_inp += syn.weight;

            // whenever a spike arrives here at it's post_neuron, this means, that
            // the pre-neuron fired some time ago (delay time-steps). It can be the
            // case that the post_neuron has fired ealier, in which case we have to
            // depress the synapse according to the STDP rule.
            syn.eff_d += pre_neuron_stdp - post_neuron_stdp;
        }
    }

    pub fn connect(&mut self,
                   pre_neuron: NeuronId,
                   post_neuron: NeuronId,
                   delay: Delay,
                   weight: Num)
                   -> SynapseId {
        assert!(pre_neuron.index() < self.neurons.len());
        assert!(post_neuron.index() < self.neurons.len());
        assert!(delay > 0);

        if delay > self.max_delay {
            self.max_delay = delay;
        }

        let synapse = Synapse {
            pre_neuron: pre_neuron,
            post_neuron: post_neuron,
            delay: delay,
            weight: weight,
            eff_d: 0.0,
        };
        let synapse_id = SynapseId::from(self.synapses.len());

        self.synapses.push(synapse);
        self.neurons[pre_neuron.index()].post_synapses.push(synapse_id);
        self.neurons[post_neuron.index()].pre_synapses.push(synapse_id);

        return synapse_id;
    }

    pub fn update_state<E, F>(&mut self,
                              stdp_fire_reset: Num,
                              stdp_decay: Num,
                              enqueue_future_spike: &mut E,
                              fired_callback: &mut F)
        where E: FnMut(SynapseId, Delay),
              F: FnMut(NeuronId)
    {
        // for (i, mut neuron) in network.neurons.iter_mut().enumerate() {
        // XXX
        for i in 0..self.neurons.len() {
            let syn_i = self.neurons[i].i_ext + self.neurons[i].i_inp;

            let (new_state, fired) = self.neurons[i].state.step_1ms(syn_i, &self.neurons[i].config);
            self.neurons[i].state = new_state;

            // decay STDP
            self.neurons[i].stdp *= stdp_decay;

            if fired {
                fired_callback(NeuronId::from(i));

                // Reset the neurons STDP to a high value.
                self.neurons[i].stdp = stdp_fire_reset;

                for &syn_id in self.neurons[i].post_synapses.iter() {
                    enqueue_future_spike(syn_id, self.synapses[syn_id.index()].delay);
                }

                // Excite the synapses that might have led to the firing of the underlying neuron.
                // We do this by adding the synapses pre_neuron's STDP value to the synapses eff_d
                // (efficacy derivative) value.
                //
                // We do not update the synapses weight value immediatly, but only once very while
                // (TODO), so that STDP reflects more LTP (Long Term Potentiation).
                for &syn_id in self.neurons[i].pre_synapses.iter() {
                    let stdp = self.neurons[self.synapses[syn_id.index()].pre_neuron.index()].stdp;
                    self.synapses[syn_id.index()].eff_d += stdp;
                }
            }
        }
    }

    pub fn update_synapse_weights(&mut self,
                                  min_syn_weight: Num,
                                  max_syn_weight: Num,
                                  eff_d_decay: Num) {
        for syn in self.synapses.iter_mut() {
            let new_weight = syn.weight + syn.eff_d;

            // Restrict synapse weight min_syn_weight .. max_syn_weight
            if new_weight < min_syn_weight {
                syn.weight = min_syn_weight;
            } else if new_weight > max_syn_weight {
                syn.weight = max_syn_weight;
            } else {
                syn.weight = new_weight;
            }
            syn.eff_d *= eff_d_decay; // decay
        }
    }
}
<commit_msg>Refactor<commit_after>use super::neuron_state::NeuronState;
use super::neuron_config::NeuronConfig;
use super::{Num, SynapseId, NeuronId, Delay};

struct Neuron {
    state: NeuronState,
    config: NeuronConfig,
    i_ext: Num,
    i_inp: Num,

    // XXX: Have a list of `active` synapses, which are active
    // once a neuron fires on it. The `active` synapses track
    // themselves, once they become inactive. Use a similar
    // `decay` process as for STDP for the action potential,
    // so that the shape of the spike is less sharp. A high
    // decay rate can simulate the old behaviour.
    //
    // Spike-Time Dependent Plasticity
    //
    // when a neuron fires, we set this value to STDP_FIRE_RESET
    // (0.1 for example), and during every time-step we decay
    // it by STDP_DECAY e.g. 0.95.
    stdp: Num,

    // XXX: Rename to Connection and incoming/outgoing?
    pre_synapses: Vec<SynapseId>,
    post_synapses: Vec<SynapseId>,
}

impl Neuron {
    // Update the internal neuron state according to the synaptic input.
    // Returns true when neuron fired.
    fn update_state(&mut self, stdp_decay: Num, stdp_fire_reset: Num) -> bool {
        // synaptic input
        let syn_i = self.i_ext + self.i_inp;

        let (new_state, fired) = self.state.step_1ms(syn_i, &self.config);
        self.state = new_state;

        if fired {
            // Reset the neurons STDP to a high value.
            self.stdp = stdp_fire_reset;
        } else {
            // decay STDP
            self.stdp *= stdp_decay;
        }

        return fired;
    }
}

struct Synapse {
    pre_neuron: NeuronId,
    post_neuron: NeuronId,
    delay: Delay,
    weight: Num,

    // efficiacy derivative used for STDP
    eff_d: Num, // ... learning parameters
}

pub struct Network {
    neurons: Vec<Neuron>,
    synapses: Vec<Synapse>,
    max_delay: Delay,
}

impl Network {
    pub fn new() -> Network {
        Network {
            neurons: Vec::new(),
            synapses: Vec::new(),
            max_delay: 0,
        }
    }

    pub fn n_neurons_of<F>(&mut self, n: usize, f: F) -> Vec<NeuronId>
        where F: Fn(usize) -> NeuronConfig
    {
        (0..n).map(|i| self.create_neuron(f(i))).collect()
    }

    pub fn save_state(&self) -> Vec<NeuronState> {
        self.neurons.iter().enumerate().map(|(_, n)| n.state).collect()
    }

    pub fn create_neuron(&mut self, config: NeuronConfig) -> NeuronId {
        let neuron = Neuron {
            state: NeuronState::new(),
            config: config,
            stdp: 0.0,
            i_ext: 0.0,
            i_inp: 0.0,
            pre_synapses: Vec::new(),
            post_synapses: Vec::new(),
        };
        let neuron_id = NeuronId::from(self.neurons.len());
        self.neurons.push(neuron);
        return neuron_id;
    }

    pub fn max_delay(&self) -> Delay {
        self.max_delay
    }

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

    pub fn connect_all(&mut self, a: &[NeuronId], b: &[NeuronId], delay: Delay, weight: Num) {
        for &i in a.iter() {
            for &o in b.iter() {
                let _ = self.connect(i, o, delay, weight);
            }
        }
    }

    /// Reset the input currents of all neurons
    pub fn reset_all_input_currents(&mut self) {
        for neuron in self.neurons.iter_mut() {
            neuron.i_inp = 0.0;
        }
    }

    /// Excite ```neuron_id``` with ```current```.
    pub fn set_external_input(&mut self, neuron_id: NeuronId, current: Num) {
        self.neurons[neuron_id.index()].i_ext = current;
    }

    /// The synapses ```firing_synapses``` fire. Update the network state.
    pub fn process_firing_synapses(&mut self, firing_synapses: &[SynapseId]) {
        for &syn_id in firing_synapses {
            let syn = &mut self.synapses[syn_id.index()];

            let pre_neuron_stdp = self.neurons[syn.pre_neuron.index()].stdp;
            let post_neuron = &mut self.neurons[syn.post_neuron.index()];
            let post_neuron_stdp = post_neuron.stdp;

            post_neuron.i_inp += syn.weight;

            // whenever a spike arrives here at it's post_neuron, this means, that
            // the pre-neuron fired some time ago (delay time-steps). It can be the
            // case that the post_neuron has fired ealier, in which case we have to
            // depress the synapse according to the STDP rule.
            syn.eff_d += pre_neuron_stdp - post_neuron_stdp;
        }
    }

    pub fn connect(&mut self,
                   pre_neuron: NeuronId,
                   post_neuron: NeuronId,
                   delay: Delay,
                   weight: Num)
                   -> SynapseId {
        assert!(pre_neuron.index() < self.neurons.len());
        assert!(post_neuron.index() < self.neurons.len());
        assert!(delay > 0);

        if delay > self.max_delay {
            self.max_delay = delay;
        }

        let synapse = Synapse {
            pre_neuron: pre_neuron,
            post_neuron: post_neuron,
            delay: delay,
            weight: weight,
            eff_d: 0.0,
        };
        let synapse_id = SynapseId::from(self.synapses.len());

        self.synapses.push(synapse);
        self.neurons[pre_neuron.index()].post_synapses.push(synapse_id);
        self.neurons[post_neuron.index()].pre_synapses.push(synapse_id);

        return synapse_id;
    }

    pub fn update_state<E, F>(&mut self,
                              stdp_fire_reset: Num,
                              stdp_decay: Num,
                              enqueue_future_spike: &mut E,
                              fired_callback: &mut F)
        where E: FnMut(SynapseId, Delay),
              F: FnMut(NeuronId)
    {
        for i in 0..self.neurons.len() {
            let fired = self.neurons[i].update_state(stdp_decay, stdp_fire_reset);

            if fired {
                let neuron = &self.neurons[i];

                fired_callback(NeuronId::from(i));

                for &syn_id in neuron.post_synapses.iter() {
                    enqueue_future_spike(syn_id, self.synapses[syn_id.index()].delay);
                }

                // Excite the synapses that might have led to the firing of the underlying neuron.
                // We do this by adding the synapses pre_neuron's STDP value to the synapses eff_d
                // (efficacy derivative) value.
                //
                // We do not update the synapses weight value immediatly, but only once very while
                // (TODO), so that STDP reflects more LTP (Long Term Potentiation).
                for &syn_id in neuron.pre_synapses.iter() {
                    let stdp = self.neurons[self.synapses[syn_id.index()].pre_neuron.index()].stdp;
                    self.synapses[syn_id.index()].eff_d += stdp;
                }
            }
        }
    }

    pub fn update_synapse_weights(&mut self,
                                  min_syn_weight: Num,
                                  max_syn_weight: Num,
                                  eff_d_decay: Num) {
        for syn in self.synapses.iter_mut() {
            let new_weight = syn.weight + syn.eff_d;

            // Restrict synapse weight min_syn_weight .. max_syn_weight
            syn.weight = if new_weight < min_syn_weight {
                min_syn_weight
            } else if new_weight > max_syn_weight {
                max_syn_weight
            } else {
                new_weight
            };
            syn.eff_d *= eff_d_decay; // decay
        }
    }
}
<|endoftext|>


<commit_before>use luminance::{Dim2, Equation, Factor, Flat, Framebuffer, Mode, Pipe, Pipeline, RenderCommand, ShadingCommand, Tess, TessRender, TessVertices, Uniform, Unit, Vertex, VertexFormat};
use std::cell::RefCell;

use resource::Res;
use scene::Scene;
use shader::Program;
use text::TextTexture;
use texture::{RGBA32F, Texture};

/// Vertex used in overlay’s objects.
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Vert {
  /// Position.
  pub pos: [f32; 3],
  /// Color.
  pub color: [f32; 4]
}

impl Vert {
  pub fn new(pos: [f32; 3], color: [f32; 4]) -> Self {
    Vert {
      pos: pos,
      color: color
    }
  }
}

impl Vertex for Vert {
  fn vertex_format() -> VertexFormat {
    <([f32; 3], [f32; 4]) as Vertex>::vertex_format()
  }
}

#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Triangle(pub Vert, pub Vert, pub Vert);

#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Quad(pub Vert, pub Vert, pub Vert, pub Vert);

#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Disc {
  center: Vert,
  radius: f32
}

impl Disc {
  pub fn new(center: Vert, radius: f32) -> Self {
    Disc {
      center: center,
      radius: radius
    }
  }
}

impl Vertex for Disc {
  fn vertex_format() -> VertexFormat {
    <(Vert, f32) as Vertex>::vertex_format()
  }
}

pub type Texture2D = Texture<Flat, Dim2, RGBA32F>;

pub struct Text<'a> {
  text_texture: &'a TextTexture,
  left_upper: Vert
}

impl<'a> Text<'a> {
  pub fn new(text_texture: &'a TextTexture, left_upper: Vert) -> Self {
    Text {
      text_texture: text_texture,
      left_upper: left_upper
    }
  }
}

const DISC_SCREEN_RATIO: &'static Uniform<f32> = &Uniform::new(0);

const TEXT_SAMPLER: &'static Uniform<Unit> = &Uniform::new(0);
const TEXT_POS: &'static Uniform<[f32; 3]> = &Uniform::new(1);
const TEXT_SIZE: &'static Uniform<[f32; 2]> = &Uniform::new(2);
const TEXT_SCALE: &'static Uniform<f32> = &Uniform::new(3);
const TEXT_COLOR: &'static Uniform<[f32; 4]> = &Uniform::new(4);

/// A renderer responsible of rendering shapes.
pub struct Renderer {
  framebuffer: Framebuffer<Flat, Dim2, Texture2D, ()>,
  ratio: f32,
  tri_program: Res<Program>,
  tris: RefCell<Tess>,
  tri_vert_nb: RefCell<usize>,
  quads: RefCell<Tess>,
  quad_vert_nb: RefCell<usize>,
  disc_program: Res<Program>,
  discs: RefCell<Tess>,
  disc_vert_nb: RefCell<usize>,
  text_program: Res<Program>,
  text_quad: Tess,
  overlay_unit: OverlayUnit,
}

impl Renderer {
  pub fn new(w: u32, h: u32, max_tris: usize, max_quads: usize, max_discs: usize, scene: &mut Scene) -> Self {
    let fb = Framebuffer::new((w, h), 0).unwrap();

    let tri_program = scene.get("spectra/overlay/triangle.glsl", vec![]).unwrap();
    let tris = Tess::new(Mode::Triangle, TessVertices::Reserve::<Vert>(max_tris * 3), None);

    let quads = Tess::new(Mode::TriangleStrip, TessVertices::Reserve::<Vert>(max_quads * 4), None);

    let disc_program = scene.get("spectra/overlay/disc.glsl", vec![DISC_SCREEN_RATIO.sem("ratio")]).unwrap();
    let discs = Tess::new(Mode::Point, TessVertices::Reserve::<Disc>(max_discs), None);

    let text_program = scene.get("spectra/overlay/text.glsl", vec![
      TEXT_SAMPLER.sem("text_texture"),
      TEXT_POS.sem("pos"),
      TEXT_SIZE.sem("size"),
      TEXT_SCALE.sem("scale"),
      TEXT_COLOR.sem("color")
    ]).unwrap();

    let text_quad = Tess::attributeless(Mode::TriangleStrip, 4);

    Renderer {
      framebuffer: fb,
      ratio: w as f32 / h as f32,
      tri_program: tri_program,
      tris: RefCell::new(tris),
      tri_vert_nb: RefCell::new(0),
      quads: RefCell::new(quads),
      quad_vert_nb: RefCell::new(0),
      disc_program: disc_program,
      discs: RefCell::new(discs),
      disc_vert_nb: RefCell::new(0),
      text_program: text_program,
      text_quad: text_quad,
      overlay_unit: OverlayUnit::new(w, h)
    }
  }

  fn dispatch(&self, tris: &mut Tess, quads: &mut Tess, discs: &mut Tess, input: &RenderInput) {
    let mut tris = tris.as_slice_mut().unwrap();
    let mut tri_i = 0;
    let mut quads = quads.as_slice_mut().unwrap();
    let mut quad_i = 0;
    let mut discs = discs.as_slice_mut().unwrap();
    let mut disc_i = 0;

    for &Triangle(a, b, c) in input.triangles {
      let abc = [a, b, c];

      for &v in &abc {
        tris[tri_i] = v;
        tri_i += 1;
      }
    }

    for &Quad(a, b, c, d) in input.quads {
      let abcd = [a, b, c, d];

      for &v in &abcd {
        quads[quad_i] = v;
        quad_i += 1;
      }
    }

    for disc in input.discs {
      discs[disc_i] = *disc;
      disc_i += 1;
    }

    *self.tri_vert_nb.borrow_mut() = tri_i;
    *self.quad_vert_nb.borrow_mut() = quad_i;
    *self.disc_vert_nb.borrow_mut() = disc_i;
  }

  pub fn render(&self, input: RenderInput) -> &Texture2D {
    self.dispatch(&mut self.tris.borrow_mut(), &mut self.quads.borrow_mut(), &mut self.discs.borrow_mut(), &input);

    let tris_ref = self.tris.borrow();
    let tris = TessRender::one_sub(&tris_ref, *self.tri_vert_nb.borrow());
    let discs_ref = self.discs.borrow();
    let discs = TessRender::one_sub(&discs_ref, *self.disc_vert_nb.borrow());
    let text_quad = TessRender::one_whole(&self.text_quad);

    // FIXME: no alloc?
    let text_uniforms: Vec<_> = input.texts.map(|(texts, text_scale)| texts.iter().map(|text| {
      let (tex_w, tex_h) = text.text_texture.size();

      [
        TEXT_SAMPLER.alter(Unit::new(0)),
        TEXT_POS.alter(text.left_upper.pos),
        TEXT_SIZE.alter(self.overlay_unit.from_window(tex_w, tex_h)),
        TEXT_SCALE.alter(text_scale),
        TEXT_COLOR.alter(text.left_upper.color),
      ]
    }).collect()).unwrap_or(Vec::new());

    let text_textures: Vec<_> = input.texts.map(|(texts, _)| texts.iter().map(|text| [&***text.text_texture]).collect()).unwrap_or(Vec::new());

    let text_render_cmds: Vec<_> = input.texts.iter().enumerate().map(|(i, _)| {
        let blending = (Equation::Additive, Factor::One, Factor::SrcAlphaComplement);
        Pipe::empty()
          .uniforms(&text_uniforms[i])
          .textures(&text_textures[i])
          .unwrap(RenderCommand::new(Some(blending), true, vec![
            Pipe::new(text_quad.clone())
          ]))
      }).collect();

    let disc_uniforms = [
      DISC_SCREEN_RATIO.alter(self.ratio)
    ];

    Pipeline::new(&self.framebuffer, [0., 0., 0., 0.], &[], &[], vec![
      // render triangles
      Pipe::new(ShadingCommand::new(&self.tri_program.borrow(), vec![
        Pipe::new(RenderCommand::new(None, true, vec![
          Pipe::new(tris)
        ]))
      ])),
      // render discs
      Pipe::empty()
        .uniforms(&disc_uniforms)
        .unwrap(ShadingCommand::new(&self.disc_program.borrow(), vec![
          Pipe::new(RenderCommand::new(None, true, vec![
            Pipe::new(discs)
          ]))
        ])),
      // render texts
      Pipe::new(ShadingCommand::new(&self.text_program.borrow(), text_render_cmds))
    ]).run();

    &self.framebuffer.color_slot
  }
}

#[derive(Clone)]
pub struct RenderInput<'a, 'b> where 'b: 'a {
  triangles: &'a [Triangle],
  quads: &'a [Quad],
  discs: &'a [Disc],
  texts: Option<(&'a [Text<'b>], f32)>
}

impl<'a, 'b> RenderInput<'a, 'b> where 'b: 'a {
  pub fn new() -> Self {
    RenderInput {
      triangles: &[],
      quads: &[],
      discs: &[],
      texts: None,
    }
  }

  pub fn triangles(self, triangles: &'a [Triangle]) -> Self {
    RenderInput {
      triangles: triangles,
      ..self
    }
  }

  pub fn quads(self, quads: &'a [Quad]) -> Self {
    RenderInput {
      quads: quads,
      ..self
    }
  }

  pub fn discs(self, discs: &'a [Disc]) -> Self {
    RenderInput {
      discs: discs,
      ..self
    }
  }

  pub fn texts(self, texts: &'a [Text<'b>], scale: f32) -> Self {
    RenderInput {
      texts: Some((texts, scale.max(0.))),
      ..self
    }
  }
}

/// Overlay units are used to position stuff in overlay in a universal way and screen independent
/// way. The screen uses normalized coordinates with the origin at lower left as the following
/// diagram:
///
/// ^ y (1)
/// |
/// |
/// |
/// O------> x (1)
#[derive(Copy, Clone, Debug, PartialEq)]
struct OverlayUnit {
  rw: f32,
  rh: f32
}

impl OverlayUnit {
  pub fn new(w: u32, h: u32) -> Self {
    OverlayUnit {
      rw: 1. / (w as f32),
      rh: 1. / (h as f32)
    }
  }

  pub fn from_window(&self, x: u32, y: u32) -> [f32; 2] {
    let x_ = x as f32 * self.rw;
    assert!(x_ >= 0. && x_ <= 1., "x={}", x_);

    let y_ = y as f32 * self.rh;
    assert!(y_ >= 0. && y_ <= 1., "y={}", y_);

    [x_, y_]
  }
}
<commit_msg>Added UnitConverter directly into overlay::Renderer.<commit_after>use luminance::{Dim2, Equation, Factor, Flat, Framebuffer, Mode, Pipe, Pipeline, RenderCommand, ShadingCommand, Tess, TessRender, TessVertices, Uniform, Unit, Vertex, VertexFormat};
use std::cell::RefCell;

use resource::Res;
use scene::Scene;
use shader::Program;
use text::TextTexture;
use texture::{RGBA32F, Texture};

/// Vertex used in overlay’s objects. Position coordinates are in *window space*.
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Vert {
  /// Position.
  pub pos: [f32; 3],
  /// Color.
  pub color: [f32; 4]
}

impl Vert {
  pub fn new(pos: [f32; 3], color: [f32; 4]) -> Self {
    Vert {
      pos: pos,
      color: color
    }
  }

  /// Convert the vertex’ position to *clip space*.
  ///
  /// > Note: the depth coordinate is not affected.
  fn to_clip_space(&self, converter: &UnitConverter) -> Self {
    let converted = converter.from_window(self.pos[0], self.pos[1]);
    let pos_ = [converted[0], converted[1], self.pos[2]];

    Vert {
      pos: pos_,
      color: self.color
    }
  }
}

impl Vertex for Vert {
  fn vertex_format() -> VertexFormat {
    <([f32; 3], [f32; 4]) as Vertex>::vertex_format()
  }
}

#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Triangle(pub Vert, pub Vert, pub Vert);

#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Quad(pub Vert, pub Vert, pub Vert, pub Vert);

#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Disc {
  center: Vert,
  radius: f32
}

impl Disc {
  pub fn new(center: Vert, radius: f32) -> Self {
    Disc {
      center: center,
      radius: radius
    }
  }

  fn to_clip_space(&self, converter: &UnitConverter) -> Self {
    Disc {
      center: self.center.to_clip_space(converter),
      radius: self.radius
    }
  }
}

impl Vertex for Disc {
  fn vertex_format() -> VertexFormat {
    <(Vert, f32) as Vertex>::vertex_format()
  }
}

pub type Texture2D = Texture<Flat, Dim2, RGBA32F>;

pub struct Text<'a> {
  text_texture: &'a TextTexture,
  left_upper: Vert
}

impl<'a> Text<'a> {
  pub fn new(text_texture: &'a TextTexture, left_upper: Vert) -> Self {
    Text {
      text_texture: text_texture,
      left_upper: left_upper
    }
  }
}

const DISC_SCREEN_RATIO: &'static Uniform<f32> = &Uniform::new(0);

const TEXT_SAMPLER: &'static Uniform<Unit> = &Uniform::new(0);
const TEXT_POS: &'static Uniform<[f32; 3]> = &Uniform::new(1);
const TEXT_SIZE: &'static Uniform<[f32; 2]> = &Uniform::new(2);
const TEXT_SCALE: &'static Uniform<f32> = &Uniform::new(3);
const TEXT_COLOR: &'static Uniform<[f32; 4]> = &Uniform::new(4);

/// A renderer responsible of rendering shapes.
pub struct Renderer {
  framebuffer: Framebuffer<Flat, Dim2, Texture2D, ()>,
  ratio: f32,
  tri_program: Res<Program>,
  tris: RefCell<Tess>,
  tri_vert_nb: RefCell<usize>,
  quads: RefCell<Tess>,
  quad_vert_nb: RefCell<usize>,
  disc_program: Res<Program>,
  discs: RefCell<Tess>,
  disc_vert_nb: RefCell<usize>,
  text_program: Res<Program>,
  text_quad: Tess,
  unit_converter: UnitConverter,
}

impl Renderer {
  pub fn new(w: u32, h: u32, max_tris: usize, max_quads: usize, max_discs: usize, scene: &mut Scene) -> Self {
    let fb = Framebuffer::new((w, h), 0).unwrap();

    let tri_program = scene.get("spectra/overlay/triangle.glsl", vec![]).unwrap();
    let tris = Tess::new(Mode::Triangle, TessVertices::Reserve::<Vert>(max_tris * 3), None);

    let quads = Tess::new(Mode::TriangleStrip, TessVertices::Reserve::<Vert>(max_quads * 4), None);

    let disc_program = scene.get("spectra/overlay/disc.glsl", vec![DISC_SCREEN_RATIO.sem("ratio")]).unwrap();
    let discs = Tess::new(Mode::Point, TessVertices::Reserve::<Disc>(max_discs), None);

    let text_program = scene.get("spectra/overlay/text.glsl", vec![
      TEXT_SAMPLER.sem("text_texture"),
      TEXT_POS.sem("pos"),
      TEXT_SIZE.sem("size"),
      TEXT_SCALE.sem("scale"),
      TEXT_COLOR.sem("color")
    ]).unwrap();

    let text_quad = Tess::attributeless(Mode::TriangleStrip, 4);

    Renderer {
      framebuffer: fb,
      ratio: w as f32 / h as f32,
      tri_program: tri_program,
      tris: RefCell::new(tris),
      tri_vert_nb: RefCell::new(0),
      quads: RefCell::new(quads),
      quad_vert_nb: RefCell::new(0),
      disc_program: disc_program,
      discs: RefCell::new(discs),
      disc_vert_nb: RefCell::new(0),
      text_program: text_program,
      text_quad: text_quad,
      unit_converter: UnitConverter::new(w, h)
    }
  }

  // Dispatch the supported shape.
  fn dispatch(&self, tris: &mut Tess, quads: &mut Tess, discs: &mut Tess, input: &RenderInput) {
    let mut tris = tris.as_slice_mut().unwrap();
    let mut tri_i = 0;
    let mut quads = quads.as_slice_mut().unwrap();
    let mut quad_i = 0;
    let mut discs = discs.as_slice_mut().unwrap();
    let mut disc_i = 0;

    for &Triangle(a, b, c) in input.triangles {
      let abc = [a, b, c];

      for &v in &abc {
        tris[tri_i] = v.to_clip_space(&self.unit_converter);
        tri_i += 1;
      }
    }

    for &Quad(a, b, c, d) in input.quads {
      let abcd = [a, b, c, d];

      for &v in &abcd {
        quads[quad_i] = v.to_clip_space(&self.unit_converter);
        quad_i += 1;
      }
    }

    for disc in input.discs {
      discs[disc_i] = disc.to_clip_space(&self.unit_converter);
      disc_i += 1;
    }

    *self.tri_vert_nb.borrow_mut() = tri_i;
    *self.quad_vert_nb.borrow_mut() = quad_i;
    *self.disc_vert_nb.borrow_mut() = disc_i;
  }

  pub fn render(&self, input: RenderInput) -> &Texture2D {
    self.dispatch(&mut self.tris.borrow_mut(), &mut self.quads.borrow_mut(), &mut self.discs.borrow_mut(), &input);

    let tris_ref = self.tris.borrow();
    let tris = TessRender::one_sub(&tris_ref, *self.tri_vert_nb.borrow());
    let discs_ref = self.discs.borrow();
    let discs = TessRender::one_sub(&discs_ref, *self.disc_vert_nb.borrow());
    let text_quad = TessRender::one_whole(&self.text_quad);

    // FIXME: no alloc?
    let text_uniforms: Vec<_> = input.texts.map(|(texts, text_scale)| texts.iter().map(|text| {
      let (tex_w, tex_h) = text.text_texture.size();

      [
        TEXT_SAMPLER.alter(Unit::new(0)),
        TEXT_POS.alter(text.left_upper.pos),
        TEXT_SIZE.alter(self.unit_converter.from_window(tex_w as f32, tex_h as f32)),
        TEXT_SCALE.alter(text_scale),
        TEXT_COLOR.alter(text.left_upper.color),
      ]
    }).collect()).unwrap_or(Vec::new());

    let text_textures: Vec<_> = input.texts.map(|(texts, _)| texts.iter().map(|text| [&***text.text_texture]).collect()).unwrap_or(Vec::new());

    let text_render_cmds: Vec<_> = input.texts.iter().enumerate().map(|(i, _)| {
        let blending = (Equation::Additive, Factor::One, Factor::SrcAlphaComplement);
        Pipe::empty()
          .uniforms(&text_uniforms[i])
          .textures(&text_textures[i])
          .unwrap(RenderCommand::new(Some(blending), true, vec![
            Pipe::new(text_quad.clone())
          ]))
      }).collect();

    let disc_uniforms = [
      DISC_SCREEN_RATIO.alter(self.ratio)
    ];

    Pipeline::new(&self.framebuffer, [0., 0., 0., 0.], &[], &[], vec![
      // render triangles
      Pipe::new(ShadingCommand::new(&self.tri_program.borrow(), vec![
        Pipe::new(RenderCommand::new(None, true, vec![
          Pipe::new(tris)
        ]))
      ])),
      // render discs
      Pipe::empty()
        .uniforms(&disc_uniforms)
        .unwrap(ShadingCommand::new(&self.disc_program.borrow(), vec![
          Pipe::new(RenderCommand::new(None, true, vec![
            Pipe::new(discs)
          ]))
        ])),
      // render texts
      Pipe::new(ShadingCommand::new(&self.text_program.borrow(), text_render_cmds))
    ]).run();

    &self.framebuffer.color_slot
  }
}

#[derive(Clone)]
pub struct RenderInput<'a, 'b> where 'b: 'a {
  triangles: &'a [Triangle],
  quads: &'a [Quad],
  discs: &'a [Disc],
  texts: Option<(&'a [Text<'b>], f32)>
}

impl<'a, 'b> RenderInput<'a, 'b> where 'b: 'a {
  pub fn new() -> Self {
    RenderInput {
      triangles: &[],
      quads: &[],
      discs: &[],
      texts: None,
    }
  }

  pub fn triangles(self, triangles: &'a [Triangle]) -> Self {
    RenderInput {
      triangles: triangles,
      ..self
    }
  }

  pub fn quads(self, quads: &'a [Quad]) -> Self {
    RenderInput {
      quads: quads,
      ..self
    }
  }

  pub fn discs(self, discs: &'a [Disc]) -> Self {
    RenderInput {
      discs: discs,
      ..self
    }
  }

  pub fn texts(self, texts: &'a [Text<'b>], scale: f32) -> Self {
    RenderInput {
      texts: Some((texts, scale.max(0.))),
      ..self
    }
  }
}

/// A *unit converter* is used to position stuff in overlay in a universal and screen independent
/// way.
///
/// The idea is that you provide should handle *window space* coordinates only. This type will then
/// help compute normalized coordinates the renderer can understand.
///
/// For the record, *window space* coordinates are defined as below – given a viewport size of
/// *w × h*:
///
/// ^ y = h
/// |
/// |
/// |    x = w
/// O------>
///
/// The formula used to convert from *window space* to what we call *clip space* is:
///
/// > x' = 2x / w - 1
/// > y' = 2y / h - 1
#[derive(Copy, Clone, Debug, PartialEq)]
struct UnitConverter {
  twice_rw: f32,
  twice_rh: f32
}

impl UnitConverter {
  /// Build a unit converter by giving it the size of the viewport.
  pub fn new(w: u32, h: u32) -> Self {
    UnitConverter {
      twice_rw: 2. / (w as f32),
      twice_rh: 2. / (h as f32)
    }
  }

  /// Convert from *window space* coordinates.
  pub fn from_window(&self, x: f32, y: f32) -> [f32; 2] {
    let x_ = x * self.twice_rw - 1.;
    assert!(x_ >= -1. && x_ <= 1., "x={}", x_);

    let y_ = y * self.twice_rh;
    assert!(y_ >= -1. && y_ <= 1., "y={}", y_);

    [x_, y_]
  }
}
<|endoftext|>


<commit_before>use libc::{c_int, c_char, c_uint, size_t, ptrdiff_t, c_double};

use tree::{ParseStatus, Encoding, NodeType};

use tree::node::CNode;
use tree::document::CDocument;
use tree::parse_result::CParseResult;

extern "C" {
    pub fn pugi_version() -> c_int;

    pub fn pugi_parse_flag_cdata() -> c_uint;
    pub fn pugi_parse_flag_comments() -> c_uint;
    pub fn pugi_parse_flag_declaration() -> c_uint;
    pub fn pugi_parse_flag_default() -> c_uint;
    pub fn pugi_parse_flag_doctype() -> c_uint;
    pub fn pugi_parse_flag_eol() -> c_uint;
    pub fn pugi_parse_flag_escapes() -> c_uint;
    pub fn pugi_parse_flag_fragment() -> c_uint;
    pub fn pugi_parse_flag_full() -> c_uint;
    pub fn pugi_parse_flag_minimal() -> c_uint;
    pub fn pugi_parse_flag_pi() -> c_uint;
    pub fn pugi_parse_flag_trim_pcdata() -> c_uint;
    pub fn pugi_parse_flag_ws_pcdata() -> c_uint;
    pub fn pugi_parse_flag_ws_pcdata_single() -> c_uint;
    pub fn pugi_parse_flag_wconv_attribute() -> c_uint;
    pub fn pugi_parse_flag_wnorm_attribute() -> c_uint;

    pub fn pugi_format_flag_default() -> c_uint;
    pub fn pugi_format_flag_indent() -> c_uint;
    pub fn pugi_format_flag_indent_attributes() -> c_uint;
    pub fn pugi_format_flag_no_empty_element_tags() -> c_uint;
    pub fn pugi_format_flag_no_declaration() -> c_uint;
    pub fn pugi_format_flag_no_escapes() -> c_uint;
    pub fn pugi_format_flag_raw() -> c_uint;
    pub fn pugi_format_flag_save_file_text() -> c_uint;
    pub fn pugi_format_flag_write_bom() -> c_uint;

    pub fn pugi_parse_result_status(parse_result: *const CParseResult) -> ParseStatus;
    pub fn pugi_parse_result_offset(parse_result: *const CParseResult) -> ptrdiff_t;
    pub fn pugi_parse_result_encoding(parse_result: *const CParseResult) -> Encoding;
    pub fn pugi_parse_result_description(parse_result: *const CParseResult) -> *const c_char;

    pub fn pugi_delete_parse_result(parse_result: *const CParseResult);

    pub fn pugi_new_document() -> *mut CDocument;
    pub fn pugi_delete_document(document: *mut CDocument);

    pub fn pugi_reset_document_with(document: *mut CDocument, proto: *mut CDocument);

    pub fn pugi_load_file(document: *mut CDocument, path: *const c_char, options: c_uint,
                      encoding: Encoding)
        -> *const CParseResult;

    pub fn pugi_load_buffer(document: *mut CDocument, contents: *const c_char, size: size_t,
                        options: c_uint, encoding: Encoding)
        -> *const CParseResult;

    pub fn pugi_save_file(document: *mut CDocument, path: *const c_char, indent: *const c_char,
                      options: c_uint, encoding: Encoding)
        -> c_int;

    pub fn pugi_delete_node(node: *mut CNode);

    pub fn pugi_node_equal(lhs: *mut CNode, rhs: *mut CNode) -> c_int;

    pub fn pugi_node_hash_value(node: *mut CNode) -> size_t;

    pub fn pugi_node_type(node: *mut CNode) -> NodeType;
    pub fn pugi_node_name(node: *mut CNode) -> *const c_char;
    pub fn pugi_node_value(node: *mut CNode) -> *const c_char;

    pub fn pugi_node_parent(node: *mut CNode) -> *mut CNode;
    pub fn pugi_node_child(node: *mut CNode, name: *const c_char) -> *mut CNode;

    pub fn pugi_node_first_child(node: *mut CNode) -> *mut CNode;
    pub fn pugi_node_last_child(node: *mut CNode) -> *mut CNode;
    pub fn pugi_node_next_sibling(node: *mut CNode) -> *mut CNode;
    pub fn pugi_node_previous_sibling(node: *mut CNode) -> *mut CNode;
    pub fn pugi_node_next_sibling_by_name(node: *mut CNode, name: *const c_char) -> *mut CNode;
    pub fn pugi_node_previous_sibling_by_name(node: *mut CNode, name: *const c_char) -> *mut CNode;

    pub fn pugi_node_find_child_by_name_and_attribute(node: *mut CNode, name: *const c_char,
                                                  attribute_name: *const c_char,
                                                  attribute_value: *const c_char)
        -> *mut CNode;
    pub fn pugi_node_find_child_by_attribute(node: *mut CNode, attribute_name: *const c_char,
                                         attribute_value: *const c_char)
        -> *mut CNode;

    pub fn pugi_node_child_value(node: *mut CNode) -> *const c_char;
    pub fn pugi_node_child_value_by_name(node: *mut CNode, name: *const c_char) -> *mut CNode;

    pub fn pugi_node_text(node: *mut CNode) -> *const c_char;

    // pub fn pugi_node_attribute(node: *mut CNode, name: *const c_char) -> *mut CAttribute;

    pub fn pugi_node_path(node: *mut CNode) -> *const c_char;

    pub fn pugi_node_first_element_by_path(node: *mut CNode, path: *const c_char, del: c_char)
        -> *mut CNode;

    pub fn pugi_node_root(node: *mut CNode) -> *mut CNode;

    pub fn pugi_node_set_name(node: *mut CNode, name: *const c_char) -> c_int;
    pub fn pugi_node_set_value(node: *mut CNode, name: *const c_char) -> c_int;

    pub fn pugi_node_append_attribute(node: *mut CNode, name: *const c_char, value: *const c_char)
        -> c_int;
    pub fn pugi_node_prepend_attribute(node: *mut CNode, name: *const c_char, value: *const c_char)
        -> c_int;

    pub fn pugi_node_append_child(node: *mut CNode, node_type: NodeType) -> *mut CNode;
    pub fn pugi_node_prepend_child(node: *mut CNode, node_type: NodeType) -> *mut CNode;

    pub fn pugi_node_append_copy(node: *mut CNode, proto: *mut CNode) -> *mut CNode;
    pub fn pugi_node_prepend_copy(node: *mut CNode, proto: *mut CNode) -> *mut CNode;

    pub fn pugi_node_remove_attribute(node: *mut CNode, name: *const c_char) -> c_int;
    pub fn pugi_node_remove_child(node: *mut CNode, to_be_removed_child: *mut CNode) -> c_int;

    // pub fn pugi_node_print(node: *mut CNode,

    // pub fn pugi_node_find_attribute_by_predicate
    // pub fn pugi_node_find_child_by_predicate
    // pub fn pugi_node_find_node_by_predicate

    // pub fn pugi_node_map_sibling
    // pub fn pugi_node_map_attributes

    // pub fn pugi_xpath_delete_xpath_node(node: *mut CXPathNode);

    // pub fn pugi_xpath_node_node(node: *mut CXPathNode) -> *mut CNode;
    // pub fn pugi_xpath_node_attribute(node: *mut CXPathNode) -> *mut CAttribute;

    // pub fn pugi_xpath_delete_xpath_node_set(node_set: *const CNodeSet);

    // pub fn pugi_xpath_node_set_size(node_set: *const CNodeSet) -> size_t;
    // pub fn pugi_xpath_node_set_is_empty(node_set: *const CNodeSet) -> c_int;

    // pub fn pugi_xpath_node_set_index(node_set: *mut CNodeSet, index: size_t) -> *mut CXPathNode;

    // pub fn pugi_xpath_node_set_map

    // pub fn pugi_xpath_delete_xpath_query(xpath: *const CXPath);

    // pub fn pugi_xpath_query_evaluate_boolean(xpath: *const CXPath, node: *mut CNode) -> c_int;
    // pub fn pugi_xpath_query_evaluate_number(xpath: *const CXPath, node: *mut CNode) -> c_double;
    // pub fn pugi_xpath_query_evaluate_string(xpath: *const CXPath, node: *mut CNode) -> *const c_char;
    // pub fn pugi_xpath_query_evaluate_node_set(xpath: *const CXPath, node: *mut CNode)
    //     -> *const CNodeSet;

    // pub fn pugi_xpath_query_return_type(xpath: *const CXPath) -> XPathValueType;

    // pub fn pugi_xpath_query_parse_is_success(xpath: *const CXPath) -> c_int;

    // pub fn pugi_xpath_select_single_node(node: *mut CNode, xpath: *const CXPath) -> *mut CXPathNode;
    // pub fn pugi_xpath_select_nodes(node: *mut CNode, xpath: *const CXPath) -> *const CNodeSet;
}
<commit_msg>use of libc::c_double is unneded for now in wrapper<commit_after>use libc::{c_int, c_char, c_uint, size_t, ptrdiff_t};

use tree::{ParseStatus, Encoding, NodeType};

use tree::node::CNode;
use tree::document::CDocument;
use tree::parse_result::CParseResult;

extern "C" {
    pub fn pugi_version() -> c_int;

    pub fn pugi_parse_flag_cdata() -> c_uint;
    pub fn pugi_parse_flag_comments() -> c_uint;
    pub fn pugi_parse_flag_declaration() -> c_uint;
    pub fn pugi_parse_flag_default() -> c_uint;
    pub fn pugi_parse_flag_doctype() -> c_uint;
    pub fn pugi_parse_flag_eol() -> c_uint;
    pub fn pugi_parse_flag_escapes() -> c_uint;
    pub fn pugi_parse_flag_fragment() -> c_uint;
    pub fn pugi_parse_flag_full() -> c_uint;
    pub fn pugi_parse_flag_minimal() -> c_uint;
    pub fn pugi_parse_flag_pi() -> c_uint;
    pub fn pugi_parse_flag_trim_pcdata() -> c_uint;
    pub fn pugi_parse_flag_ws_pcdata() -> c_uint;
    pub fn pugi_parse_flag_ws_pcdata_single() -> c_uint;
    pub fn pugi_parse_flag_wconv_attribute() -> c_uint;
    pub fn pugi_parse_flag_wnorm_attribute() -> c_uint;

    pub fn pugi_format_flag_default() -> c_uint;
    pub fn pugi_format_flag_indent() -> c_uint;
    pub fn pugi_format_flag_indent_attributes() -> c_uint;
    pub fn pugi_format_flag_no_empty_element_tags() -> c_uint;
    pub fn pugi_format_flag_no_declaration() -> c_uint;
    pub fn pugi_format_flag_no_escapes() -> c_uint;
    pub fn pugi_format_flag_raw() -> c_uint;
    pub fn pugi_format_flag_save_file_text() -> c_uint;
    pub fn pugi_format_flag_write_bom() -> c_uint;

    pub fn pugi_parse_result_status(parse_result: *const CParseResult) -> ParseStatus;
    pub fn pugi_parse_result_offset(parse_result: *const CParseResult) -> ptrdiff_t;
    pub fn pugi_parse_result_encoding(parse_result: *const CParseResult) -> Encoding;
    pub fn pugi_parse_result_description(parse_result: *const CParseResult) -> *const c_char;

    pub fn pugi_delete_parse_result(parse_result: *const CParseResult);

    pub fn pugi_new_document() -> *mut CDocument;
    pub fn pugi_delete_document(document: *mut CDocument);

    pub fn pugi_reset_document_with(document: *mut CDocument, proto: *mut CDocument);

    pub fn pugi_load_file(document: *mut CDocument, path: *const c_char, options: c_uint,
                      encoding: Encoding)
        -> *const CParseResult;

    pub fn pugi_load_buffer(document: *mut CDocument, contents: *const c_char, size: size_t,
                        options: c_uint, encoding: Encoding)
        -> *const CParseResult;

    pub fn pugi_save_file(document: *mut CDocument, path: *const c_char, indent: *const c_char,
                      options: c_uint, encoding: Encoding)
        -> c_int;

    pub fn pugi_delete_node(node: *mut CNode);

    pub fn pugi_node_equal(lhs: *mut CNode, rhs: *mut CNode) -> c_int;

    pub fn pugi_node_hash_value(node: *mut CNode) -> size_t;

    pub fn pugi_node_type(node: *mut CNode) -> NodeType;
    pub fn pugi_node_name(node: *mut CNode) -> *const c_char;
    pub fn pugi_node_value(node: *mut CNode) -> *const c_char;

    pub fn pugi_node_parent(node: *mut CNode) -> *mut CNode;
    pub fn pugi_node_child(node: *mut CNode, name: *const c_char) -> *mut CNode;

    pub fn pugi_node_first_child(node: *mut CNode) -> *mut CNode;
    pub fn pugi_node_last_child(node: *mut CNode) -> *mut CNode;
    pub fn pugi_node_next_sibling(node: *mut CNode) -> *mut CNode;
    pub fn pugi_node_previous_sibling(node: *mut CNode) -> *mut CNode;
    pub fn pugi_node_next_sibling_by_name(node: *mut CNode, name: *const c_char) -> *mut CNode;
    pub fn pugi_node_previous_sibling_by_name(node: *mut CNode, name: *const c_char) -> *mut CNode;

    pub fn pugi_node_find_child_by_name_and_attribute(node: *mut CNode, name: *const c_char,
                                                  attribute_name: *const c_char,
                                                  attribute_value: *const c_char)
        -> *mut CNode;
    pub fn pugi_node_find_child_by_attribute(node: *mut CNode, attribute_name: *const c_char,
                                         attribute_value: *const c_char)
        -> *mut CNode;

    pub fn pugi_node_child_value(node: *mut CNode) -> *const c_char;
    pub fn pugi_node_child_value_by_name(node: *mut CNode, name: *const c_char) -> *mut CNode;

    pub fn pugi_node_text(node: *mut CNode) -> *const c_char;

    // pub fn pugi_node_attribute(node: *mut CNode, name: *const c_char) -> *mut CAttribute;

    pub fn pugi_node_path(node: *mut CNode) -> *const c_char;

    pub fn pugi_node_first_element_by_path(node: *mut CNode, path: *const c_char, del: c_char)
        -> *mut CNode;

    pub fn pugi_node_root(node: *mut CNode) -> *mut CNode;

    pub fn pugi_node_set_name(node: *mut CNode, name: *const c_char) -> c_int;
    pub fn pugi_node_set_value(node: *mut CNode, name: *const c_char) -> c_int;

    pub fn pugi_node_append_attribute(node: *mut CNode, name: *const c_char, value: *const c_char)
        -> c_int;
    pub fn pugi_node_prepend_attribute(node: *mut CNode, name: *const c_char, value: *const c_char)
        -> c_int;

    pub fn pugi_node_append_child(node: *mut CNode, node_type: NodeType) -> *mut CNode;
    pub fn pugi_node_prepend_child(node: *mut CNode, node_type: NodeType) -> *mut CNode;

    pub fn pugi_node_append_copy(node: *mut CNode, proto: *mut CNode) -> *mut CNode;
    pub fn pugi_node_prepend_copy(node: *mut CNode, proto: *mut CNode) -> *mut CNode;

    pub fn pugi_node_remove_attribute(node: *mut CNode, name: *const c_char) -> c_int;
    pub fn pugi_node_remove_child(node: *mut CNode, to_be_removed_child: *mut CNode) -> c_int;

    // pub fn pugi_node_print(node: *mut CNode,

    // pub fn pugi_node_find_attribute_by_predicate
    // pub fn pugi_node_find_child_by_predicate
    // pub fn pugi_node_find_node_by_predicate

    // pub fn pugi_node_map_sibling
    // pub fn pugi_node_map_attributes

    // pub fn pugi_xpath_delete_xpath_node(node: *mut CXPathNode);

    // pub fn pugi_xpath_node_node(node: *mut CXPathNode) -> *mut CNode;
    // pub fn pugi_xpath_node_attribute(node: *mut CXPathNode) -> *mut CAttribute;

    // pub fn pugi_xpath_delete_xpath_node_set(node_set: *const CNodeSet);

    // pub fn pugi_xpath_node_set_size(node_set: *const CNodeSet) -> size_t;
    // pub fn pugi_xpath_node_set_is_empty(node_set: *const CNodeSet) -> c_int;

    // pub fn pugi_xpath_node_set_index(node_set: *mut CNodeSet, index: size_t) -> *mut CXPathNode;

    // pub fn pugi_xpath_node_set_map

    // pub fn pugi_xpath_delete_xpath_query(xpath: *const CXPath);

    // pub fn pugi_xpath_query_evaluate_boolean(xpath: *const CXPath, node: *mut CNode) -> c_int;
    // pub fn pugi_xpath_query_evaluate_number(xpath: *const CXPath, node: *mut CNode) -> c_double;
    // pub fn pugi_xpath_query_evaluate_string(xpath: *const CXPath, node: *mut CNode) -> *const c_char;
    // pub fn pugi_xpath_query_evaluate_node_set(xpath: *const CXPath, node: *mut CNode)
    //     -> *const CNodeSet;

    // pub fn pugi_xpath_query_return_type(xpath: *const CXPath) -> XPathValueType;

    // pub fn pugi_xpath_query_parse_is_success(xpath: *const CXPath) -> c_int;

    // pub fn pugi_xpath_select_single_node(node: *mut CNode, xpath: *const CXPath) -> *mut CXPathNode;
    // pub fn pugi_xpath_select_nodes(node: *mut CNode, xpath: *const CXPath) -> *const CNodeSet;
}
<|endoftext|>


<commit_before>use pow::*;
use std::mem;
#[cfg(unix)]
use std::fs::File;
#[cfg(unix)]
use std::os::unix::io::AsRawFd;

/// Contains the Heartbeat and its window data buffer.
pub struct Heartbeat {
    pub hb: heartbeat_pow_context,
    pub hbr: Vec<heartbeat_pow_record>,
}

impl Heartbeat {
    /// Allocate and initialize a new `Heartbeat`.
    pub fn new(window_size: usize,
               hwc_callback: Option<heartbeat_pow_window_complete>) -> Result<Heartbeat, &'static str> {
        let mut hbr = Vec::with_capacity(window_size);
        unsafe {
            let mut hb = mem::uninitialized();
            match heartbeat_pow_init(&mut hb, hbr.capacity() as u64, hbr.as_mut_ptr(), hwc_callback) {
                0 => Ok(Heartbeat { hb: hb, hbr: hbr, }),
                _ => Err("Failed to initialize heartbeat")
            }
        }
    }

    /// Issue a heartbeat
    pub fn heartbeat_pow(&mut self,
                         tag: u64,
                         work: u64,
                         start_time: u64,
                         end_time: u64,
                         start_energy: u64,
                         end_energy: u64) {
        unsafe {
            heartbeat_pow(&mut self.hb, tag, work, start_time, end_time, start_energy, end_energy)
        }
    }

    #[cfg(unix)]
    pub fn log_window_buffer(&self, log: File, print_header: bool) -> Result<(), &'static str> {
        let ph: i32 = match print_header {
            true => 1,
            false => 0,
        };
        unsafe {
            match heartbeat_pow_log_window_buffer(&self.hb, log.as_raw_fd(), ph) {
                0 => Ok(()),
                _ => Err("Error logging window buffer"),
            }
        }
    }

    /// Utility function to get the most recent user-specified tag
    pub fn get_tag(&self) -> u64 {
        unsafe {
            hb_pow_get_user_tag(&self.hb)
        }
    }

    /// Utility function to get the current window performance.
    pub fn get_window_perf(&self) -> f64 {
        unsafe {
            hb_pow_get_window_perf(&self.hb)
        }
    }

    /// Utility function to get the current window power.
    pub fn get_window_pwr(&self) -> f64 {
        unsafe {
            hb_pow_get_window_power(&self.hb)
        }
    }
}

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

    #[test]
    fn test_simple() {
        const TIME_INC: u64 = 1000000000;
        const ENERGY_INC: u64 = 1000000;
        let mut hb = Heartbeat::new(5, None).unwrap();
        let mut start_time: u64 = 0;
        let mut end_time: u64 = TIME_INC;
        let mut start_energy: u64 = 0;
        let mut end_energy: u64 = ENERGY_INC;
        let mut tag: u64 = 0;
        for _ in 0..10 {
            hb.heartbeat_pow(tag, 1, start_time, end_time, start_energy, end_energy);
            assert!(hb.get_tag() == tag);
            assert!(hb.get_window_perf() == 1.0);
            assert!(hb.get_window_pwr() == 1.0);
            tag += 1;
            start_time = end_time;
            end_time += TIME_INC;
            start_energy = end_energy;
            end_energy += ENERGY_INC;
        }
    }
}
<commit_msg>Rename Heartbeat in wrapper to HeartbeatPow to better reflect the type<commit_after>use pow::*;
use std::mem;
#[cfg(unix)]
use std::fs::File;
#[cfg(unix)]
use std::os::unix::io::AsRawFd;

/// Contains the Heartbeat and its window data buffer.
pub struct HeartbeatPow {
    pub hb: heartbeat_pow_context,
    pub hbr: Vec<heartbeat_pow_record>,
}

impl HeartbeatPow {
    /// Allocate and initialize a new `Heartbeat`.
    pub fn new(window_size: usize,
               hwc_callback: Option<heartbeat_pow_window_complete>) -> Result<HeartbeatPow, &'static str> {
        let mut hbr = Vec::with_capacity(window_size);
        unsafe {
            let mut hb = mem::uninitialized();
            match heartbeat_pow_init(&mut hb, hbr.capacity() as u64, hbr.as_mut_ptr(), hwc_callback) {
                0 => Ok(HeartbeatPow { hb: hb, hbr: hbr, }),
                _ => Err("Failed to initialize heartbeat")
            }
        }
    }

    /// Issue a heartbeat
    pub fn heartbeat_pow(&mut self,
                         tag: u64,
                         work: u64,
                         start_time: u64,
                         end_time: u64,
                         start_energy: u64,
                         end_energy: u64) {
        unsafe {
            heartbeat_pow(&mut self.hb, tag, work, start_time, end_time, start_energy, end_energy)
        }
    }

    #[cfg(unix)]
    pub fn log_window_buffer(&self, log: File, print_header: bool) -> Result<(), &'static str> {
        let ph: i32 = match print_header {
            true => 1,
            false => 0,
        };
        unsafe {
            match heartbeat_pow_log_window_buffer(&self.hb, log.as_raw_fd(), ph) {
                0 => Ok(()),
                _ => Err("Error logging window buffer"),
            }
        }
    }

    /// Utility function to get the most recent user-specified tag
    pub fn get_tag(&self) -> u64 {
        unsafe {
            hb_pow_get_user_tag(&self.hb)
        }
    }

    /// Utility function to get the current window performance.
    pub fn get_window_perf(&self) -> f64 {
        unsafe {
            hb_pow_get_window_perf(&self.hb)
        }
    }

    /// Utility function to get the current window power.
    pub fn get_window_pwr(&self) -> f64 {
        unsafe {
            hb_pow_get_window_power(&self.hb)
        }
    }
}

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

    #[test]
    fn test_simple() {
        const TIME_INC: u64 = 1000000000;
        const ENERGY_INC: u64 = 1000000;
        let mut hb = HeartbeatPow::new(5, None).unwrap();
        let mut start_time: u64 = 0;
        let mut end_time: u64 = TIME_INC;
        let mut start_energy: u64 = 0;
        let mut end_energy: u64 = ENERGY_INC;
        let mut tag: u64 = 0;
        for _ in 0..10 {
            hb.heartbeat_pow(tag, 1, start_time, end_time, start_energy, end_energy);
            assert!(hb.get_tag() == tag);
            assert!(hb.get_window_perf() == 1.0);
            assert!(hb.get_window_pwr() == 1.0);
            tag += 1;
            start_time = end_time;
            end_time += TIME_INC;
            start_energy = end_energy;
            end_energy += ENERGY_INC;
        }
    }
}
<|endoftext|>


<commit_before>use core::cmp::{Eq, Ord};
use std::list;
use std::list::{List, Cons, Nil};

/**
 * A purely functional Pairing Heap [FSST86]
 *
 * Our implementation uses Linked List (cons cells) so may not be the
 * fastest way to implement this in Rust.
 *
 * This implementation is a port of the Standard ML found in Okasaki's
 * Purely Functional Data Structures.
 */
pub enum PairingHeap<E: Copy Eq Ord> {
  Empty_,
  PairingHeap_(@{
    head: E,
    rest: @List<PairingHeap<E>>
  })
}

pub trait Heap<E: Copy Eq Ord> {
  // I would really love for these to return Heaps but my knowledge
  // of Rust is too limited to make that work.
  pure fn is_empty() -> bool;
  pure fn insert(elem: E) -> PairingHeap<E>;
  pure fn find_min() -> (Option<E>, PairingHeap<E>);
  pure fn delete_min() -> (Option<E>, PairingHeap<E>);
}

pure fn Empty<E: Copy Eq Ord>() -> PairingHeap<E> {
  return Empty_;
}

pure fn PairingHeap<E: Copy Eq Ord>(initial_value: E) -> PairingHeap<E> {
  return PairingHeap_(@{
    head: initial_value,
    rest: @Nil
  });
}

impl<E: Copy Eq Ord> PairingHeap<E> : Eq {
  pure fn eq(other: &PairingHeap<E>) -> bool {
    match (self, *other) {
      (Empty_, Empty_) => {true}
      (PairingHeap_(heapA), PairingHeap_(heapB)) => {
        return (heapA.head == heapB.head) && (heapA.rest == heapB.rest);
      }
      //(Empty_, PairingHeap_(_)) => {false} // why are these unreachable?
      //(PairingHeap_(_), Empty) => {false}
      (_, _) => {false}
    }
  }

  pure fn ne(other: &PairingHeap<E>) -> bool { !(self).eq(other) }
}

impl<E: Copy Eq Ord> PairingHeap<E> : Heap<E> {
  pure fn is_empty() -> bool {
    match self {
      Empty_ => { return true; }
      _ => {return false; }
    };
  }

  pure fn insert(e: E) -> PairingHeap<E> {
    return self.merge(PairingHeap(e));
  }

  pure fn find_min() -> (Option<E>, PairingHeap<E>) {
    match self {
      Empty_ => { return (None, self); }
      p@PairingHeap_(heap) => { return (Some(heap.head), p); }
    }
  }

  // Deletes the minimum item without returning it
  pure fn delete_min() -> (Option<E>, PairingHeap<E>) {
    match self {
      Empty_ => {(None, self)}
      PairingHeap_(heap) => {(Some(heap.head), self.mergePairs(heap.rest))}
    }
  }

  pure fn merge(other: PairingHeap<E>) -> PairingHeap<E> {
    match (self, other) {
      (Empty_, b) => { return b; }
      (a, Empty_) => { return a; }
      (x@PairingHeap_(heapA), y@PairingHeap_(heapB)) => {
        if (heapA.head.le(&heapB.head)) {
          return PairingHeap_(@{
            head: heapA.head,
            rest: @Cons(y, heapA.rest)
          });
        } else {
          return PairingHeap_(@{
            head: heapB.head,
            rest: @Cons(x, heapB.rest)
          });
        }
      }
    }
  }

  pure fn mergePairs(heaps: @List<PairingHeap<E>>) -> PairingHeap<E> {
    match heaps {
      // Why are @-signs required for pattern matching here?
      @Cons(a, @Cons(b, xs)) => {a.merge(b).merge(self.mergePairs(xs))}
      @Cons(elem, @Nil) => {elem}
      @Nil => {Empty()}
    }
  }
}

#[test]
fn test_heap_create() {
  let heap = PairingHeap(1);
  assert(!heap.is_empty());

  // inference fails on this without a type declaration.
  let heap : PairingHeap<()> = Empty();
  assert(heap.is_empty());
}

#[test]
fn test_heap_insert() {
  let v1 = PairingHeap(10);
  let v2 = v1.insert(1);
  let (one, v3) = v2.delete_min();
  let (ten, v4) = v3.delete_min();
  let (e, v5) = v4.delete_min();

  assert(one == Some(1));
  assert(ten == Some(10));
  assert(v4 == Empty_);
  assert(e == None);
  assert(v5 == Empty_);
}

#[test]
fn test_heap_insert_delete_interleved() {
  let v1 = PairingHeap(10);
  let (a, v2) = v1.delete_min();
  assert(a == Some(10));
  assert(v2 == Empty_);

  let v3 = v2.insert(9);
  let v4 = v3.insert(8);
  let v5 = v4.insert(11);

  let (b, v6) = v5.delete_min();
  assert(b == Some(8));

  let v7 = v6.insert(7);
  let v8 = v7.insert(12);

  let (c, v9) = v8.delete_min();
  assert(c == Some(7));

  let (d, v10) = v9.delete_min();
  assert(d == Some(9));

  let (e, v11) = v10.delete_min();
  assert(e == Some(11));

  let (f, v12) = v11.delete_min();
  assert(f == Some(12));

  let (g, v13) = v12.delete_min();
  assert(g == None);
  assert(v13 == Empty_);
}

#[test]
fn test_immutable_heap() {
  let heap = PairingHeap(10);
  let x1 = heap.insert(1);

  let (a, v1) = heap.delete_min();
  assert(a == Some(10));
  assert(v1 == Empty_);

  let (b, x2) = x1.delete_min();
  assert(b == Some(1));
  assert(x2 != Empty_);
}

<commit_msg>renaming mergePairs -> merge_pairs<commit_after>use core::cmp::{Eq, Ord};
use std::list;
use std::list::{List, Cons, Nil};

/**
 * A purely functional Pairing Heap [FSST86]
 *
 * Our implementation uses Linked List (cons cells) so may not be the
 * fastest way to implement this in Rust.
 *
 * This implementation is a port of the Standard ML found in Okasaki's
 * Purely Functional Data Structures.
 */
pub enum PairingHeap<E: Copy Eq Ord> {
  Empty_,
  PairingHeap_(@{
    head: E,
    rest: @List<PairingHeap<E>>
  })
}

pub trait Heap<E: Copy Eq Ord> {
  // I would really love for these to return Heaps but my knowledge
  // of Rust is too limited to make that work.
  pure fn is_empty() -> bool;
  pure fn insert(elem: E) -> PairingHeap<E>;
  pure fn find_min() -> (Option<E>, PairingHeap<E>);
  pure fn delete_min() -> (Option<E>, PairingHeap<E>);
}

pure fn Empty<E: Copy Eq Ord>() -> PairingHeap<E> {
  return Empty_;
}

pure fn PairingHeap<E: Copy Eq Ord>(initial_value: E) -> PairingHeap<E> {
  return PairingHeap_(@{
    head: initial_value,
    rest: @Nil
  });
}

impl<E: Copy Eq Ord> PairingHeap<E> : Eq {
  pure fn eq(other: &PairingHeap<E>) -> bool {
    match (self, *other) {
      (Empty_, Empty_) => {true}
      (PairingHeap_(heapA), PairingHeap_(heapB)) => {
        return (heapA.head == heapB.head) && (heapA.rest == heapB.rest);
      }
      //(Empty_, PairingHeap_(_)) => {false} // why are these unreachable?
      //(PairingHeap_(_), Empty) => {false}
      (_, _) => {false}
    }
  }

  pure fn ne(other: &PairingHeap<E>) -> bool { !(self).eq(other) }
}

impl<E: Copy Eq Ord> PairingHeap<E> : Heap<E> {
  pure fn is_empty() -> bool {
    match self {
      Empty_ => { return true; }
      _ => {return false; }
    };
  }

  pure fn insert(e: E) -> PairingHeap<E> {
    return self.merge(PairingHeap(e));
  }

  pure fn find_min() -> (Option<E>, PairingHeap<E>) {
    match self {
      Empty_ => { return (None, self); }
      p@PairingHeap_(heap) => { return (Some(heap.head), p); }
    }
  }

  // Deletes the minimum item without returning it
  pure fn delete_min() -> (Option<E>, PairingHeap<E>) {
    match self {
      Empty_ => {(None, self)}
      PairingHeap_(heap) => {(Some(heap.head), self.merge_pairs(heap.rest))}
    }
  }

  pure fn merge(other: PairingHeap<E>) -> PairingHeap<E> {
    match (self, other) {
      (Empty_, b) => { return b; }
      (a, Empty_) => { return a; }
      (x@PairingHeap_(heapA), y@PairingHeap_(heapB)) => {
        if (heapA.head.le(&heapB.head)) {
          return PairingHeap_(@{
            head: heapA.head,
            rest: @Cons(y, heapA.rest)
          });
        } else {
          return PairingHeap_(@{
            head: heapB.head,
            rest: @Cons(x, heapB.rest)
          });
        }
      }
    }
  }

  pure fn merge_pairs(heaps: @List<PairingHeap<E>>) -> PairingHeap<E> {
    match heaps {
      // Why are @-signs required for pattern matching here?
      @Cons(a, @Cons(b, xs)) => {a.merge(b).merge(self.merge_pairs(xs))}
      @Cons(elem, @Nil) => {elem}
      @Nil => {Empty()}
    }
  }
}

#[test]
fn test_heap_create() {
  let heap = PairingHeap(1);
  assert(!heap.is_empty());

  // inference fails on this without a type declaration.
  let heap : PairingHeap<()> = Empty();
  assert(heap.is_empty());
}

#[test]
fn test_heap_insert() {
  let v1 = PairingHeap(10);
  let v2 = v1.insert(1);
  let (one, v3) = v2.delete_min();
  let (ten, v4) = v3.delete_min();
  let (e, v5) = v4.delete_min();

  assert(one == Some(1));
  assert(ten == Some(10));
  assert(v4 == Empty_);
  assert(e == None);
  assert(v5 == Empty_);
}

#[test]
fn test_heap_insert_delete_interleved() {
  let v1 = PairingHeap(10);
  let (a, v2) = v1.delete_min();
  assert(a == Some(10));
  assert(v2 == Empty_);

  let v3 = v2.insert(9);
  let v4 = v3.insert(8);
  let v5 = v4.insert(11);

  let (b, v6) = v5.delete_min();
  assert(b == Some(8));

  let v7 = v6.insert(7);
  let v8 = v7.insert(12);

  let (c, v9) = v8.delete_min();
  assert(c == Some(7));

  let (d, v10) = v9.delete_min();
  assert(d == Some(9));

  let (e, v11) = v10.delete_min();
  assert(e == Some(11));

  let (f, v12) = v11.delete_min();
  assert(f == Some(12));

  let (g, v13) = v12.delete_min();
  assert(g == None);
  assert(v13 == Empty_);
}

#[test]
fn test_immutable_heap() {
  let heap = PairingHeap(10);
  let x1 = heap.insert(1);

  let (a, v1) = heap.delete_min();
  assert(a == Some(10));
  assert(v1 == Empty_);

  let (b, x2) = x1.delete_min();
  assert(b == Some(1));
  assert(x2 != Empty_);
}

<|endoftext|>


<commit_before><commit_msg>Add a custom type for Section<commit_after><|endoftext|>


<commit_before><commit_msg>Move to the new if let syntax<commit_after><|endoftext|>


<commit_before><commit_msg>Ignore cast_lossless Clippy pedantic lint<commit_after><|endoftext|>


<commit_before><commit_msg>Add documentation and some tests.<commit_after><|endoftext|>


<commit_before>use std::io;
use std::str::replace;

// read_input keeps taking in lines from stdin until a single newline
// is entered. It returns a String.
pub fn read_input() -> String {
    let mut story = "".to_string();
    println!("Please enter a line of the story. Enter a blank line to stop");
    loop {
        let input = io::stdin().read_line().ok().expect("Failed to read line.");
        let line = input.as_slice();
        if line == "\n" {
            break;
        }
        else {
            story.push_str(line);
        }
    }
    story.to_string()
}

// fill_blanks takes in a string, representing the current template
// and both prompts and replaces for an item in brackets [].
// A string, the modified story, is returned.
#[allow(unused_variables)]
pub fn fill_blanks(s: &str) -> String {
    let mut l_iter = s.match_indices("[");
    let mut r_iter = s.match_indices("]");
    let l_duple = l_iter.next();
    let r_duple = r_iter.next();
    let l_index = match l_duple {
        Some((x, y)) => x,
        None => -1,
    };
    let r_index = match r_duple {
        Some((x, y)) => y,
        None => -1,
    };
    if l_index == -1 {
        s.to_string()
    }
    else {
        println!("Give me a/an {}!", s.slice(l_index + 1, r_index - 1));
        let input = std::io::stdin().read_line().ok().expect("Failed to fill blank.");
        replace(s.as_slice(), s.slice(l_index, r_index), input.as_slice().trim())
    }
}
<commit_msg>updating<commit_after>#[feature(plugin)]
#[macro_use] #[plugin] #[no_link]
extern crate regex_macros;
extern crate regex;
use std::io;
use regex::Regex;

// read_input keeps taking in lines from stdin until a single newline
// is entered. It returns a String.
pub fn read_input() -> String {
    let mut story = "".to_string();
    println!("Please enter a line of the story. Enter a blank line to stop");
    loop {
        let input = io::stdin().read_line().ok().expect("Failed to read line.");
        let line = input.as_slice();
        if line == "\n" {
            break;
        }
        else {
            story.push_str(line);
        }
    }
    story.to_string()
}

// fill_blanks takes in a string, representing the current template
// and both prompts and replaces for an item in brackets [].
// A string, the modified story, is returned.
#[allow(unused_variables)]
pub fn fill_blanks(s: &str) -> String {
    let mut l_iter = s.match_indices("[");
    let mut r_iter = s.match_indices("]");
    let l_duple = l_iter.next();
    let r_duple = r_iter.next();
    let l_index = match l_duple {
        Some((x, y)) => x,
        None => -1,
    };
    let r_index = match r_duple {
        Some((x, y)) => y,
        None => -1,
    };
    if l_index == -1 {
        s.to_string()
    }
    else {
        println!("Give me a/an {}!", s.slice(l_index + 1, r_index - 1));
        let input = std::io::stdin().read_line().ok().expect("Failed to fill blank.");
        let re = regex!(s.as_slice());
        re.replace(s.slice(l_index, r_index), input.as_slice().trim());
        re.as_str().to_string();
    }
}
<|endoftext|>


<commit_before><commit_msg>Implemente Vector arithmetics<commit_after><|endoftext|>