<commit_before>/// Reads numbers from stdin, one per line, and writes them to a serialized histogram on stdout.

extern crate hdrsample;
extern crate clap;

use std::io;
use std::io::{Write, BufRead};
use std::fmt::Display;

use clap::{App, Arg, SubCommand};

use hdrsample::{Histogram, RecordError};
use hdrsample::serialization::{V2Serializer, V2SerializeError, V2DeflateSerializer, V2DeflateSerializeError, Deserializer, DeserializeError};

fn main() {
    let default_max = format!("{}", u64::max_value());
    let matches = App::new("hdrsample cli")
            .subcommand(SubCommand::with_name("serialize")
                    .about("Transform number-per-line input from stdin into a serialized histogram on stdout")
                    .arg(Arg::with_name("min")
                            .long("min")
                            .help("Minimum discernible value")
                            .takes_value(true)
                            .default_value("1"))
                    .arg(Arg::with_name("max")
                            .long("max")
                            .help("Maximum trackable value")
                            .takes_value(true)
                            .default_value(default_max.as_str()))
                    .arg(Arg::with_name("sigfig")
                            .long("sigfig")
                            .help("Number of significant digits")
                            .takes_value(true)
                            .default_value("3"))
                    .arg(Arg::with_name("compression")
                            .short("c")
                            .long("compression")
                            .help("Enable compression"))
                    .arg(Arg::with_name("resize")
                            .short("r")
                            .long("resize")
                            .help("Enable auto resize")))
            .subcommand(SubCommand::with_name("iter-quantiles")
                    .about("Display quantiles to stdout from serialized histogram stdin")
                    .arg(Arg::with_name("ticks")
                            .short("t")
                            .long("ticks-per-half")
                            .takes_value(true)
                            .required(true)
                            .help("Ticks per half distance"))
                    .arg(Arg::with_name("quantile-precision")
                            .long("quantile-precision")
                            .takes_value(true)
                            .default_value("20")))
            .get_matches();

    let stdin = std::io::stdin();
    let stdin = stdin.lock();

    let stdout = std::io::stdout();
    let stdout = stdout.lock();

    match matches.subcommand_name() {
        Some("serialize") => {
            let sub_matches = matches.subcommand_matches("serialize").unwrap();
            let min = sub_matches.value_of("min").unwrap().parse().unwrap();
            let max = sub_matches.value_of("max").unwrap().parse().unwrap();
            let sigfig = sub_matches.value_of("sigfig").unwrap().parse().unwrap();

            let mut h: Histogram<u64> = Histogram::new_with_bounds(min, max, sigfig).unwrap();

            if sub_matches.is_present("resize") {
                h.auto(true);
            }

            serialize(stdin, stdout, h, sub_matches.is_present("compression"))
        }
        Some("iter-quantiles") => {
            let sub_matches = matches.subcommand_matches("iter-quantiles").unwrap();
            let ticks_per_half = sub_matches.value_of("ticks").unwrap().parse().unwrap();
            let quantile_precision = sub_matches.value_of("quantile-precision").unwrap().parse().unwrap();
            quantiles(stdin, stdout, quantile_precision, ticks_per_half)
        }
        _ => unreachable!()
    }.expect("Subcommand failed")
}

/// Read numbers, one from each line, from stdin and output the resulting serialized histogram.
fn serialize<R: BufRead, W: Write>(reader: R, mut writer: W, mut h: Histogram<u64>, compression: bool) -> Result<(), CliError> {
    for num in reader.lines()
            .map(|l| l.expect("Should be able to read stdin"))
            .map(|s| s.parse().expect("Each line must be a u64")) {
        h.record(num)?;
    }

    if compression {
        V2DeflateSerializer::new().serialize(&h, &mut writer)?;
    } else {
        V2Serializer::new().serialize(&h, &mut writer)?;
    }

    Ok(())
}

/// Output histogram data in a format similar to the Java impl's
/// `AbstractHistogram#outputPercentileDistribution`.
fn quantiles<R: BufRead, W: Write>(mut reader: R, mut writer: W, quantile_precision: usize, ticks_per_half: u32) -> Result<(), CliError> {
    let hist: Histogram<u64> = Deserializer::new().deserialize(&mut reader)?;

    writer.write_all(
        format!(
            "{:>12} {:>quantile_precision$} {:>quantile_precision$} {:>10} {:>14}\n\n",
            "Value",
            "QuantileValue",
            "QuantileIteration",
            "TotalCount",
            "1/(1-Quantile)",
            quantile_precision = quantile_precision + 2 // + 2 from leading "0." for numbers
        ).as_ref(),
    )?;
    let mut sum = 0;
    for v in hist.iter_quantiles(ticks_per_half) {
        sum += v.count_since_last_iteration();
        if v.quantile() < 1.0 {
            writer.write_all(
                format!(
                    "{:12} {:1.*} {:1.*} {:10} {:14.2}\n",
                    v.value_iterated_to(),
                    quantile_precision,
                    v.quantile(),
                    quantile_precision,
                    v.quantile_iterated_to(),
                    sum,
                    1_f64 / (1_f64 - v.quantile())
                ).as_ref(),
            )?;
        } else {
            writer.write_all(
                format!(
                    "{:12} {:1.*} {:1.*} {:10} {:>14}\n",
                    v.value_iterated_to(),
                    quantile_precision,
                    v.quantile(),
                    quantile_precision,
                    v.quantile_iterated_to(),
                    sum,
                    "∞"
                ).as_ref(),
            )?;
        }
    }

    fn write_extra_data<T1: Display, T2: Display, W: Write>(
        writer: &mut W, label1: &str, data1: T1, label2: &str, data2: T2) -> Result<(), io::Error> {
        writer.write_all(format!("#[{:10} = {:12.2}, {:14} = {:12.2}]\n",
                                 label1, data1, label2, data2).as_ref())
    }

    write_extra_data(&mut writer, "Mean", hist.mean(), "StdDeviation", hist.stdev())?;
    write_extra_data(&mut writer, "Max", hist.max(), "Total count", hist.count())?;
    write_extra_data(&mut writer, "Buckets", hist.buckets(), "SubBuckets", hist.len())?;

    Ok(())
}

// A handy way to enable ? use in subcommands by mapping common errors.
// Normally I frown on excessive use of From as it's too "magic", but in the limited confines of
// subcommands, the convenience seems worth it.
#[derive(Debug)]
enum CliError {
    IoError(io::Error),
    HistogramSerializeError(V2SerializeError),
    HistogramSerializeCompressedError(V2DeflateSerializeError),
    HistogramDeserializeError(DeserializeError),
    HistogramRecordError(RecordError)
}

impl From<io::Error> for CliError {
    fn from(e: io::Error) -> Self {
        CliError::IoError(e)
    }
}

impl From<V2SerializeError> for CliError {
    fn from(e: V2SerializeError) -> Self {
        CliError::HistogramSerializeError(e)
    }
}

impl From<V2DeflateSerializeError> for CliError {
    fn from(e: V2DeflateSerializeError) -> Self {
        CliError::HistogramSerializeCompressedError(e)
    }
}

impl From<RecordError> for CliError {
    fn from(e: RecordError) -> Self {
        CliError::HistogramRecordError(e)
    }
}

impl From<DeserializeError> for CliError {
    fn from(e: DeserializeError) -> Self {
        CliError::HistogramDeserializeError(e)
    }
}
<commit_msg>Use quantile_iterated_to() in iter-quantiles example.<commit_after>/// Reads numbers from stdin, one per line, and writes them to a serialized histogram on stdout.

extern crate hdrsample;
extern crate clap;

use std::io;
use std::io::{Write, BufRead};
use std::fmt::Display;

use clap::{App, Arg, SubCommand};

use hdrsample::{Histogram, RecordError};
use hdrsample::serialization::{V2Serializer, V2SerializeError, V2DeflateSerializer, V2DeflateSerializeError, Deserializer, DeserializeError};

fn main() {
    let default_max = format!("{}", u64::max_value());
    let matches = App::new("hdrsample cli")
            .subcommand(SubCommand::with_name("serialize")
                    .about("Transform number-per-line input from stdin into a serialized histogram on stdout")
                    .arg(Arg::with_name("min")
                            .long("min")
                            .help("Minimum discernible value")
                            .takes_value(true)
                            .default_value("1"))
                    .arg(Arg::with_name("max")
                            .long("max")
                            .help("Maximum trackable value")
                            .takes_value(true)
                            .default_value(default_max.as_str()))
                    .arg(Arg::with_name("sigfig")
                            .long("sigfig")
                            .help("Number of significant digits")
                            .takes_value(true)
                            .default_value("3"))
                    .arg(Arg::with_name("compression")
                            .short("c")
                            .long("compression")
                            .help("Enable compression"))
                    .arg(Arg::with_name("resize")
                            .short("r")
                            .long("resize")
                            .help("Enable auto resize")))
            .subcommand(SubCommand::with_name("iter-quantiles")
                    .about("Display quantiles to stdout from serialized histogram stdin")
                    .arg(Arg::with_name("ticks")
                            .short("t")
                            .long("ticks-per-half")
                            .takes_value(true)
                            .required(true)
                            .help("Ticks per half distance"))
                    .arg(Arg::with_name("quantile-precision")
                            .long("quantile-precision")
                            .takes_value(true)
                            .default_value("20")))
            .get_matches();

    let stdin = std::io::stdin();
    let stdin = stdin.lock();

    let stdout = std::io::stdout();
    let stdout = stdout.lock();

    match matches.subcommand_name() {
        Some("serialize") => {
            let sub_matches = matches.subcommand_matches("serialize").unwrap();
            let min = sub_matches.value_of("min").unwrap().parse().unwrap();
            let max = sub_matches.value_of("max").unwrap().parse().unwrap();
            let sigfig = sub_matches.value_of("sigfig").unwrap().parse().unwrap();

            let mut h: Histogram<u64> = Histogram::new_with_bounds(min, max, sigfig).unwrap();

            if sub_matches.is_present("resize") {
                h.auto(true);
            }

            serialize(stdin, stdout, h, sub_matches.is_present("compression"))
        }
        Some("iter-quantiles") => {
            let sub_matches = matches.subcommand_matches("iter-quantiles").unwrap();
            let ticks_per_half = sub_matches.value_of("ticks").unwrap().parse().unwrap();
            let quantile_precision = sub_matches.value_of("quantile-precision").unwrap().parse().unwrap();
            quantiles(stdin, stdout, quantile_precision, ticks_per_half)
        }
        _ => unreachable!()
    }.expect("Subcommand failed")
}

/// Read numbers, one from each line, from stdin and output the resulting serialized histogram.
fn serialize<R: BufRead, W: Write>(reader: R, mut writer: W, mut h: Histogram<u64>, compression: bool) -> Result<(), CliError> {
    for num in reader.lines()
            .map(|l| l.expect("Should be able to read stdin"))
            .map(|s| s.parse().expect("Each line must be a u64")) {
        h.record(num)?;
    }

    if compression {
        V2DeflateSerializer::new().serialize(&h, &mut writer)?;
    } else {
        V2Serializer::new().serialize(&h, &mut writer)?;
    }

    Ok(())
}

/// Output histogram data in a format similar to the Java impl's
/// `AbstractHistogram#outputPercentileDistribution`.
fn quantiles<R: BufRead, W: Write>(mut reader: R, mut writer: W, quantile_precision: usize, ticks_per_half: u32) -> Result<(), CliError> {
    let hist: Histogram<u64> = Deserializer::new().deserialize(&mut reader)?;

    writer.write_all(
        format!(
            "{:>12} {:>quantile_precision$} {:>quantile_precision$} {:>10} {:>14}\n\n",
            "Value",
            "QuantileValue",
            "QuantileIteration",
            "TotalCount",
            "1/(1-Quantile)",
            quantile_precision = quantile_precision + 2 // + 2 from leading "0." for numbers
        ).as_ref(),
    )?;
    let mut sum = 0;
    for v in hist.iter_quantiles(ticks_per_half) {
        sum += v.count_since_last_iteration();
        if v.quantile_iterated_to() < 1.0 {
            writer.write_all(
                format!(
                    "{:12} {:1.*} {:1.*} {:10} {:14.2}\n",
                    v.value_iterated_to(),
                    quantile_precision,
                    v.quantile(),
                    quantile_precision,
                    v.quantile_iterated_to(),
                    sum,
                    1_f64 / (1_f64 - v.quantile_iterated_to())
                ).as_ref(),
            )?;
        } else {
            writer.write_all(
                format!(
                    "{:12} {:1.*} {:1.*} {:10} {:>14}\n",
                    v.value_iterated_to(),
                    quantile_precision,
                    v.quantile(),
                    quantile_precision,
                    v.quantile_iterated_to(),
                    sum,
                    "∞"
                ).as_ref(),
            )?;
        }
    }

    fn write_extra_data<T1: Display, T2: Display, W: Write>(
        writer: &mut W, label1: &str, data1: T1, label2: &str, data2: T2) -> Result<(), io::Error> {
        writer.write_all(format!("#[{:10} = {:12.2}, {:14} = {:12.2}]\n",
                                 label1, data1, label2, data2).as_ref())
    }

    write_extra_data(&mut writer, "Mean", hist.mean(), "StdDeviation", hist.stdev())?;
    write_extra_data(&mut writer, "Max", hist.max(), "Total count", hist.count())?;
    write_extra_data(&mut writer, "Buckets", hist.buckets(), "SubBuckets", hist.len())?;

    Ok(())
}

// A handy way to enable ? use in subcommands by mapping common errors.
// Normally I frown on excessive use of From as it's too "magic", but in the limited confines of
// subcommands, the convenience seems worth it.
#[derive(Debug)]
enum CliError {
    IoError(io::Error),
    HistogramSerializeError(V2SerializeError),
    HistogramSerializeCompressedError(V2DeflateSerializeError),
    HistogramDeserializeError(DeserializeError),
    HistogramRecordError(RecordError)
}

impl From<io::Error> for CliError {
    fn from(e: io::Error) -> Self {
        CliError::IoError(e)
    }
}

impl From<V2SerializeError> for CliError {
    fn from(e: V2SerializeError) -> Self {
        CliError::HistogramSerializeError(e)
    }
}

impl From<V2DeflateSerializeError> for CliError {
    fn from(e: V2DeflateSerializeError) -> Self {
        CliError::HistogramSerializeCompressedError(e)
    }
}

impl From<RecordError> for CliError {
    fn from(e: RecordError) -> Self {
        CliError::HistogramRecordError(e)
    }
}

impl From<DeserializeError> for CliError {
    fn from(e: DeserializeError) -> Self {
        CliError::HistogramDeserializeError(e)
    }
}
<|endoftext|>


<commit_before>use super::{EmptyCompleter, Status};
use crate as ion_shell;
use builtins_proc::builtin;
use calc::{eval, eval_polish, CalcError, Value};
use liner::Context;
use std::io::{self, Read};

const REPL_GUIDE: &str = r#"Ion's integrated calculator
Type in expressions to have them evaluated.
Type "help" for help."#;

fn calc_or_polish_calc(args: &str) -> Result<Value, CalcError> {
    match eval(args) {
        Ok(t) => Ok(t),
        Err(_) => eval_polish(args),
    }
}

#[builtin(
    desc = "Floating-point calculator",
    man = "
SYNOPSIS
    math [EXPRESSION]

DESCRIPTION
    Evaluates arithmetic expressions

SPECIAL EXPRESSIONS
    help (only in interactive mode)
        prints this help text

    --help (only in non-interactive mode)
        prints this help text

    exit (only in interactive mode)
        exits the program

NOTATIONS
    infix notation
        e.g. 3 * 4 + 5

    polish notation
        e.g. + * 3 4 5

EXAMPLES
    Add two plus two in infix notation
        math 2+2

    Add two plus two in polish notation
        math + 2 2

AUTHOR
    Written by Hunter Goldstein."
)]
pub fn math(args: &[crate::types::Str], _: &mut crate::Shell<'_>) -> Status {
    if args.get(1).is_some() {
        let result = calc_or_polish_calc(&args[1..].join(" "));
        match result {
            Ok(v) => {
                println!("{}", v);
                Status::SUCCESS
            }
            Err(e) => Status::error(format!("{}", e)),
        }
    } else if atty::is(atty::Stream::Stdin) {
        println!("{}", REPL_GUIDE);
        let mut context = Context::new();
        loop {
            match context
                .read_line("ion-math: ", None, &mut EmptyCompleter)
                .as_ref()
                .map(AsRef::as_ref)
            {
                Ok("") => return Status::SUCCESS,
                Ok(text) if text.trim() == "exit" => return Status::SUCCESS,
                Ok(s) => {
                    let result = calc_or_polish_calc(s);
                    match result {
                        Ok(v) => println!("{}", v),
                        Err(e) => eprintln!("{}", e),
                    }
                }
                Err(err) => {
                    eprintln!("{}", err);
                    return Status::SUCCESS;
                }
            }
        }
    } else {
        let mut input = String::with_capacity(1024);
        io::stdin().read_to_string(&mut input).unwrap();

        let result = calc_or_polish_calc(&input);
        match result {
            Ok(v) => {
                println!("{}", v);
                Status::SUCCESS
            }
            Err(e) => Status::error(format!("{}", e)),
        }
    }
}
<commit_msg>feat: Add an intregrated man page to the math builtin<commit_after>use super::{EmptyCompleter, Status};
use crate as ion_shell;
use builtins_proc::builtin;
use calc::{eval, eval_polish, CalcError, Value};
use liner::Context;
use std::io::{self, Read};

const REPL_GUIDE: &str = r#"Ion's integrated calculator
Type in expressions to have them evaluated.
Type "help" for help."#;

const REPL_HELP: &str = r#"
Ion-math is a floating-point calculator
You can use infix (ex: 1 + 2 * 3) or polish (+ * 2 3 1) notations.
Non-operator, non-number sequences will be treated as variables for interpolation.

Examples:
    $ 1 + 3-2
    >> 2
    $ 0.00001 + 0.0001
    >> 0.00011

    In Ion if $a = 2, $b = 3, $c = 7
    $ a * b * c
    >> 42
"#;

fn calc_or_polish_calc(args: &str) -> Result<Value, CalcError> {
    match eval(args) {
        Ok(t) => Ok(t),
        Err(_) => eval_polish(args),
    }
}

#[builtin(
    desc = "Floating-point calculator",
    man = "
SYNOPSIS
    math [EXPRESSION]

DESCRIPTION
    Evaluates arithmetic expressions

SPECIAL EXPRESSIONS
    help (only in interactive mode)
        prints this help text

    --help (only in non-interactive mode)
        prints this help text

    exit (only in interactive mode)
        exits the program

NOTATIONS
    infix notation
        e.g. 3 * 4 + 5

    polish notation
        e.g. + * 3 4 5

EXAMPLES
    Add two plus two in infix notation
        math 2+2

    Add two plus two in polish notation
        math + 2 2

AUTHOR
    Written by Hunter Goldstein."
)]
pub fn math(args: &[crate::types::Str], _: &mut crate::Shell<'_>) -> Status {
    if args.get(1).is_some() {
        let result = calc_or_polish_calc(&args[1..].join(" "));
        match result {
            Ok(v) => {
                println!("{}", v);
                Status::SUCCESS
            }
            Err(e) => Status::error(format!("{}", e)),
        }
    } else if atty::is(atty::Stream::Stdin) {
        println!("{}", REPL_GUIDE);
        let mut context = Context::new();
        loop {
            match context
                .read_line("ion-math: ", None, &mut EmptyCompleter)
                .as_ref()
                .map(AsRef::as_ref)
            {
                Ok("") => return Status::SUCCESS,
                Ok(text) if text.trim() == "exit" => return Status::SUCCESS,
                Ok(text) if text.trim() == "help" => eprintln!("{}", REPL_HELP),
                Ok(s) => {
                    let result = calc_or_polish_calc(s);
                    match result {
                        Ok(v) => println!("{}", v),
                        Err(e) => eprintln!("{}", e),
                    }
                }
                Err(err) => {
                    eprintln!("{}", err);
                    return Status::SUCCESS;
                }
            }
        }
    } else {
        let mut input = String::with_capacity(1024);
        io::stdin().read_to_string(&mut input).unwrap();

        let result = calc_or_polish_calc(&input);
        match result {
            Ok(v) => {
                println!("{}", v);
                Status::SUCCESS
            }
            Err(e) => Status::error(format!("{}", e)),
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#[test]
fn test_clone() {
    let a = (1i, "2");
    let b = a.clone();
    assert_eq!(a, b);
}

#[test]
fn test_getters() {
    macro_rules! test_getter(
        ($x:expr, $valN:ident, $refN:ident, $mutN:ident,
         $init:expr, $incr:expr, $result:expr) => ({
            assert_eq!($x.$valN(), $init);
            assert_eq!(*$x.$refN(), $init);
            *$x.$mutN() += $incr;
            assert_eq!(*$x.$refN(), $result);
        })
    )
    let mut x = (0u8, 1u16, 2u32, 3u64, 4u, 5i8, 6i16, 7i32, 8i64, 9i, 10f32, 11f64);
    test_getter!(x, val0,  ref0,  mut0,  0,    1,   1);
    test_getter!(x, val1,  ref1,  mut1,  1,    1,   2);
    test_getter!(x, val2,  ref2,  mut2,  2,    1,   3);
    test_getter!(x, val3,  ref3,  mut3,  3,    1,   4);
    test_getter!(x, val4,  ref4,  mut4,  4,    1,   5);
    test_getter!(x, val5,  ref5,  mut5,  5,    1,   6);
    test_getter!(x, val6,  ref6,  mut6,  6,    1,   7);
    test_getter!(x, val7,  ref7,  mut7,  7,    1,   8);
    test_getter!(x, val8,  ref8,  mut8,  8,    1,   9);
    test_getter!(x, val9,  ref9,  mut9,  9,    1,   10);
    test_getter!(x, val10, ref10, mut10, 10.0, 1.0, 11.0);
    test_getter!(x, val11, ref11, mut11, 11.0, 1.0, 12.0);
}

#[test]
fn test_tuple_cmp() {
    let (small, big) = ((1u, 2u, 3u), (3u, 2u, 1u));

    let nan = 0.0f64/0.0;

    // PartialEq
    assert_eq!(small, small);
    assert_eq!(big, big);
    assert!(small != big);
    assert!(big != small);

    // PartialOrd
    assert!(small < big);
    assert!(!(small < small));
    assert!(!(big < small));
    assert!(!(big < big));

    assert!(small <= small);
    assert!(big <= big);

    assert!(big > small);
    assert!(small >= small);
    assert!(big >= small);
    assert!(big >= big);

    assert!(!((1.0f64, 2.0f64) < (nan, 3.0)));
    assert!(!((1.0f64, 2.0f64) <= (nan, 3.0)));
    assert!(!((1.0f64, 2.0f64) > (nan, 3.0)));
    assert!(!((1.0f64, 2.0f64) >= (nan, 3.0)));
    assert!(((1.0f64, 2.0f64) < (2.0, nan)));
    assert!(!((2.0f64, 2.0f64) < (2.0, nan)));

    // Ord
    assert!(small.cmp(&small) == Equal);
    assert!(big.cmp(&big) == Equal);
    assert!(small.cmp(&big) == Less);
    assert!(big.cmp(&small) == Greater);
}

#[test]
fn test_show() {
    let s = format!("{}", (1i,));
    assert_eq!(s, "(1,)");
    let s = format!("{}", (1i, true));
    assert_eq!(s, "(1, true)");
    let s = format!("{}", (1i, "hi", true));
    assert_eq!(s, "(1, hi, true)");
}
<commit_msg>Tuple test no longer needed. Is already in run-pass tests<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#[test]
fn test_clone() {
    let a = (1i, "2");
    let b = a.clone();
    assert_eq!(a, b);
}

#[test]
fn test_tuple_cmp() {
    let (small, big) = ((1u, 2u, 3u), (3u, 2u, 1u));

    let nan = 0.0f64/0.0;

    // PartialEq
    assert_eq!(small, small);
    assert_eq!(big, big);
    assert!(small != big);
    assert!(big != small);

    // PartialOrd
    assert!(small < big);
    assert!(!(small < small));
    assert!(!(big < small));
    assert!(!(big < big));

    assert!(small <= small);
    assert!(big <= big);

    assert!(big > small);
    assert!(small >= small);
    assert!(big >= small);
    assert!(big >= big);

    assert!(!((1.0f64, 2.0f64) < (nan, 3.0)));
    assert!(!((1.0f64, 2.0f64) <= (nan, 3.0)));
    assert!(!((1.0f64, 2.0f64) > (nan, 3.0)));
    assert!(!((1.0f64, 2.0f64) >= (nan, 3.0)));
    assert!(((1.0f64, 2.0f64) < (2.0, nan)));
    assert!(!((2.0f64, 2.0f64) < (2.0, nan)));

    // Ord
    assert!(small.cmp(&small) == Equal);
    assert!(big.cmp(&big) == Equal);
    assert!(small.cmp(&big) == Less);
    assert!(big.cmp(&small) == Greater);
}

#[test]
fn test_show() {
    let s = format!("{}", (1i,));
    assert_eq!(s, "(1,)");
    let s = format!("{}", (1i, true));
    assert_eq!(s, "(1, true)");
    let s = format!("{}", (1i, "hi", true));
    assert_eq!(s, "(1, hi, true)");
}
<|endoftext|>


<commit_before>use rand::Rng;
use std::fmt;

/// Simple implementation of [Reservoir Sampling](https://en.wikipedia.org/wiki/Reservoir_sampling)
/// with [fast approximation](https://erikerlandson.github.io/blog/2015/11/20/very-fast-reservoir-sampling/)
pub struct ReservoirSampling<T, R>
where
    R: Rng,
{
    k: usize,
    rng: R,
    reservoir: Vec<T>,
    i: usize,
    skip_until: usize,
}

impl<T, R> ReservoirSampling<T, R>
where
    R: Rng,
{
    /// Create new reservoir sampler that keeps `k` samples and uses `rng` for its random
    /// decisions.
    pub fn new(k: usize, rng: R) -> ReservoirSampling<T, R> {
        ReservoirSampling {
            k: k,
            rng: rng,
            reservoir: vec![],
            i: 0,
            skip_until: 0,
        }
    }

    /// Number of samples that should be kept.
    pub fn k(&self) -> usize {
        self.k
    }

    /// Read-only copy of the reservoir. Contains at most `k` entries.
    pub fn reservoir(&self) -> &Vec<T> {
        &self.reservoir
    }

    /// Number of data points seen.
    pub fn i(&self) -> usize {
        self.i
    }

    /// Observe new data point.
    pub fn add(&mut self, obj: T) {
        let t = self.k * 4; // TODO: make this a parameter

        if self.i < self.k {
            // initial fill-up
            self.reservoir.push(obj)
        } else if self.i < t {
            // normal reservoir sampling
            let j = self.rng.gen_range::<usize>(0, self.i);
            if j < self.k {
                self.reservoir[j] = obj;
            }
        } else if self.i >= self.skip_until {
            // fast skipping approximation
            let j = self.rng.gen_range::<usize>(0, self.k);
            self.reservoir[j] = obj;

            // calculate next skip
            let p = (self.k as f64) / ((self.i + 1) as f64);
            let u = 1. - self.rng.gen_range::<f64>(0., 1.); // (0.0, 1.0]
            let g = (u.ln() / (1. - p).ln()).floor() as usize;
            self.skip_until = self.i + g;
        }

        self.i += 1;
    }

    /// Checks if reservoir is empty (i.e. no data points where observed)
    pub fn is_empty(&self) -> bool {
        self.i == 0
    }

    /// Clear sampler state. It now behaves like a fresh one (i.e. no data points seen so far).
    pub fn clear(&mut self) {
        self.i = 0;
        self.skip_until = 0;
        self.reservoir.clear();
    }
}

impl<T, R> fmt::Debug for ReservoirSampling<T, R>
where
    R: Rng,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "ReservoirSampling {{ k: {} }}", self.k)
    }
}

#[cfg(test)]
mod tests {
    use super::ReservoirSampling;
    use rand::ChaChaRng;

    #[test]
    fn getter() {
        let rs = ReservoirSampling::<u64, ChaChaRng>::new(10, ChaChaRng::new_unseeded());
        assert_eq!(rs.k(), 10);
        assert_eq!(rs.i(), 0);
        assert_eq!(rs.reservoir(), &vec![]);
    }

    #[test]
    fn empty() {
        let rs = ReservoirSampling::<u64, ChaChaRng>::new(10, ChaChaRng::new_unseeded());
        assert!(rs.is_empty());
        assert!(rs.reservoir().is_empty());
    }

    #[test]
    fn add_k() {
        let mut rs = ReservoirSampling::<u64, ChaChaRng>::new(10, ChaChaRng::new_unseeded());
        for i in 0..10 {
            rs.add(i);
        }
        assert_eq!(rs.i(), 10);
        assert_eq!(rs.reservoir(), &vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
    }

    #[test]
    fn add_parts() {
        let mut rs = ReservoirSampling::<u64, ChaChaRng>::new(100, ChaChaRng::new_unseeded());
        for _ in 0..1500 {
            rs.add(0);
        }
        for _ in 0..7500 {
            rs.add(1);
        }
        for _ in 0..1000 {
            rs.add(0);
        }
        assert!((rs.reservoir().iter().sum::<u64>() as i64 - 75).abs() < 5);
    }

    #[test]
    fn debug() {
        let rs = ReservoirSampling::<u64, ChaChaRng>::new(10, ChaChaRng::new_unseeded());
        assert_eq!(format!("{:?}", rs), "ReservoirSampling { k: 10 }");
    }

    #[test]
    fn add_clear() {
        let mut rs = ReservoirSampling::<u64, ChaChaRng>::new(10, ChaChaRng::new_unseeded());
        for i in 0..10 {
            rs.add(i);
        }
        rs.clear();
        for i in 10..20 {
            rs.add(i);
        }
        assert_eq!(rs.i(), 10);
        assert_eq!(
            rs.reservoir(),
            &vec![10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
        );
    }
}
<commit_msg>reservoirsampling: fix test name<commit_after>use rand::Rng;
use std::fmt;

/// Simple implementation of [Reservoir Sampling](https://en.wikipedia.org/wiki/Reservoir_sampling)
/// with [fast approximation](https://erikerlandson.github.io/blog/2015/11/20/very-fast-reservoir-sampling/)
pub struct ReservoirSampling<T, R>
where
    R: Rng,
{
    k: usize,
    rng: R,
    reservoir: Vec<T>,
    i: usize,
    skip_until: usize,
}

impl<T, R> ReservoirSampling<T, R>
where
    R: Rng,
{
    /// Create new reservoir sampler that keeps `k` samples and uses `rng` for its random
    /// decisions.
    pub fn new(k: usize, rng: R) -> ReservoirSampling<T, R> {
        ReservoirSampling {
            k: k,
            rng: rng,
            reservoir: vec![],
            i: 0,
            skip_until: 0,
        }
    }

    /// Number of samples that should be kept.
    pub fn k(&self) -> usize {
        self.k
    }

    /// Read-only copy of the reservoir. Contains at most `k` entries.
    pub fn reservoir(&self) -> &Vec<T> {
        &self.reservoir
    }

    /// Number of data points seen.
    pub fn i(&self) -> usize {
        self.i
    }

    /// Observe new data point.
    pub fn add(&mut self, obj: T) {
        let t = self.k * 4; // TODO: make this a parameter

        if self.i < self.k {
            // initial fill-up
            self.reservoir.push(obj)
        } else if self.i < t {
            // normal reservoir sampling
            let j = self.rng.gen_range::<usize>(0, self.i);
            if j < self.k {
                self.reservoir[j] = obj;
            }
        } else if self.i >= self.skip_until {
            // fast skipping approximation
            let j = self.rng.gen_range::<usize>(0, self.k);
            self.reservoir[j] = obj;

            // calculate next skip
            let p = (self.k as f64) / ((self.i + 1) as f64);
            let u = 1. - self.rng.gen_range::<f64>(0., 1.); // (0.0, 1.0]
            let g = (u.ln() / (1. - p).ln()).floor() as usize;
            self.skip_until = self.i + g;
        }

        self.i += 1;
    }

    /// Checks if reservoir is empty (i.e. no data points where observed)
    pub fn is_empty(&self) -> bool {
        self.i == 0
    }

    /// Clear sampler state. It now behaves like a fresh one (i.e. no data points seen so far).
    pub fn clear(&mut self) {
        self.i = 0;
        self.skip_until = 0;
        self.reservoir.clear();
    }
}

impl<T, R> fmt::Debug for ReservoirSampling<T, R>
where
    R: Rng,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "ReservoirSampling {{ k: {} }}", self.k)
    }
}

#[cfg(test)]
mod tests {
    use super::ReservoirSampling;
    use rand::ChaChaRng;

    #[test]
    fn getter() {
        let rs = ReservoirSampling::<u64, ChaChaRng>::new(10, ChaChaRng::new_unseeded());
        assert_eq!(rs.k(), 10);
        assert_eq!(rs.i(), 0);
        assert_eq!(rs.reservoir(), &vec![]);
    }

    #[test]
    fn empty() {
        let rs = ReservoirSampling::<u64, ChaChaRng>::new(10, ChaChaRng::new_unseeded());
        assert!(rs.is_empty());
        assert!(rs.reservoir().is_empty());
    }

    #[test]
    fn add_k() {
        let mut rs = ReservoirSampling::<u64, ChaChaRng>::new(10, ChaChaRng::new_unseeded());
        for i in 0..10 {
            rs.add(i);
        }
        assert_eq!(rs.i(), 10);
        assert_eq!(rs.reservoir(), &vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
    }

    #[test]
    fn add_parts() {
        let mut rs = ReservoirSampling::<u64, ChaChaRng>::new(100, ChaChaRng::new_unseeded());
        for _ in 0..1500 {
            rs.add(0);
        }
        for _ in 0..7500 {
            rs.add(1);
        }
        for _ in 0..1000 {
            rs.add(0);
        }
        assert!((rs.reservoir().iter().sum::<u64>() as i64 - 75).abs() < 5);
    }

    #[test]
    fn debug() {
        let rs = ReservoirSampling::<u64, ChaChaRng>::new(10, ChaChaRng::new_unseeded());
        assert_eq!(format!("{:?}", rs), "ReservoirSampling { k: 10 }");
    }

    #[test]
    fn clear() {
        let mut rs = ReservoirSampling::<u64, ChaChaRng>::new(10, ChaChaRng::new_unseeded());
        for i in 0..10 {
            rs.add(i);
        }
        rs.clear();
        for i in 10..20 {
            rs.add(i);
        }
        assert_eq!(rs.i(), 10);
        assert_eq!(
            rs.reservoir(),
            &vec![10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
        );
    }
}
<|endoftext|>


<commit_before>use circle::Circle;
use fx32::Fx32;
use fx32::Fx32Small;
use ray2::Ray2;
use vec2::Vec2;
use wide_line::WideLine;

use std::cmp;

use std::io::Error;
use std::io::prelude::*;
use std::io::BufWriter;
use std::fs::File;

#[derive (Clone, Copy)]
pub enum Ray2TraceResult {
	Hit (Fx32, Vec2 <Fx32>, Vec2 <Fx32Small>),
	Miss,
}

pub fn fold_closer_result (a: Ray2TraceResult, b: Ray2TraceResult) -> Ray2TraceResult {
	match a {
		Ray2TraceResult::Miss => {
			return b;
		},
		Ray2TraceResult::Hit (a_t, ..) => {
			match b {
				Ray2TraceResult::Miss => {
					return a;
				},
				Ray2TraceResult::Hit (b_t, ..) => {
					if a_t < b_t {
						return a;
					}
					else {
						return b;
					}
				}
			}
		},
	}
}

pub fn write_vec2 <T> (writer: &mut T, v: &Vec2 <Fx32>) where T: Write {
	write! (writer, "v {} 0 {}\n", v.x.to_f64 () / 256.0, v.y.to_f64 () / 256.0).unwrap ();
}

pub fn test_ray_trace () -> Result <(), Error> {
	let scale = 1;
	//let scale_fx = Fx32::from_int (scale);

	let obstacle = vec! [
	Circle {
		center: Vec2 {x: Fx32::from_q (133, scale), y: Fx32::from_q (512 - 34, scale)},
		radius: Fx32::from_q (20, scale),
	},
	Circle {
		center: Vec2 {x: Fx32::from_q (256, scale), y: Fx32::from_q (501, scale)},
		radius: Fx32::from_q (20, scale),
	},
	Circle {
		center: Vec2 {x: Fx32::from_q (404, scale), y: Fx32::from_q (501, scale)},
		radius: Fx32::from_q (20, scale),
	},
	];

	let lines = vec! [
	WideLine {
		start: obstacle [0].center,
		end: obstacle [1].center,
		radius: Fx32::from_q (20, scale),
	},
	WideLine {
		start: obstacle [1].center,
		end: obstacle [2].center,
		radius: Fx32::from_q (20, scale),
	},
	];

	let mut num_bounces = 0;
	let mut num_ticks = 0;

	let inv_dt = 8;
	let gravity = Vec2::<Fx32> {
		x: Fx32::from_q (0, 1),
		y: Fx32::from_q (2, 1),
	};

	let obj_file = try!(File::create("lines.obj"));
	let mut writer = BufWriter::new (obj_file);

	let mut vertex_i = 1;
	let mut polyline_start = vertex_i;

	for x in 66..202 {
		let x = x * 2;
		let mut particle = Ray2 {
			start: Vec2 {
				x: Fx32::from_q (x * 2 + 1, scale * 2),
				y: Fx32::from_q (0, scale)
			},
			dir: Vec2 {
				x: Fx32::from_q (0, scale),
				y: Fx32::from_q (1, scale),
			},
		};

		write_vec2 (&mut writer, &particle.start);
		vertex_i += 1;

		for _ in 0..4000 {
			let trace_result = {
				let point_results = obstacle.iter ().map (|obstacle| ray_trace_circle_2 (&particle, obstacle));

				let line_results = lines.iter ().map (|line| ray_trace_line (&particle, line));

				point_results.chain (line_results).fold ( Ray2TraceResult::Miss, fold_closer_result)
			};

			let dt = Fx32::from_q (1, inv_dt).to_small ();

			match trace_result {
				Ray2TraceResult::Miss => {
					//let air_drag = Fx32 { x: particle.dir.length_sq ().x / -16384 };
					//let air_force = particle.dir * air_drag;
					let new_dir = particle.dir + gravity * dt;// + Vec2::<Fx32>::from (air_force * dt);
					let sum_dir = particle.dir + new_dir;
					let average_dir = Vec2::<Fx32> {
						x: Fx32 { x: sum_dir.x.x / 2 },
						y: Fx32 { x: sum_dir.y.x / 2 },
					};

					particle.start = particle.start + (average_dir * dt);
					particle.dir = new_dir;
				},
				Ray2TraceResult::Hit (_, ccd_pos, normal) => {
					particle.start = ccd_pos;
					particle.dir = particle.dir.reflect (normal) * Fx32::from_q (1023, 1024);
					//particle.dir = normal;
					num_bounces += 1;
				},
			};

			write_vec2 (&mut writer, &particle.start);
			vertex_i += 1;

			num_ticks += 1;

			if particle.start.y > 768 {
				break;
			}
		}

		for i in polyline_start..vertex_i - 1 {
			try! (write! (writer, "f {} {}\n", i, i + 1));
		}
		polyline_start = vertex_i
	}

	println! ("num_bounces: {}", num_bounces);
	println! ("num_ticks: {}", num_ticks);

	Ok (())
}

pub struct Basis2 {
	pub x: Vec2 <Fx32Small>,
	pub y: Vec2 <Fx32Small>,
}

// Constructs a basis to ray space
// Such that the ray is the X axis
pub fn get_ray_basis (ray: &Ray2, ray_length: Fx32) -> Basis2 {
	let basis_x_big = if ray_length == 0 {
		ray.dir
	}
	else {
		ray.dir / ray_length
	};

	Basis2 {
		x: basis_x_big.to_small (),
		y: basis_x_big.cross ().to_small (),
	}
}

impl Basis2 {
	pub fn to_space (&self, v: &Vec2 <Fx32>) -> Vec2 <Fx32> {
		Vec2::<Fx32> {
			x: *v * self.x,
			y: *v * self.y,
		}
	}

	pub fn from_space (&self, v: &Vec2 <Fx32>) -> Vec2 <Fx32> {
		Vec2::<Fx32> {
			x: (v.x * self.x.x) + (v.y * self.y.x),
			y: (v.x * self.x.y) + (v.y * self.y.y),
		}
	}
}

pub fn ray_trace_line (ray: &Ray2, line: &WideLine) -> Ray2TraceResult {
	if line.start == line.end {
		// Line has zero length and so zero collision area
		// If we run through the math we may get a 0 / 0 result
		// so just drop it now
		return Ray2TraceResult::Miss;
	}

	let line_tangent: Vec2 <Fx32> = line.end - line.start;
	let line_tangent = Vec2::<Fx32> {
		x: line_tangent.x * Fx32::from_q (1, 256),
		y: line_tangent.y * Fx32::from_q (1, 256),
	};
	let line_normal = line_tangent.cross ().normalized ();

	let sdf: Fx32 = (ray.start - line.start) * line_normal;

	// Flip the normal so it's towards the ray
	// This will allow us to extrude the correct side
	let line_normal = if sdf > 0 {
		line_normal
	}
	else {
		-line_normal
	};

	if sdf.abs () <= line.radius {
		// Ray has already started inside and we should push it out
		let towards = -Fx32::from (ray.dir * line_normal);

		let big_normal: Vec2 <Fx32> = line_normal.into ();
		let safe_point = ray.start + big_normal * (line.radius - sdf.abs ());

		if towards > 0 {
			// Ray is moving deeper inside - Pop it out and reflect it
			return Ray2TraceResult::Hit (
				Fx32::from_int (0),
				safe_point,
				line_normal,
			);
		}
		else {
			// Ray is moving out - Pop it out but consume its timestep
			return Ray2TraceResult::Hit (
				Fx32::from_int (1),
				safe_point,
				line_normal,
			);
		}
	}

	let extrude_vector = line.radius * Vec2::<Fx32>::from (line_normal);
	// Extrude the line
	let line = WideLine {
		start: line.start + extrude_vector,
		end: line.end + extrude_vector,
		radius: Fx32::from_int (0),
	};

	let ray_length = ray.dir.length ();

	if ray_length == 0 {
		return Ray2TraceResult::Miss;
	}

	let basis = get_ray_basis (ray, ray_length);

	// Transform the line to ray space
	let line = WideLine {
		start: basis.to_space (&(line.start - ray.start)),
		end: basis.to_space (&(line.end - ray.start)),
		radius: line.radius,
	};

	// Line will have zero y difference resulting in a divide by zero
	if line.start.y == line.end.y {
		return Ray2TraceResult::Miss;
	}

	// Apply SAT
	if line.start.y >= 0 && line.end.y >= 0 {
		return Ray2TraceResult::Miss;
	}
	else if line.start.y <= 0 && line.end.y <= 0 {
		return Ray2TraceResult::Miss;
	}

	// If we get here, we know that the obstacle line crosses our ray somewhere

	// Note: Lines must not have 0 length
	let obstacle_t = (-line.start.y) / (line.end.y - line.start.y);

	assert! (obstacle_t >= 0);
	assert! (obstacle_t <= 1, format!("{:?}", ray_length));

	let crossing_x = line.start.x * (Fx32::from_int (1) - obstacle_t) + line.end.x * obstacle_t;

	if crossing_x < 0 || crossing_x > ray_length {
		return Ray2TraceResult::Miss;
	}

	// The line segments intersect
	let t = crossing_x / ray_length;

	//let world_normal = basis.from_space (&Vec2::<Fx32>::from (line_normal));
	//assert! (world_normal.length_sq () < Fx32::from_int (4), "Long normal");
	/*
	let world_normal = Vec2::<Fx32> {
		x: Fx32::from_q (1, 128),
		y: Fx32::from_q (1, 1),
	};
	*/
	return Ray2TraceResult::Hit (
		t,
		ray.start + ray.dir * t,
		line_normal,
	);
}

pub fn ray_trace_circle_2 (ray: &Ray2, circle: &Circle) -> Ray2TraceResult {
	let ray_length = ray.dir.length ();
	let basis = get_ray_basis (ray, ray_length);

	let center_in_ray_space = basis.to_space (&(circle.center - ray.start));

	if center_in_ray_space.x < 0 {
		return Ray2TraceResult::Miss;
	}

	if center_in_ray_space.x > ray_length + circle.radius {
		return Ray2TraceResult::Miss;
	}

	if center_in_ray_space.y.abs () >= circle.radius {
		// Prevents a negative root later on
		return Ray2TraceResult::Miss;
	}

	let ray_space_x = center_in_ray_space.x - (circle.radius.square () - center_in_ray_space.y.square ()).sqrt ();

	if ray_space_x > ray_length || ray_length == 0 {
		return Ray2TraceResult::Miss;
	}

	let t = ray_space_x / ray_length;
	let ccd_pos = ray.start + ray.dir * t;

	if t <= 1 {
		return Ray2TraceResult::Hit (
			Fx32 { x: cmp::max (t.x, Fx32::from_int (0).x) },
			ccd_pos,
			((ccd_pos - circle.center) / circle.radius).to_small (),
		);
	}
	else {
		return Ray2TraceResult::Miss;
	}
}
<commit_msg>Fixing a bug where lines were infinitely long<commit_after>use circle::Circle;
use fx32::Fx32;
use fx32::Fx32Small;
use ray2::Ray2;
use vec2::Vec2;
use wide_line::WideLine;

use std::cmp;

use std::io::Error;
use std::io::prelude::*;
use std::io::BufWriter;
use std::fs::File;

#[derive (Clone, Copy)]
pub enum Ray2TraceResult {
	Hit (Fx32, Vec2 <Fx32>, Vec2 <Fx32Small>),
	Miss,
}

pub fn fold_closer_result (a: Ray2TraceResult, b: Ray2TraceResult) -> Ray2TraceResult {
	match a {
		Ray2TraceResult::Miss => {
			return b;
		},
		Ray2TraceResult::Hit (a_t, ..) => {
			match b {
				Ray2TraceResult::Miss => {
					return a;
				},
				Ray2TraceResult::Hit (b_t, ..) => {
					if a_t < b_t {
						return a;
					}
					else {
						return b;
					}
				}
			}
		},
	}
}

pub fn write_vec2 <T> (writer: &mut T, v: &Vec2 <Fx32>) where T: Write {
	write! (writer, "v {} 0 {}\n", v.x.to_f64 () / 256.0, v.y.to_f64 () / 256.0).unwrap ();
}

pub fn apply_dt (ray: &Ray2, dt: Fx32Small) -> Ray2 {
	Ray2 {
		start: ray.start,
		dir: ray.dir * dt,
	}
}

pub fn test_ray_trace () -> Result <(), Error> {
	let scale = 1;
	//let scale_fx = Fx32::from_int (scale);

	let obstacle = vec! [
	Circle {
		center: Vec2 {x: Fx32::from_q (133, scale), y: Fx32::from_q (512 - 34, scale)},
		radius: Fx32::from_q (20, scale),
	},
	Circle {
		center: Vec2 {x: Fx32::from_q (256, scale), y: Fx32::from_q (501, scale)},
		radius: Fx32::from_q (20, scale),
	},
	Circle {
		center: Vec2 {x: Fx32::from_q (404, scale), y: Fx32::from_q (501, scale)},
		radius: Fx32::from_q (20, scale),
	},
	];

	let lines = vec! [
	WideLine {
		start: obstacle [0].center,
		end: obstacle [1].center,
		radius: Fx32::from_q (20, scale),
	},
	WideLine {
		start: obstacle [1].center,
		end: obstacle [2].center,
		radius: Fx32::from_q (20, scale),
	},
	];

	let mut num_bounces = 0;
	let mut num_ticks = 0;

	let inv_dt = 4;
	let gravity = Vec2::<Fx32> {
		x: Fx32::from_q (0, 1),
		y: Fx32::from_q (2, 1),
	};

	let obj_file = try!(File::create("lines.obj"));
	let mut writer = BufWriter::new (obj_file);

	let mut vertex_i = 1;
	let mut polyline_start = vertex_i;

	for x in 66..202 {
		let x = x * 2;
		let mut particle = Ray2 {
			start: Vec2 {
				x: Fx32::from_q (x * 2 + 1, scale * 2),
				y: Fx32::from_q (0, scale)
			},
			dir: Vec2 {
				x: Fx32::from_q (0, scale),
				y: Fx32::from_q (1, scale),
			},
		};

		write_vec2 (&mut writer, &particle.start);
		vertex_i += 1;

		let dt = Fx32::from_q (1, inv_dt).to_small ();

		for _ in 0..4000 {
			let trace_result = {
				let point_results = obstacle.iter ().map (|obstacle| ray_trace_circle_2 (&apply_dt (&particle, dt), obstacle));

				let line_results = lines.iter ().map (|line| ray_trace_line (&apply_dt (&particle, dt), line));

				point_results.chain (line_results).fold ( Ray2TraceResult::Miss, fold_closer_result)
			};

			match trace_result {
				Ray2TraceResult::Miss => {
					//let air_drag = Fx32 { x: particle.dir.length_sq ().x / -16384 };
					//let air_force = particle.dir * air_drag;
					let new_dir = particle.dir + gravity * dt;// + Vec2::<Fx32>::from (air_force * dt);
					let sum_dir = particle.dir + new_dir;
					let average_dir = Vec2::<Fx32> {
						x: Fx32 { x: sum_dir.x.x / 2 },
						y: Fx32 { x: sum_dir.y.x / 2 },
					};

					particle.start = particle.start + (average_dir * dt);
					particle.dir = new_dir;
				},
				Ray2TraceResult::Hit (_, ccd_pos, normal) => {
					particle.start = ccd_pos;
					particle.dir = particle.dir.reflect (normal) * Fx32::from_q (1023, 1024);
					//particle.dir = normal;
					num_bounces += 1;
				},
			};

			write_vec2 (&mut writer, &particle.start);
			vertex_i += 1;

			num_ticks += 1;

			if particle.start.y > 768 {
				break;
			}
		}

		for i in polyline_start..vertex_i - 1 {
			try! (write! (writer, "f {} {}\n", i, i + 1));
		}
		polyline_start = vertex_i
	}

	println! ("num_bounces: {}", num_bounces);
	println! ("num_ticks: {}", num_ticks);

	Ok (())
}

pub struct Basis2 {
	pub x: Vec2 <Fx32Small>,
	pub y: Vec2 <Fx32Small>,
}

// Constructs a basis to ray space
// Such that the ray is the X axis
pub fn get_ray_basis (ray: &Ray2, ray_length: Fx32) -> Basis2 {
	let basis_x_big = if ray_length == 0 {
		ray.dir
	}
	else {
		ray.dir / ray_length
	};

	Basis2 {
		x: basis_x_big.to_small (),
		y: basis_x_big.cross ().to_small (),
	}
}

impl Basis2 {
	pub fn to_space (&self, v: &Vec2 <Fx32>) -> Vec2 <Fx32> {
		Vec2::<Fx32> {
			x: *v * self.x,
			y: *v * self.y,
		}
	}

	pub fn from_space (&self, v: &Vec2 <Fx32>) -> Vec2 <Fx32> {
		Vec2::<Fx32> {
			x: (v.x * self.x.x) + (v.y * self.y.x),
			y: (v.x * self.x.y) + (v.y * self.y.y),
		}
	}
}

pub fn ray_trace_line (ray: &Ray2, line: &WideLine) -> Ray2TraceResult {
	if line.start == line.end {
		// Line has zero length and so zero collision area
		// If we run through the math we may get a 0 / 0 result
		// so just drop it now
		return Ray2TraceResult::Miss;
	}

	let line_tangent: Vec2 <Fx32> = line.end - line.start;
	let line_tangent = Vec2::<Fx32> {
		x: line_tangent.x * Fx32::from_q (1, 256),
		y: line_tangent.y * Fx32::from_q (1, 256),
	};
	let line_normal = line_tangent.cross ().normalized ();

	let sdf: Fx32 = (ray.start - line.start) * line_normal;

	// Flip the normal so it's towards the ray
	// This will allow us to extrude the correct side
	let line_normal = if sdf > 0 {
		line_normal
	}
	else {
		-line_normal
	};

	let along = (ray.start - line.start) * line_tangent;

	if sdf.abs () <= line.radius && along > 0 && along < (line.end - line.start) * line_tangent {
		// Ray has already started inside and we should push it out
		let towards = -Fx32::from (ray.dir * line_normal);

		let big_normal: Vec2 <Fx32> = line_normal.into ();
		let safe_point = ray.start + big_normal * (line.radius - sdf.abs ());

		if towards > 0 {
			// Ray is moving deeper inside - Pop it out and reflect it
			return Ray2TraceResult::Hit (
				Fx32::from_int (0),
				safe_point,
				line_normal,
			);
		}
		else {
			// Ray is moving out - Pop it out but consume its timestep
			return Ray2TraceResult::Hit (
				Fx32::from_int (1),
				safe_point,
				line_normal,
			);
		}
	}

	let extrude_vector = line.radius * Vec2::<Fx32>::from (line_normal);
	// Extrude the line
	let line = WideLine {
		start: line.start + extrude_vector,
		end: line.end + extrude_vector,
		radius: Fx32::from_int (0),
	};

	let ray_length = ray.dir.length ();

	if ray_length == 0 {
		return Ray2TraceResult::Miss;
	}

	let basis = get_ray_basis (ray, ray_length);

	// Transform the line to ray space
	let line = WideLine {
		start: basis.to_space (&(line.start - ray.start)),
		end: basis.to_space (&(line.end - ray.start)),
		radius: line.radius,
	};

	// Line will have zero y difference resulting in a divide by zero
	if line.start.y == line.end.y {
		return Ray2TraceResult::Miss;
	}

	// Apply SAT
	if line.start.y >= 0 && line.end.y >= 0 {
		return Ray2TraceResult::Miss;
	}
	else if line.start.y <= 0 && line.end.y <= 0 {
		return Ray2TraceResult::Miss;
	}

	// If we get here, we know that the obstacle line crosses our ray somewhere

	// Note: Lines must not have 0 length
	let obstacle_t = (-line.start.y) / (line.end.y - line.start.y);

	assert! (obstacle_t >= 0);
	assert! (obstacle_t <= 1, format!("{:?}", ray_length));

	let crossing_x = line.start.x * (Fx32::from_int (1) - obstacle_t) + line.end.x * obstacle_t;

	if crossing_x < 0 || crossing_x > ray_length {
		return Ray2TraceResult::Miss;
	}

	// The line segments intersect
	let t = crossing_x / ray_length;

	//let world_normal = basis.from_space (&Vec2::<Fx32>::from (line_normal));
	//assert! (world_normal.length_sq () < Fx32::from_int (4), "Long normal");
	/*
	let world_normal = Vec2::<Fx32> {
		x: Fx32::from_q (1, 128),
		y: Fx32::from_q (1, 1),
	};
	*/
	return Ray2TraceResult::Hit (
		t,
		ray.start + ray.dir * t,
		line_normal,
	);
}

pub fn ray_trace_circle_2 (ray: &Ray2, circle: &Circle) -> Ray2TraceResult {
	let ray_length = ray.dir.length ();
	let basis = get_ray_basis (ray, ray_length);

	let center_in_ray_space = basis.to_space (&(circle.center - ray.start));

	if center_in_ray_space.x < 0 {
		return Ray2TraceResult::Miss;
	}

	if center_in_ray_space.x > ray_length + circle.radius {
		return Ray2TraceResult::Miss;
	}

	if center_in_ray_space.y.abs () >= circle.radius {
		// Prevents a negative root later on
		return Ray2TraceResult::Miss;
	}

	let ray_space_x = center_in_ray_space.x - (circle.radius.square () - center_in_ray_space.y.square ()).sqrt ();

	if ray_space_x > ray_length || ray_length == 0 {
		return Ray2TraceResult::Miss;
	}

	let t = ray_space_x / ray_length;
	let ccd_pos = ray.start + ray.dir * t;

	if t <= 1 {
		return Ray2TraceResult::Hit (
			Fx32 { x: cmp::max (t.x, Fx32::from_int (0).x) },
			ccd_pos,
			((ccd_pos - circle.center) / circle.radius).to_small (),
		);
	}
	else {
		return Ray2TraceResult::Miss;
	}
}
<|endoftext|>


<commit_before>fn main() {
    println!("Hello, world!");
}
<commit_msg>Example of struct definition<commit_after>fn main() {
    println!("Hello, world!");
}

struct User {
    username: String,
    email: String,
    sign_in_count: u64,
    active: bool
}
<|endoftext|>


<commit_before>extern crate libc;
use libc::{c_int, c_ulonglong, size_t};

extern {
  pub fn sodium_init() -> c_int;

  pub fn randombytes_buf(buf: *mut u8,
                         size: size_t);

  pub fn crypto_auth_hmacsha512256(a: *mut u8,
                                   m: *const u8,
                                   mlen: c_ulonglong,
                                   k: *const u8) -> c_int;
  pub fn crypto_auth_hmacsha512256_verify(a: *const u8,
                                          m: *const u8,
                                          mlen: c_ulonglong,
                                          k: *const u8) -> c_int;
  pub fn crypto_auth_hmacsha256(a: *mut u8,
                                m: *const u8,
                                mlen: c_ulonglong,
                                k: *const u8) -> c_int;
  pub fn crypto_auth_hmacsha256_verify(a: *const u8,
                                       m: *const u8,
                                       mlen: c_ulonglong,
                                       k: *const u8) -> c_int;
  pub fn crypto_onetimeauth_poly1305(a: *mut u8,
                                     m: *const u8,
                                     mlen: c_ulonglong,
                                     k: *const u8) -> c_int;
  pub fn crypto_onetimeauth_poly1305_verify(a: *const u8,
                                            m: *const u8,
                                            mlen: c_ulonglong,
                                            k: *const u8) -> c_int;

  pub fn crypto_stream_aes128ctr(c: *mut u8,
                                 clen: c_ulonglong,
                                 n: *const u8,
                                 k: *const u8) -> c_int;
  pub fn crypto_stream_aes128ctr_xor(c: *mut u8,
                                     m: *const u8,
                                     mlen: c_ulonglong,
                                     n: *const u8,
                                     k: *const u8) -> c_int;
  pub fn crypto_stream_salsa20(c: *mut u8,
                               clen: c_ulonglong,
                               n: *const u8,
                               k: *const u8) -> c_int;
  pub fn crypto_stream_salsa20_xor(c: *mut u8,
                                   m: *const u8,
                                   mlen: c_ulonglong,
                                   n: *const u8,
                                   k: *const u8) -> c_int;
  pub fn crypto_stream_salsa208(c: *mut u8,
                                clen: c_ulonglong,
                                n: *const u8,
                                k: *const u8) -> c_int;
  pub fn crypto_stream_salsa208_xor(c: *mut u8,
                                    m: *const u8,
                                    mlen: c_ulonglong,
                                    n: *const u8,
                                    k: *const u8) -> c_int;
  pub fn crypto_stream_salsa2012(c: *mut u8,
                                 clen: c_ulonglong,
                                 n: *const u8,
                                 k: *const u8) -> c_int;
  pub fn crypto_stream_salsa2012_xor(c: *mut u8,
                                     m: *const u8,
                                     mlen: c_ulonglong,
                                     n: *const u8,
                                     k: *const u8) -> c_int;
  pub fn crypto_stream_xsalsa20(c: *mut u8,
                                clen: c_ulonglong,
                                n: *const u8,
                                k: *const u8) -> c_int;
  pub fn crypto_stream_xsalsa20_xor(c: *mut u8,
                                    m: *const u8,
                                    mlen: c_ulonglong,
                                    n: *const u8,
                                    k: *const u8) -> c_int;

  pub fn crypto_hash_sha256(h: *mut u8,
                            m: *const u8,
                            mlen: c_ulonglong) -> c_int;
  pub fn crypto_hash_sha512(h: *mut u8,
                            m: *const u8,
                            mlen: c_ulonglong) -> c_int;

  pub fn crypto_scalarmult_curve25519(q: *mut u8,
                                      n: *const u8,
                                      p: *const u8) -> c_int;
  pub fn crypto_scalarmult_curve25519_base(q: *mut u8,
                                           n: *const u8) -> c_int;

  pub fn crypto_box_curve25519xsalsa20poly1305_keypair(pk: *mut u8,
                                                       sk: *mut u8) -> c_int;
  pub fn crypto_box_curve25519xsalsa20poly1305(c: *mut u8,
                                               m: *const u8,
                                               mlen: c_ulonglong,
                                               n: *const u8,
                                               pk: *const u8,
                                               sk: *const u8) -> c_int;
  pub fn crypto_box_curve25519xsalsa20poly1305_open(m: *mut u8,
                                                    c: *const u8,
                                                    clen: c_ulonglong,
                                                    n: *const u8,
                                                    pk: *const u8,
                                                    sk: *const u8) -> c_int;
  pub fn crypto_box_curve25519xsalsa20poly1305_beforenm(k: *mut u8,
                                                        pk: *const u8,
                                                        sk: *const u8) -> c_int;
  pub fn crypto_box_curve25519xsalsa20poly1305_afternm(c: *mut u8,
                                                       m: *const u8,
                                                       mlen: c_ulonglong,
                                                       n: *const u8,
                                                       k: *const u8) -> c_int;
  pub fn crypto_box_curve25519xsalsa20poly1305_open_afternm(m: *mut u8,
                                                            c: *const u8,
                                                            clen: c_ulonglong,
                                                            n: *const u8,
                                                            k: *const u8) -> c_int;

  pub fn crypto_sign_ed25519_keypair(pk: *mut u8,
                                     sk: *mut u8) -> c_int;
  pub fn crypto_sign_ed25519_seed_keypair(pk: *mut u8,
                                          sk: *mut u8,
                                          seed: *const u8) -> c_int;
  pub fn crypto_sign_ed25519(sm: *mut u8,
                             smlen: *mut c_ulonglong,
                             m: *const u8,
                             mlen: c_ulonglong,
                             sk: *const u8) -> c_int;
  pub fn crypto_sign_ed25519_open(m: *mut u8,
                                  mlen: *mut c_ulonglong,
                                  sm: *const u8,
                                  smlen: c_ulonglong,
                                  pk: *const u8) -> c_int;

  pub fn crypto_sign_edwards25519sha512batch_keypair(pk: *mut u8,
                                                     sk: *mut u8) -> c_int;
  pub fn crypto_sign_edwards25519sha512batch(sm: *mut u8,
                                             smlen: *mut c_ulonglong,
                                             m: *const u8,
                                             mlen: c_ulonglong,
                                             sk: *const u8) -> c_int;
  pub fn crypto_sign_edwards25519sha512batch_open(m: *mut u8,
                                                  mlen: *mut c_ulonglong,
                                                  sm: *const u8,
                                                  smlen: c_ulonglong,
                                                  pk: *const u8) -> c_int;

  pub fn crypto_shorthash_siphash24(h: *mut u8,
                                    m: *const u8,
                                    mlen: c_ulonglong,
                                    k: *const u8) -> c_int;

  pub fn crypto_verify_16(x: *const u8, y: *const u8) -> c_int;
  pub fn crypto_verify_32(x: *const u8, y: *const u8) -> c_int;

  pub fn crypto_secretbox_xsalsa20poly1305(c: *mut u8,
                                           m: *const u8,
                                           mlen: c_ulonglong,
                                           n: *const u8,
                                           k: *const u8) -> c_int;
  pub fn crypto_secretbox_xsalsa20poly1305_open(m: *mut u8,
                                                c: *const u8,
                                                clen: c_ulonglong,
                                                n: *const u8,
                                                k: *const u8) -> c_int;
}
<commit_msg>libsodium-sys: added stream constant and tests for stream constants<commit_after>#![allow(non_upper_case_globals)]

extern crate libc;
use libc::{c_int, c_ulonglong, c_char, size_t};

pub const crypto_stream_KEYBYTES : size_t = crypto_stream_xsalsa20_KEYBYTES;
pub const crypto_stream_NONCEBYTES : size_t = crypto_stream_xsalsa20_NONCEBYTES;
pub const crypto_stream_PRIMITIVE : &'static str = "xsalsa20";

pub const crypto_stream_aes128ctr_KEYBYTES : size_t = 16;
pub const crypto_stream_aes128ctr_NONCEBYTES : size_t = 16;
pub const crypto_stream_aes128ctr_BEFORENMBYTES : size_t = 1408;

pub const crypto_stream_chacha20_KEYBYTES : size_t = 32;
pub const crypto_stream_chacha20_NONCEBYTES : size_t = 8;

pub const crypto_stream_salsa20_KEYBYTES : size_t = 32;
pub const crypto_stream_salsa20_NONCEBYTES : size_t = 8;

pub const crypto_stream_salsa2012_KEYBYTES : size_t = 32;
pub const crypto_stream_salsa2012_NONCEBYTES : size_t = 8;

pub const crypto_stream_salsa208_KEYBYTES : size_t = 32;
pub const crypto_stream_salsa208_NONCEBYTES : size_t = 8;

pub const crypto_stream_xsalsa20_KEYBYTES : size_t = 32;
pub const crypto_stream_xsalsa20_NONCEBYTES : size_t = 24;

extern {
  pub fn sodium_init() -> c_int;

  pub fn randombytes_buf(buf: *mut u8,
                         size: size_t);

  pub fn crypto_auth_hmacsha512256(a: *mut u8,
                                   m: *const u8,
                                   mlen: c_ulonglong,
                                   k: *const u8) -> c_int;
  pub fn crypto_auth_hmacsha512256_verify(a: *const u8,
                                          m: *const u8,
                                          mlen: c_ulonglong,
                                          k: *const u8) -> c_int;
  pub fn crypto_auth_hmacsha256(a: *mut u8,
                                m: *const u8,
                                mlen: c_ulonglong,
                                k: *const u8) -> c_int;
  pub fn crypto_auth_hmacsha256_verify(a: *const u8,
                                       m: *const u8,
                                       mlen: c_ulonglong,
                                       k: *const u8) -> c_int;
  pub fn crypto_onetimeauth_poly1305(a: *mut u8,
                                     m: *const u8,
                                     mlen: c_ulonglong,
                                     k: *const u8) -> c_int;
  pub fn crypto_onetimeauth_poly1305_verify(a: *const u8,
                                            m: *const u8,
                                            mlen: c_ulonglong,
                                            k: *const u8) -> c_int;

  pub fn crypto_stream_keybytes() -> size_t;
  pub fn crypto_stream_noncebytes() -> size_t;
  pub fn crypto_stream_primitive() -> *const c_char;

  pub fn crypto_stream_aes128ctr(c: *mut u8,
                                 clen: c_ulonglong,
                                 n: *const u8,
                                 k: *const u8) -> c_int;
  pub fn crypto_stream_aes128ctr_xor(c: *mut u8,
                                     m: *const u8,
                                     mlen: c_ulonglong,
                                     n: *const u8,
                                     k: *const u8) -> c_int;
  pub fn crypto_stream_aes128ctr_keybytes() -> size_t;
  pub fn crypto_stream_aes128ctr_noncebytes() -> size_t;
  pub fn crypto_stream_aes128ctr_beforenmbytes() -> size_t;

  pub fn crypto_stream_chacha20_keybytes() -> size_t;
  pub fn crypto_stream_chacha20_noncebytes() -> size_t;

  pub fn crypto_stream_salsa20(c: *mut u8,
                               clen: c_ulonglong,
                               n: *const u8,
                               k: *const u8) -> c_int;
  pub fn crypto_stream_salsa20_xor(c: *mut u8,
                                   m: *const u8,
                                   mlen: c_ulonglong,
                                   n: *const u8,
                                   k: *const u8) -> c_int;
  pub fn crypto_stream_salsa20_keybytes() -> size_t;
  pub fn crypto_stream_salsa20_noncebytes() -> size_t;

  pub fn crypto_stream_salsa208(c: *mut u8,
                                clen: c_ulonglong,
                                n: *const u8,
                                k: *const u8) -> c_int;
  pub fn crypto_stream_salsa208_xor(c: *mut u8,
                                    m: *const u8,
                                    mlen: c_ulonglong,
                                    n: *const u8,
                                    k: *const u8) -> c_int;
  pub fn crypto_stream_salsa208_keybytes() -> size_t;
  pub fn crypto_stream_salsa208_noncebytes() -> size_t;

  pub fn crypto_stream_salsa2012(c: *mut u8,
                                 clen: c_ulonglong,
                                 n: *const u8,
                                 k: *const u8) -> c_int;
  pub fn crypto_stream_salsa2012_xor(c: *mut u8,
                                     m: *const u8,
                                     mlen: c_ulonglong,
                                     n: *const u8,
                                     k: *const u8) -> c_int;
  pub fn crypto_stream_salsa2012_keybytes() -> size_t;
  pub fn crypto_stream_salsa2012_noncebytes() -> size_t;

  pub fn crypto_stream_xsalsa20(c: *mut u8,
                                clen: c_ulonglong,
                                n: *const u8,
                                k: *const u8) -> c_int;
  pub fn crypto_stream_xsalsa20_xor(c: *mut u8,
                                    m: *const u8,
                                    mlen: c_ulonglong,
                                    n: *const u8,
                                    k: *const u8) -> c_int;
  pub fn crypto_stream_xsalsa20_keybytes() -> size_t;
  pub fn crypto_stream_xsalsa20_noncebytes() -> size_t;

  pub fn crypto_hash_sha256(h: *mut u8,
                            m: *const u8,
                            mlen: c_ulonglong) -> c_int;
  pub fn crypto_hash_sha512(h: *mut u8,
                            m: *const u8,
                            mlen: c_ulonglong) -> c_int;

  pub fn crypto_scalarmult_curve25519(q: *mut u8,
                                      n: *const u8,
                                      p: *const u8) -> c_int;
  pub fn crypto_scalarmult_curve25519_base(q: *mut u8,
                                           n: *const u8) -> c_int;

  pub fn crypto_box_curve25519xsalsa20poly1305_keypair(pk: *mut u8,
                                                       sk: *mut u8) -> c_int;
  pub fn crypto_box_curve25519xsalsa20poly1305(c: *mut u8,
                                               m: *const u8,
                                               mlen: c_ulonglong,
                                               n: *const u8,
                                               pk: *const u8,
                                               sk: *const u8) -> c_int;
  pub fn crypto_box_curve25519xsalsa20poly1305_open(m: *mut u8,
                                                    c: *const u8,
                                                    clen: c_ulonglong,
                                                    n: *const u8,
                                                    pk: *const u8,
                                                    sk: *const u8) -> c_int;
  pub fn crypto_box_curve25519xsalsa20poly1305_beforenm(k: *mut u8,
                                                        pk: *const u8,
                                                        sk: *const u8) -> c_int;
  pub fn crypto_box_curve25519xsalsa20poly1305_afternm(c: *mut u8,
                                                       m: *const u8,
                                                       mlen: c_ulonglong,
                                                       n: *const u8,
                                                       k: *const u8) -> c_int;
  pub fn crypto_box_curve25519xsalsa20poly1305_open_afternm(m: *mut u8,
                                                            c: *const u8,
                                                            clen: c_ulonglong,
                                                            n: *const u8,
                                                            k: *const u8) -> c_int;

  pub fn crypto_sign_ed25519_keypair(pk: *mut u8,
                                     sk: *mut u8) -> c_int;
  pub fn crypto_sign_ed25519_seed_keypair(pk: *mut u8,
                                          sk: *mut u8,
                                          seed: *const u8) -> c_int;
  pub fn crypto_sign_ed25519(sm: *mut u8,
                             smlen: *mut c_ulonglong,
                             m: *const u8,
                             mlen: c_ulonglong,
                             sk: *const u8) -> c_int;
  pub fn crypto_sign_ed25519_open(m: *mut u8,
                                  mlen: *mut c_ulonglong,
                                  sm: *const u8,
                                  smlen: c_ulonglong,
                                  pk: *const u8) -> c_int;

  pub fn crypto_sign_edwards25519sha512batch_keypair(pk: *mut u8,
                                                     sk: *mut u8) -> c_int;
  pub fn crypto_sign_edwards25519sha512batch(sm: *mut u8,
                                             smlen: *mut c_ulonglong,
                                             m: *const u8,
                                             mlen: c_ulonglong,
                                             sk: *const u8) -> c_int;
  pub fn crypto_sign_edwards25519sha512batch_open(m: *mut u8,
                                                  mlen: *mut c_ulonglong,
                                                  sm: *const u8,
                                                  smlen: c_ulonglong,
                                                  pk: *const u8) -> c_int;

  pub fn crypto_shorthash_siphash24(h: *mut u8,
                                    m: *const u8,
                                    mlen: c_ulonglong,
                                    k: *const u8) -> c_int;

  pub fn crypto_verify_16(x: *const u8, y: *const u8) -> c_int;
  pub fn crypto_verify_32(x: *const u8, y: *const u8) -> c_int;

  pub fn crypto_secretbox_xsalsa20poly1305(c: *mut u8,
                                           m: *const u8,
                                           mlen: c_ulonglong,
                                           n: *const u8,
                                           k: *const u8) -> c_int;
  pub fn crypto_secretbox_xsalsa20poly1305_open(m: *mut u8,
                                                c: *const u8,
                                                clen: c_ulonglong,
                                                n: *const u8,
                                                k: *const u8) -> c_int;
}

#[test]
fn test_crypto_stream_keybytes() {
    assert!(unsafe { crypto_stream_keybytes() } == crypto_stream_KEYBYTES)
}
#[test]
fn test_crypto_stream_noncebytes() {
    assert!(unsafe { crypto_stream_noncebytes() } == crypto_stream_NONCEBYTES)
}
#[test]
fn test_crypto_stream_primitive() {
    let s = unsafe {
        std::c_str::CString::new(crypto_stream_primitive(), false)
    };
    assert!(s.as_bytes_no_nul() == crypto_stream_PRIMITIVE.as_bytes());
}

#[test]
fn test_crypto_stream_aes128ctr_keybytes() {
    assert!(unsafe { crypto_stream_aes128ctr_keybytes() } == crypto_stream_aes128ctr_KEYBYTES)
}
#[test]
fn test_crypto_stream_aes128ctr_noncebytes() {
    assert!(unsafe { crypto_stream_aes128ctr_noncebytes() } == crypto_stream_aes128ctr_NONCEBYTES)
}
#[test]
fn test_crypto_stream_aes128ctr_beforenmbytes() {
    assert!(unsafe { crypto_stream_aes128ctr_beforenmbytes() } == crypto_stream_aes128ctr_BEFORENMBYTES)
}

#[test]
fn test_crypto_stream_chacha20_keybytes() {
    assert!(unsafe { crypto_stream_chacha20_keybytes() } == crypto_stream_chacha20_KEYBYTES)
}
#[test]
fn test_crypto_stream_chacha20_noncebytes() {
    assert!(unsafe { crypto_stream_chacha20_noncebytes() } == crypto_stream_chacha20_NONCEBYTES)
}

#[test]
fn test_crypto_stream_salsa20_keybytes() {
    assert!(unsafe { crypto_stream_salsa20_keybytes() } == crypto_stream_salsa20_KEYBYTES)
}
#[test]
fn test_crypto_stream_salsa20_noncebytes() {
    assert!(unsafe { crypto_stream_salsa20_noncebytes() } == crypto_stream_salsa20_NONCEBYTES)
}

#[test]
fn test_crypto_stream_salsa208_keybytes() {
    assert!(unsafe { crypto_stream_salsa208_keybytes() } == crypto_stream_salsa208_KEYBYTES)
}
#[test]
fn test_crypto_stream_salsa208_noncebytes() {
    assert!(unsafe { crypto_stream_salsa208_noncebytes() } == crypto_stream_salsa208_NONCEBYTES)
}

#[test]
fn test_crypto_stream_salsa2012_keybytes() {
    assert!(unsafe { crypto_stream_salsa2012_keybytes() } == crypto_stream_salsa2012_KEYBYTES)
}
#[test]
fn test_crypto_stream_salsa2012_noncebytes() {
    assert!(unsafe { crypto_stream_salsa2012_noncebytes() } == crypto_stream_salsa2012_NONCEBYTES)
}

#[test]
fn test_crypto_stream_xsalsa20_keybytes() {
    assert!(unsafe { crypto_stream_xsalsa20_keybytes() } == crypto_stream_xsalsa20_KEYBYTES)
}
#[test]
fn test_crypto_stream_xsalsa20_noncebytes() {
    assert!(unsafe { crypto_stream_xsalsa20_noncebytes() } == crypto_stream_xsalsa20_NONCEBYTES)
}
<|endoftext|>