<commit_before>//! The `ast` module contains a lot of useful functionality
//! to create and walk through the ast (abstract syntaxtree)

use frontend::lexer::Token;
use backend::zcode::zfile;
use backend::zcode::zfile::{FormattingState};
use std::collections::HashMap;

//==============================
// ast

pub struct AST {
    passages: Vec<ASTNode>
}

/// add zcode based on tokens
fn gen_zcode<'a>(node: &'a ASTNode, state: FormattingState, mut out: &mut zfile::Zfile, mut var_table: &mut HashMap<&'a str, u8>, mut var_id: &mut u8) {
    let mut state_copy = state.clone();

    match node {
        &ASTNode::Passage(ref node) => {
            match &node.category {
                &Token::TokPassageName(ref name) => {
                    out.routine(name, 0);
                },
                _ => {
                    debug!("no match 1");
                }
            };

            for child in &node.childs {
                gen_zcode(child, state_copy, out, var_table, var_id);
            }

            out.op_newline();
            out.op_call_1n("system_check_links");

        },
        &ASTNode::Default(ref t) => {
            match &t.category {
                &Token::TokText(ref s) => {
                    out.op_print(s);
                },
                &Token::TokNewLine => {
                    out.op_newline();
                },
                &Token::TokFormatBoldStart => {
                    state_copy.bold = true;
                    out.op_set_text_style(state_copy.bold, state_copy.inverted, state_copy.mono, state_copy.italic);
                },
                &Token::TokFormatItalicStart => {
                    state_copy.italic = true;
                    out.op_set_text_style(state_copy.bold, state_copy.inverted, state_copy.mono, state_copy.italic);
                },
                &Token::TokPassageLink (ref name, ref link) => {
                    out.op_call_2n_with_address("system_add_link", link);

                    out.op_set_text_style(state_copy.bold, true, state_copy.mono, state_copy.italic);
                    let link_text = format!("{}[", name);
                    out.op_print(&link_text);
                    out.op_print_num_var(16);
                    out.op_print("]");
                    out.op_set_text_style(state_copy.bold, state_copy.inverted, state_copy.mono, state_copy.italic);
                },
                &Token::TokAssign(ref var, ref operator) => {
                    if operator == "=" {
                        if !var_table.contains_key::<str>(var) {
                            var_table.insert(&var, *var_id);
                            debug!("Assigned id {} to variable {}", var_id, var);
                            *var_id += 1;
                        }
                        let id_option = var_table.get::<str>(var);
                        if t.childs.len() == 1 {
                            match t.childs[0] {
                                ASTNode::Default(ref def) => {
                                    let actual_id :u8 = match id_option {
                                        Some(id) => {
                                            *id
                                        },
                                        None => {
                                            panic!("Variable not in var table.")
                                        }
                                    };
                                    match def.category {
                                        Token::TokInt(value) => {
                                            out.op_store_u8(actual_id, value as u8);
                                        },
                                        Token::TokBoolean(ref bool_val) => {
                                            let value = match (*bool_val).as_ref() {
                                                "true" => { 1 as u8 },
                                                _ => { 0 as u8 }
                                            };
                                            out.op_store_u8(actual_id, value);
                                        }
                                        _ => { }
                                    }
                                },
                                _ => { }
                            }
                        } else {
                            debug!("Assign Expression currently not supported.");
                        }

                    }
                },
                _ => {
                    debug!("no match 2");
                }
            };

            for child in &t.childs {
                gen_zcode(child, state_copy, out, var_table, var_id);
            }

            out.op_set_text_style(false, false, false, false);
            out.op_set_text_style(state.bold, state.inverted, state.mono, state.italic);
        }
    };
}

impl AST {
    /// convert ast to zcode
    pub fn to_zcode(&self,  out: &mut zfile::Zfile) {
        let mut var_table = HashMap::<&str, u8>::new();
        let mut var_id : u8 = 100;
        let state = FormattingState {bold: false, italic: false, mono: false, inverted: false};
        for child in &self.passages {
            gen_zcode(child, state, out, &mut var_table, &mut var_id);
        }
    }

    pub fn new() -> AST {
        AST {
            passages: Vec::new()
        }
    }

    /// prints the tree
    pub fn print(&self) {
        debug!("Abstract Syntax Tree: ");
        for child in &self.passages {
            child.print(0);
        }
        debug!("");
    }

    /// adds a passage to the path in the ast
    pub fn add_passage(&mut self, token: Token) {
        let node = ASTNode::Passage(NodePassage { category: token, childs: Vec::new() });
        self.passages.push(node);
    }

    /// adds a child to the path in the ast
    pub fn add_child(&mut self, path: &Vec<usize>, token: Token) {
        if let Some(index) = path.first() {
            let mut new_path: Vec<usize> = path.to_vec();
            new_path.remove(0);

            self.passages[*index].add_child(new_path, token)
        } else {
            self.passages.push(ASTNode::Default(NodeDefault { category: token, childs: Vec::new() }));
        }
    }

    /// counts the childs of the path in the asts
    pub fn count_childs(&self, path: Vec<usize>) -> usize {
        if let Some(index) = path.first() {
            let mut new_path: Vec<usize> = path.to_vec();
            new_path.remove(0);

            self.passages[*index].count_childs(new_path)
        } else {
            self.passages.len()
        }
    }
}

// ================================
// node types
enum ASTNode {
    Default (NodeDefault),
    Passage (NodePassage)
}

struct NodePassage {
    category: Token,
    pub childs: Vec<ASTNode>,
    /*tags: Vec<ASTNode>*/
}

struct NodeDefault {
    category: Token,
    childs: Vec<ASTNode>
}

impl ASTNode {
    /// adds an child to the path in the ast
    pub fn add_child(&mut self, path: Vec<usize>, token: Token) {
        if let Some(index) = path.first() {
            let mut new_path: Vec<usize> = path.to_vec();
            new_path.remove(0);

            match self {
                &mut ASTNode::Default(ref mut node) => node.childs[*index].add_child(new_path, token),
                &mut ASTNode::Passage(ref mut node) => node.childs[*index].add_child(new_path, token),
            }
        } else {
            match self {
                &mut ASTNode::Default(ref mut node) => node.childs.push(ASTNode::Default(NodeDefault { category: token, childs: Vec::new() } )),
                &mut ASTNode::Passage(ref mut node) => node.childs.push(ASTNode::Default(NodeDefault { category: token, childs: Vec::new() } )),
            }
        }
    }

    /// counts the childs of the current path in the ast
    pub fn count_childs(&self, path: Vec<usize>) -> usize {
        if let Some(index) = path.first() {
            let mut new_path: Vec<usize> = path.to_vec();
            new_path.remove(0);

            match self {
                &ASTNode::Default(ref node) => node.childs[*index].count_childs(new_path),
                &ASTNode::Passage(ref node) => node.childs[*index].count_childs(new_path),
            }
        } else {
            match self {
                &ASTNode::Default(ref node) => node.childs.len(),
                &ASTNode::Passage(ref node) => node.childs.len(),
            }
        }
    }

    /// prints an node of an ast
    pub fn print(&self, indent: usize) {
        let mut spaces = "".to_string();
        for _ in 0..indent {
            spaces.push_str(" ");
        }

        match self {
            &ASTNode::Passage(ref t) => {
                debug!("{}|- : {:?}", spaces, t.category);
                for child in &t.childs {
                    child.print(indent+2);
                }
            },
            &ASTNode::Default(ref t) => {
                debug!("{}|- : {:?}", spaces, t.category);
                for child in &t.childs {
                    child.print(indent+2);
                }
            }
        }
    }
}
<commit_msg>Decremented start id<commit_after>//! The `ast` module contains a lot of useful functionality
//! to create and walk through the ast (abstract syntaxtree)

use frontend::lexer::Token;
use backend::zcode::zfile;
use backend::zcode::zfile::{FormattingState};
use std::collections::HashMap;

//==============================
// ast

pub struct AST {
    passages: Vec<ASTNode>
}

/// add zcode based on tokens
fn gen_zcode<'a>(node: &'a ASTNode, state: FormattingState, mut out: &mut zfile::Zfile, mut var_table: &mut HashMap<&'a str, u8>, mut var_id: &mut u8) {
    let mut state_copy = state.clone();

    match node {
        &ASTNode::Passage(ref node) => {
            match &node.category {
                &Token::TokPassageName(ref name) => {
                    out.routine(name, 0);
                },
                _ => {
                    debug!("no match 1");
                }
            };

            for child in &node.childs {
                gen_zcode(child, state_copy, out, var_table, var_id);
            }

            out.op_newline();
            out.op_call_1n("system_check_links");

        },
        &ASTNode::Default(ref t) => {
            match &t.category {
                &Token::TokText(ref s) => {
                    out.op_print(s);
                },
                &Token::TokNewLine => {
                    out.op_newline();
                },
                &Token::TokFormatBoldStart => {
                    state_copy.bold = true;
                    out.op_set_text_style(state_copy.bold, state_copy.inverted, state_copy.mono, state_copy.italic);
                },
                &Token::TokFormatItalicStart => {
                    state_copy.italic = true;
                    out.op_set_text_style(state_copy.bold, state_copy.inverted, state_copy.mono, state_copy.italic);
                },
                &Token::TokPassageLink (ref name, ref link) => {
                    out.op_call_2n_with_address("system_add_link", link);

                    out.op_set_text_style(state_copy.bold, true, state_copy.mono, state_copy.italic);
                    let link_text = format!("{}[", name);
                    out.op_print(&link_text);
                    out.op_print_num_var(16);
                    out.op_print("]");
                    out.op_set_text_style(state_copy.bold, state_copy.inverted, state_copy.mono, state_copy.italic);
                },
                &Token::TokAssign(ref var, ref operator) => {
                    if operator == "=" {
                        if !var_table.contains_key::<str>(var) {
                            var_table.insert(&var, *var_id);
                            debug!("Assigned id {} to variable {}", var_id, var);
                            *var_id += 1;
                        }
                        let id_option = var_table.get::<str>(var);
                        if t.childs.len() == 1 {
                            match t.childs[0] {
                                ASTNode::Default(ref def) => {
                                    let actual_id :u8 = match id_option {
                                        Some(id) => {
                                            *id
                                        },
                                        None => {
                                            panic!("Variable not in var table.")
                                        }
                                    };
                                    match def.category {
                                        Token::TokInt(value) => {
                                            out.op_store_u8(actual_id, value as u8);
                                        },
                                        Token::TokBoolean(ref bool_val) => {
                                            let value = match (*bool_val).as_ref() {
                                                "true" => { 1 as u8 },
                                                _ => { 0 as u8 }
                                            };
                                            out.op_store_u8(actual_id, value);
                                        }
                                        _ => { }
                                    }
                                },
                                _ => { }
                            }
                        } else {
                            debug!("Assign Expression currently not supported.");
                        }

                    }
                },
                _ => {
                    debug!("no match 2");
                }
            };

            for child in &t.childs {
                gen_zcode(child, state_copy, out, var_table, var_id);
            }

            out.op_set_text_style(false, false, false, false);
            out.op_set_text_style(state.bold, state.inverted, state.mono, state.italic);
        }
    };
}

impl AST {
    /// convert ast to zcode
    pub fn to_zcode(&self,  out: &mut zfile::Zfile) {
        let mut var_table = HashMap::<&str, u8>::new();
        let mut var_id : u8 = 25;
        let state = FormattingState {bold: false, italic: false, mono: false, inverted: false};
        for child in &self.passages {
            gen_zcode(child, state, out, &mut var_table, &mut var_id);
        }
    }

    pub fn new() -> AST {
        AST {
            passages: Vec::new()
        }
    }

    /// prints the tree
    pub fn print(&self) {
        debug!("Abstract Syntax Tree: ");
        for child in &self.passages {
            child.print(0);
        }
        debug!("");
    }

    /// adds a passage to the path in the ast
    pub fn add_passage(&mut self, token: Token) {
        let node = ASTNode::Passage(NodePassage { category: token, childs: Vec::new() });
        self.passages.push(node);
    }

    /// adds a child to the path in the ast
    pub fn add_child(&mut self, path: &Vec<usize>, token: Token) {
        if let Some(index) = path.first() {
            let mut new_path: Vec<usize> = path.to_vec();
            new_path.remove(0);

            self.passages[*index].add_child(new_path, token)
        } else {
            self.passages.push(ASTNode::Default(NodeDefault { category: token, childs: Vec::new() }));
        }
    }

    /// counts the childs of the path in the asts
    pub fn count_childs(&self, path: Vec<usize>) -> usize {
        if let Some(index) = path.first() {
            let mut new_path: Vec<usize> = path.to_vec();
            new_path.remove(0);

            self.passages[*index].count_childs(new_path)
        } else {
            self.passages.len()
        }
    }
}

// ================================
// node types
enum ASTNode {
    Default (NodeDefault),
    Passage (NodePassage)
}

struct NodePassage {
    category: Token,
    pub childs: Vec<ASTNode>,
    /*tags: Vec<ASTNode>*/
}

struct NodeDefault {
    category: Token,
    childs: Vec<ASTNode>
}

impl ASTNode {
    /// adds an child to the path in the ast
    pub fn add_child(&mut self, path: Vec<usize>, token: Token) {
        if let Some(index) = path.first() {
            let mut new_path: Vec<usize> = path.to_vec();
            new_path.remove(0);

            match self {
                &mut ASTNode::Default(ref mut node) => node.childs[*index].add_child(new_path, token),
                &mut ASTNode::Passage(ref mut node) => node.childs[*index].add_child(new_path, token),
            }
        } else {
            match self {
                &mut ASTNode::Default(ref mut node) => node.childs.push(ASTNode::Default(NodeDefault { category: token, childs: Vec::new() } )),
                &mut ASTNode::Passage(ref mut node) => node.childs.push(ASTNode::Default(NodeDefault { category: token, childs: Vec::new() } )),
            }
        }
    }

    /// counts the childs of the current path in the ast
    pub fn count_childs(&self, path: Vec<usize>) -> usize {
        if let Some(index) = path.first() {
            let mut new_path: Vec<usize> = path.to_vec();
            new_path.remove(0);

            match self {
                &ASTNode::Default(ref node) => node.childs[*index].count_childs(new_path),
                &ASTNode::Passage(ref node) => node.childs[*index].count_childs(new_path),
            }
        } else {
            match self {
                &ASTNode::Default(ref node) => node.childs.len(),
                &ASTNode::Passage(ref node) => node.childs.len(),
            }
        }
    }

    /// prints an node of an ast
    pub fn print(&self, indent: usize) {
        let mut spaces = "".to_string();
        for _ in 0..indent {
            spaces.push_str(" ");
        }

        match self {
            &ASTNode::Passage(ref t) => {
                debug!("{}|- : {:?}", spaces, t.category);
                for child in &t.childs {
                    child.print(indent+2);
                }
            },
            &ASTNode::Default(ref t) => {
                debug!("{}|- : {:?}", spaces, t.category);
                for child in &t.childs {
                    child.print(indent+2);
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>use std::default::Default;

#[derive(Debug, Copy, Clone)]
pub struct TexturePackerConfig {
    //
    // layout configuration
    //
    /// Max width of the packed image. Default value is `1024`.
    pub max_width: u32,
    /// Max height of the packed image. Default value is `1024`.
    pub max_height: u32,
    /// True to allow rotation of the input images. Default value is `true`.
    pub allow_rotation: bool,

    //
    // texture configuration
    //
    /// Size of the padding on the outer edge of the packed image in pixel. Default value is `0`.
    pub border_padding: u32,
    /// Size of the padding between frames in pixel. Default value is `2`
    pub texture_padding: u32,

    /// True to trim the empty pixels of the input images. Default value is `true`.
    pub trim: bool,

    /// True to draw the red line on the edge of the each frames. Useful for debugging. Default
    /// value is `false`.
    pub texture_outlines: bool,
}

impl Default for TexturePackerConfig {
    fn default() -> TexturePackerConfig {
        TexturePackerConfig {
            max_width: 1024,
            max_height: 1024,
            allow_rotation: true,

            border_padding: 0,
            texture_padding: 2,

            trim: true,

            texture_outlines: false,
        }
    }
}
<commit_msg>docs: Document texture_packer_config module contents<commit_after>use std::default::Default;

/// Configuration for a texture packer.
#[derive(Debug, Copy, Clone)]
pub struct TexturePackerConfig {
    //
    // layout configuration
    //
    /// Max width of the packed image. Default value is `1024`.
    pub max_width: u32,
    /// Max height of the packed image. Default value is `1024`.
    pub max_height: u32,
    /// True to allow rotation of the input images. Default value is `true`.
    pub allow_rotation: bool,

    //
    // texture configuration
    //
    /// Size of the padding on the outer edge of the packed image in pixel. Default value is `0`.
    pub border_padding: u32,
    /// Size of the padding between frames in pixel. Default value is `2`
    pub texture_padding: u32,

    /// True to trim the empty pixels of the input images. Default value is `true`.
    pub trim: bool,

    /// True to draw the red line on the edge of the each frames. Useful for debugging. Default
    /// value is `false`.
    pub texture_outlines: bool,
}

impl Default for TexturePackerConfig {
    fn default() -> TexturePackerConfig {
        TexturePackerConfig {
            max_width: 1024,
            max_height: 1024,
            allow_rotation: true,

            border_padding: 0,
            texture_padding: 2,

            trim: true,

            texture_outlines: false,
        }
    }
}
<|endoftext|>


<commit_before>extern mod std;

#[test]
fn test_tokenize() {
    assert tokenize( ~"(1 2 3)" ) == ~[~"(", ~"1", ~"2", ~"3", ~")"];
}

#[test]
fn test_addspaces() {
    assert addspaces( ~"(1 2 3)" ) == ~" ( 1 2 3 ) "
}

fn addspaces( input:&str ) -> ~str {
    str::replace(str::replace(input, ")", " ) "), "(", " ( ")
}

fn tokenize( input:&str ) -> ~[~str] {
    str::split_str_nonempty(addspaces(input), " ")
}

enum Expression {
    Value(int),
    Symbol(~str),
    List(~[Expression])
    }

fn main() {
    let Blah:Expression = List(~[Value(1), List(~[Value(1), Symbol(~"xyz")])]);
    io::println( "(begin 1 2)" )
}
<commit_msg>Add more tests to tokenize<commit_after>extern mod std;

#[test]
fn test_tokenize() {
    assert tokenize( ~"(1 2 3)" ) == ~[~"(", ~"1", ~"2", ~"3", ~")"];
}

#[test]
fn test_tokenize_empty() {
    assert tokenize( ~"" ) == ~[];
}

#[test]
fn test_tokenize_no_spaces() {
    assert tokenize( ~"one" ) == ~[~"one"];
}

#[test]
fn test_addspaces() {
    assert addspaces( ~"(1 2 3)" ) == ~" ( 1 2 3 ) "
}

fn addspaces( input:&str ) -> ~str {
    str::replace(str::replace(input, ")", " ) "), "(", " ( ")
}

fn tokenize( input:&str ) -> ~[~str] {
    str::split_str_nonempty(addspaces(input), " ")
}

enum Expression {
    Value(int),
    Symbol(~str),
    List(~[Expression])
    }

fn main() {
    let Blah:Expression = List(~[Value(1), List(~[Value(1), Symbol(~"xyz")])]);
    io::println( "(begin 1 2)" )
}
<|endoftext|>


<commit_before>use Icon;
use backend::Core;
use cache;
use calx::{clamp, cycle_anim, CellVector, FovValue, HexFov, Space, Transformation};
use calx_ecs::Entity;
use euclid::{Rect, TypedRect, TypedVector2D, TypedVector3D, vec2, vec3};
use render::{self, Angle, Layer};
use sprite::{Coloring, Sprite};
use std::collections::HashMap;
use std::iter::FromIterator;
use std::rc::Rc;
use world::{FovStatus, Location, Query, TerrainQuery, World};

/// Useful general constant for cell dimension ops.
pub static PIXEL_UNIT: f32 = 16.0;

pub struct WorldView {
    pub cursor_loc: Option<Location>,
    pub show_cursor: bool,
    camera_loc: Location,
    screen_area: TypedRect<f32, ScreenSpace>,
    fov: Option<HashMap<CellVector, Vec<Location>>>,
}

impl WorldView {
    pub fn new(camera_loc: Location, screen_area: Rect<f32>) -> WorldView {
        WorldView {
            cursor_loc: None,
            show_cursor: false,
            camera_loc: camera_loc,
            screen_area: ScreenRect::from_untyped(&screen_area),
            fov: None,
        }
    }

    pub fn set_camera(&mut self, loc: Location) {
        if loc != self.camera_loc {
            self.camera_loc = loc;
            self.fov = None;
        }
    }

    /// Recompute the cached screen view if the cache has been invalidated.
    fn ensure_fov(&mut self, world: &World) {
        if self.fov.is_none() {
            // Chart area, center in origin, inflated by tile width in every direction to get the
            // cells partially on screen included.
            let center = (self.screen_area.origin + self.screen_area.size / 2.0
                - vec2(PIXEL_UNIT / 2.0, 0.0))
                .to_vector();
            let bounds = self.screen_area
                .translate(&-(self.screen_area.origin + center).to_vector())
                .inflate(PIXEL_UNIT * 2.0, PIXEL_UNIT * 2.0);

            self.fov = Some(screen_fov(world, self.camera_loc, bounds));
        }
    }

    pub fn draw(&mut self, world: &World, core: &mut Core) {
        let current_sector = self.camera_loc.sector();
        self.camera_loc = current_sector.center();

        self.ensure_fov(world);

        let center = (self.screen_area.origin + self.screen_area.size / 2.0
            - vec2(PIXEL_UNIT / 2.0, 10.0))
            .to_vector();
        let chart = self.fov.as_ref().unwrap();
        let mut sprites = Vec::new();
        let mouse_pos = ScreenVector::from_untyped(&core.mouse_pos().to_vector());
        let cursor_pos = (mouse_pos - center).to_cell_space();

        for (&chart_pos, origins) in chart.iter() {
            assert!(!origins.is_empty());

            let mut loc = origins[0] + chart_pos;

            // Relative player pos to currently drawn thing.
            let mut player_pos = None;
            if let Some(player) = world.player() {
                if let Some(player_loc) = world.location(player) {
                    if let Some(vec) = player_loc.v2_at(loc) {
                        player_pos = Some(vec);
                    }
                }
            }

            let in_map_memory;

            // If the chart position is in live FOV, we want to show the deepest stack coordinate.
            // If it's not, we want to start looking for the map memory one from the top of the
            // stack.
            if get_fov(world, loc) == Some(FovStatus::Seen) {
                in_map_memory = false;
            } else {
                in_map_memory = true;
                // Only accept map memory from the base layer (top of origins stack)
                loc = origins[origins.len() - 1] + chart_pos;

                let mut gate_point = false;
                // Special case for terrain immediately below a portal when the portal destination
                // is in map memory, it should be drawn as a gate icon in map memory.
                if let Some(endpoint) = world.portal(loc) {
                    if get_fov(world, endpoint) == Some(FovStatus::Remembered) {
                        gate_point = true;
                    }
                }

                if !gate_point && get_fov(world, loc) != Some(FovStatus::Remembered) {
                    // Bail out if there's no memory
                    continue;
                }
            }

            let screen_pos = ScreenVector::from_cell_space(chart_pos) + center;

            let ambient = world.light_level(loc);

            // Tile is outside current sector and can't be entered, graphical cues to point this
            // out may be needed.
            let blocked_offsector =
                loc.sector() != current_sector && world.terrain(loc).is_narrow_obstacle();

            if blocked_offsector && !in_map_memory {
                sprites.push(Sprite::new(
                    Layer::Decal,
                    screen_pos,
                    cache::misc(Icon::BlockedOffSectorCell),
                ));
            }

            let mut terrain_sprite_buffer = Vec::new();

            render::draw_terrain_sprites(world, loc, |layer, angle, brush, frame_idx| {
                let color = if in_map_memory {
                    Coloring::MapMemory
                } else {
                    let diffuse = if angle == Angle::Up || angle == Angle::South {
                        // Angle::South is for all the non-wall props, don't shade them
                        1.0
                    } else {
                        let normal = angle.normal();
                        // When underground, use the player position as light position instead of
                        // constant-dir sunlight.
                        let light_dir = if world.is_underground(loc) && player_pos.is_some() {
                            PhysicsVector::from_cell_space(player_pos.unwrap()).normalize()
                        } else {
                            vec3(-(2.0f32.sqrt()) / 2.0, 2.0f32.sqrt() / 2.0, 0.0)
                        };
                        clamp(0.1, 1.0, -light_dir.dot(normal))
                    };

                    Coloring::Shaded { ambient, diffuse }
                };
                terrain_sprite_buffer.push(
                    Sprite::new(layer, screen_pos, Rc::clone(brush))
                        .idx(frame_idx)
                        .color(color),
                );
            });

            let mut entity_sprite_buffer = Vec::new();

            let (mobs, items): (Vec<Entity>, Vec<Entity>) = world
                .entities_at(loc)
                .into_iter()
                .partition(|&e| world.is_mob(e));

            // Draw non-mob entities, these are static and shown in map memory
            // FIXME: This should not use live entity data for the remembered objects, since it
            // will then show the object moving around without the player observing it.
            for &i in &items {
                if let Some(desc) = world.ecs().desc.get(i) {
                    let color = if in_map_memory {
                        Coloring::MapMemory
                    } else {
                        Coloring::Shaded {
                            ambient,
                            diffuse: 1.0,
                        }
                    };
                    entity_sprite_buffer.push(
                        Sprite::new(Layer::Object, screen_pos, cache::entity(desc.icon))
                            .color(color),
                    );
                }
            }

            // Draw mobs in directly seen cells
            if !in_map_memory {
                for &i in &mobs {
                    if let Some(desc) = world.ecs().desc.get(i) {
                        let frame_idx = if world.is_bobbing(i) {
                            cycle_anim(1.0 / 3.0, 2)
                        } else {
                            0
                        };
                        entity_sprite_buffer.push(
                            Sprite::new(Layer::Object, screen_pos, cache::entity(desc.icon))
                                .idx(frame_idx)
                                .color(Coloring::Shaded {
                                    ambient,
                                    diffuse: 1.0,
                                }),
                        );
                        draw_health_pips(&mut entity_sprite_buffer, world, i, screen_pos);
                    }
                }
            }

            // A doorway wall should be drawn on top of entities, but regular terrain blocks should
            // go below them.
            //
            // (Disabled. This is visually correct, but the wall graphic ends up obstructing the
            // mob sprite almost completely, and it's more important to be able to see what mob is
            // standing in the doorway than for things to be visually nice.)

            // if world.terrain(loc).is_wall() {
            //     sprites.extend_from_slice(&entity_sprite_buffer);
            //     sprites.extend_from_slice(&terrain_sprite_buffer);
            // } else {
            sprites.extend_from_slice(&terrain_sprite_buffer);
            sprites.extend_from_slice(&entity_sprite_buffer);
            // }
        }

        // Draw cursor.
        if let Some(origins) = chart.get(&cursor_pos) {
            let screen_pos = ScreenVector::from_cell_space(cursor_pos) + center;
            let loc = origins[0] + cursor_pos;
            self.cursor_loc = Some(loc);

            if self.show_cursor {
                sprites.push(Sprite::new(
                    Layer::Decal,
                    screen_pos,
                    cache::misc(Icon::CursorBottom),
                ));
                sprites.push(Sprite::new(
                    Layer::Effect,
                    screen_pos,
                    cache::misc(Icon::CursorTop),
                ));
            }
        } else {
            self.cursor_loc = None;
        }

        sprites.sort();

        for i in &sprites {
            i.draw(core)
        }

        fn get_fov(world: &World, loc: Location) -> Option<FovStatus> {
            if let Some(player) = world.player() {
                world
                    .ecs()
                    .map_memory
                    .get(player)
                    .map_or(Some(FovStatus::Seen), |fov| fov.status(loc))
            } else {
                Some(FovStatus::Seen)
            }
        }

        fn draw_health_pips(
            sprites: &mut Vec<Sprite>,
            world: &World,
            e: Entity,
            screen_pos: ScreenVector,
        ) {
            if !world.is_mob(e) {
                return;
            }

            let hp = world.hp(e);
            let max_hp = world.max_hp(e);

            if hp == max_hp {
                // Perfect health, draw nothing
                return;
            }

            let limit = ((hp * 5) as f32 / max_hp as f32).ceil() as i32;

            for x in 0..5 {
                let pos = screen_pos + vec2(x as f32 * 4.0 - 10.0, -10.0);
                let brush = cache::misc(if x < limit {
                    Icon::HealthPip
                } else {
                    Icon::DarkHealthPip
                });
                sprites.push(Sprite::new(Layer::Effect, pos, brush));
            }
        }
    }
}

#[derive(Clone)]
struct ScreenFov<'a> {
    w: &'a World,
    screen_area: TypedRect<f32, ScreenSpace>,
    origins: Vec<Location>,
}

impl<'a> PartialEq for ScreenFov<'a> {
    fn eq(&self, other: &Self) -> bool {
        self.w as *const World == other.w as *const World && self.screen_area == other.screen_area
            && self.origins == other.origins
    }
}

impl<'a> Eq for ScreenFov<'a> {}

impl<'a> FovValue for ScreenFov<'a> {
    fn advance(&self, offset: CellVector) -> Option<Self> {
        if !self.screen_area
            .contains(&ScreenVector::from_cell_space(offset).to_point())
        {
            return None;
        }

        let loc = self.origins[0] + offset;

        let mut ret = self.clone();
        // Go through a portal if terrain on our side of the portal is a void cell.
        //
        // With non-void terrain on top of the portal, just show our side and stay on the current
        // frame as far as FOV is concerned.
        if let Some(dest) = self.w.visible_portal(loc) {
            if self.w.is_border_portal(loc) {
                // A border portal will just overwrite the current origin. Map memory will
                // transition seamlessly to show the things past the border portal
                ret.origins[0] = dest - offset;
            } else {
                // A hole portal will add a new layer to the origins stack,
                // we still need to be able to show the previous layer when
                // showing map memory.
                ret.origins.insert(0, dest - offset);
            }
        }

        Some(ret)
    }
}

/// Return the field of view chart for drawing a screen.
///
/// The stack of locations in the return value lists origins for coordinate frames that have been
/// passed through when traversing portals, in reverse order. The first value is the origin of the
/// coordinate space you probably want to show for that point.
pub fn screen_fov(
    w: &World,
    origin: Location,
    screen_area: TypedRect<f32, ScreenSpace>,
) -> HashMap<CellVector, Vec<Location>> {
    let init = ScreenFov {
        w: w,
        screen_area: screen_area,
        origins: vec![origin],
    };

    HashMap::from_iter(HexFov::new(init).map(|(pos, a)| (pos, a.origins)))
}

/// On-screen tile display pixel coordinates.
pub struct ScreenSpace;

// a = PIXEL_UNIT
//
// |   a   -a |
// | a/2  a/2 |
//
// |  1/2a  1/a |
// | -1/2a  1/a |

impl Transformation for ScreenSpace {
    type Element = f32;

    fn unproject<V: Into<[i32; 2]>>(v: V) -> [Self::Element; 2] {
        let v = v.into();
        let v = [v[0] as f32, v[1] as f32];
        [
            v[0] * PIXEL_UNIT - v[1] * PIXEL_UNIT,
            v[0] * PIXEL_UNIT / 2.0 + v[1] * PIXEL_UNIT / 2.0,
        ]
    }

    fn project<V: Into<[Self::Element; 2]>>(v: V) -> [i32; 2] {
        let v = v.into();

        // Use a custom function here instead of the matrix inverse, because the naive matrix
        // version projects into an isometric grid instead of the more square on-screen hex cells
        // and feels off when aiming with the mouse.
        let c = PIXEL_UNIT / 2.0;
        let column = ((v[0] + c) / (c * 2.0)).floor();
        let row = ((v[1] - column * c) / (c * 2.0)).floor();
        [(column + row) as i32, row as i32]
    }
}

pub type ScreenVector = TypedVector2D<f32, ScreenSpace>;
pub type ScreenRect = TypedRect<f32, ScreenSpace>;

/// 3D physics space, used for eg. lighting.
pub struct PhysicsSpace;

// |    1    -1 |
// | -1/2  -1/2 |
//
// |  1/2  -1 |
// | -1/2  -1 |

impl Transformation for PhysicsSpace {
    type Element = f32;

    fn unproject<V: Into<[i32; 2]>>(v: V) -> [Self::Element; 2] {
        let v = v.into();
        let v = [v[0] as f32, v[1] as f32];
        [v[0] - v[1], -v[0] / 2.0 - v[1] / 2.0]
    }

    fn project<V: Into<[Self::Element; 2]>>(v: V) -> [i32; 2] {
        let v = v.into();
        [
            (v[0] / 2.0 - v[1]).round() as i32,
            (-v[0] / 2.0 - v[1]).round() as i32,
        ]
    }
}

pub type PhysicsVector = TypedVector3D<f32, PhysicsSpace>;
<commit_msg>Fix lighting bug where doorways go totally black when standing in them<commit_after>use Icon;
use backend::Core;
use cache;
use calx::{clamp, cycle_anim, CellVector, FovValue, HexFov, Space, Transformation};
use calx_ecs::Entity;
use euclid::{Rect, TypedRect, TypedVector2D, TypedVector3D, vec2, vec3};
use render::{self, Angle, Layer};
use sprite::{Coloring, Sprite};
use std::collections::HashMap;
use std::iter::FromIterator;
use std::rc::Rc;
use world::{FovStatus, Location, Query, TerrainQuery, World};

/// Useful general constant for cell dimension ops.
pub static PIXEL_UNIT: f32 = 16.0;

pub struct WorldView {
    pub cursor_loc: Option<Location>,
    pub show_cursor: bool,
    camera_loc: Location,
    screen_area: TypedRect<f32, ScreenSpace>,
    fov: Option<HashMap<CellVector, Vec<Location>>>,
}

impl WorldView {
    pub fn new(camera_loc: Location, screen_area: Rect<f32>) -> WorldView {
        WorldView {
            cursor_loc: None,
            show_cursor: false,
            camera_loc: camera_loc,
            screen_area: ScreenRect::from_untyped(&screen_area),
            fov: None,
        }
    }

    pub fn set_camera(&mut self, loc: Location) {
        if loc != self.camera_loc {
            self.camera_loc = loc;
            self.fov = None;
        }
    }

    /// Recompute the cached screen view if the cache has been invalidated.
    fn ensure_fov(&mut self, world: &World) {
        if self.fov.is_none() {
            // Chart area, center in origin, inflated by tile width in every direction to get the
            // cells partially on screen included.
            let center = (self.screen_area.origin + self.screen_area.size / 2.0
                - vec2(PIXEL_UNIT / 2.0, 0.0))
                .to_vector();
            let bounds = self.screen_area
                .translate(&-(self.screen_area.origin + center).to_vector())
                .inflate(PIXEL_UNIT * 2.0, PIXEL_UNIT * 2.0);

            self.fov = Some(screen_fov(world, self.camera_loc, bounds));
        }
    }

    pub fn draw(&mut self, world: &World, core: &mut Core) {
        let current_sector = self.camera_loc.sector();
        self.camera_loc = current_sector.center();

        self.ensure_fov(world);

        let center = (self.screen_area.origin + self.screen_area.size / 2.0
            - vec2(PIXEL_UNIT / 2.0, 10.0))
            .to_vector();
        let chart = self.fov.as_ref().unwrap();
        let mut sprites = Vec::new();
        let mouse_pos = ScreenVector::from_untyped(&core.mouse_pos().to_vector());
        let cursor_pos = (mouse_pos - center).to_cell_space();

        for (&chart_pos, origins) in chart.iter() {
            assert!(!origins.is_empty());

            let mut loc = origins[0] + chart_pos;

            // Relative player pos to currently drawn thing.
            let mut player_pos = None;
            if let Some(player) = world.player() {
                if let Some(player_loc) = world.location(player) {
                    if let Some(vec) = player_loc.v2_at(loc) {
                        player_pos = Some(vec);
                    }
                }
            }

            let in_map_memory;

            // If the chart position is in live FOV, we want to show the deepest stack coordinate.
            // If it's not, we want to start looking for the map memory one from the top of the
            // stack.
            if get_fov(world, loc) == Some(FovStatus::Seen) {
                in_map_memory = false;
            } else {
                in_map_memory = true;
                // Only accept map memory from the base layer (top of origins stack)
                loc = origins[origins.len() - 1] + chart_pos;

                let mut gate_point = false;
                // Special case for terrain immediately below a portal when the portal destination
                // is in map memory, it should be drawn as a gate icon in map memory.
                if let Some(endpoint) = world.portal(loc) {
                    if get_fov(world, endpoint) == Some(FovStatus::Remembered) {
                        gate_point = true;
                    }
                }

                if !gate_point && get_fov(world, loc) != Some(FovStatus::Remembered) {
                    // Bail out if there's no memory
                    continue;
                }
            }

            let screen_pos = ScreenVector::from_cell_space(chart_pos) + center;

            let ambient = world.light_level(loc);

            // Tile is outside current sector and can't be entered, graphical cues to point this
            // out may be needed.
            let blocked_offsector =
                loc.sector() != current_sector && world.terrain(loc).is_narrow_obstacle();

            if blocked_offsector && !in_map_memory {
                sprites.push(Sprite::new(
                    Layer::Decal,
                    screen_pos,
                    cache::misc(Icon::BlockedOffSectorCell),
                ));
            }

            let mut terrain_sprite_buffer = Vec::new();

            render::draw_terrain_sprites(world, loc, |layer, angle, brush, frame_idx| {
                let color = if in_map_memory {
                    Coloring::MapMemory
                } else {
                    let diffuse = if angle == Angle::Up || angle == Angle::South {
                        // Angle::South is for all the non-wall props, don't shade them
                        1.0
                    } else {
                        let normal = angle.normal();
                        // When underground, use the player position as light position instead of
                        // constant-dir sunlight.
                        let light_dir = if world.is_underground(loc) && player_pos.is_some() {
                            // XXX: Things get screwy if location is the same as player location
                            // (eg. when player stands in a doorway), hack around that by
                            // displacing the zero position.
                            let center_pos = if player_pos == Some(vec2(0, 0)) {
                                vec2(1, 1)
                            } else {
                                player_pos.unwrap()
                            };
                            PhysicsVector::from_cell_space(center_pos).normalize()
                        } else {
                            vec3(-(2.0f32.sqrt()) / 2.0, 2.0f32.sqrt() / 2.0, 0.0)
                        };
                        clamp(0.1, 1.0, -light_dir.dot(normal))
                    };

                    Coloring::Shaded { ambient, diffuse }
                };
                terrain_sprite_buffer.push(
                    Sprite::new(layer, screen_pos, Rc::clone(brush))
                        .idx(frame_idx)
                        .color(color),
                );
            });

            let mut entity_sprite_buffer = Vec::new();

            let (mobs, items): (Vec<Entity>, Vec<Entity>) = world
                .entities_at(loc)
                .into_iter()
                .partition(|&e| world.is_mob(e));

            // Draw non-mob entities, these are static and shown in map memory
            // FIXME: This should not use live entity data for the remembered objects, since it
            // will then show the object moving around without the player observing it.
            for &i in &items {
                if let Some(desc) = world.ecs().desc.get(i) {
                    let color = if in_map_memory {
                        Coloring::MapMemory
                    } else {
                        Coloring::Shaded {
                            ambient,
                            diffuse: 1.0,
                        }
                    };
                    entity_sprite_buffer.push(
                        Sprite::new(Layer::Object, screen_pos, cache::entity(desc.icon))
                            .color(color),
                    );
                }
            }

            // Draw mobs in directly seen cells
            if !in_map_memory {
                for &i in &mobs {
                    if let Some(desc) = world.ecs().desc.get(i) {
                        let frame_idx = if world.is_bobbing(i) {
                            cycle_anim(1.0 / 3.0, 2)
                        } else {
                            0
                        };
                        entity_sprite_buffer.push(
                            Sprite::new(Layer::Object, screen_pos, cache::entity(desc.icon))
                                .idx(frame_idx)
                                .color(Coloring::Shaded {
                                    ambient,
                                    diffuse: 1.0,
                                }),
                        );
                        draw_health_pips(&mut entity_sprite_buffer, world, i, screen_pos);
                    }
                }
            }

            // A doorway wall should be drawn on top of entities, but regular terrain blocks should
            // go below them.
            //
            // (Disabled. This is visually correct, but the wall graphic ends up obstructing the
            // mob sprite almost completely, and it's more important to be able to see what mob is
            // standing in the doorway than for things to be visually nice.)

            // if world.terrain(loc).is_wall() {
            //     sprites.extend_from_slice(&entity_sprite_buffer);
            //     sprites.extend_from_slice(&terrain_sprite_buffer);
            // } else {
            sprites.extend_from_slice(&terrain_sprite_buffer);
            sprites.extend_from_slice(&entity_sprite_buffer);
            // }
        }

        // Draw cursor.
        if let Some(origins) = chart.get(&cursor_pos) {
            let screen_pos = ScreenVector::from_cell_space(cursor_pos) + center;
            let loc = origins[0] + cursor_pos;
            self.cursor_loc = Some(loc);

            if self.show_cursor {
                sprites.push(Sprite::new(
                    Layer::Decal,
                    screen_pos,
                    cache::misc(Icon::CursorBottom),
                ));
                sprites.push(Sprite::new(
                    Layer::Effect,
                    screen_pos,
                    cache::misc(Icon::CursorTop),
                ));
            }
        } else {
            self.cursor_loc = None;
        }

        sprites.sort();

        for i in &sprites {
            i.draw(core)
        }

        fn get_fov(world: &World, loc: Location) -> Option<FovStatus> {
            if let Some(player) = world.player() {
                world
                    .ecs()
                    .map_memory
                    .get(player)
                    .map_or(Some(FovStatus::Seen), |fov| fov.status(loc))
            } else {
                Some(FovStatus::Seen)
            }
        }

        fn draw_health_pips(
            sprites: &mut Vec<Sprite>,
            world: &World,
            e: Entity,
            screen_pos: ScreenVector,
        ) {
            if !world.is_mob(e) {
                return;
            }

            let hp = world.hp(e);
            let max_hp = world.max_hp(e);

            if hp == max_hp {
                // Perfect health, draw nothing
                return;
            }

            let limit = ((hp * 5) as f32 / max_hp as f32).ceil() as i32;

            for x in 0..5 {
                let pos = screen_pos + vec2(x as f32 * 4.0 - 10.0, -10.0);
                let brush = cache::misc(if x < limit {
                    Icon::HealthPip
                } else {
                    Icon::DarkHealthPip
                });
                sprites.push(Sprite::new(Layer::Effect, pos, brush));
            }
        }
    }
}

#[derive(Clone)]
struct ScreenFov<'a> {
    w: &'a World,
    screen_area: TypedRect<f32, ScreenSpace>,
    origins: Vec<Location>,
}

impl<'a> PartialEq for ScreenFov<'a> {
    fn eq(&self, other: &Self) -> bool {
        self.w as *const World == other.w as *const World && self.screen_area == other.screen_area
            && self.origins == other.origins
    }
}

impl<'a> Eq for ScreenFov<'a> {}

impl<'a> FovValue for ScreenFov<'a> {
    fn advance(&self, offset: CellVector) -> Option<Self> {
        if !self.screen_area
            .contains(&ScreenVector::from_cell_space(offset).to_point())
        {
            return None;
        }

        let loc = self.origins[0] + offset;

        let mut ret = self.clone();
        // Go through a portal if terrain on our side of the portal is a void cell.
        //
        // With non-void terrain on top of the portal, just show our side and stay on the current
        // frame as far as FOV is concerned.
        if let Some(dest) = self.w.visible_portal(loc) {
            if self.w.is_border_portal(loc) {
                // A border portal will just overwrite the current origin. Map memory will
                // transition seamlessly to show the things past the border portal
                ret.origins[0] = dest - offset;
            } else {
                // A hole portal will add a new layer to the origins stack,
                // we still need to be able to show the previous layer when
                // showing map memory.
                ret.origins.insert(0, dest - offset);
            }
        }

        Some(ret)
    }
}

/// Return the field of view chart for drawing a screen.
///
/// The stack of locations in the return value lists origins for coordinate frames that have been
/// passed through when traversing portals, in reverse order. The first value is the origin of the
/// coordinate space you probably want to show for that point.
pub fn screen_fov(
    w: &World,
    origin: Location,
    screen_area: TypedRect<f32, ScreenSpace>,
) -> HashMap<CellVector, Vec<Location>> {
    let init = ScreenFov {
        w: w,
        screen_area: screen_area,
        origins: vec![origin],
    };

    HashMap::from_iter(HexFov::new(init).map(|(pos, a)| (pos, a.origins)))
}

/// On-screen tile display pixel coordinates.
pub struct ScreenSpace;

// a = PIXEL_UNIT
//
// |   a   -a |
// | a/2  a/2 |
//
// |  1/2a  1/a |
// | -1/2a  1/a |

impl Transformation for ScreenSpace {
    type Element = f32;

    fn unproject<V: Into<[i32; 2]>>(v: V) -> [Self::Element; 2] {
        let v = v.into();
        let v = [v[0] as f32, v[1] as f32];
        [
            v[0] * PIXEL_UNIT - v[1] * PIXEL_UNIT,
            v[0] * PIXEL_UNIT / 2.0 + v[1] * PIXEL_UNIT / 2.0,
        ]
    }

    fn project<V: Into<[Self::Element; 2]>>(v: V) -> [i32; 2] {
        let v = v.into();

        // Use a custom function here instead of the matrix inverse, because the naive matrix
        // version projects into an isometric grid instead of the more square on-screen hex cells
        // and feels off when aiming with the mouse.
        let c = PIXEL_UNIT / 2.0;
        let column = ((v[0] + c) / (c * 2.0)).floor();
        let row = ((v[1] - column * c) / (c * 2.0)).floor();
        [(column + row) as i32, row as i32]
    }
}

pub type ScreenVector = TypedVector2D<f32, ScreenSpace>;
pub type ScreenRect = TypedRect<f32, ScreenSpace>;

/// 3D physics space, used for eg. lighting.
pub struct PhysicsSpace;

// |    1    -1 |
// | -1/2  -1/2 |
//
// |  1/2  -1 |
// | -1/2  -1 |

impl Transformation for PhysicsSpace {
    type Element = f32;

    fn unproject<V: Into<[i32; 2]>>(v: V) -> [Self::Element; 2] {
        let v = v.into();
        let v = [v[0] as f32, v[1] as f32];
        [v[0] - v[1], -v[0] / 2.0 - v[1] / 2.0]
    }

    fn project<V: Into<[Self::Element; 2]>>(v: V) -> [i32; 2] {
        let v = v.into();
        [
            (v[0] / 2.0 - v[1]).round() as i32,
            (-v[0] / 2.0 - v[1]).round() as i32,
        ]
    }
}

pub type PhysicsVector = TypedVector3D<f32, PhysicsSpace>;
<|endoftext|>


<commit_before>extern crate num;
extern crate rand;
extern crate bignum = "bignum#0.1.1-pre";

use bignum::{BigUint, ToBigUint, RandBigInt};
use num::{div_mod_floor, Integer};
use std::num::{Zero, One, pow, Float, FromPrimitive};
use rand::{task_rng, Rng};
use rand::distributions::range::SampleRange;
use std::vec::Vec;
use std::iter;
use std::iter::{FromIterator};
use std::clone::Clone;
use std::ops::{Shr, BitAnd};
use std::bool;

static pow_offsets : &'static[uint] = &[0u, 4u, 6u, 10u, 12u, 16u];

#[inline]
fn big<T: ToBigUint>(i : T) -> BigUint {
    i.to_biguint().unwrap()
}

// Source: https://gist.github.com/jsanders/8739134#file-generate_big_primes-rs-L35
fn mod_exp<T: Integer + Clone + Shr<uint,T> + BitAnd<T,T>>
    (base: &T, exponent: &T, modulus: &T) -> T {

    let (zero, one): (T, T) = (Zero::zero(), One::one());
    let mut result = one.clone();
    let mut baseAcc = base.clone();
    let mut exponentAcc = exponent.clone();

    while exponentAcc > zero {
        // Accumulate current base if current exponent bit is 1
        if (exponentAcc & one) == one {
            result = result.mul(&baseAcc);
            result = result.rem(modulus);
        }
        // Get next base by squaring
        baseAcc = baseAcc * baseAcc;
        baseAcc = baseAcc % *modulus;

        // Get next bit of exponent
        exponentAcc = exponentAcc.shr(&1);
    }
    result

}

// Rabin-Miller primality test, probabilistic
fn try_composite(a : &BigUint, d : &BigUint, n : &BigUint, s : &BigUint) -> bool {

    let one : BigUint = One::one();
    if mod_exp(a, d, n) == one {
        return false
    }
    let mut i = 0u;
    loop {
        if big(i) == *s {
            break
        }
        if mod_exp(a, &(pow(one+one, i) * *d), n) == *n-one {
            return false
        }
        i += 1;
    }
    true

}
fn rm_is_prime(n : &BigUint) -> bool {

    let (zero, one): (BigUint, BigUint) = (Zero::zero(), One::one());
    let two = one + one;

    assert!(n >= &two);

    let mut s = zero.clone();
    let mut d = *n-one;
    let num_trials = 5;
    if n == &two {
        return true
    } else if n == &one || n.is_even() {
        return false
    } else {
        loop {
            let (quotient, remainder) = div_mod_floor(d.clone(), two.clone());
            if remainder == one { break }
            s = s + one;
            d = quotient;
        }
    }

    let mut rng = task_rng();
    for _ in range(0, num_trials) {
        let a = rng.gen_biguint_range(&two, n);
        if try_composite(&a, &d, n, &s) {
            return false
        }
    }
    true

}

fn fermat_is_prime(n : &BigUint) -> bool {
    let (zero, one): (BigUint, BigUint) = (Zero::zero(), One::one());
    let two = one + one;

    if n == &two {
        true
    } else if n.is_even() {
        false
    } else if mod_exp(&two, &(n-one), n) == one {
        true
    } else {
        false
    }
}

fn is_valid_pow(prime : &BigUint) -> bool {
    for offset in [big(0u), big(4u), big(6u), big(10u), big(12u), big(16u)].iter() {
        if !fermat_is_prime(&(*prime + *offset)) {
            return false;
        }
    }
    true
}

// Simple sieve
fn simple_sieve(primes : &mut Vec<bool>, max_sieve : uint, verbose : bool) -> Vec<uint> {
    #[inline]
    fn int_sqrt(n: uint) -> uint { (n as f64).sqrt() as uint }

    if primes.len() <= max_sieve {
        *primes = Vec::from_elem(max_sieve+1, true);
        *primes.get_mut(0) = false;
        *primes.get_mut(1) = false;
        for prime in range(2, int_sqrt(max_sieve) + 1) {
            if *primes.get(prime) {
                for multiple in iter::range_step(prime * prime, max_sieve + 1, prime) {
                    *primes.get_mut(multiple) = false
                }
                if verbose { println!("Sieved {}", prime) }
            }
        }
    }
    if verbose { println!("Finished sieving") }
    range(2, max_sieve+1).filter(|&n| *primes.get(n)).collect()
}

fn gen_prime(max_val : &BigUint, max_sieve : uint, verbose : bool) -> uint {

    fn candidate_killed_by(candidate : &BigUint, prime : &BigUint) -> bool {
        let zero : BigUint = Zero::zero();
        for &offset in pow_offsets.iter() {
            let o : BigUint = FromPrimitive::from_uint(offset).unwrap();
            if (*candidate + o) % *prime == zero {
                return true;
            }
        }
        false
    }

    fn add_next_prime (max_val : &BigUint, offsets : Vec<BigUint>, prime : BigUint, primorial : BigUint) -> Vec<BigUint> {
        let (zero, one): (BigUint, BigUint) = (Zero::zero(), One::one());
        let mut base : BigUint = Zero::zero();
        let mut new_offsets : Vec<BigUint> = Vec::new();
        let mut counter = zero.clone();
        while counter < prime {
            if base > *max_val {
                break
            }
            for o in offsets.iter() {
                    let val = base + *o;
                    if val > *max_val {
                        break
                    }
                    if !candidate_killed_by(&val, &prime) {
                        new_offsets.push(val);
                    }
            }
            base = base + primorial;
            counter = counter + one;
        }
        return new_offsets
    }

    let primorial_start : uint = 7u;
    let mut primorial : uint = 210u;  // 2*3*5*7
    let mut offsets : Vec<BigUint> = Vec::from_slice([big(97u)]);

    let mut primes : Vec<bool> = Vec::new();

    for &i in simple_sieve(&mut primes, max_sieve, verbose).iter() {
        if i <= primorial_start {
            continue
        }
        offsets = add_next_prime(max_val, offsets, big(i), big(primorial));
        primorial = primorial * i;
    }
    let mut count : uint = 0;
    for o in offsets.iter() {
        if is_valid_pow(o) {
            count = count + 1;
            if verbose { println!("prime: {}", o) }
        }
    }
    count
}

#[cfg(test)]
mod test_primes {
    use super::{big, gen_prime, simple_sieve};

    #[test]
    fn gen_prime_is_correct() {
        assert!(gen_prime(&big(100000000), 29, false) == 81u);
    }

    #[test]
    fn simple_sieve_is_correct() {
        assert!(simple_sieve(5000000, false).len() == 348513);
    }
}

fn main() {
    println!("{}", gen_prime(&big(100000000), 29, true));
}<commit_msg>Now returns list of candidates<commit_after>extern crate num;
extern crate rand;
extern crate bignum = "bignum#0.1.1-pre";

use bignum::{BigUint, ToBigUint, RandBigInt};
use num::{div_mod_floor, Integer};
use std::num::{Zero, One, pow, Float, FromPrimitive};
use rand::{task_rng, Rng};
use rand::distributions::range::SampleRange;
use std::vec::Vec;
use std::iter;
use std::iter::{FromIterator};
use std::clone::Clone;
use std::ops::{Shr, BitAnd};
use std::bool;

static pow_offsets : &'static[uint] = &[0u, 4u, 6u, 10u, 12u, 16u];

#[inline]
fn big<T: ToBigUint>(i : T) -> BigUint {
    i.to_biguint().unwrap()
}

// Source: https://gist.github.com/jsanders/8739134#file-generate_big_primes-rs-L35
fn mod_exp<T: Integer + Clone + Shr<uint,T> + BitAnd<T,T>>
    (base: &T, exponent: &T, modulus: &T) -> T {

    let (zero, one): (T, T) = (Zero::zero(), One::one());
    let mut result = one.clone();
    let mut baseAcc = base.clone();
    let mut exponentAcc = exponent.clone();

    while exponentAcc > zero {
        // Accumulate current base if current exponent bit is 1
        if (exponentAcc & one) == one {
            result = result.mul(&baseAcc);
            result = result.rem(modulus);
        }
        // Get next base by squaring
        baseAcc = baseAcc * baseAcc;
        baseAcc = baseAcc % *modulus;

        // Get next bit of exponent
        exponentAcc = exponentAcc.shr(&1);
    }
    result

}

// Rabin-Miller primality test, probabilistic
fn try_composite(a : &BigUint, d : &BigUint, n : &BigUint, s : &BigUint) -> bool {

    let one : BigUint = One::one();
    if mod_exp(a, d, n) == one {
        return false
    }
    let mut i = 0u;
    loop {
        if big(i) == *s {
            break
        }
        if mod_exp(a, &(pow(one+one, i) * *d), n) == *n-one {
            return false
        }
        i += 1;
    }
    true

}
fn rm_is_prime(n : &BigUint) -> bool {

    let (zero, one): (BigUint, BigUint) = (Zero::zero(), One::one());
    let two = one + one;

    assert!(n >= &two);

    let mut s = zero.clone();
    let mut d = *n-one;
    let num_trials = 5;
    if n == &two {
        return true
    } else if n == &one || n.is_even() {
        return false
    } else {
        loop {
            let (quotient, remainder) = div_mod_floor(d.clone(), two.clone());
            if remainder == one { break }
            s = s + one;
            d = quotient;
        }
    }

    let mut rng = task_rng();
    for _ in range(0, num_trials) {
        let a = rng.gen_biguint_range(&two, n);
        if try_composite(&a, &d, n, &s) {
            return false
        }
    }
    true

}

fn fermat_is_prime(n : &BigUint) -> bool {
    let (zero, one): (BigUint, BigUint) = (Zero::zero(), One::one());
    let two = one + one;

    if n == &two {
        true
    } else if n.is_even() {
        false
    } else if mod_exp(&two, &(n-one), n) == one {
        true
    } else {
        false
    }
}

fn is_valid_pow(prime : &BigUint) -> bool {
    for offset in [big(0u), big(4u), big(6u), big(10u), big(12u), big(16u)].iter() {
        if !fermat_is_prime(&(*prime + *offset)) {
            return false;
        }
    }
    true
}

// Simple sieve
fn simple_sieve(primes : &mut Vec<bool>, max_sieve : uint, verbose : bool) -> Vec<uint> {
    #[inline]
    fn int_sqrt(n: uint) -> uint { (n as f64).sqrt() as uint }

    if primes.len() <= max_sieve {
        *primes = Vec::from_elem(max_sieve+1, true);
        *primes.get_mut(0) = false;
        *primes.get_mut(1) = false;
        for prime in range(2, int_sqrt(max_sieve) + 1) {
            if *primes.get(prime) {
                for multiple in iter::range_step(prime * prime, max_sieve + 1, prime) {
                    *primes.get_mut(multiple) = false
                }
                if verbose { println!("Sieved {}", prime) }
            }
        }
    }
    if verbose { println!("Finished sieving") }
    range(2, max_sieve+1).filter(|&n| *primes.get(n)).collect()
}

fn gen_prime(base_val : &BigUint, max_val : &BigUint, max_sieve : uint, verbose : bool) -> Vec<BigUint> {

    fn candidate_killed_by(candidate : &BigUint, prime : &BigUint) -> bool {
        let zero : BigUint = Zero::zero();
        for &offset in pow_offsets.iter() {
            let o : BigUint = FromPrimitive::from_uint(offset).unwrap();
            if (*candidate + o) % *prime == zero {
                return true;
            }
        }
        false
    }

    fn add_next_prime (max_val : &BigUint, offsets : Vec<BigUint>, prime : BigUint, primorial : BigUint) -> Vec<BigUint> {
        let (zero, one): (BigUint, BigUint) = (Zero::zero(), One::one());
        let mut base : BigUint = Zero::zero();
        let mut new_offsets : Vec<BigUint> = Vec::new();
        let mut counter = zero.clone();
        while counter < prime {
            if base > *max_val {
                break
            }
            for o in offsets.iter() {
                    let val = base + *o;
                    if val > *max_val {
                        break
                    }
                    if !candidate_killed_by(&val, &prime) {
                        new_offsets.push(val);
                    }
            }
            base = base + primorial;
            counter = counter + one;
        }
        return new_offsets
    }

    let primorial_start : uint = 7u;
    let mut primorial : uint = 210u;  // 2*3*5*7
    let mut offsets : Vec<BigUint> = Vec::from_slice([big(97u)]);

    let mut primes : Vec<bool> = Vec::new();

    for &i in simple_sieve(&mut primes, max_sieve, verbose).iter() {
        if i <= primorial_start {
            continue
        }
        offsets = add_next_prime(max_val, offsets, big(i), big(primorial));
        primorial = primorial * i;
    }
    offsets.retain(|o| o >= base_val && is_valid_pow(o));
    offsets
}

#[cfg(test)]
mod test_primes {
    use super::{big, gen_prime, simple_sieve};

    #[test]
    fn gen_prime_is_correct() {
        assert!(gen_prime(&big(0), &big(100000000), 29, false).len() == 81u);
    }

    #[test]
    fn simple_sieve_is_correct() {
        assert!(simple_sieve(&mut Vec::new(), 5000000, false).len() == 348513);
    }
}

fn main() {
    println!("{}", gen_prime(&big(0), &big(100000000), 29, true).len());
}<|endoftext|>


<commit_before>//#![feature(macro_rules)]
//use std::any::{Any, TypeId};
use std::cmp::Ordering;
use std::collections::HashMap;
use std::ops::{Add, Sub};

/*
{start: }
*/
type Matrix<T> = HashMap<&'static str, HashMap<&'static str, Option<T>>>;

struct DistanceMatrix<T> {
    length: usize,
    inner_max: Matrix<T>,
}

impl<T> DistanceMatrix<T>
where
    T: Add + Sub + Ord,
{
    fn new(input: Matrix<T>) -> Self {
        DistanceMatrix {
            length: input.len(),
            inner_max: input,
        }
    }

    fn new_dijkstra_on(&mut self, end: &'static str) {}
}

//struct nil;
// type check function template
/*
fn is_nil<T: ?Sized + Any>(o: &T) -> bool {
    TypeId::of::<i32>() == TypeId::of::<T>()
}*/

// new_distance_matrix!()
// cannot check type in macro body. so do not need this macro
macro_rules! new_distance_matrix {
    ($([$($x:expr),*]),*) => {{
        vec![$(vec![$(
            if is_nil($x) {
                None
            }else{
                Some($x)
            }
        ),*]),*]
    }};
    ($($x:expr),*) => {{

    }};
}

fn main() {
    let test0: Matrix<u32> = [(
        "a",
        [("b", Some(6)), ("c", Some(3))] as HashMap<&'static str, Option<u32>>,
    )];
    println!("{:?}", test0);
    //println!("{:?}", new_distance_matrix![[1, 2, 3], [4, 5, 6], [7, 8]]);
}
<commit_msg>a bit<commit_after>//#![feature(macro_rules)]
//use std::any::{Any, TypeId};
use std::cmp::{Ordering, PartialOrd};
use std::collections::{HashMap, HashSet};
use std::ops::{Add, Deref, Sub};

/*
{start: {to: {distance, path}}}
 */
type Detail<Value> = (Value, Vec<&'static str>);
type Matrix<Value> = HashMap<&'static str, HashMap<&'static str, Detail<Value>>>;

/*
impl<T> Deref for Detail<T> {
    type Target = (T, Vec<&'static str>);

    fn deref(&self) -> &Self {
        &(*self.0, *self.1)
    }
}*/

struct DistanceMatrix<T> {
    length: usize,
    inner_max: Matrix<T>,
}

impl<T> DistanceMatrix<T>
where
    T: Add<Output = T> + Sub + Ord + Copy,
{
    fn new(input: Matrix<T>) -> Self {
        DistanceMatrix {
            length: input.len(),
            inner_max: input,
        }
    }

    fn path(&mut self, start: &'static str, to: &'static str) -> Option<Vec<&'static str>> {
        match self.inner_max.get(start) {
            Some(data) => match data.get(to) {
                Some((_, p)) => return Some(p.clone()),
                None => return None,
            },
            None => return None,
        }
    }

    fn val_between(&mut self, start: &'static str, to: &'static str) -> Option<T> {
        match self.inner_max.get(start) {
            Some(data) => match data.get(to) {
                Some((v, _)) => return Some(*v),
                None => return None,
            },
            None => return None,
        }
    }

    fn new_dijkstra_on(&mut self, start: &'static str) {
        let mut all_notes = self
            .inner_max
            .keys()
            .map(|x| *x)
            .collect::<HashSet<&'static str>>();
        all_notes.remove(start);

        let mut smallest_nodes_connected: (&'static str, Detail<T>);
        {
            let this_nodes_data = match self.inner_max.get(start) {
                Some(data) => data.clone(),
                None => {
                    println!("{}", "do not have this node");
                    return;
                }
            };

            // find shortest node of start
            let (a, b) = this_nodes_data
                .iter()
                .map(|x| x)
                .min_by_key(|(_, v)| v.0)
                .unwrap();
            smallest_nodes_connected = (*a, b.clone());
        }

        all_notes.remove(smallest_nodes_connected.0);

        let mut distance_to_now: T;
        let mut path_to_now: Vec<&'static str>;

        println!("{:?}", smallest_nodes_connected.0);
        while (!all_notes.is_empty()) {
            let distance_to_now: T;
            let path_to_now: Vec<&'static str>;

            {
                distance_to_now = self.val_between(start, smallest_nodes_connected.0).unwrap();
                path_to_now = self.path(start, smallest_nodes_connected.0).unwrap();
            }

            let this_nodes_data = match { self.inner_max.get_mut(smallest_nodes_connected.0) } {
                Some(data) => data.clone(),
                None => {
                    println!("{}", "do not have this node");
                    return;
                }
            };

            //update start node
            for (k, v) in this_nodes_data.iter() {
                if let Some(v_old) = self.val_between(start, k) {
                    if (distance_to_now + v.0) < { v_old } {
                        let mut new_path = path_to_now.clone();
                        new_path.push(k);
                        self.inner_max
                            .get_mut(start)
                            .unwrap()
                            .insert(k, (distance_to_now + v.0, new_path));
                    }
                } else {
                    let mut new_path = path_to_now.clone();
                    new_path.push(k);
                    self.inner_max
                        .get_mut(start)
                        .unwrap()
                        .insert(k, (distance_to_now + v.0, new_path));
                }
            }

            all_notes.remove(smallest_nodes_connected.0);
        }
    }
}

//struct nil;
// type check function template
/*
fn is_nil<T: ?Sized + Any>(o: &T) -> bool {
    TypeId::of::<i32>() == TypeId::of::<T>()
}*/

// new_distance_matrix!()
// cannot check type in macro body. so do not need this macro
/*
macro_rules! new_distance_matrix {
    ($([$($x:expr),*]),*) => {{
        vec![$(vec![$(
            if is_nil($x) {
                None
            }else{
                Some($x)
            }
        ),*]),*]
    }};
    ($($x:expr),*) => {{

    }};
}*/

fn main() {
    //let test0: Matrix<u32>;
    //println!("{:?}", test0);
    //println!("{:?}", new_distance_matrix![[1, 2, 3], [4, 5, 6], [7, 8]]);

    let mut testcaseM1: Matrix<u32> = HashMap::new();
    testcaseM1.insert(
        "a",
        [("b", (6 as u32, vec![])), ("c", (3 as u32, vec![]))]
            .iter()
            .cloned()
            .collect(),
    );
    testcaseM1.insert(
        "b",
        [
            ("a", (6 as u32, vec![])),
            ("c", (2 as u32, vec![])),
            ("d", (5 as u32, vec![])),
        ]
            .iter()
            .cloned()
            .collect(),
    );
    println!("{:?}", testcaseM1);

    let mut testcase1: DistanceMatrix<u32>;
    testcase1 = DistanceMatrix {
        length: 4,
        inner_max: testcaseM1,
    };

    //Option<(&&str, &(u32, std::vec::Vec<u32>))>
    println!("{:?}", testcase1.new_dijkstra_on("a"));
}
<|endoftext|>


<commit_before>use llvm_sys::core::{LLVMIsAMDNode, LLVMIsAMDString, LLVMGetMDString, LLVMGetMDNodeNumOperands, LLVMGetMDNodeOperands};
use llvm_sys::prelude::LLVMValueRef;

#[llvm_versions(7.0..=latest)]
use llvm_sys::prelude::LLVMMetadataRef;
#[llvm_versions(7.0..=latest)]
use llvm_sys::core::LLVMValueAsMetadata;

use crate::support::LLVMString;
use crate::values::traits::AsValueRef;
use crate::values::{BasicMetadataValueEnum, Value};

use std::ffi::CStr;
use std::fmt;

// TODOC: Varies by version
#[cfg(feature = "llvm3-6")]
pub const FIRST_CUSTOM_METADATA_KIND_ID: u32 = 12;
#[cfg(feature = "llvm3-7")]
pub const FIRST_CUSTOM_METADATA_KIND_ID: u32 = 14;
#[cfg(feature = "llvm3-8")]
pub const FIRST_CUSTOM_METADATA_KIND_ID: u32 = 18;
#[cfg(feature = "llvm3-9")]
pub const FIRST_CUSTOM_METADATA_KIND_ID: u32 = 20;
#[cfg(feature = "llvm4-0")]
pub const FIRST_CUSTOM_METADATA_KIND_ID: u32 = 22;
#[cfg(feature = "llvm5-0")]
pub const FIRST_CUSTOM_METADATA_KIND_ID: u32 = 23;
#[cfg(feature = "llvm6-0")]
pub const FIRST_CUSTOM_METADATA_KIND_ID: u32 = 25;
#[cfg(feature = "llvm7-0")]
pub const FIRST_CUSTOM_METADATA_KIND_ID: u32 = 25;
#[cfg(feature = "llvm8-0")]
pub const FIRST_CUSTOM_METADATA_KIND_ID: u32 = 26;
#[cfg(feature = "llvm9-0")]
pub const FIRST_CUSTOM_METADATA_KIND_ID: u32 = 28;
#[cfg(any(feature = "llvm10-0", feature = "llvm11-0", feature = "llvm12-0"))]
pub const FIRST_CUSTOM_METADATA_KIND_ID: u32 = 30;

#[derive(PartialEq, Eq, Clone, Copy, Hash)]
pub struct MetadataValue<'ctx> {
    metadata_value: Value<'ctx>,
}

impl<'ctx> MetadataValue<'ctx> {
    pub(crate) unsafe fn new(value: LLVMValueRef) -> Self {
        assert!(!value.is_null());
        assert!(!LLVMIsAMDNode(value).is_null() || !LLVMIsAMDString(value).is_null());

        MetadataValue {
            metadata_value: Value::new(value),
        }
    }

    #[llvm_versions(7.0..=latest)]
    pub(crate) fn as_metadata_ref(self) -> LLVMMetadataRef {
        unsafe {
            LLVMValueAsMetadata(self.as_value_ref())
        }
    }

    // SubTypes: This can probably go away with subtypes
    pub fn is_node(self) -> bool {
        unsafe {
            LLVMIsAMDNode(self.as_value_ref()) == self.as_value_ref()
        }
    }

    // SubTypes: This can probably go away with subtypes
    pub fn is_string(self) -> bool {
        unsafe {
            LLVMIsAMDString(self.as_value_ref()) == self.as_value_ref()
        }
    }

    pub fn get_string_value(&self) -> Option<&CStr> {
        if self.is_node() {
            return None;
        }

        let mut len = 0;
        let c_str = unsafe {
            CStr::from_ptr(LLVMGetMDString(self.as_value_ref(), &mut len))
        };

        Some(c_str)
    }

    // SubTypes: Node only one day
    pub fn get_node_size(self) -> u32 {
        if self.is_string() {
            return 0;
        }

        unsafe {
            LLVMGetMDNodeNumOperands(self.as_value_ref())
        }
    }

    // SubTypes: Node only one day
    // REVIEW: BasicMetadataValueEnum only if you can put metadata in metadata...
    pub fn get_node_values(self) -> Vec<BasicMetadataValueEnum<'ctx>> {
        if self.is_string() {
            return Vec::new();
        }

        let count = self.get_node_size() as usize;
        let mut vec: Vec<LLVMValueRef> = Vec::with_capacity(count);
        let ptr = vec.as_mut_ptr();

        unsafe {
            LLVMGetMDNodeOperands(self.as_value_ref(), ptr);

            vec.set_len(count)
        };

        vec.iter()
            .map(|val| unsafe { BasicMetadataValueEnum::new(*val) })
            .collect()
    }

    pub fn print_to_string(self) -> LLVMString {
        self.metadata_value.print_to_string()
    }

    pub fn print_to_stderr(self) {
        self.metadata_value.print_to_stderr()
    }

    pub fn replace_all_uses_with(self, other: &MetadataValue<'ctx>) {
        self.metadata_value.replace_all_uses_with(other.as_value_ref())
    }
}

impl AsValueRef for MetadataValue<'_> {
    fn as_value_ref(&self) -> LLVMValueRef {
        self.metadata_value.value
    }
}

impl fmt::Debug for MetadataValue<'_> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let mut d = f.debug_struct("MetadataValue");
        d.field("address", &self.as_value_ref());

        if self.is_string() {
            d.field("value", &self.get_string_value().unwrap());
        } else {
            d.field("values", &self.get_node_values());
        }

        d.field("repr", &self.print_to_string());

        d.finish()
    }
}
<commit_msg>bump number of metadata items<commit_after>use llvm_sys::core::{LLVMIsAMDNode, LLVMIsAMDString, LLVMGetMDString, LLVMGetMDNodeNumOperands, LLVMGetMDNodeOperands};
use llvm_sys::prelude::LLVMValueRef;

#[llvm_versions(7.0..=latest)]
use llvm_sys::prelude::LLVMMetadataRef;
#[llvm_versions(7.0..=latest)]
use llvm_sys::core::LLVMValueAsMetadata;

use crate::support::LLVMString;
use crate::values::traits::AsValueRef;
use crate::values::{BasicMetadataValueEnum, Value};

use std::ffi::CStr;
use std::fmt;

// TODOC: Varies by version
#[cfg(feature = "llvm3-6")]
pub const FIRST_CUSTOM_METADATA_KIND_ID: u32 = 12;
#[cfg(feature = "llvm3-7")]
pub const FIRST_CUSTOM_METADATA_KIND_ID: u32 = 14;
#[cfg(feature = "llvm3-8")]
pub const FIRST_CUSTOM_METADATA_KIND_ID: u32 = 18;
#[cfg(feature = "llvm3-9")]
pub const FIRST_CUSTOM_METADATA_KIND_ID: u32 = 20;
#[cfg(feature = "llvm4-0")]
pub const FIRST_CUSTOM_METADATA_KIND_ID: u32 = 22;
#[cfg(feature = "llvm5-0")]
pub const FIRST_CUSTOM_METADATA_KIND_ID: u32 = 23;
#[cfg(feature = "llvm6-0")]
pub const FIRST_CUSTOM_METADATA_KIND_ID: u32 = 25;
#[cfg(feature = "llvm7-0")]
pub const FIRST_CUSTOM_METADATA_KIND_ID: u32 = 25;
#[cfg(feature = "llvm8-0")]
pub const FIRST_CUSTOM_METADATA_KIND_ID: u32 = 26;
#[cfg(feature = "llvm9-0")]
pub const FIRST_CUSTOM_METADATA_KIND_ID: u32 = 28;
#[cfg(any(feature = "llvm10-0", feature = "llvm11-0"))]
pub const FIRST_CUSTOM_METADATA_KIND_ID: u32 = 30;
#[cfg(feature = "llvm12-0")]
pub const FIRST_CUSTOM_METADATA_KIND_ID: u32 = 31;

#[derive(PartialEq, Eq, Clone, Copy, Hash)]
pub struct MetadataValue<'ctx> {
    metadata_value: Value<'ctx>,
}

impl<'ctx> MetadataValue<'ctx> {
    pub(crate) unsafe fn new(value: LLVMValueRef) -> Self {
        assert!(!value.is_null());
        assert!(!LLVMIsAMDNode(value).is_null() || !LLVMIsAMDString(value).is_null());

        MetadataValue {
            metadata_value: Value::new(value),
        }
    }

    #[llvm_versions(7.0..=latest)]
    pub(crate) fn as_metadata_ref(self) -> LLVMMetadataRef {
        unsafe {
            LLVMValueAsMetadata(self.as_value_ref())
        }
    }

    // SubTypes: This can probably go away with subtypes
    pub fn is_node(self) -> bool {
        unsafe {
            LLVMIsAMDNode(self.as_value_ref()) == self.as_value_ref()
        }
    }

    // SubTypes: This can probably go away with subtypes
    pub fn is_string(self) -> bool {
        unsafe {
            LLVMIsAMDString(self.as_value_ref()) == self.as_value_ref()
        }
    }

    pub fn get_string_value(&self) -> Option<&CStr> {
        if self.is_node() {
            return None;
        }

        let mut len = 0;
        let c_str = unsafe {
            CStr::from_ptr(LLVMGetMDString(self.as_value_ref(), &mut len))
        };

        Some(c_str)
    }

    // SubTypes: Node only one day
    pub fn get_node_size(self) -> u32 {
        if self.is_string() {
            return 0;
        }

        unsafe {
            LLVMGetMDNodeNumOperands(self.as_value_ref())
        }
    }

    // SubTypes: Node only one day
    // REVIEW: BasicMetadataValueEnum only if you can put metadata in metadata...
    pub fn get_node_values(self) -> Vec<BasicMetadataValueEnum<'ctx>> {
        if self.is_string() {
            return Vec::new();
        }

        let count = self.get_node_size() as usize;
        let mut vec: Vec<LLVMValueRef> = Vec::with_capacity(count);
        let ptr = vec.as_mut_ptr();

        unsafe {
            LLVMGetMDNodeOperands(self.as_value_ref(), ptr);

            vec.set_len(count)
        };

        vec.iter()
            .map(|val| unsafe { BasicMetadataValueEnum::new(*val) })
            .collect()
    }

    pub fn print_to_string(self) -> LLVMString {
        self.metadata_value.print_to_string()
    }

    pub fn print_to_stderr(self) {
        self.metadata_value.print_to_stderr()
    }

    pub fn replace_all_uses_with(self, other: &MetadataValue<'ctx>) {
        self.metadata_value.replace_all_uses_with(other.as_value_ref())
    }
}

impl AsValueRef for MetadataValue<'_> {
    fn as_value_ref(&self) -> LLVMValueRef {
        self.metadata_value.value
    }
}

impl fmt::Debug for MetadataValue<'_> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let mut d = f.debug_struct("MetadataValue");
        d.field("address", &self.as_value_ref());

        if self.is_string() {
            d.field("value", &self.get_string_value().unwrap());
        } else {
            d.field("values", &self.get_node_values());
        }

        d.field("repr", &self.print_to_string());

        d.finish()
    }
}
<|endoftext|>


<commit_before>use std::mem;
use std::ptr;
use std::sync::Arc;
use std::sync::Mutex;
use std::sync::MutexGuard;

use device::Device;

use OomError;
use SynchronizedVulkanObject;
use VulkanObject;
use VulkanPointers;
use check_errors;
use vk;

/// Pool from which descriptor sets are allocated from.
///
/// A pool has a maximum number of descriptor sets and a maximum number of descriptors (one value
/// per descriptor type) it can allocate.
pub struct DescriptorPool {
    pool: Mutex<vk::DescriptorPool>,
    device: Arc<Device>,
}

impl DescriptorPool {
    /// Initializes a new pool.
    // FIXME: capacity of the pool
    pub fn new(device: &Arc<Device>) -> Result<Arc<DescriptorPool>, OomError> {
        let vk = device.pointers();

        // FIXME: arbitrary
        let pool_sizes = vec![
            vk::DescriptorPoolSize {
                ty: vk::DESCRIPTOR_TYPE_UNIFORM_BUFFER,
                descriptorCount: 10,
            },
            vk::DescriptorPoolSize {
                ty: vk::DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
                descriptorCount: 10,
            }
        ];

        let pool = unsafe {
            let infos = vk::DescriptorPoolCreateInfo {
                sType: vk::STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
                pNext: ptr::null(),
                flags: 0,   // TODO:
                maxSets: 100,       // TODO: let user choose
                poolSizeCount: pool_sizes.len() as u32,
                pPoolSizes: pool_sizes.as_ptr(),
            };

            let mut output = mem::uninitialized();
            try!(check_errors(vk.CreateDescriptorPool(device.internal_object(), &infos,
                                                      ptr::null(), &mut output)));
            output
        };

        Ok(Arc::new(DescriptorPool {
            pool: Mutex::new(pool),
            device: device.clone(),
        }))
    }

    /// Returns the device this pool was created from.
    #[inline]
    pub fn device(&self) -> &Arc<Device> {
        &self.device
    }
}

unsafe impl SynchronizedVulkanObject for DescriptorPool {
    type Object = vk::DescriptorPool;

    #[inline]
    fn internal_object_guard(&self) -> MutexGuard<vk::DescriptorPool> {
        self.pool.lock().unwrap()
    }
}

impl Drop for DescriptorPool {
    #[inline]
    fn drop(&mut self) {
        unsafe {
            let vk = self.device.pointers();
            let pool = self.pool.lock().unwrap();
            vk.DestroyDescriptorPool(self.device.internal_object(), *pool, ptr::null());
        }
    }
}

#[cfg(test)]
mod tests {
    use descriptor_set::DescriptorPool;

    #[test]
    fn create() {
        let (device, _) = gfx_dev_and_queue!();
        let _ = DescriptorPool::new(&device).unwrap();
    }

    #[test]
    fn device() {
        let (device, _) = gfx_dev_and_queue!();
        let pool = DescriptorPool::new(&device).unwrap();
        assert_eq!(&**pool.device() as *const _, &*device as *const _);
    }
}
<commit_msg>Create all descriptor pools with FREE_DESCRIPTOR_SET_BIT for now<commit_after>use std::mem;
use std::ptr;
use std::sync::Arc;
use std::sync::Mutex;
use std::sync::MutexGuard;

use device::Device;

use OomError;
use SynchronizedVulkanObject;
use VulkanObject;
use VulkanPointers;
use check_errors;
use vk;

/// Pool from which descriptor sets are allocated from.
///
/// A pool has a maximum number of descriptor sets and a maximum number of descriptors (one value
/// per descriptor type) it can allocate.
pub struct DescriptorPool {
    pool: Mutex<vk::DescriptorPool>,
    device: Arc<Device>,
}

impl DescriptorPool {
    /// Initializes a new pool.
    // FIXME: capacity of the pool
    pub fn new(device: &Arc<Device>) -> Result<Arc<DescriptorPool>, OomError> {
        let vk = device.pointers();

        // FIXME: arbitrary
        let pool_sizes = vec![
            vk::DescriptorPoolSize {
                ty: vk::DESCRIPTOR_TYPE_UNIFORM_BUFFER,
                descriptorCount: 10,
            },
            vk::DescriptorPoolSize {
                ty: vk::DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
                descriptorCount: 10,
            }
        ];

        let pool = unsafe {
            let infos = vk::DescriptorPoolCreateInfo {
                sType: vk::STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
                pNext: ptr::null(),
                flags: vk::DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,   // TODO:
                maxSets: 100,       // TODO: let user choose
                poolSizeCount: pool_sizes.len() as u32,
                pPoolSizes: pool_sizes.as_ptr(),
            };

            let mut output = mem::uninitialized();
            try!(check_errors(vk.CreateDescriptorPool(device.internal_object(), &infos,
                                                      ptr::null(), &mut output)));
            output
        };

        Ok(Arc::new(DescriptorPool {
            pool: Mutex::new(pool),
            device: device.clone(),
        }))
    }

    /// Returns the device this pool was created from.
    #[inline]
    pub fn device(&self) -> &Arc<Device> {
        &self.device
    }
}

unsafe impl SynchronizedVulkanObject for DescriptorPool {
    type Object = vk::DescriptorPool;

    #[inline]
    fn internal_object_guard(&self) -> MutexGuard<vk::DescriptorPool> {
        self.pool.lock().unwrap()
    }
}

impl Drop for DescriptorPool {
    #[inline]
    fn drop(&mut self) {
        unsafe {
            let vk = self.device.pointers();
            let pool = self.pool.lock().unwrap();
            vk.DestroyDescriptorPool(self.device.internal_object(), *pool, ptr::null());
        }
    }
}

#[cfg(test)]
mod tests {
    use descriptor_set::DescriptorPool;

    #[test]
    fn create() {
        let (device, _) = gfx_dev_and_queue!();
        let _ = DescriptorPool::new(&device).unwrap();
    }

    #[test]
    fn device() {
        let (device, _) = gfx_dev_and_queue!();
        let pool = DescriptorPool::new(&device).unwrap();
        assert_eq!(&**pool.device() as *const _, &*device as *const _);
    }
}
<|endoftext|>