<commit_before>//! A antialiasing oscillator.
//!
//! ## Waveforms
//!
//! The oscillator supports several classical waveforms. The square, triangle,
//! and saw waves support both aliased and antialiased variants.
//!
//! The aliased variants produce pure signals; for example, a square wave only
//! emits two values: `-1.0` and `+1.0`. This is useful when a control signal is
//! wanted, but produces aliasing in the frequency domain.
//!
//! The antialiased variants use PolyBLEP (polynomial bandlimited step) to
//! mitigate the aliasing in the pure signals. This results in a much cleaner
//! audible signal, and is more desirable for most musical purposes.
//!
//! ## Pitch Bend
//!
//! The oscillator supports pitch bending as an additional modifier of the base
//! frequency. This makes it easier to bend a single note when working with
//! MIDI, rather than manually tracking the base frequency and computing a new
//! frequency yourself.
//!
//! ## Low Frequency Oscillator
//!
//! The oscillator supports a low frequency oscillator (LFO) as optional input.
//! If provided, then the LFO is used to modulate the frequency of the
//! oscillator, producing a vibrato.
//!
//! ## Example
//!
//! The oscillator uses a builder pattern for initialization. The following will
//! set up an antialiased saw wave at 440 Hz, with a 0.1 step vibrato:
//!
//! ```
//! use oxcable::oscillator::*;
//! let osc = Oscillator::new(Saw(PolyBlep)).freq(440.0).lfo_intensity(0.1);
//! ```

use std::f32::consts::PI;
use num::traits::Float;
use rand::random;

use types::{SAMPLE_RATE, AudioDevice, MessageReceiver, Sample, Time};

/// Defines the messages that the Oscillator supports.
#[derive(Clone, Copy, Debug)]
pub enum Message {
    /// Sets the frequency in Hz.
    SetFreq(f32),
    /// Sets the waveform type.
    SetWaveform(Waveform),
    /// Sets the LFO vibrato depth, in steps.
    SetLFOIntensity(f32),
    /// Sets the pitch transposition, in steps.
    SetTranspose(f32),
    /// Sets the pitch bend, in steps.
    SetBend(f32),
}
pub use self::Message::*;

/// Antialiasing method for certain waveforms.
#[derive(Clone, Copy, Debug)]
pub enum AntialiasType {
    /// Naive, aliasing waveforms.
    Aliased,
    /// Antialiasing using PolyBLEP.
    PolyBlep
}
pub use self::AntialiasType::*;

/// Oscillator waveforms.
#[derive(Clone, Copy, Debug)]
pub enum Waveform {
    /// A sine wave.
    Sine,
    /// A saw wave.
    Saw(AntialiasType),
    /// A square wave.
    Square(AntialiasType),
    /// A triangle wave.
    Tri(AntialiasType),
    /// Pure white noise.
    WhiteNoise,
    /// A series of impulses.
    PulseTrain
}
pub use self::Waveform::*;

/// An oscillator that generates a periodic waveform.
pub struct Oscillator {
    waveform: Waveform,
    lfo_intensity: f32,
    transpose: f32,
    bend: f32,
    phase: f32,
    phase_delta: f32,
    last_sample: Sample,
}

impl Oscillator {
    /// Returns an oscillator with the specified waveform.
    pub fn new(waveform: Waveform) -> Self {
        Oscillator {
            waveform: waveform,
            lfo_intensity: 0.0,
            transpose: 1.0,
            bend: 1.0,
            phase: 0.0,
            phase_delta: 0.0,
            last_sample: 0.0
        }
    }

    /// Sets the frequency of the waveform, and return the same oscillator.
    pub fn freq(mut self, freq: f32) -> Self {
        self.handle_message(SetFreq(freq));
        self
    }

    /// Sets the frequency transposition (in steps), and return the same
    /// oscillator.
    pub fn transpose(mut self, steps: f32) -> Self {
        self.handle_message(SetTranspose(steps));
        self
    }

    /// Sets the intensity of the LFO vibrato, and return the same oscillator.
    ///
    /// The intensity is provided in half steps (1/2ths of an octave).
    pub fn lfo_intensity(mut self, lfo_intensity: f32) -> Self {
        self.handle_message(SetLFOIntensity(lfo_intensity));
        self
    }
}

impl MessageReceiver for Oscillator {
    type Msg = Message;
    fn handle_message(&mut self, msg: Message) {
        match msg {
            SetFreq(freq) => {
                self.phase_delta = freq*2.0*PI/(SAMPLE_RATE as f32);
            },
            SetWaveform(waveform) => {
                self.waveform = waveform;
            },
            SetLFOIntensity(steps) => {
                self.lfo_intensity = steps/12.0;
            },
            SetTranspose(steps) => {
                self.transpose = 2.0.powf(steps/12.0);
            },
            SetBend(steps) => {
                self.bend = 2.0.powf(steps/12.0);
            },
        }
    }
}

impl AudioDevice for Oscillator {
    fn num_inputs(&self) -> usize {
        1
    }

    fn num_outputs(&self) -> usize {
        1
    }

    fn tick(&mut self, _: Time, inputs: &[Sample], outputs: &mut[Sample]) {
        // Tick the phase
        let phase_delta = if inputs.len() > 0 {
            self.phase_delta*2.0.powf(inputs[0]*self.lfo_intensity)
        } else {
            self.phase_delta
        } * self.bend * self.transpose;
        self.phase += phase_delta;
        if self.phase >= 2.0*PI {
            self.phase -= 2.0*PI;
        }

        // Compute the next sample
        let s: Sample = match self.waveform.clone() {
            Sine => self.phase.sin(),
            Saw(aa) => {
                let mut out = self.phase/PI -1.0;
                match aa {
                    PolyBlep => {
                        out -= poly_belp_offset(self.phase/(2.0*PI),
                                                phase_delta/(2.0*PI));
                    },
                    _ => ()
                }
                out
            },
            Square(aa) => {
                let mut out = if self.phase < PI { 1.0 } else { -1.0 };
                match aa {
                    PolyBlep => {
                        // two discontinuities, at rising and falling edges
                        out += poly_belp_offset(self.phase/(2.0*PI),
                                                phase_delta/(2.0*PI));
                        out -= poly_belp_offset(self.phase/(2.0*PI)+0.5 % 1.0,
                                                phase_delta/(2.0*PI));
                    },
                    _ => ()
                }
                out
            },
            Tri(aa) => {
                // Compute a square wave signal
                let mut out = if self.phase < PI { 1.0 } else { -1.0 };
                match aa {
                    PolyBlep => {
                        // two discontinuities, at rising and falling edges
                        out += poly_belp_offset(self.phase/(2.0*PI),
                                                phase_delta/(2.0*PI));
                        out -= poly_belp_offset(self.phase/(2.0*PI)+0.5 % 1.0,
                                                phase_delta/(2.0*PI));
                    },
                    _ => ()
                }

                // Perform leaky integration
                phase_delta*out + (1.0-phase_delta)*self.last_sample
            },
            WhiteNoise => 2.0*random::<f32>() - 1.0,
            PulseTrain => {
                // If we wrapped around...
                if self.phase < self.phase_delta {
                    1.0
                } else {
                    0.0
                }
            }
        };

        // Push the sample out
        self.last_sample = s;
        outputs[0] = s;
    }
}

/// Computes an offset for PolyBLEP antialiasing
///
/// `t` should be the current waveform phase, normalized
/// `dt` should be the change in phase for one sample time, normalized
fn poly_belp_offset(t: f32, dt: f32) -> f32 {
    if t < dt { // t ~= 0
        let t = t / dt;
        -t*t + 2.0*t - 1.0
    } else if t > 1.0-dt { // t ~= 1
        let t = (t-1.0) / dt;
        t*t + 2.0*t + 1.0
    } else {
        0.0
    }
}

#[cfg(test)]
mod test {
    use testing::flt_eq;
    use super::{Aliased, Oscillator, Waveform};
    use types::{AudioDevice, Sample, Time};

    const FREQ: f32 = 4410.0;
    fn get_one_cycle(osc: &mut Oscillator) -> [Sample; 10] {
        let mut output = [0.0; 10];
        for t in 0..10 {
            osc.tick(t as Time, &[], &mut output[t..t+1]);
        }
        output
    }

    fn check(actual: &[Sample], expected: &[Sample]) {
        println!("actual:\n    {:?}", actual);
        println!("expected:\n    {:?}", expected);
        assert_eq!(actual.len(), expected.len());
        for (a, e) in actual.iter().zip(expected) {
            assert!(flt_eq(*a, *e));
        }
    }

    #[test]
    fn test_naive_square() {
        let mut osc = Oscillator::new(Waveform::Square(Aliased)).freq(FREQ);
        check(&get_one_cycle(&mut osc),
              &[1.0, 1.0, 1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0]);
    }

    #[test]
    fn test_naive_saw() {
        let mut osc = Oscillator::new(Waveform::Saw(Aliased)).freq(FREQ);
        check(&get_one_cycle(&mut osc),
              &[-0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, -1.0]);
    }

    #[test]
    fn test_pulse() {
        let mut osc = Oscillator::new(Waveform::PulseTrain).freq(FREQ);
        check(&get_one_cycle(&mut osc),
              &[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0]);
    }
}
<commit_msg>Clean up oscillator BLEP code.<commit_after>//! A antialiasing oscillator.
//!
//! ## Waveforms
//!
//! The oscillator supports several classical waveforms. The square, triangle,
//! and saw waves support both aliased and antialiased variants.
//!
//! The aliased variants produce pure signals; for example, a square wave only
//! emits two values: `-1.0` and `+1.0`. This is useful when a control signal is
//! wanted, but produces aliasing in the frequency domain.
//!
//! The antialiased variants use PolyBLEP (polynomial bandlimited step) to
//! mitigate the aliasing in the pure signals. This results in a much cleaner
//! audible signal, and is more desirable for most musical purposes.
//!
//! ## Pitch Bend
//!
//! The oscillator supports pitch bending as an additional modifier of the base
//! frequency. This makes it easier to bend a single note when working with
//! MIDI, rather than manually tracking the base frequency and computing a new
//! frequency yourself.
//!
//! ## Low Frequency Oscillator
//!
//! The oscillator supports a low frequency oscillator (LFO) as optional input.
//! If provided, then the LFO is used to modulate the frequency of the
//! oscillator, producing a vibrato.
//!
//! ## Example
//!
//! The oscillator uses a builder pattern for initialization. The following will
//! set up an antialiased saw wave at 440 Hz, with a 0.1 step vibrato:
//!
//! ```
//! use oxcable::oscillator::*;
//! let osc = Oscillator::new(Saw(PolyBlep)).freq(440.0).lfo_intensity(0.1);
//! ```

use std::f32::consts::PI;
use num::traits::Float;
use rand::random;

use types::{SAMPLE_RATE, AudioDevice, MessageReceiver, Sample, Time};

/// Defines the messages that the Oscillator supports.
#[derive(Clone, Copy, Debug)]
pub enum Message {
    /// Sets the frequency in Hz.
    SetFreq(f32),
    /// Sets the waveform type.
    SetWaveform(Waveform),
    /// Sets the LFO vibrato depth, in steps.
    SetLFOIntensity(f32),
    /// Sets the pitch transposition, in steps.
    SetTranspose(f32),
    /// Sets the pitch bend, in steps.
    SetBend(f32),
}
pub use self::Message::*;

/// Antialiasing method for certain waveforms.
#[derive(Clone, Copy, Debug)]
pub enum AntialiasType {
    /// Naive, aliasing waveforms.
    Aliased,
    /// Antialiasing using PolyBLEP.
    PolyBlep
}
pub use self::AntialiasType::*;

/// Oscillator waveforms.
#[derive(Clone, Copy, Debug)]
pub enum Waveform {
    /// A sine wave.
    Sine,
    /// A saw wave.
    Saw(AntialiasType),
    /// A square wave.
    Square(AntialiasType),
    /// A triangle wave.
    Tri(AntialiasType),
    /// Pure white noise.
    WhiteNoise,
    /// A series of impulses.
    PulseTrain
}
pub use self::Waveform::*;

/// An oscillator that generates a periodic waveform.
pub struct Oscillator {
    waveform: Waveform,
    lfo_intensity: f32,
    transpose: f32,
    bend: f32,
    phase: f32,
    phase_delta: f32,
    last_sample: Sample,
}

impl Oscillator {
    /// Returns an oscillator with the specified waveform.
    pub fn new(waveform: Waveform) -> Self {
        Oscillator {
            waveform: waveform,
            lfo_intensity: 0.0,
            transpose: 1.0,
            bend: 1.0,
            phase: 0.0,
            phase_delta: 0.0,
            last_sample: 0.0
        }
    }

    /// Sets the frequency of the waveform, and return the same oscillator.
    pub fn freq(mut self, freq: f32) -> Self {
        self.handle_message(SetFreq(freq));
        self
    }

    /// Sets the frequency transposition (in steps), and return the same
    /// oscillator.
    pub fn transpose(mut self, steps: f32) -> Self {
        self.handle_message(SetTranspose(steps));
        self
    }

    /// Sets the intensity of the LFO vibrato, and return the same oscillator.
    ///
    /// The intensity is provided in half steps (1/2ths of an octave).
    pub fn lfo_intensity(mut self, lfo_intensity: f32) -> Self {
        self.handle_message(SetLFOIntensity(lfo_intensity));
        self
    }
}

impl MessageReceiver for Oscillator {
    type Msg = Message;
    fn handle_message(&mut self, msg: Message) {
        match msg {
            SetFreq(freq) => {
                self.phase_delta = freq*2.0*PI/(SAMPLE_RATE as f32);
            },
            SetWaveform(waveform) => {
                self.waveform = waveform;
            },
            SetLFOIntensity(steps) => {
                self.lfo_intensity = steps/12.0;
            },
            SetTranspose(steps) => {
                self.transpose = 2.0.powf(steps/12.0);
            },
            SetBend(steps) => {
                self.bend = 2.0.powf(steps/12.0);
            },
        }
    }
}

impl AudioDevice for Oscillator {
    fn num_inputs(&self) -> usize {
        1
    }

    fn num_outputs(&self) -> usize {
        1
    }

    fn tick(&mut self, _: Time, inputs: &[Sample], outputs: &mut[Sample]) {
        // Tick the phase
        let phase_delta = if inputs.len() > 0 {
            self.phase_delta*2.0.powf(inputs[0]*self.lfo_intensity)
        } else {
            self.phase_delta
        } * self.bend * self.transpose;
        self.phase += phase_delta;
        if self.phase >= 2.0*PI {
            self.phase -= 2.0*PI;
        }

        // Compute the next sample
        self.last_sample = match self.waveform {
            Sine => self.phase.sin(),
            Saw(_) => {
                self.phase/PI -1.0 +
                    poly_blep(self.waveform, self.phase, phase_delta)
            },
            Square(_) => {
                (if self.phase < PI { 1.0 } else { -1.0 }) +
                    poly_blep(self.waveform, self.phase, phase_delta)
            },
            Tri(_) => {
                // Compute a square wave signal
                let out = (if self.phase < PI { 1.0 } else { -1.0 }) +
                    poly_blep(self.waveform, self.phase, phase_delta);

                // Perform leaky integration
                phase_delta*out + (1.0-phase_delta)*self.last_sample
            },
            WhiteNoise => 2.0*random::<f32>() - 1.0,
            PulseTrain => {
                // If we wrapped around...
                if self.phase < self.phase_delta { 1.0 } else { 0.0 }
            }
        };
        outputs[0] = self.last_sample;
    }
}

/// Computes the PolyBLEP step for a given waveform type. This should be added
/// to the naive waveform.
///
/// `waveform` should be the waveform we are antialiasing.
/// `phase` should be the current phase, from 0 to 2pi.
/// `phase_delta` should be the change in phase for one tick.
fn poly_blep(waveform: Waveform, phase: f32, phase_delta: f32) -> Sample {
    match waveform {
        Saw(PolyBlep) => {
            -1.0*poly_blep_offset(phase/(2.0*PI), phase_delta/(2.0*PI))
        },
        Square(PolyBlep) | Tri(PolyBlep) => {
            let t = phase/(2.0*PI);
            let dt = phase_delta/(2.0*PI);
            poly_blep_offset(t, dt) - poly_blep_offset((t+0.5) % 1.0, dt)
        },
        _ => 0.0
    }
}

/// Computes a single offset for PolyBLEP antialiasing.
///
/// `t` should be the current waveform phase, normalized.
/// `dt` should be the change in phase for one sample time, normalized.
fn poly_blep_offset(t: f32, dt: f32) -> f32 {
    if t < dt { // t ~= 0
        let t = t / dt;
        -t*t + 2.0*t - 1.0
    } else if t > 1.0-dt { // t ~= 1
        let t = (t-1.0) / dt;
        t*t + 2.0*t + 1.0
    } else {
        0.0
    }
}

#[cfg(test)]
mod test {
    use testing::flt_eq;
    use super::{Aliased, Oscillator, Waveform};
    use types::{AudioDevice, Sample, Time};

    const FREQ: f32 = 4410.0;
    fn get_one_cycle(osc: &mut Oscillator) -> [Sample; 10] {
        let mut output = [0.0; 10];
        for t in 0..10 {
            osc.tick(t as Time, &[], &mut output[t..t+1]);
        }
        output
    }

    fn check(actual: &[Sample], expected: &[Sample]) {
        println!("actual:\n    {:?}", actual);
        println!("expected:\n    {:?}", expected);
        assert_eq!(actual.len(), expected.len());
        for (a, e) in actual.iter().zip(expected) {
            assert!(flt_eq(*a, *e));
        }
    }

    #[test]
    fn test_naive_square() {
        let mut osc = Oscillator::new(Waveform::Square(Aliased)).freq(FREQ);
        check(&get_one_cycle(&mut osc),
              &[1.0, 1.0, 1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0]);
    }

    #[test]
    fn test_naive_saw() {
        let mut osc = Oscillator::new(Waveform::Saw(Aliased)).freq(FREQ);
        check(&get_one_cycle(&mut osc),
              &[-0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, -1.0]);
    }

    #[test]
    fn test_pulse() {
        let mut osc = Oscillator::new(Waveform::PulseTrain).freq(FREQ);
        check(&get_one_cycle(&mut osc),
              &[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0]);
    }
}
<|endoftext|>


<commit_before>//! # Command Parser
//!
//! The ``commands::parser`` module provides:
//!
//! * Functionality for building a tree of commands based on their names.
//! * Parsing tokenized input to select a command. Input tokenization can
//!   be performed by the ``commands::tokenizer`` module.
//! * Validating parameters.
//! * Performing completion on commands and parameters.
//!
//! The parser is still a work in progress but is rapidly advancing.

#![allow(dead_code)]

pub mod nodes;
pub mod completion;

use std::collections::HashMap;
use std::rc::Rc;
use parser::nodes::*;
use tokenizer::{Token, TokenType};

/// Command parser
///
/// The lifetime parameter `'p` refers to the lifetime of the
/// root node of the command tree that was used to create this
/// parser.
///
/// The lifetime parameter `'p` refers to the lifetime of the parser
/// and of the tokens passed into this parser.
pub struct Parser<'p> {
    current_node: &'p Rc<Node>,
    /// The nodes which have been accepted during `parse` or `advance`.
    pub nodes: Vec<&'p Rc<Node>>,
    /// The tokens which have been accepted during `parse` or `advance`.
    pub tokens: Vec<&'p Token<'p>>,
    commands: Vec<Rc<CommandNode>>,
    parameters: HashMap<String, String>,
}

impl<'p> Parser<'p> {
    /// Construct a parser with a root node.
    pub fn new(initial_node: &'p Rc<Node>) -> Parser<'p> {
        Parser {
            current_node: initial_node,
            nodes: vec![],
            tokens: vec![],
            commands: vec![],
            parameters: HashMap::new(),
        }
    }

    /// XXX: Temporarily public.
    pub fn push_command(&mut self, command: Rc<CommandNode>) {
        self.commands.push(command);
    }

    /// Parse a vector of tokens, advancing through the
    /// node hierarchy.
    pub fn parse(&mut self, tokens: Vec<&'p Token<'p>>) {
        for token in tokens {
            if token.token_type != TokenType::Whitespace {
                self.advance(token);
            }
        }
    }

    /// Parse a single token, advancing through the node hierarchy.
    pub fn advance(&mut self, token: &'p Token<'p>) {
        unimplemented!();
    }

    /// Execute the command that has been accepted by the parser.
    ///
    /// * XXX: This isn't implemented yet.
    /// * XXX: This should be returning a Result probably.
    pub fn execute(&self) {
        if !self.commands.is_empty() {
            // self.commands[0].execute(self)
        }
    }

    /// Verify that the parser is in a valid state with
    /// respect to having accepted a command and all
    /// required parameters.
    ///
    /// * XXX: This isn't implemented yet.
    /// * XXX: This should be returning Option or Result
    ///        with an enum for the various error conditions.
    pub fn verify(&self) -> bool {
        if self.commands.is_empty() {
            // XXX: We'll want an enum error here with a Result.
            return false;
        } else {
            for expected in self.commands[0].parameters() {
                if expected.required() {
                    // if !self.parameters.contains_key(expected.name()) {
                    // return false;
                    // }
                }
            }
        }
        true
    }
}
<commit_msg>parser: Implement much of advance.<commit_after>//! # Command Parser
//!
//! The ``commands::parser`` module provides:
//!
//! * Functionality for building a tree of commands based on their names.
//! * Parsing tokenized input to select a command. Input tokenization can
//!   be performed by the ``commands::tokenizer`` module.
//! * Validating parameters.
//! * Performing completion on commands and parameters.
//!
//! The parser is still a work in progress but is rapidly advancing.

#![allow(dead_code)]

pub mod nodes;
pub mod completion;

use std::collections::HashMap;
use std::rc::Rc;
use parser::nodes::*;
use tokenizer::{Token, TokenType};

/// Command parser
///
/// The lifetime parameter `'p` refers to the lifetime of the
/// root node of the command tree that was used to create this
/// parser.
///
/// The lifetime parameter `'p` refers to the lifetime of the parser
/// and of the tokens passed into this parser.
pub struct Parser<'p> {
    current_node: &'p Rc<Node>,
    /// The nodes which have been accepted during `parse` or `advance`.
    pub nodes: Vec<&'p Rc<Node>>,
    /// The tokens which have been accepted during `parse` or `advance`.
    pub tokens: Vec<&'p Token<'p>>,
    commands: Vec<&'p Rc<CommandNode>>,
    parameters: HashMap<String, String>,
}

impl<'p> Parser<'p> {
    /// Construct a parser with a root node.
    pub fn new(initial_node: &'p Rc<Node>) -> Parser<'p> {
        Parser {
            current_node: initial_node,
            nodes: vec![],
            tokens: vec![],
            commands: vec![],
            parameters: HashMap::new(),
        }
    }

    /// Parse a vector of tokens, advancing through the
    /// node hierarchy.
    pub fn parse(&mut self, tokens: Vec<&'p Token<'p>>) {
        for token in tokens {
            if token.token_type != TokenType::Whitespace {
                self.advance(token);
            }
        }
    }

    /// Parse a single token, advancing through the node hierarchy.
    pub fn advance(&mut self, token: &'p Token<'p>) {
        let matches = self.current_node
                          .successors()
                          .into_iter()
                          .filter(|n| n.acceptable(self) && n.matches(self, token))
                          .collect::<Vec<_>>();
        match matches.len() {
            1 => {
                let matching_node = &matches[0];
                matching_node.accept(self, token);
                self.current_node = matching_node.clone();
                self.nodes.push(matching_node);
                self.tokens.push(token);
            }
            0 => panic!("No matches for '{}'.", token.text),
            _ => panic!("Ambiguous matches for '{}'.", token.text),
        }
    }

    /// Execute the command that has been accepted by the parser.
    ///
    /// * XXX: This isn't implemented yet.
    /// * XXX: This should be returning a Result probably.
    pub fn execute(&self) {
        if !self.commands.is_empty() {
            // self.commands[0].execute(self)
        }
    }

    /// Verify that the parser is in a valid state with
    /// respect to having accepted a command and all
    /// required parameters.
    ///
    /// * XXX: This isn't implemented yet.
    /// * XXX: This should be returning Option or Result
    ///        with an enum for the various error conditions.
    pub fn verify(&self) -> bool {
        if self.commands.is_empty() {
            // XXX: We'll want an enum error here with a Result.
            return false;
        } else {
            for expected in self.commands[0].parameters() {
                if expected.required() {
                    // if !self.parameters.contains_key(expected.name()) {
                    // return false;
                    // }
                }
            }
        }
        true
    }
}

trait Advance {
    fn acceptable(&self, parser: &Parser) -> bool;

    fn matches(&self, parser: &Parser, token: &Token) -> bool;
}

impl Advance for Node {
    fn acceptable(&self, parser: &Parser) -> bool {
        unimplemented!();
        // !parser.nodes.contains(self)
    }

    fn matches(&self, parser: &Parser, token: &Token) -> bool {
        self.name().starts_with(token.text)
    }
}

trait Accept {
    fn accept<'p>(&'p self, parser: &mut Parser<'p>, token: &Token);
}

impl Accept for Node {
    fn accept<'p>(&'p self, parser: &mut Parser<'p>, token: &Token) {}
}

impl Accept for Rc<CommandNode> {
    fn accept<'p>(&'p self, parser: &mut Parser<'p>, token: &Token) {
        match self.handler() {
            Some(handler) => parser.commands.push(self),
            _ => {}
        }
    }
}

impl Accept for Rc<ParameterNode> {
    fn accept<'p>(&'p self, parser: &mut Parser<'p>, token: &Token) {
        if self.repeatable() {
            unimplemented!();
        } else {
            parser.parameters.insert(self.name().clone(), token.text.to_string());
        }
    }
}
<|endoftext|>


<commit_before>use smallvec::smallvec;

use crate::traits::{Obligation, ObligationCause, PredicateObligation};
use rustc_data_structures::fx::FxHashSet;
use rustc_middle::ty::outlives::Component;
use rustc_middle::ty::{self, ToPredicate, TyCtxt, WithConstness};
use rustc_span::symbol::Ident;

pub fn anonymize_predicate<'tcx>(
    tcx: TyCtxt<'tcx>,
    pred: ty::Predicate<'tcx>,
) -> ty::Predicate<'tcx> {
    match *pred.kind() {
        ty::PredicateKind::ForAll(binder) => {
            let new = ty::PredicateKind::ForAll(tcx.anonymize_late_bound_regions(binder));
            tcx.reuse_or_mk_predicate(pred, new)
        }
        ty::PredicateKind::Atom(_) => pred,
    }
}

struct PredicateSet<'tcx> {
    tcx: TyCtxt<'tcx>,
    set: FxHashSet<ty::Predicate<'tcx>>,
}

impl PredicateSet<'tcx> {
    fn new(tcx: TyCtxt<'tcx>) -> Self {
        Self { tcx, set: Default::default() }
    }

    fn insert(&mut self, pred: ty::Predicate<'tcx>) -> bool {
        // We have to be careful here because we want
        //
        //    for<'a> Foo<&'a i32>
        //
        // and
        //
        //    for<'b> Foo<&'b i32>
        //
        // to be considered equivalent. So normalize all late-bound
        // regions before we throw things into the underlying set.
        self.set.insert(anonymize_predicate(self.tcx, pred))
    }
}

impl Extend<ty::Predicate<'tcx>> for PredicateSet<'tcx> {
    fn extend<I: IntoIterator<Item = ty::Predicate<'tcx>>>(&mut self, iter: I) {
        for pred in iter {
            self.insert(pred);
        }
    }

    fn extend_one(&mut self, pred: ty::Predicate<'tcx>) {
        self.insert(pred);
    }

    fn extend_reserve(&mut self, additional: usize) {
        Extend::<ty::Predicate<'tcx>>::extend_reserve(&mut self.set, additional);
    }
}

///////////////////////////////////////////////////////////////////////////
// `Elaboration` iterator
///////////////////////////////////////////////////////////////////////////

/// "Elaboration" is the process of identifying all the predicates that
/// are implied by a source predicate. Currently, this basically means
/// walking the "supertraits" and other similar assumptions. For example,
/// if we know that `T: Ord`, the elaborator would deduce that `T: PartialOrd`
/// holds as well. Similarly, if we have `trait Foo: 'static`, and we know that
/// `T: Foo`, then we know that `T: 'static`.
pub struct Elaborator<'tcx> {
    stack: Vec<PredicateObligation<'tcx>>,
    visited: PredicateSet<'tcx>,
}

pub fn elaborate_trait_ref<'tcx>(
    tcx: TyCtxt<'tcx>,
    trait_ref: ty::PolyTraitRef<'tcx>,
) -> Elaborator<'tcx> {
    elaborate_predicates(tcx, std::iter::once(trait_ref.without_const().to_predicate(tcx)))
}

pub fn elaborate_trait_refs<'tcx>(
    tcx: TyCtxt<'tcx>,
    trait_refs: impl Iterator<Item = ty::PolyTraitRef<'tcx>>,
) -> Elaborator<'tcx> {
    let predicates = trait_refs.map(|trait_ref| trait_ref.without_const().to_predicate(tcx));
    elaborate_predicates(tcx, predicates)
}

pub fn elaborate_predicates<'tcx>(
    tcx: TyCtxt<'tcx>,
    predicates: impl Iterator<Item = ty::Predicate<'tcx>>,
) -> Elaborator<'tcx> {
    let obligations = predicates
        .map(|predicate| {
            predicate_obligation(predicate, ty::ParamEnv::empty(), ObligationCause::dummy())
        })
        .collect();
    elaborate_obligations(tcx, obligations)
}

pub fn elaborate_obligations<'tcx>(
    tcx: TyCtxt<'tcx>,
    mut obligations: Vec<PredicateObligation<'tcx>>,
) -> Elaborator<'tcx> {
    let mut visited = PredicateSet::new(tcx);
    obligations.retain(|obligation| visited.insert(obligation.predicate));
    Elaborator { stack: obligations, visited }
}

fn predicate_obligation<'tcx>(
    predicate: ty::Predicate<'tcx>,
    param_env: ty::ParamEnv<'tcx>,
    cause: ObligationCause<'tcx>,
) -> PredicateObligation<'tcx> {
    Obligation { cause, param_env, recursion_depth: 0, predicate }
}

impl Elaborator<'tcx> {
    pub fn filter_to_traits(self) -> FilterToTraits<Self> {
        FilterToTraits::new(self)
    }

    fn elaborate(&mut self, obligation: &PredicateObligation<'tcx>) {
        let tcx = self.visited.tcx;

        let bound_predicate = obligation.predicate.bound_atom();
        match bound_predicate.skip_binder() {
            ty::PredicateAtom::Trait(data, _) => {
                // Get predicates declared on the trait.
                let predicates = tcx.super_predicates_of(data.def_id());

                let obligations = predicates.predicates.iter().map(|&(pred, _)| {
                    predicate_obligation(
                        pred.subst_supertrait(tcx, &bound_predicate.rebind(data.trait_ref)),
                        obligation.param_env,
                        obligation.cause.clone(),
                    )
                });
                debug!("super_predicates: data={:?}", data);

                // Only keep those bounds that we haven't already seen.
                // This is necessary to prevent infinite recursion in some
                // cases. One common case is when people define
                // `trait Sized: Sized { }` rather than `trait Sized { }`.
                let visited = &mut self.visited;
                let obligations = obligations.filter(|o| visited.insert(o.predicate));

                self.stack.extend(obligations);
            }
            ty::PredicateAtom::WellFormed(..) => {
                // Currently, we do not elaborate WF predicates,
                // although we easily could.
            }
            ty::PredicateAtom::ObjectSafe(..) => {
                // Currently, we do not elaborate object-safe
                // predicates.
            }
            ty::PredicateAtom::Subtype(..) => {
                // Currently, we do not "elaborate" predicates like `X <: Y`,
                // though conceivably we might.
            }
            ty::PredicateAtom::Projection(..) => {
                // Nothing to elaborate in a projection predicate.
            }
            ty::PredicateAtom::ClosureKind(..) => {
                // Nothing to elaborate when waiting for a closure's kind to be inferred.
            }
            ty::PredicateAtom::ConstEvaluatable(..) => {
                // Currently, we do not elaborate const-evaluatable
                // predicates.
            }
            ty::PredicateAtom::ConstEquate(..) => {
                // Currently, we do not elaborate const-equate
                // predicates.
            }
            ty::PredicateAtom::RegionOutlives(..) => {
                // Nothing to elaborate from `'a: 'b`.
            }
            ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(ty_max, r_min)) => {
                // We know that `T: 'a` for some type `T`. We can
                // often elaborate this. For example, if we know that
                // `[U]: 'a`, that implies that `U: 'a`. Similarly, if
                // we know `&'a U: 'b`, then we know that `'a: 'b` and
                // `U: 'b`.
                //
                // We can basically ignore bound regions here. So for
                // example `for<'c> Foo<'a,'c>: 'b` can be elaborated to
                // `'a: 'b`.

                // Ignore `for<'a> T: 'a` -- we might in the future
                // consider this as evidence that `T: 'static`, but
                // I'm a bit wary of such constructions and so for now
                // I want to be conservative. --nmatsakis
                if r_min.is_late_bound() {
                    return;
                }

                let visited = &mut self.visited;
                let mut components = smallvec![];
                tcx.push_outlives_components(ty_max, &mut components);
                self.stack.extend(
                    components
                        .into_iter()
                        .filter_map(|component| match component {
                            Component::Region(r) => {
                                if r.is_late_bound() {
                                    None
                                } else {
                                    Some(ty::PredicateAtom::RegionOutlives(ty::OutlivesPredicate(
                                        r, r_min,
                                    )))
                                }
                            }

                            Component::Param(p) => {
                                let ty = tcx.mk_ty_param(p.index, p.name);
                                Some(ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(
                                    ty, r_min,
                                )))
                            }

                            Component::UnresolvedInferenceVariable(_) => None,

                            Component::Projection(_) | Component::EscapingProjection(_) => {
                                // We can probably do more here. This
                                // corresponds to a case like `<T as
                                // Foo<'a>>::U: 'b`.
                                None
                            }
                        })
                        .map(|predicate_kind| predicate_kind.to_predicate(tcx))
                        .filter(|&predicate| visited.insert(predicate))
                        .map(|predicate| {
                            predicate_obligation(
                                predicate,
                                obligation.param_env,
                                obligation.cause.clone(),
                            )
                        }),
                );
            }
            ty::PredicateAtom::TypeWellFormedFromEnv(..) => {
                // Nothing to elaborate
            }
        }
    }
}

impl Iterator for Elaborator<'tcx> {
    type Item = PredicateObligation<'tcx>;

    fn size_hint(&self) -> (usize, Option<usize>) {
        (self.stack.len(), None)
    }

    fn next(&mut self) -> Option<Self::Item> {
        // Extract next item from top-most stack frame, if any.
        if let Some(obligation) = self.stack.pop() {
            self.elaborate(&obligation);
            Some(obligation)
        } else {
            None
        }
    }
}

///////////////////////////////////////////////////////////////////////////
// Supertrait iterator
///////////////////////////////////////////////////////////////////////////

pub type Supertraits<'tcx> = FilterToTraits<Elaborator<'tcx>>;

pub fn supertraits<'tcx>(
    tcx: TyCtxt<'tcx>,
    trait_ref: ty::PolyTraitRef<'tcx>,
) -> Supertraits<'tcx> {
    elaborate_trait_ref(tcx, trait_ref).filter_to_traits()
}

pub fn transitive_bounds<'tcx>(
    tcx: TyCtxt<'tcx>,
    bounds: impl Iterator<Item = ty::PolyTraitRef<'tcx>>,
) -> Supertraits<'tcx> {
    elaborate_trait_refs(tcx, bounds).filter_to_traits()
}

/// A specialized variant of `elaborate_trait_refs` that only elaborates trait references that may
/// define the given associated type `assoc_name`. It uses the
/// `super_predicates_that_define_assoc_type` query to avoid enumerating super-predicates that
/// aren't related to `assoc_item`.  This is used when resolving types like `Self::Item` or
/// `T::Item` and helps to avoid cycle errors (see e.g. #35237).
pub fn transitive_bounds_that_define_assoc_type<'tcx>(
    tcx: TyCtxt<'tcx>,
    bounds: impl Iterator<Item = ty::PolyTraitRef<'tcx>>,
    assoc_name: Ident,
) -> FxHashSet<ty::PolyTraitRef<'tcx>> {
    let mut stack: Vec<_> = bounds.collect();
    let mut trait_refs = FxHashSet::default();

    while let Some(trait_ref) = stack.pop() {
        if trait_refs.insert(trait_ref) {
            let super_predicates =
                tcx.super_predicates_that_define_assoc_type((trait_ref.def_id(), Some(assoc_name)));
            for (super_predicate, _) in super_predicates.predicates {
                let bound_predicate = super_predicate.bound_atom();
                let subst_predicate = super_predicate
                    .subst_supertrait(tcx, &bound_predicate.rebind(trait_ref.skip_binder()));
                if let Some(binder) = subst_predicate.to_opt_poly_trait_ref() {
                    stack.push(binder.value);
                }
            }
        }
    }

    trait_refs
}

///////////////////////////////////////////////////////////////////////////
// Other
///////////////////////////////////////////////////////////////////////////

/// A filter around an iterator of predicates that makes it yield up
/// just trait references.
pub struct FilterToTraits<I> {
    base_iterator: I,
}

impl<I> FilterToTraits<I> {
    fn new(base: I) -> FilterToTraits<I> {
        FilterToTraits { base_iterator: base }
    }
}

impl<'tcx, I: Iterator<Item = PredicateObligation<'tcx>>> Iterator for FilterToTraits<I> {
    type Item = ty::PolyTraitRef<'tcx>;

    fn next(&mut self) -> Option<ty::PolyTraitRef<'tcx>> {
        while let Some(obligation) = self.base_iterator.next() {
            if let Some(data) = obligation.predicate.to_opt_poly_trait_ref() {
                return Some(data.value);
            }
        }
        None
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let (_, upper) = self.base_iterator.size_hint();
        (0, upper)
    }
}
<commit_msg>Return FxIndexSet instead of FxHashSet to avoid order errors on different platforms<commit_after>use smallvec::smallvec;

use crate::traits::{Obligation, ObligationCause, PredicateObligation};
use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
use rustc_middle::ty::outlives::Component;
use rustc_middle::ty::{self, ToPredicate, TyCtxt, WithConstness};
use rustc_span::symbol::Ident;

pub fn anonymize_predicate<'tcx>(
    tcx: TyCtxt<'tcx>,
    pred: ty::Predicate<'tcx>,
) -> ty::Predicate<'tcx> {
    match *pred.kind() {
        ty::PredicateKind::ForAll(binder) => {
            let new = ty::PredicateKind::ForAll(tcx.anonymize_late_bound_regions(binder));
            tcx.reuse_or_mk_predicate(pred, new)
        }
        ty::PredicateKind::Atom(_) => pred,
    }
}

struct PredicateSet<'tcx> {
    tcx: TyCtxt<'tcx>,
    set: FxHashSet<ty::Predicate<'tcx>>,
}

impl PredicateSet<'tcx> {
    fn new(tcx: TyCtxt<'tcx>) -> Self {
        Self { tcx, set: Default::default() }
    }

    fn insert(&mut self, pred: ty::Predicate<'tcx>) -> bool {
        // We have to be careful here because we want
        //
        //    for<'a> Foo<&'a i32>
        //
        // and
        //
        //    for<'b> Foo<&'b i32>
        //
        // to be considered equivalent. So normalize all late-bound
        // regions before we throw things into the underlying set.
        self.set.insert(anonymize_predicate(self.tcx, pred))
    }
}

impl Extend<ty::Predicate<'tcx>> for PredicateSet<'tcx> {
    fn extend<I: IntoIterator<Item = ty::Predicate<'tcx>>>(&mut self, iter: I) {
        for pred in iter {
            self.insert(pred);
        }
    }

    fn extend_one(&mut self, pred: ty::Predicate<'tcx>) {
        self.insert(pred);
    }

    fn extend_reserve(&mut self, additional: usize) {
        Extend::<ty::Predicate<'tcx>>::extend_reserve(&mut self.set, additional);
    }
}

///////////////////////////////////////////////////////////////////////////
// `Elaboration` iterator
///////////////////////////////////////////////////////////////////////////

/// "Elaboration" is the process of identifying all the predicates that
/// are implied by a source predicate. Currently, this basically means
/// walking the "supertraits" and other similar assumptions. For example,
/// if we know that `T: Ord`, the elaborator would deduce that `T: PartialOrd`
/// holds as well. Similarly, if we have `trait Foo: 'static`, and we know that
/// `T: Foo`, then we know that `T: 'static`.
pub struct Elaborator<'tcx> {
    stack: Vec<PredicateObligation<'tcx>>,
    visited: PredicateSet<'tcx>,
}

pub fn elaborate_trait_ref<'tcx>(
    tcx: TyCtxt<'tcx>,
    trait_ref: ty::PolyTraitRef<'tcx>,
) -> Elaborator<'tcx> {
    elaborate_predicates(tcx, std::iter::once(trait_ref.without_const().to_predicate(tcx)))
}

pub fn elaborate_trait_refs<'tcx>(
    tcx: TyCtxt<'tcx>,
    trait_refs: impl Iterator<Item = ty::PolyTraitRef<'tcx>>,
) -> Elaborator<'tcx> {
    let predicates = trait_refs.map(|trait_ref| trait_ref.without_const().to_predicate(tcx));
    elaborate_predicates(tcx, predicates)
}

pub fn elaborate_predicates<'tcx>(
    tcx: TyCtxt<'tcx>,
    predicates: impl Iterator<Item = ty::Predicate<'tcx>>,
) -> Elaborator<'tcx> {
    let obligations = predicates
        .map(|predicate| {
            predicate_obligation(predicate, ty::ParamEnv::empty(), ObligationCause::dummy())
        })
        .collect();
    elaborate_obligations(tcx, obligations)
}

pub fn elaborate_obligations<'tcx>(
    tcx: TyCtxt<'tcx>,
    mut obligations: Vec<PredicateObligation<'tcx>>,
) -> Elaborator<'tcx> {
    let mut visited = PredicateSet::new(tcx);
    obligations.retain(|obligation| visited.insert(obligation.predicate));
    Elaborator { stack: obligations, visited }
}

fn predicate_obligation<'tcx>(
    predicate: ty::Predicate<'tcx>,
    param_env: ty::ParamEnv<'tcx>,
    cause: ObligationCause<'tcx>,
) -> PredicateObligation<'tcx> {
    Obligation { cause, param_env, recursion_depth: 0, predicate }
}

impl Elaborator<'tcx> {
    pub fn filter_to_traits(self) -> FilterToTraits<Self> {
        FilterToTraits::new(self)
    }

    fn elaborate(&mut self, obligation: &PredicateObligation<'tcx>) {
        let tcx = self.visited.tcx;

        let bound_predicate = obligation.predicate.bound_atom();
        match bound_predicate.skip_binder() {
            ty::PredicateAtom::Trait(data, _) => {
                // Get predicates declared on the trait.
                let predicates = tcx.super_predicates_of(data.def_id());

                let obligations = predicates.predicates.iter().map(|&(pred, _)| {
                    predicate_obligation(
                        pred.subst_supertrait(tcx, &bound_predicate.rebind(data.trait_ref)),
                        obligation.param_env,
                        obligation.cause.clone(),
                    )
                });
                debug!("super_predicates: data={:?}", data);

                // Only keep those bounds that we haven't already seen.
                // This is necessary to prevent infinite recursion in some
                // cases. One common case is when people define
                // `trait Sized: Sized { }` rather than `trait Sized { }`.
                let visited = &mut self.visited;
                let obligations = obligations.filter(|o| visited.insert(o.predicate));

                self.stack.extend(obligations);
            }
            ty::PredicateAtom::WellFormed(..) => {
                // Currently, we do not elaborate WF predicates,
                // although we easily could.
            }
            ty::PredicateAtom::ObjectSafe(..) => {
                // Currently, we do not elaborate object-safe
                // predicates.
            }
            ty::PredicateAtom::Subtype(..) => {
                // Currently, we do not "elaborate" predicates like `X <: Y`,
                // though conceivably we might.
            }
            ty::PredicateAtom::Projection(..) => {
                // Nothing to elaborate in a projection predicate.
            }
            ty::PredicateAtom::ClosureKind(..) => {
                // Nothing to elaborate when waiting for a closure's kind to be inferred.
            }
            ty::PredicateAtom::ConstEvaluatable(..) => {
                // Currently, we do not elaborate const-evaluatable
                // predicates.
            }
            ty::PredicateAtom::ConstEquate(..) => {
                // Currently, we do not elaborate const-equate
                // predicates.
            }
            ty::PredicateAtom::RegionOutlives(..) => {
                // Nothing to elaborate from `'a: 'b`.
            }
            ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(ty_max, r_min)) => {
                // We know that `T: 'a` for some type `T`. We can
                // often elaborate this. For example, if we know that
                // `[U]: 'a`, that implies that `U: 'a`. Similarly, if
                // we know `&'a U: 'b`, then we know that `'a: 'b` and
                // `U: 'b`.
                //
                // We can basically ignore bound regions here. So for
                // example `for<'c> Foo<'a,'c>: 'b` can be elaborated to
                // `'a: 'b`.

                // Ignore `for<'a> T: 'a` -- we might in the future
                // consider this as evidence that `T: 'static`, but
                // I'm a bit wary of such constructions and so for now
                // I want to be conservative. --nmatsakis
                if r_min.is_late_bound() {
                    return;
                }

                let visited = &mut self.visited;
                let mut components = smallvec![];
                tcx.push_outlives_components(ty_max, &mut components);
                self.stack.extend(
                    components
                        .into_iter()
                        .filter_map(|component| match component {
                            Component::Region(r) => {
                                if r.is_late_bound() {
                                    None
                                } else {
                                    Some(ty::PredicateAtom::RegionOutlives(ty::OutlivesPredicate(
                                        r, r_min,
                                    )))
                                }
                            }

                            Component::Param(p) => {
                                let ty = tcx.mk_ty_param(p.index, p.name);
                                Some(ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(
                                    ty, r_min,
                                )))
                            }

                            Component::UnresolvedInferenceVariable(_) => None,

                            Component::Projection(_) | Component::EscapingProjection(_) => {
                                // We can probably do more here. This
                                // corresponds to a case like `<T as
                                // Foo<'a>>::U: 'b`.
                                None
                            }
                        })
                        .map(|predicate_kind| predicate_kind.to_predicate(tcx))
                        .filter(|&predicate| visited.insert(predicate))
                        .map(|predicate| {
                            predicate_obligation(
                                predicate,
                                obligation.param_env,
                                obligation.cause.clone(),
                            )
                        }),
                );
            }
            ty::PredicateAtom::TypeWellFormedFromEnv(..) => {
                // Nothing to elaborate
            }
        }
    }
}

impl Iterator for Elaborator<'tcx> {
    type Item = PredicateObligation<'tcx>;

    fn size_hint(&self) -> (usize, Option<usize>) {
        (self.stack.len(), None)
    }

    fn next(&mut self) -> Option<Self::Item> {
        // Extract next item from top-most stack frame, if any.
        if let Some(obligation) = self.stack.pop() {
            self.elaborate(&obligation);
            Some(obligation)
        } else {
            None
        }
    }
}

///////////////////////////////////////////////////////////////////////////
// Supertrait iterator
///////////////////////////////////////////////////////////////////////////

pub type Supertraits<'tcx> = FilterToTraits<Elaborator<'tcx>>;

pub fn supertraits<'tcx>(
    tcx: TyCtxt<'tcx>,
    trait_ref: ty::PolyTraitRef<'tcx>,
) -> Supertraits<'tcx> {
    elaborate_trait_ref(tcx, trait_ref).filter_to_traits()
}

pub fn transitive_bounds<'tcx>(
    tcx: TyCtxt<'tcx>,
    bounds: impl Iterator<Item = ty::PolyTraitRef<'tcx>>,
) -> Supertraits<'tcx> {
    elaborate_trait_refs(tcx, bounds).filter_to_traits()
}

/// A specialized variant of `elaborate_trait_refs` that only elaborates trait references that may
/// define the given associated type `assoc_name`. It uses the
/// `super_predicates_that_define_assoc_type` query to avoid enumerating super-predicates that
/// aren't related to `assoc_item`.  This is used when resolving types like `Self::Item` or
/// `T::Item` and helps to avoid cycle errors (see e.g. #35237).
pub fn transitive_bounds_that_define_assoc_type<'tcx>(
    tcx: TyCtxt<'tcx>,
    bounds: impl Iterator<Item = ty::PolyTraitRef<'tcx>>,
    assoc_name: Ident,
) -> FxIndexSet<ty::PolyTraitRef<'tcx>> {
    let mut stack: Vec<_> = bounds.collect();
    let mut trait_refs = FxIndexSet::default();

    while let Some(trait_ref) = stack.pop() {
        if trait_refs.insert(trait_ref) {
            let super_predicates =
                tcx.super_predicates_that_define_assoc_type((trait_ref.def_id(), Some(assoc_name)));
            for (super_predicate, _) in super_predicates.predicates {
                let bound_predicate = super_predicate.bound_atom();
                let subst_predicate = super_predicate
                    .subst_supertrait(tcx, &bound_predicate.rebind(trait_ref.skip_binder()));
                if let Some(binder) = subst_predicate.to_opt_poly_trait_ref() {
                    stack.push(binder.value);
                }
            }
        }
    }

    trait_refs
}

///////////////////////////////////////////////////////////////////////////
// Other
///////////////////////////////////////////////////////////////////////////

/// A filter around an iterator of predicates that makes it yield up
/// just trait references.
pub struct FilterToTraits<I> {
    base_iterator: I,
}

impl<I> FilterToTraits<I> {
    fn new(base: I) -> FilterToTraits<I> {
        FilterToTraits { base_iterator: base }
    }
}

impl<'tcx, I: Iterator<Item = PredicateObligation<'tcx>>> Iterator for FilterToTraits<I> {
    type Item = ty::PolyTraitRef<'tcx>;

    fn next(&mut self) -> Option<ty::PolyTraitRef<'tcx>> {
        while let Some(obligation) = self.base_iterator.next() {
            if let Some(data) = obligation.predicate.to_opt_poly_trait_ref() {
                return Some(data.value);
            }
        }
        None
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let (_, upper) = self.base_iterator.size_hint();
        (0, upper)
    }
}
<|endoftext|>


<commit_before>mod screen;
mod main_menu_screen;
mod battle_screen;

pub use self::screen::*;
pub use self::main_menu_screen::*;
pub use self::battle_screen::*;
<commit_msg>pub mod screen<commit_after>pub mod screen;
mod main_menu_screen;
mod battle_screen;

pub use self::screen::*;
pub use self::main_menu_screen::*;
pub use self::battle_screen::*;
<|endoftext|>


<commit_before>#[crate_id = "sobol#0.1"];
#[comment = "Sobol indices evaluator"];
#[license = "MIT"];

extern crate extra;
extern crate collections;

use params::{Params, Float, Range};
use model::{Model,Gompertz};
use std::vec;
mod model;
mod params;
mod workers;

fn sample(pr: &Params, num_real : uint) -> ~[Params] {
    let mut samples : ~[Params] = ~[];
    for _ in range(0, num_real) {
        samples.push(pr.realize());
    }
    samples
}
#[test]
fn test_sample() {
    let mut ranges=Params::new();
    ranges.insert("alpha", Range(0.0, 1.0));
    let samples=sample(&ranges, 10);

    assert_eq!(samples.len(), 10);
    for pp in samples.iter() {
        let value=pp.get_float("alpha");
        assert!((value>=0.0)&&(value<=1.0));
    }
}

#[allow(dead_code)]
fn eval_model(pr: &Params) -> f64 {
    let model : Gompertz = Model::setup(pr);
    model.run(pr.get_float("tmax"))
}

fn get_couples(n : uint) -> ~[(uint, uint)] {
    let mut res : ~[(uint, uint)]=~[];
    for i in range(0, n) {
        for j in range(i, n) {
            if i!=j {
                res.push( (i,j));
            }
        }
    }
    res
}

#[test]
fn test_get_couples() {
    let res=get_couples(3);

    assert_eq!(res[0], (0,1));
    assert_eq!(res[1], (0,2));
    assert_eq!(res[2], (1,2));
}

// First order Sobol indices
#[allow(dead_code)]
fn calc_sobol_1(pr: &Params, nsamp : uint) -> collections::HashMap<~str, f64> {
    let samples_1=sample(pr, nsamp);
    let samples_2=sample(pr, nsamp);

    let big_one : ~[Params] = vec::append(samples_1.clone(), samples_2);

    // Average and deviation computaion
    let resvec=big_one.map(eval_model);
    let avg=resvec.iter().fold(0.0, |acc, &item| acc+item)/(resvec.len() as f64);
    let var=resvec.iter().fold(0.0, |acc, &item| acc+item*item)/(resvec.len() as f64)-avg*avg;

    let mut Sp: collections::HashMap<~str, f64> = collections::HashMap::new();
    let vkeys=pr.varying_keys();
    for k in vkeys.iter() {
        let mut sump=0.0f64;
        for snum in range(0, nsamp) {
            let mut new_p=samples_2[snum].clone();
            new_p.set(k.to_owned(),Float(samples_1[snum].get_float(k.to_owned())));

            sump=sump+eval_model(&new_p)*eval_model(&samples_1[snum]);
        }
        let Up=sump/(nsamp as f64);
        Sp.insert(k.to_owned(), (Up-avg*avg)/var);
    }

    Sp
}

// Second order Sobol indices
#[allow(dead_code)]
fn calc_sobol_2(pr: &Params, sob1 : &collections::HashMap<~str, f64>, nsamp : uint) -> ~[(~str, ~str, f64)] {
    let samples_1=sample(pr, nsamp);
    let samples_2=sample(pr, nsamp);
    let keys=pr.varying_keys();
    let couples=get_couples(keys.len());

    let big_one : ~[Params] = vec::append(samples_1.clone(), samples_2);

    // Average and deviation computaion
    let resvec=big_one.map(eval_model);
    let avg=resvec.iter().fold(0.0, |acc, &item| acc+item)/(resvec.len() as f64);
    let var=resvec.iter().fold(0.0, |acc, &item| acc+item*item)/(resvec.len() as f64)-avg*avg;

    let mut Spr : ~[(~str, ~str, f64)]=~[];

    for &cpl in couples.iter() {
        let (i,j) = cpl;
        let ref key1=keys[i]; let ref key2=keys[j];
        let mut sump=0.0f64;
        for snum in range(0, nsamp) {
            let mut new_p=samples_2[snum].clone();
            new_p.set(key1.to_owned(),Float(samples_1[snum].get_float(key1.to_owned())));
            new_p.set(key2.to_owned(),Float(samples_1[snum].get_float(key2.to_owned())));

            sump=sump+eval_model(&new_p)*eval_model(&samples_1[snum]);
        }
        let Upr=sump/(nsamp as f64);
        let Vp=*sob1.find_equiv(key1).unwrap();
        let Vr=*sob1.find_equiv(key2).unwrap();
        Spr.push((key1.to_owned(), key2.to_owned(), (Upr-avg*avg-Vr-Vp)/var));
    }

    Spr
}

// Total Sobol indices
fn calc_sobol_total(pr: &Params, nsamp: uint) -> collections::HashMap<~str, f64> {
    let samples_1=sample(pr, nsamp);
    let samples_2=sample(pr, nsamp);

    let big_one : ~[Params] = vec::append(samples_1.clone(), samples_2);

    // Average and deviation computaion
    let resvec=big_one.map(eval_model);
    let avg=resvec.iter().fold(0.0, |acc, &item| acc+item)/(resvec.len() as f64);
    let var=resvec.iter().fold(0.0, |acc, &item| acc+item*item)/(resvec.len() as f64)-avg*avg;

    let mut Sp: collections::HashMap<~str, f64> = collections::HashMap::new();
    let vkeys=pr.varying_keys();
    for k in vkeys.iter() {
        let mut sump=0.0f64;
        for snum in range(0, nsamp) {
            let mut new_p=samples_1[snum].clone();
            new_p.set(k.to_owned(),Float(samples_2[snum].get_float(k.slice_from(0))));

            sump=sump+eval_model(&new_p)*eval_model(&samples_1[snum]);
        }
        let Up=sump/(nsamp as f64);
        Sp.insert(k.to_owned(), 1.0-(Up-avg*avg)/var);
    }

    Sp
}

//
// Entry point
//
#[allow(dead_code)]
fn main() {
  let mut ranges=Params::new();
  ranges.insert("alpha", Range(0.01, 1.0)); ranges.insert("K", Range(0.01, 1.0));
  ranges.insert("C0", Range(0.001, 0.01)); ranges.insert("tmax", Float(10f64));

  let samples=sample(&ranges,5000);
  let resvec=samples.map(eval_model);

  let avg=resvec.iter().fold(0.0, |acc, &item| acc+item)/(resvec.len() as f64);
  let var=resvec.iter().fold(0.0, |acc, &item| acc+item*item)/(resvec.len() as f64)-avg*avg;

  println!("Mean value = {}, Standard Deviation = {}\n", avg, var);

  println!("First order Sobol indices");
  let sob_1=calc_sobol_1(&ranges,15000);
  for (k, v) in sob_1.iter() {
    println!("\t{:s} = {:f}", *k, *v);
  }

  println!("\nSecond order Sobol indices");
  let sob_2=calc_sobol_2(&ranges, &sob_1, 7500);
  for vv in sob_2.iter() {
    let (ref k1,ref k2,v) = *vv;
    println!("\t{:s} x {:s} = {:f}", *k1, *k2, v);
  }

  println!("\nTotal Sobol indices");
  let sob_t=calc_sobol_total(&ranges, 15000);
  for (k, v) in sob_t.iter() {
    println!("\t{:s} = {:f}", *k, *v);
  }

}

<commit_msg>Remove workers mod<commit_after>#[crate_id = "sobol#0.1"];
#[comment = "Sobol indices evaluator"];
#[license = "MIT"];

extern crate extra;
extern crate collections;

use params::{Params, Float, Range};
use model::{Model,Gompertz};
use std::vec;
mod model;
mod params;

fn sample(pr: &Params, num_real : uint) -> ~[Params] {
    let mut samples : ~[Params] = ~[];
    for _ in range(0, num_real) {
        samples.push(pr.realize());
    }
    samples
}
#[test]
fn test_sample() {
    let mut ranges=Params::new();
    ranges.insert("alpha", Range(0.0, 1.0));
    let samples=sample(&ranges, 10);

    assert_eq!(samples.len(), 10);
    for pp in samples.iter() {
        let value=pp.get_float("alpha");
        assert!((value>=0.0)&&(value<=1.0));
    }
}

#[allow(dead_code)]
fn eval_model(pr: &Params) -> f64 {
    let model : Gompertz = Model::setup(pr);
    model.run(pr.get_float("tmax"))
}

fn get_couples(n : uint) -> ~[(uint, uint)] {
    let mut res : ~[(uint, uint)]=~[];
    for i in range(0, n) {
        for j in range(i, n) {
            if i!=j {
                res.push( (i,j));
            }
        }
    }
    res
}

#[test]
fn test_get_couples() {
    let res=get_couples(3);

    assert_eq!(res[0], (0,1));
    assert_eq!(res[1], (0,2));
    assert_eq!(res[2], (1,2));
}

// First order Sobol indices
#[allow(dead_code)]
fn calc_sobol_1(pr: &Params, nsamp : uint) -> collections::HashMap<~str, f64> {
    let samples_1=sample(pr, nsamp);
    let samples_2=sample(pr, nsamp);

    let big_one : ~[Params] = vec::append(samples_1.clone(), samples_2);

    // Average and deviation computaion
    let resvec=big_one.map(eval_model);
    let avg=resvec.iter().fold(0.0, |acc, &item| acc+item)/(resvec.len() as f64);
    let var=resvec.iter().fold(0.0, |acc, &item| acc+item*item)/(resvec.len() as f64)-avg*avg;

    let mut Sp: collections::HashMap<~str, f64> = collections::HashMap::new();
    let vkeys=pr.varying_keys();
    for k in vkeys.iter() {
        let mut sump=0.0f64;
        for snum in range(0, nsamp) {
            let mut new_p=samples_2[snum].clone();
            new_p.set(k.to_owned(),Float(samples_1[snum].get_float(k.to_owned())));

            sump=sump+eval_model(&new_p)*eval_model(&samples_1[snum]);
        }
        let Up=sump/(nsamp as f64);
        Sp.insert(k.to_owned(), (Up-avg*avg)/var);
    }

    Sp
}

// Second order Sobol indices
#[allow(dead_code)]
fn calc_sobol_2(pr: &Params, sob1 : &collections::HashMap<~str, f64>, nsamp : uint) -> ~[(~str, ~str, f64)] {
    let samples_1=sample(pr, nsamp);
    let samples_2=sample(pr, nsamp);
    let keys=pr.varying_keys();
    let couples=get_couples(keys.len());

    let big_one : ~[Params] = vec::append(samples_1.clone(), samples_2);

    // Average and deviation computaion
    let resvec=big_one.map(eval_model);
    let avg=resvec.iter().fold(0.0, |acc, &item| acc+item)/(resvec.len() as f64);
    let var=resvec.iter().fold(0.0, |acc, &item| acc+item*item)/(resvec.len() as f64)-avg*avg;

    let mut Spr : ~[(~str, ~str, f64)]=~[];

    for &cpl in couples.iter() {
        let (i,j) = cpl;
        let ref key1=keys[i]; let ref key2=keys[j];
        let mut sump=0.0f64;
        for snum in range(0, nsamp) {
            let mut new_p=samples_2[snum].clone();
            new_p.set(key1.to_owned(),Float(samples_1[snum].get_float(key1.to_owned())));
            new_p.set(key2.to_owned(),Float(samples_1[snum].get_float(key2.to_owned())));

            sump=sump+eval_model(&new_p)*eval_model(&samples_1[snum]);
        }
        let Upr=sump/(nsamp as f64);
        let Vp=*sob1.find_equiv(key1).unwrap();
        let Vr=*sob1.find_equiv(key2).unwrap();
        Spr.push((key1.to_owned(), key2.to_owned(), (Upr-avg*avg-Vr-Vp)/var));
    }

    Spr
}

// Total Sobol indices
fn calc_sobol_total(pr: &Params, nsamp: uint) -> collections::HashMap<~str, f64> {
    let samples_1=sample(pr, nsamp);
    let samples_2=sample(pr, nsamp);

    let big_one : ~[Params] = vec::append(samples_1.clone(), samples_2);

    // Average and deviation computaion
    let resvec=big_one.map(eval_model);
    let avg=resvec.iter().fold(0.0, |acc, &item| acc+item)/(resvec.len() as f64);
    let var=resvec.iter().fold(0.0, |acc, &item| acc+item*item)/(resvec.len() as f64)-avg*avg;

    let mut Sp: collections::HashMap<~str, f64> = collections::HashMap::new();
    let vkeys=pr.varying_keys();
    for k in vkeys.iter() {
        let mut sump=0.0f64;
        for snum in range(0, nsamp) {
            let mut new_p=samples_1[snum].clone();
            new_p.set(k.to_owned(),Float(samples_2[snum].get_float(k.slice_from(0))));

            sump=sump+eval_model(&new_p)*eval_model(&samples_1[snum]);
        }
        let Up=sump/(nsamp as f64);
        Sp.insert(k.to_owned(), 1.0-(Up-avg*avg)/var);
    }

    Sp
}

//
// Entry point
//
#[allow(dead_code)]
fn main() {
  let mut ranges=Params::new();
  ranges.insert("alpha", Range(0.01, 1.0)); ranges.insert("K", Range(0.01, 1.0));
  ranges.insert("C0", Range(0.001, 0.01)); ranges.insert("tmax", Float(10f64));

  let samples=sample(&ranges,5000);
  let resvec=samples.map(eval_model);

  let avg=resvec.iter().fold(0.0, |acc, &item| acc+item)/(resvec.len() as f64);
  let var=resvec.iter().fold(0.0, |acc, &item| acc+item*item)/(resvec.len() as f64)-avg*avg;

  println!("Mean value = {}, Standard Deviation = {}\n", avg, var);

  println!("First order Sobol indices");
  let sob_1=calc_sobol_1(&ranges,15000);
  for (k, v) in sob_1.iter() {
    println!("\t{:s} = {:f}", *k, *v);
  }

  println!("\nSecond order Sobol indices");
  let sob_2=calc_sobol_2(&ranges, &sob_1, 7500);
  for vv in sob_2.iter() {
    let (ref k1,ref k2,v) = *vv;
    println!("\t{:s} x {:s} = {:f}", *k1, *k2, v);
  }

  println!("\nTotal Sobol indices");
  let sob_t=calc_sobol_total(&ranges, 15000);
  for (k, v) in sob_t.iter() {
    println!("\t{:s} = {:f}", *k, *v);
  }

}

<|endoftext|>


<commit_before>use std::f64;
use error::StatsError;

pub trait Statistics {
    /// Evaluates the sample mean, an estimate of the population
    /// mean.
    ///
    /// # Remarks
    ///
    /// Returns `f64::NAN` if data is empty or an entry is `f64::NAN`
    fn mean(&self) -> f64;

    /// Evaluates the geometric mean of the data
    ///
    /// # Remarks
    ///
    /// Returns `f64::NAN` if data is empty or an entry is `f64::NAN`
    fn geometric_mean(&self) -> f64;

    /// Evaluates the harmonic mean of the data
    ///
    /// # Remarks
    ///
    /// Returns `f64::NAN` if data is empty or an entry is `f64::NAN`
    fn harmonic_mean(&self) -> f64;

    /// Estimates the unbiased population variance from the provided samples
    ///
    /// # Remarks
    ///
    /// On a dataset of size `N`, `N-1` is used as a normalizer (Bessel's correction).
    ///
    /// Returns `f64::NAN` if data has less than two entries or if any entry is `f64::NAN`
    fn variance(&self) -> f64;

    /// Evaluates the population variance from a full population.
    ///
    /// # Remarks
    ///
    /// On a dataset of size `N`, `N` is used as a normalizer and would thus
    /// be biased if applied to a subset
    ///
    /// Returns `f64::NAN` if data is empty or an entry is `f64::NAN`
    fn population_variance(&self) -> f64;

    /// Estimates the unbiased population standard deviation from the provided samples
    ///
    /// # Remarks
    ///
    /// On a dataset of size `N`, `N-1` is used as a normalizer (Bessel's correction).
    ///
    /// Returns `f64::NAN` if data has less than two entries or if any entry is `f64::NAN`
    fn std_dev(&self) -> f64;

    /// Evaluates the population standard deviation from a full population.
    ///
    /// # Remarks
    ///
    /// On a dataset of size `N`, `N` is used as a normalizer and would thus
    /// be biased if applied to a subset
    ///
    /// Returns `f64::NAN` if data is empty or an entry is `f64::NAN`
    fn population_std_dev(&self) -> f64;

    /// Estimates the unbiased population covariance between the two provided samples
    ///
    /// # Remarks
    ///
    /// On a dataset of size `N`, `N-1` is used as a normalizer (Bessel's correction).
    ///
    /// Returns `f64::NAN` if data has less than two entries or if any entry is `f64::NAN`
    ///
    /// # Panics
    ///
    /// If the two sample containers do not contain the same number of elements
    fn covariance(&self, other: &Self) -> f64;
}

impl Statistics for [f64] {
    fn mean(&self) -> f64 {
        if self.len() == 0 {
            return f64::NAN;
        }

        let mut m = 0.0;
        self.iter()
            .fold(0.0, |acc, x| {
                m += 1.0;
                acc + (x - acc) / m
            })
    }

    fn geometric_mean(&self) -> f64 {
        if self.len() == 0 {
            return f64::NAN;
        }

        (self.iter().fold(0.0, |acc, x| acc + x.ln()) / self.len() as f64).exp()
    }

    fn harmonic_mean(&self) -> f64 {
        if self.len() == 0 {
            return f64::NAN;
        }

        self.len() as f64 / self.iter().fold(0.0, |acc, x| acc + 1.0 / x)
    }

    fn variance(&self) -> f64 {
        if self.len() <= 1 {
            return f64::NAN;
        }

        unsafe {
            let mut var = 0.0;
            let mut t = *self.get_unchecked(0);
            for i in 1..self.len() {
                t += *self.get_unchecked(i);
                let diff = (i as f64 + 1.0) * *self.get_unchecked(i) - t;
                var += (diff * diff) / ((i + 1) * i) as f64;
            }
            var / (self.len() - 1) as f64
        }
    }

    fn population_variance(&self) -> f64 {
        if self.len() == 0 {
            return f64::NAN;
        }

        unsafe {
            let mut var = 0.0;
            let mut t = *self.get_unchecked(0);
            for i in 1..self.len() {
                t += *self.get_unchecked(i);
                let diff = (i as f64 + 1.0) * *self.get_unchecked(i) - t;
                var += (diff * diff) / ((i + 1) * i) as f64
            }
            var / self.len() as f64
        }
    }

    fn std_dev(&self) -> f64 {
        self.variance().sqrt()
    }

    fn population_std_dev(&self) -> f64 {
        self.population_variance().sqrt()
    }

    fn covariance(&self, other: &[f64]) -> f64 {
        let n1 = self.len();
        let n2 = other.len();
        assert!(n1 == n2, format!("{}", StatsError::VectorsSameLength));
        if n1 <= 1 {
            return f64::NAN;
        }

        let mean1 = self.mean();
        let mean2 = other.mean();
        self.iter()
            .zip(other.iter())
            .fold(0.0, |acc, x| acc + (x.0 - mean1) * (x.1 - mean2)) / (n1 - 1) as f64
    }
}
<commit_msg>continued implementation of array statistics<commit_after>use std::f64;
use error::StatsError;

pub trait Statistics {
    /// Returns the minimum value in the data
    ///
    /// # Rermarks
    ///
    /// Returns `f64::NAN` if data is empty or an entry is `f64::NAN`
    fn min(&self) -> f64;

    /// Returns the maximum value in the data
    ///
    /// # Rermarks
    ///
    /// Returns `f64::NAN` if data is empty or an entry is `f64::NAN`
    fn max(&self) -> f64;

    /// Returns the minimum absolute value in the data
    ///
    /// # Rermarks
    ///
    /// Returns `f64::NAN` if data is empty or an entry is `f64::NAN`
    fn abs_min(&self) -> f64;

    /// Returns the maximum absolute value in the data
    ///
    /// # Rermarks
    ///
    /// Returns `f64::NAN` if data is empty or an entry is `f64::NAN`
    fn abs_max(&self) -> f64;

    /// Evaluates the sample mean, an estimate of the population
    /// mean.
    ///
    /// # Remarks
    ///
    /// Returns `f64::NAN` if data is empty or an entry is `f64::NAN`
    fn mean(&self) -> f64;

    /// Evaluates the geometric mean of the data
    ///
    /// # Remarks
    ///
    /// Returns `f64::NAN` if data is empty or an entry is `f64::NAN`
    fn geometric_mean(&self) -> f64;

    /// Evaluates the harmonic mean of the data
    ///
    /// # Remarks
    ///
    /// Returns `f64::NAN` if data is empty or an entry is `f64::NAN`
    fn harmonic_mean(&self) -> f64;

    /// Estimates the unbiased population variance from the provided samples
    ///
    /// # Remarks
    ///
    /// On a dataset of size `N`, `N-1` is used as a normalizer (Bessel's correction).
    ///
    /// Returns `f64::NAN` if data has less than two entries or if any entry is `f64::NAN`
    fn variance(&self) -> f64;

    /// Evaluates the population variance from a full population.
    ///
    /// # Remarks
    ///
    /// On a dataset of size `N`, `N` is used as a normalizer and would thus
    /// be biased if applied to a subset
    ///
    /// Returns `f64::NAN` if data is empty or an entry is `f64::NAN`
    fn population_variance(&self) -> f64;

    /// Estimates the unbiased population standard deviation from the provided samples
    ///
    /// # Remarks
    ///
    /// On a dataset of size `N`, `N-1` is used as a normalizer (Bessel's correction).
    ///
    /// Returns `f64::NAN` if data has less than two entries or if any entry is `f64::NAN`
    fn std_dev(&self) -> f64;

    /// Evaluates the population standard deviation from a full population.
    ///
    /// # Remarks
    ///
    /// On a dataset of size `N`, `N` is used as a normalizer and would thus
    /// be biased if applied to a subset
    ///
    /// Returns `f64::NAN` if data is empty or an entry is `f64::NAN`
    fn population_std_dev(&self) -> f64;

    /// Estimates the unbiased population covariance between the two provided samples
    ///
    /// # Remarks
    ///
    /// On a dataset of size `N`, `N-1` is used as a normalizer (Bessel's correction).
    ///
    /// Returns `f64::NAN` if data has less than two entries or if any entry is `f64::NAN`
    ///
    /// # Panics
    ///
    /// If the two sample containers do not contain the same number of elements
    fn covariance(&self, other: &Self) -> f64;

    /// Evaluates the population covariance between the two provider populations
    ///
    /// # Remarks
    ///
    /// On a dataset of size `N`, `N` is used as a normalizer and would thus be
    /// biased if applied to a subset
    ///
    /// Returns `f64::NAN` if data is empty or any entry is `f64::NAN`
    ///
    /// # Panics
    ///
    /// If the two sample containers do not contain the same number of elements
    fn population_covariance(&self, other: &Self) -> f64;

    /// Estimates the quadratic mean (Root Mean Square) of the data
    ///
    /// # Remarks
    ///
    /// Returns `f64::NAN` if data is empty or any entry is `f64::NAN`
    fn quadratic_mean(&self) -> f64;

    /// Returns the order statistic `(order 1..N)` from the data
    ///
    /// # Remarks
    ///
    /// No sorting is assumed. Order must be one-based (between `1` and `N` inclusive)
    /// Returns `f64::NAN` if order is outside the viable range or data is empty.
    fn order_statistic(&mut self, order: usize) -> f64;
}

impl Statistics for [f64] {
    fn min(&self) -> f64 {
        if self.len() == 0 {
            return f64::NAN;
        }

        self.iter().fold(f64::INFINITY, |acc, &x| if x < acc || x.is_nan() { x } else { acc })
    }

    fn max(&self) -> f64 {
        if self.len() == 0 {
            return f64::NAN;
        }

        self.iter().fold(f64::NEG_INFINITY, |acc, &x| if x > acc || x.is_nan() { x } else { acc })
    }

    fn abs_min(&self) -> f64 {
        if self.len() == 0 {
            return f64::NAN;
        }

        self.iter()
            .map(|x| x.abs())
            .fold(f64::INFINITY, |acc, x| if x < acc || x.is_nan() { x } else { acc })
    }

    fn abs_max(&self) -> f64 {
        if self.len() == 0 {
            return f64::NAN;
        }

        self.iter()
            .map(|x| x.abs())
            .fold(f64::NEG_INFINITY, |acc, x| if x > acc || x.is_nan() { x } else { acc })
    }

    fn mean(&self) -> f64 {
        if self.len() == 0 {
            return f64::NAN;
        }

        let mut m = 0.0;
        self.iter()
            .fold(0.0, |acc, &x| {
                m += 1.0;
                acc + (x - acc) / m
            })
    }

    fn geometric_mean(&self) -> f64 {
        if self.len() == 0 {
            return f64::NAN;
        }

        (self.iter().fold(0.0, |acc, &x| acc + x.ln()) / self.len() as f64).exp()
    }

    fn harmonic_mean(&self) -> f64 {
        if self.len() == 0 {
            return f64::NAN;
        }

        self.len() as f64 / self.iter().fold(0.0, |acc, &x| acc + 1.0 / x)
    }

    fn variance(&self) -> f64 {
        if self.len() <= 1 {
            return f64::NAN;
        }

        unsafe {
            let mut var = 0.0;
            let mut t = *self.get_unchecked(0);
            for i in 1..self.len() {
                t += *self.get_unchecked(i);
                let diff = (i as f64 + 1.0) * *self.get_unchecked(i) - t;
                var += (diff * diff) / ((i + 1) * i) as f64;
            }
            var / (self.len() - 1) as f64
        }
    }

    fn population_variance(&self) -> f64 {
        if self.len() == 0 {
            return f64::NAN;
        }

        unsafe {
            let mut var = 0.0;
            let mut t = *self.get_unchecked(0);
            for i in 1..self.len() {
                t += *self.get_unchecked(i);
                let diff = (i as f64 + 1.0) * *self.get_unchecked(i) - t;
                var += (diff * diff) / ((i + 1) * i) as f64
            }
            var / self.len() as f64
        }
    }

    fn std_dev(&self) -> f64 {
        self.variance().sqrt()
    }

    fn population_std_dev(&self) -> f64 {
        self.population_variance().sqrt()
    }

    fn covariance(&self, other: &[f64]) -> f64 {
        let n1 = self.len();
        let n2 = other.len();
        assert!(n1 == n2, format!("{}", StatsError::VectorsSameLength));
        if n1 <= 1 {
            return f64::NAN;
        }

        let mean1 = self.mean();
        let mean2 = other.mean();
        self.iter()
            .zip(other.iter())
            .fold(0.0, |acc, x| acc + (x.0 - mean1) * (x.1 - mean2)) / (n1 - 1) as f64
    }

    fn population_covariance(&self, other: &[f64]) -> f64 {
        let n1 = self.len();
        let n2 = other.len();
        assert!(n1 == n2, format!("{}", StatsError::VectorsSameLength));
        if n1 == 0 {
            return f64::NAN;
        }

        let mean1 = self.mean();
        let mean2 = other.mean();
        self.iter()
            .zip(other.iter())
            .fold(0.0, |acc, x| acc + (x.0 - mean1) * (x.1 - mean2)) / n1 as f64
    }

    fn quadratic_mean(&self) -> f64 {
        if self.len() == 0 {
            return f64::NAN;
        }

        let mut m = 0.0;
        self.iter()
            .fold(0.0, |acc, &x| {
                m += 1.0;
                acc + (x * x - acc) / m
            })
    }

    /// Returns the order statistic `(order 1..N)` from the data
    ///
    /// # Remarks
    ///
    /// No sorting is assumed. Order must be one-based (between `1` and `N` inclusive).
    /// Returns `f64::NAN` if order is outside the viable range or data is empty.
    ///
    /// **NOTE:** This method works inplace for arrays and may cause the array to be reordered
    fn order_statistic(&mut self, order: usize) -> f64 {
        let n = self.len();
        match order {
            1 => self.min(),
            _ if order == n => self.max(),
            _ if order < 1 || order > n => f64::NAN,
            _ => select_inplace(self, order - 1)
        }
    }
}

// Selection algorithm from Numerical Recipes
// See: https://en.wikipedia.org/wiki/Selection_algorithm
fn select_inplace(arr: &mut [f64], rank: usize) -> f64 {
    if rank == 0 {
        return arr.min();
    }
    if rank > arr.len() - 1 {
        return arr.max();
    }

    unsafe {
        let mut low = 0;
        let mut high = arr.len() - 1;
        loop {
            if high <= low + 1 {
                if high == low + 1 && *arr.get_unchecked(high) < *arr.get_unchecked(low) {
                    arr.swap(low, high)
                }
                return *arr.get_unchecked(rank);
            }

            let middle = (low + high) >> 1;
            arr.swap(middle, low + 1);

            if *arr.get_unchecked(low) > *arr.get_unchecked(high) {
                arr.swap(low, high);
            }
            if *arr.get_unchecked(low + 1) > *arr.get_unchecked(high) {
                arr.swap(low + 1, high);
            }
            if *arr.get_unchecked(low) > *arr.get_unchecked(low + 1) {
                arr.swap(low, low + 1);
            }

            let mut begin = low + 1;
            let mut end = high;
            let pivot = *arr.get_unchecked(begin);
            loop {
                loop {
                    begin += 1;
                    if *arr.get_unchecked(begin) < pivot {
                        break;
                    }
                }
                loop {
                    end -= 1;
                    if *arr.get_unchecked(end) > pivot {
                        break;
                    }
                }
                if end < begin {
                    break;
                }
                arr.swap(begin, end);
            }

            arr[low + 1] = *arr.get_unchecked(end);
            arr[end] = pivot;

            if end >= rank {
                high = end - 1;
            }
            if end <= rank {
                low = begin;
            }
        }
    }
}
<|endoftext|>


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

//! Core types

pub mod block;
pub mod hash;
pub mod transaction;
#[allow(dead_code)]
#[macro_use]

pub use self::block::{Block, BlockHeader};
pub use self::transaction::{Transaction, Input, Output, TxProof};
use self::hash::{Hash, Hashed, ZERO_HASH};
use ser::{Writeable, Writer, Error, ser_vec};

use time;

use std::fmt;
use std::cmp::Ordering;

use secp;
use secp::{Secp256k1, Signature, Message};
use secp::key::SecretKey;
use secp::pedersen::*;

use tiny_keccak::Keccak;

/// The block subsidy amount
pub const REWARD: u64 = 1_000_000_000;

/// Block interval, in seconds
pub const BLOCK_TIME_SEC: u8 = 15;

/// Cuckoo-cycle proof size (cycle length)
pub const PROOFSIZE: usize = 42;

/// Implemented by types that hold inputs and outputs including Pedersen
/// commitments. Handles the collection of the commitments as well as their
/// summing, taking potential explicit overages of fees into account.
pub trait Committed {
	/// Gathers commitments and sum them.
	fn sum_commitments(&self, secp: &Secp256k1) -> Result<Commitment, secp::Error> {
		// first, verify each range proof
		let ref outputs = self.outputs_committed();
		for output in *outputs {
			try!(output.verify_proof(secp))
		}

		// then gather the commitments
		let mut input_commits = filter_map_vec!(self.inputs_committed(), |inp| inp.commitment());
		let mut output_commits = filter_map_vec!(self.outputs_committed(), |out| out.commitment());

		// add the overage as input commitment if positive, as an output commitment if
		// negative
		let overage = self.overage();
		if overage != 0 {
			let over_commit = secp.commit_value(overage.abs() as u64).unwrap();
			if overage > 0 {
				input_commits.push(over_commit);
			} else {
				output_commits.push(over_commit);
			}
		}

		// sum all that stuff
		secp.commit_sum(input_commits, output_commits)
	}

	/// Vector of committed inputs to verify
	fn inputs_committed(&self) -> &Vec<Input>;

	/// Vector of committed inputs to verify
	fn outputs_committed(&self) -> &Vec<Output>;

	/// The overage amount expected over the commitments. Can be negative (a
	/// fee) or positive (a reward).
	fn overage(&self) -> i64;
}

/// Proof of work
#[derive(Copy)]
pub struct Proof(pub [u32; PROOFSIZE]);

impl fmt::Debug for Proof {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		try!(write!(f, "Cuckoo("));
		for (i, val) in self.0[..].iter().enumerate() {
			try!(write!(f, "{:x}", val));
			if i < PROOFSIZE - 1 {
				write!(f, " ");
			}
		}
		write!(f, ")")
	}
}
impl PartialOrd for Proof {
	fn partial_cmp(&self, other: &Proof) -> Option<Ordering> {
		self.0.partial_cmp(&other.0)
	}
}
impl PartialEq for Proof {
	fn eq(&self, other: &Proof) -> bool {
		self.0[..] == other.0[..]
	}
}
impl Eq for Proof {}
impl Clone for Proof {
	fn clone(&self) -> Proof {
		*self
	}
}

impl Proof {
	/// Builds a proof with all bytes zeroed out
	pub fn zero() -> Proof {
		Proof([0; 42])
	}
	/// Builds a proof from a vector of exactly PROOFSIZE (42) u32.
	pub fn from_vec(v: Vec<u32>) -> Proof {
		assert!(v.len() == PROOFSIZE);
		let mut p = [0; PROOFSIZE];
		for (n, elem) in v.iter().enumerate() {
			p[n] = *elem;
		}
		Proof(p)
	}
	/// Converts the proof to a vector of u64s
	pub fn to_u64s(&self) -> Vec<u64> {
		let mut nonces = Vec::with_capacity(PROOFSIZE);
		for n in self.0.iter() {
			nonces.push(*n as u64);
		}
		nonces
	}
	/// Converts the proof to a vector of u32s
	pub fn to_u32s(&self) -> Vec<u32> {
		self.0.to_vec()
	}
}

/// Two hashes that will get hashed together in a Merkle tree to build the next
/// level up.
struct HPair(Hash, Hash);
impl Hashed for HPair {
	fn bytes(&self) -> Vec<u8> {
		let mut data = Vec::with_capacity(64);
		data.extend_from_slice(self.0.to_slice());
		data.extend_from_slice(self.1.to_slice());
		return data;
	}
}
/// An iterator over hashes in a vector that pairs them to build a row in a
/// Merkle tree. If the vector has an odd number of hashes, it appends a zero hash
struct HPairIter(Vec<Hash>);
impl Iterator for HPairIter {
	type Item = HPair;

	fn next(&mut self) -> Option<HPair> {
		self.0.pop().map(|first| HPair(first, self.0.pop().unwrap_or(ZERO_HASH)))
	}
}
/// A row in a Merkle tree. Can be built from a vector of hashes. Calculates
/// the next level up, or can recursively go all the way up to its root.
struct MerkleRow(Vec<HPair>);
impl MerkleRow {
	fn new(hs: Vec<Hash>) -> MerkleRow {
		MerkleRow(HPairIter(hs).map(|hp| hp).collect())
	}
	fn up(&self) -> MerkleRow {
		MerkleRow::new(map_vec!(self.0, |hp| hp.hash()))
	}
	fn root(&self) -> Hash {
		if self.0.len() == 0 {
			vec![].hash()
		} else if self.0.len() == 1 {
			self.0[0].hash()
		} else {
			self.up().root()
		}
	}
}

#[cfg(test)]
mod test {
	use super::*;
	use super::hash::{Hash, Hashed, ZERO_HASH};
	use secp;
	use secp::Secp256k1;
	use secp::key::SecretKey;
	use rand::Rng;
	use rand::os::OsRng;

	fn new_secp() -> Secp256k1 {
		secp::Secp256k1::with_caps(secp::ContextFlag::Commit)
	}

	#[test]
	#[should_panic(expected = "InvalidSecretKey")]
	fn zero_commit() {
		// a transaction whose commitment sums to zero shouldn't validate
		let ref secp = new_secp();
		let mut rng = OsRng::new().unwrap();

		let skey = SecretKey::new(secp, &mut rng);
		let outh = ZERO_HASH;
		let tx = Transaction::new(vec![Input::OvertInput {
			                               output: outh,
			                               value: 10,
			                               blindkey: skey,
		                               }],
		                          vec![Output::OvertOutput {
			                               value: 1,
			                               blindkey: skey,
		                               }],
		                          9);
		// blinding should fail as signing with a zero r*G shouldn't work
		tx.blind(&secp).unwrap();
	}

	#[test]
	fn reward_empty_block() {
		let mut rng = OsRng::new().unwrap();
		let ref secp = new_secp();
		let skey = SecretKey::new(secp, &mut rng);

		let b = Block::new(BlockHeader::default(), vec![], skey).unwrap();
		b.compact().verify(&secp).unwrap();
	}

	#[test]
	fn reward_with_tx_block() {
		let mut rng = OsRng::new().unwrap();
		let ref secp = new_secp();
		let skey = SecretKey::new(secp, &mut rng);

		let tx1 = tx2i1o(secp, &mut rng);
		let mut btx1 = tx1.blind(&secp).unwrap();
		btx1.verify_sig(&secp).unwrap();

		let b = Block::new(BlockHeader::default(), vec![&mut btx1], skey).unwrap();
		b.compact().verify(&secp).unwrap();
	}

	#[test]
	fn simple_block() {
		let mut rng = OsRng::new().unwrap();
		let ref secp = new_secp();
		let skey = SecretKey::new(secp, &mut rng);

		let tx1 = tx2i1o(secp, &mut rng);
		let mut btx1 = tx1.blind(&secp).unwrap();
		btx1.verify_sig(&secp).unwrap();

		let tx2 = tx1i1o(secp, &mut rng);
		let mut btx2 = tx2.blind(&secp).unwrap();
		btx2.verify_sig(&secp).unwrap();

		let b = Block::new(BlockHeader::default(), vec![&mut btx1, &mut btx2], skey).unwrap();
		b.verify(&secp).unwrap();
	}

	// utility producing a transaction with 2 inputs and a single outputs
	pub fn tx2i1o<R: Rng>(secp: &Secp256k1, rng: &mut R) -> Transaction {
		let outh = ZERO_HASH;
		Transaction::new(vec![Input::OvertInput {
			                      output: outh,
			                      value: 10,
			                      blindkey: SecretKey::new(secp, rng),
		                      },
		                      Input::OvertInput {
			                      output: outh,
			                      value: 11,
			                      blindkey: SecretKey::new(secp, rng),
		                      }],
		                 vec![Output::OvertOutput {
			                      value: 20,
			                      blindkey: SecretKey::new(secp, rng),
		                      }],
		                 1)
	}

	// utility producing a transaction with a single input and output
	pub fn tx1i1o<R: Rng>(secp: &Secp256k1, rng: &mut R) -> Transaction {
		let outh = ZERO_HASH;
		Transaction::new(vec![Input::OvertInput {
			                      output: outh,
			                      value: 5,
			                      blindkey: SecretKey::new(secp, rng),
		                      }],
		                 vec![Output::OvertOutput {
			                      value: 4,
			                      blindkey: SecretKey::new(secp, rng),
		                      }],
		                 1)
	}
}
<commit_msg>added comment to avoid this vulnarability sneaking back<commit_after>// Copyright 2016 The Grin Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Core types

pub mod block;
pub mod hash;
pub mod transaction;
#[allow(dead_code)]
#[macro_use]

pub use self::block::{Block, BlockHeader};
pub use self::transaction::{Transaction, Input, Output, TxProof};
use self::hash::{Hash, Hashed, ZERO_HASH};
use ser::{Writeable, Writer, Error, ser_vec};

use time;

use std::fmt;
use std::cmp::Ordering;

use secp;
use secp::{Secp256k1, Signature, Message};
use secp::key::SecretKey;
use secp::pedersen::*;

use tiny_keccak::Keccak;

/// The block subsidy amount
pub const REWARD: u64 = 1_000_000_000;

/// Block interval, in seconds
pub const BLOCK_TIME_SEC: u8 = 15;

/// Cuckoo-cycle proof size (cycle length)
pub const PROOFSIZE: usize = 42;

/// Implemented by types that hold inputs and outputs including Pedersen
/// commitments. Handles the collection of the commitments as well as their
/// summing, taking potential explicit overages of fees into account.
pub trait Committed {
	/// Gathers commitments and sum them.
	fn sum_commitments(&self, secp: &Secp256k1) -> Result<Commitment, secp::Error> {
		// first, verify each range proof
		let ref outputs = self.outputs_committed();
		for output in *outputs {
			try!(output.verify_proof(secp))
		}

		// then gather the commitments
		let mut input_commits = filter_map_vec!(self.inputs_committed(), |inp| inp.commitment());
		let mut output_commits = filter_map_vec!(self.outputs_committed(), |out| out.commitment());

		// add the overage as input commitment if positive, as an output commitment if
		// negative
		let overage = self.overage();
		if overage != 0 {
			let over_commit = secp.commit_value(overage.abs() as u64).unwrap();
			if overage > 0 {
				input_commits.push(over_commit);
			} else {
				output_commits.push(over_commit);
			}
		}

		// sum all that stuff
		secp.commit_sum(input_commits, output_commits)
	}

	/// Vector of committed inputs to verify
	fn inputs_committed(&self) -> &Vec<Input>;

	/// Vector of committed inputs to verify
	fn outputs_committed(&self) -> &Vec<Output>;

	/// The overage amount expected over the commitments. Can be negative (a
	/// fee) or positive (a reward).
	fn overage(&self) -> i64;
}

/// Proof of work
#[derive(Copy)]
pub struct Proof(pub [u32; PROOFSIZE]);

impl fmt::Debug for Proof {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		try!(write!(f, "Cuckoo("));
		for (i, val) in self.0[..].iter().enumerate() {
			try!(write!(f, "{:x}", val));
			if i < PROOFSIZE - 1 {
				write!(f, " ");
			}
		}
		write!(f, ")")
	}
}
impl PartialOrd for Proof {
	fn partial_cmp(&self, other: &Proof) -> Option<Ordering> {
		self.0.partial_cmp(&other.0)
	}
}
impl PartialEq for Proof {
	fn eq(&self, other: &Proof) -> bool {
		self.0[..] == other.0[..]
	}
}
impl Eq for Proof {}
impl Clone for Proof {
	fn clone(&self) -> Proof {
		*self
	}
}

impl Proof {
	/// Builds a proof with all bytes zeroed out
	pub fn zero() -> Proof {
		Proof([0; 42])
	}
	/// Builds a proof from a vector of exactly PROOFSIZE (42) u32.
	pub fn from_vec(v: Vec<u32>) -> Proof {
		assert!(v.len() == PROOFSIZE);
		let mut p = [0; PROOFSIZE];
		for (n, elem) in v.iter().enumerate() {
			p[n] = *elem;
		}
		Proof(p)
	}
	/// Converts the proof to a vector of u64s
	pub fn to_u64s(&self) -> Vec<u64> {
		let mut nonces = Vec::with_capacity(PROOFSIZE);
		for n in self.0.iter() {
			nonces.push(*n as u64);
		}
		nonces
	}
	/// Converts the proof to a vector of u32s
	pub fn to_u32s(&self) -> Vec<u32> {
		self.0.to_vec()
	}
}

/// Two hashes that will get hashed together in a Merkle tree to build the next
/// level up.
struct HPair(Hash, Hash);
impl Hashed for HPair {
	fn bytes(&self) -> Vec<u8> {
		let mut data = Vec::with_capacity(64);
		data.extend_from_slice(self.0.to_slice());
		data.extend_from_slice(self.1.to_slice());
		return data;
	}
}
/// An iterator over hashes in a vector that pairs them to build a row in a
/// Merkle tree. If the vector has an odd number of hashes, it appends a zero hash
/// See https://bitcointalk.org/index.php?topic=102395.0 CVE-2012-2459 (block merkle calculation exploit)
/// for the argument against duplication of last hash
struct HPairIter(Vec<Hash>);
impl Iterator for HPairIter {
	type Item = HPair;

	fn next(&mut self) -> Option<HPair> {
		self.0.pop().map(|first| HPair(first, self.0.pop().unwrap_or(ZERO_HASH)))
	}
}
/// A row in a Merkle tree. Can be built from a vector of hashes. Calculates
/// the next level up, or can recursively go all the way up to its root.
struct MerkleRow(Vec<HPair>);
impl MerkleRow {
	fn new(hs: Vec<Hash>) -> MerkleRow {
		MerkleRow(HPairIter(hs).map(|hp| hp).collect())
	}
	fn up(&self) -> MerkleRow {
		MerkleRow::new(map_vec!(self.0, |hp| hp.hash()))
	}
	fn root(&self) -> Hash {
		if self.0.len() == 0 {
			vec![].hash()
		} else if self.0.len() == 1 {
			self.0[0].hash()
		} else {
			self.up().root()
		}
	}
}

#[cfg(test)]
mod test {
	use super::*;
	use super::hash::{Hash, Hashed, ZERO_HASH};
	use secp;
	use secp::Secp256k1;
	use secp::key::SecretKey;
	use rand::Rng;
	use rand::os::OsRng;

	fn new_secp() -> Secp256k1 {
		secp::Secp256k1::with_caps(secp::ContextFlag::Commit)
	}

	#[test]
	#[should_panic(expected = "InvalidSecretKey")]
	fn zero_commit() {
		// a transaction whose commitment sums to zero shouldn't validate
		let ref secp = new_secp();
		let mut rng = OsRng::new().unwrap();

		let skey = SecretKey::new(secp, &mut rng);
		let outh = ZERO_HASH;
		let tx = Transaction::new(vec![Input::OvertInput {
			                               output: outh,
			                               value: 10,
			                               blindkey: skey,
		                               }],
		                          vec![Output::OvertOutput {
			                               value: 1,
			                               blindkey: skey,
		                               }],
		                          9);
		// blinding should fail as signing with a zero r*G shouldn't work
		tx.blind(&secp).unwrap();
	}

	#[test]
	fn reward_empty_block() {
		let mut rng = OsRng::new().unwrap();
		let ref secp = new_secp();
		let skey = SecretKey::new(secp, &mut rng);

		let b = Block::new(BlockHeader::default(), vec![], skey).unwrap();
		b.compact().verify(&secp).unwrap();
	}

	#[test]
	fn reward_with_tx_block() {
		let mut rng = OsRng::new().unwrap();
		let ref secp = new_secp();
		let skey = SecretKey::new(secp, &mut rng);

		let tx1 = tx2i1o(secp, &mut rng);
		let mut btx1 = tx1.blind(&secp).unwrap();
		btx1.verify_sig(&secp).unwrap();

		let b = Block::new(BlockHeader::default(), vec![&mut btx1], skey).unwrap();
		b.compact().verify(&secp).unwrap();
	}

	#[test]
	fn simple_block() {
		let mut rng = OsRng::new().unwrap();
		let ref secp = new_secp();
		let skey = SecretKey::new(secp, &mut rng);

		let tx1 = tx2i1o(secp, &mut rng);
		let mut btx1 = tx1.blind(&secp).unwrap();
		btx1.verify_sig(&secp).unwrap();

		let tx2 = tx1i1o(secp, &mut rng);
		let mut btx2 = tx2.blind(&secp).unwrap();
		btx2.verify_sig(&secp).unwrap();

		let b = Block::new(BlockHeader::default(), vec![&mut btx1, &mut btx2], skey).unwrap();
		b.verify(&secp).unwrap();
	}

	// utility producing a transaction with 2 inputs and a single outputs
	pub fn tx2i1o<R: Rng>(secp: &Secp256k1, rng: &mut R) -> Transaction {
		let outh = ZERO_HASH;
		Transaction::new(vec![Input::OvertInput {
			                      output: outh,
			                      value: 10,
			                      blindkey: SecretKey::new(secp, rng),
		                      },
		                      Input::OvertInput {
			                      output: outh,
			                      value: 11,
			                      blindkey: SecretKey::new(secp, rng),
		                      }],
		                 vec![Output::OvertOutput {
			                      value: 20,
			                      blindkey: SecretKey::new(secp, rng),
		                      }],
		                 1)
	}

	// utility producing a transaction with a single input and output
	pub fn tx1i1o<R: Rng>(secp: &Secp256k1, rng: &mut R) -> Transaction {
		let outh = ZERO_HASH;
		Transaction::new(vec![Input::OvertInput {
			                      output: outh,
			                      value: 5,
			                      blindkey: SecretKey::new(secp, rng),
		                      }],
		                 vec![Output::OvertOutput {
			                      value: 4,
			                      blindkey: SecretKey::new(secp, rng),
		                      }],
		                 1)
	}
}
<|endoftext|>