<commit_before>//! Concrete error types for all operations which may be invalid in a certain const context.

use rustc::hir::def_id::DefId;
use rustc::mir::BorrowKind;
use rustc::session::config::nightly_options;
use rustc::ty::TyCtxt;
use syntax::feature_gate::{emit_feature_err, GateIssue};
use syntax::symbol::sym;
use syntax_pos::{Span, Symbol};

use super::{ConstKind, Item};

use rustc_error_codes::*;

/// An operation that is not *always* allowed in a const context.
pub trait NonConstOp: std::fmt::Debug {
    /// Whether this operation can be evaluated by miri.
    const IS_SUPPORTED_IN_MIRI: bool = true;

    /// Returns a boolean indicating whether the feature gate that would allow this operation is
    /// enabled, or `None` if such a feature gate does not exist.
    fn feature_gate(_tcx: TyCtxt<'tcx>) -> Option<bool> {
        None
    }

    /// Returns `true` if this operation is allowed in the given item.
    ///
    /// This check should assume that we are not in a non-const `fn`, where all operations are
    /// legal.
    fn is_allowed_in_item(&self, item: &Item<'_, '_>) -> bool {
        Self::feature_gate(item.tcx).unwrap_or(false)
    }

    fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
        let mut err = struct_span_err!(
            item.tcx.sess,
            span,
            E0019,
            "{} contains unimplemented expression type",
            item.const_kind()
        );
        if item.tcx.sess.teach(&err.get_code().unwrap()) {
            err.note("A function call isn't allowed in the const's initialization expression \
                      because the expression's value must be known at compile-time.");
            err.note("Remember: you can't use a function call inside a const's initialization \
                      expression! However, you can use it anywhere else.");
        }
        err.emit();
    }
}

/// A `Downcast` projection.
#[derive(Debug)]
pub struct Downcast;
impl NonConstOp for Downcast {}

/// A function call where the callee is a pointer.
#[derive(Debug)]
pub struct FnCallIndirect;
impl NonConstOp for FnCallIndirect {
    fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
        let mut err = item.tcx.sess.struct_span_err(
            span,
            &format!("function pointers are not allowed in const fn"));
        err.emit();
    }
}

/// A function call where the callee is not marked as `const`.
#[derive(Debug)]
pub struct FnCallNonConst(pub DefId);
impl NonConstOp for FnCallNonConst {
    fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
        let mut err = struct_span_err!(
            item.tcx.sess,
            span,
            E0015,
            "calls in {}s are limited to constant functions, \
             tuple structs and tuple variants",
            item.const_kind(),
        );
        err.emit();
    }
}

/// A function call where the callee is not a function definition or function pointer, e.g. a
/// closure.
///
/// This can be subdivided in the future to produce a better error message.
#[derive(Debug)]
pub struct FnCallOther;
impl NonConstOp for FnCallOther {
    const IS_SUPPORTED_IN_MIRI: bool = false;
}

/// A call to a `#[unstable]` const fn or `#[rustc_const_unstable]` function.
///
/// Contains the name of the feature that would allow the use of this function.
#[derive(Debug)]
pub struct FnCallUnstable(pub DefId, pub Symbol);
impl NonConstOp for FnCallUnstable {
    fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
        let FnCallUnstable(def_id, feature) = *self;

        let mut err = item.tcx.sess.struct_span_err(span,
            &format!("`{}` is not yet stable as a const fn",
                    item.tcx.def_path_str(def_id)));
        if nightly_options::is_nightly_build() {
            help!(&mut err,
                  "add `#![feature({})]` to the \
                   crate attributes to enable",
                  feature);
        }
        err.emit();
    }
}

#[derive(Debug)]
pub struct HeapAllocation;
impl NonConstOp for HeapAllocation {
    const IS_SUPPORTED_IN_MIRI: bool = false;

    fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
        let mut err = struct_span_err!(item.tcx.sess, span, E0010,
                                       "allocations are not allowed in {}s", item.const_kind());
        err.span_label(span, format!("allocation not allowed in {}s", item.const_kind()));
        if item.tcx.sess.teach(&err.get_code().unwrap()) {
            err.note(
                "The value of statics and constants must be known at compile time, \
                 and they live for the entire lifetime of a program. Creating a boxed \
                 value allocates memory on the heap at runtime, and therefore cannot \
                 be done at compile time."
            );
        }
        err.emit();
    }
}

#[derive(Debug)]
pub struct IfOrMatch;
impl NonConstOp for IfOrMatch {
    fn feature_gate(tcx: TyCtxt<'_>) -> Option<bool> {
        Some(tcx.features().const_if_match)
    }

    fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
        // This should be caught by the HIR const-checker.
        item.tcx.sess.delay_span_bug(
            span,
            "complex control flow is forbidden in a const context",
        );
    }
}

#[derive(Debug)]
pub struct LiveDrop;
impl NonConstOp for LiveDrop {
    fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
        struct_span_err!(item.tcx.sess, span, E0493,
                         "destructors cannot be evaluated at compile-time")
            .span_label(span, format!("{}s cannot evaluate destructors",
                                      item.const_kind()))
            .emit();
    }
}

#[derive(Debug)]
pub struct Loop;
impl NonConstOp for Loop {
    fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
        // This should be caught by the HIR const-checker.
        item.tcx.sess.delay_span_bug(
            span,
            "complex control flow is forbidden in a const context",
        );
    }
}

#[derive(Debug)]
pub struct MutBorrow(pub BorrowKind);
impl NonConstOp for MutBorrow {
    fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
        let kind = self.0;
        if let BorrowKind::Mut { .. } = kind {
            let mut err = struct_span_err!(item.tcx.sess, span, E0017,
                                           "references in {}s may only refer \
                                            to immutable values", item.const_kind());
            err.span_label(span, format!("{}s require immutable values",
                                                item.const_kind()));
            if item.tcx.sess.teach(&err.get_code().unwrap()) {
                err.note("References in statics and constants may only refer \
                          to immutable values.\n\n\
                          Statics are shared everywhere, and if they refer to \
                          mutable data one might violate memory safety since \
                          holding multiple mutable references to shared data \
                          is not allowed.\n\n\
                          If you really want global mutable state, try using \
                          static mut or a global UnsafeCell.");
            }
            err.emit();
        } else {
            span_err!(item.tcx.sess, span, E0492,
                      "cannot borrow a constant which may contain \
                       interior mutability, create a static instead");
        }
    }
}

#[derive(Debug)]
pub struct MutDeref;
impl NonConstOp for MutDeref {}

#[derive(Debug)]
pub struct Panic;
impl NonConstOp for Panic {
    fn feature_gate(tcx: TyCtxt<'_>) -> Option<bool> {
        Some(tcx.features().const_panic)
    }

    fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
        emit_feature_err(
            &item.tcx.sess.parse_sess,
            sym::const_panic,
            span,
            GateIssue::Language,
            &format!("panicking in {}s is unstable", item.const_kind()),
        );
    }
}

#[derive(Debug)]
pub struct RawPtrComparison;
impl NonConstOp for RawPtrComparison {
    fn feature_gate(tcx: TyCtxt<'_>) -> Option<bool> {
        Some(tcx.features().const_compare_raw_pointers)
    }

    fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
        emit_feature_err(
            &item.tcx.sess.parse_sess,
            sym::const_compare_raw_pointers,
            span,
            GateIssue::Language,
            &format!("comparing raw pointers inside {}", item.const_kind()),
        );
    }
}

#[derive(Debug)]
pub struct RawPtrDeref;
impl NonConstOp for RawPtrDeref {
    fn feature_gate(tcx: TyCtxt<'_>) -> Option<bool> {
        Some(tcx.features().const_raw_ptr_deref)
    }

    fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
        emit_feature_err(
            &item.tcx.sess.parse_sess, sym::const_raw_ptr_deref,
            span, GateIssue::Language,
            &format!(
                "dereferencing raw pointers in {}s is unstable",
                item.const_kind(),
            ),
        );
    }
}

#[derive(Debug)]
pub struct RawPtrToIntCast;
impl NonConstOp for RawPtrToIntCast {
    fn feature_gate(tcx: TyCtxt<'_>) -> Option<bool> {
        Some(tcx.features().const_raw_ptr_to_usize_cast)
    }

    fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
        emit_feature_err(
            &item.tcx.sess.parse_sess, sym::const_raw_ptr_to_usize_cast,
            span, GateIssue::Language,
            &format!(
                "casting pointers to integers in {}s is unstable",
                item.const_kind(),
            ),
        );
    }
}

/// An access to a (non-thread-local) `static`.
#[derive(Debug)]
pub struct StaticAccess;
impl NonConstOp for StaticAccess {
    fn is_allowed_in_item(&self, item: &Item<'_, '_>) -> bool {
        item.const_kind().is_static()
    }

    fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
        let mut err = struct_span_err!(item.tcx.sess, span, E0013,
                                        "{}s cannot refer to statics, use \
                                        a constant instead", item.const_kind());
        if item.tcx.sess.teach(&err.get_code().unwrap()) {
            err.note(
                "Static and const variables can refer to other const variables. \
                    But a const variable cannot refer to a static variable."
            );
            err.help(
                "To fix this, the value can be extracted as a const and then used."
            );
        }
        err.emit();
    }
}

/// An access to a thread-local `static`.
#[derive(Debug)]
pub struct ThreadLocalAccess;
impl NonConstOp for ThreadLocalAccess {
    const IS_SUPPORTED_IN_MIRI: bool = false;

    fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
        span_err!(item.tcx.sess, span, E0625,
            "thread-local statics cannot be \
            accessed at compile-time");
    }
}

#[derive(Debug)]
pub struct Transmute;
impl NonConstOp for Transmute {
    fn feature_gate(tcx: TyCtxt<'_>) -> Option<bool> {
        Some(tcx.features().const_transmute)
    }

    fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
        emit_feature_err(
            &item.tcx.sess.parse_sess, sym::const_transmute,
            span, GateIssue::Language,
            &format!("The use of std::mem::transmute() \
            is gated in {}s", item.const_kind()));
    }
}

#[derive(Debug)]
pub struct UnionAccess;
impl NonConstOp for UnionAccess {
    fn is_allowed_in_item(&self, item: &Item<'_, '_>) -> bool {
        // Union accesses are stable in all contexts except `const fn`.
        item.const_kind() != ConstKind::ConstFn || Self::feature_gate(item.tcx).unwrap()
    }

    fn feature_gate(tcx: TyCtxt<'_>) -> Option<bool> {
        Some(tcx.features().const_fn_union)
    }

    fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
        emit_feature_err(
            &item.tcx.sess.parse_sess, sym::const_fn_union,
            span, GateIssue::Language,
            "unions in const fn are unstable",
        );
    }
}
<commit_msg>Allow `Downcast` projections if `const_if_match` enabled<commit_after>//! Concrete error types for all operations which may be invalid in a certain const context.

use rustc::hir::def_id::DefId;
use rustc::mir::BorrowKind;
use rustc::session::config::nightly_options;
use rustc::ty::TyCtxt;
use syntax::feature_gate::{emit_feature_err, GateIssue};
use syntax::symbol::sym;
use syntax_pos::{Span, Symbol};

use super::{ConstKind, Item};

use rustc_error_codes::*;

/// An operation that is not *always* allowed in a const context.
pub trait NonConstOp: std::fmt::Debug {
    /// Whether this operation can be evaluated by miri.
    const IS_SUPPORTED_IN_MIRI: bool = true;

    /// Returns a boolean indicating whether the feature gate that would allow this operation is
    /// enabled, or `None` if such a feature gate does not exist.
    fn feature_gate(_tcx: TyCtxt<'tcx>) -> Option<bool> {
        None
    }

    /// Returns `true` if this operation is allowed in the given item.
    ///
    /// This check should assume that we are not in a non-const `fn`, where all operations are
    /// legal.
    fn is_allowed_in_item(&self, item: &Item<'_, '_>) -> bool {
        Self::feature_gate(item.tcx).unwrap_or(false)
    }

    fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
        let mut err = struct_span_err!(
            item.tcx.sess,
            span,
            E0019,
            "{} contains unimplemented expression type",
            item.const_kind()
        );
        if item.tcx.sess.teach(&err.get_code().unwrap()) {
            err.note("A function call isn't allowed in the const's initialization expression \
                      because the expression's value must be known at compile-time.");
            err.note("Remember: you can't use a function call inside a const's initialization \
                      expression! However, you can use it anywhere else.");
        }
        err.emit();
    }
}

/// A `Downcast` projection.
#[derive(Debug)]
pub struct Downcast;
impl NonConstOp for Downcast {
    fn feature_gate(tcx: TyCtxt<'_>) -> Option<bool> {
        Some(tcx.features().const_if_match)
    }
}

/// A function call where the callee is a pointer.
#[derive(Debug)]
pub struct FnCallIndirect;
impl NonConstOp for FnCallIndirect {
    fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
        let mut err = item.tcx.sess.struct_span_err(
            span,
            &format!("function pointers are not allowed in const fn"));
        err.emit();
    }
}

/// A function call where the callee is not marked as `const`.
#[derive(Debug)]
pub struct FnCallNonConst(pub DefId);
impl NonConstOp for FnCallNonConst {
    fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
        let mut err = struct_span_err!(
            item.tcx.sess,
            span,
            E0015,
            "calls in {}s are limited to constant functions, \
             tuple structs and tuple variants",
            item.const_kind(),
        );
        err.emit();
    }
}

/// A function call where the callee is not a function definition or function pointer, e.g. a
/// closure.
///
/// This can be subdivided in the future to produce a better error message.
#[derive(Debug)]
pub struct FnCallOther;
impl NonConstOp for FnCallOther {
    const IS_SUPPORTED_IN_MIRI: bool = false;
}

/// A call to a `#[unstable]` const fn or `#[rustc_const_unstable]` function.
///
/// Contains the name of the feature that would allow the use of this function.
#[derive(Debug)]
pub struct FnCallUnstable(pub DefId, pub Symbol);
impl NonConstOp for FnCallUnstable {
    fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
        let FnCallUnstable(def_id, feature) = *self;

        let mut err = item.tcx.sess.struct_span_err(span,
            &format!("`{}` is not yet stable as a const fn",
                    item.tcx.def_path_str(def_id)));
        if nightly_options::is_nightly_build() {
            help!(&mut err,
                  "add `#![feature({})]` to the \
                   crate attributes to enable",
                  feature);
        }
        err.emit();
    }
}

#[derive(Debug)]
pub struct HeapAllocation;
impl NonConstOp for HeapAllocation {
    const IS_SUPPORTED_IN_MIRI: bool = false;

    fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
        let mut err = struct_span_err!(item.tcx.sess, span, E0010,
                                       "allocations are not allowed in {}s", item.const_kind());
        err.span_label(span, format!("allocation not allowed in {}s", item.const_kind()));
        if item.tcx.sess.teach(&err.get_code().unwrap()) {
            err.note(
                "The value of statics and constants must be known at compile time, \
                 and they live for the entire lifetime of a program. Creating a boxed \
                 value allocates memory on the heap at runtime, and therefore cannot \
                 be done at compile time."
            );
        }
        err.emit();
    }
}

#[derive(Debug)]
pub struct IfOrMatch;
impl NonConstOp for IfOrMatch {
    fn feature_gate(tcx: TyCtxt<'_>) -> Option<bool> {
        Some(tcx.features().const_if_match)
    }

    fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
        // This should be caught by the HIR const-checker.
        item.tcx.sess.delay_span_bug(
            span,
            "complex control flow is forbidden in a const context",
        );
    }
}

#[derive(Debug)]
pub struct LiveDrop;
impl NonConstOp for LiveDrop {
    fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
        struct_span_err!(item.tcx.sess, span, E0493,
                         "destructors cannot be evaluated at compile-time")
            .span_label(span, format!("{}s cannot evaluate destructors",
                                      item.const_kind()))
            .emit();
    }
}

#[derive(Debug)]
pub struct Loop;
impl NonConstOp for Loop {
    fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
        // This should be caught by the HIR const-checker.
        item.tcx.sess.delay_span_bug(
            span,
            "complex control flow is forbidden in a const context",
        );
    }
}

#[derive(Debug)]
pub struct MutBorrow(pub BorrowKind);
impl NonConstOp for MutBorrow {
    fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
        let kind = self.0;
        if let BorrowKind::Mut { .. } = kind {
            let mut err = struct_span_err!(item.tcx.sess, span, E0017,
                                           "references in {}s may only refer \
                                            to immutable values", item.const_kind());
            err.span_label(span, format!("{}s require immutable values",
                                                item.const_kind()));
            if item.tcx.sess.teach(&err.get_code().unwrap()) {
                err.note("References in statics and constants may only refer \
                          to immutable values.\n\n\
                          Statics are shared everywhere, and if they refer to \
                          mutable data one might violate memory safety since \
                          holding multiple mutable references to shared data \
                          is not allowed.\n\n\
                          If you really want global mutable state, try using \
                          static mut or a global UnsafeCell.");
            }
            err.emit();
        } else {
            span_err!(item.tcx.sess, span, E0492,
                      "cannot borrow a constant which may contain \
                       interior mutability, create a static instead");
        }
    }
}

#[derive(Debug)]
pub struct MutDeref;
impl NonConstOp for MutDeref {}

#[derive(Debug)]
pub struct Panic;
impl NonConstOp for Panic {
    fn feature_gate(tcx: TyCtxt<'_>) -> Option<bool> {
        Some(tcx.features().const_panic)
    }

    fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
        emit_feature_err(
            &item.tcx.sess.parse_sess,
            sym::const_panic,
            span,
            GateIssue::Language,
            &format!("panicking in {}s is unstable", item.const_kind()),
        );
    }
}

#[derive(Debug)]
pub struct RawPtrComparison;
impl NonConstOp for RawPtrComparison {
    fn feature_gate(tcx: TyCtxt<'_>) -> Option<bool> {
        Some(tcx.features().const_compare_raw_pointers)
    }

    fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
        emit_feature_err(
            &item.tcx.sess.parse_sess,
            sym::const_compare_raw_pointers,
            span,
            GateIssue::Language,
            &format!("comparing raw pointers inside {}", item.const_kind()),
        );
    }
}

#[derive(Debug)]
pub struct RawPtrDeref;
impl NonConstOp for RawPtrDeref {
    fn feature_gate(tcx: TyCtxt<'_>) -> Option<bool> {
        Some(tcx.features().const_raw_ptr_deref)
    }

    fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
        emit_feature_err(
            &item.tcx.sess.parse_sess, sym::const_raw_ptr_deref,
            span, GateIssue::Language,
            &format!(
                "dereferencing raw pointers in {}s is unstable",
                item.const_kind(),
            ),
        );
    }
}

#[derive(Debug)]
pub struct RawPtrToIntCast;
impl NonConstOp for RawPtrToIntCast {
    fn feature_gate(tcx: TyCtxt<'_>) -> Option<bool> {
        Some(tcx.features().const_raw_ptr_to_usize_cast)
    }

    fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
        emit_feature_err(
            &item.tcx.sess.parse_sess, sym::const_raw_ptr_to_usize_cast,
            span, GateIssue::Language,
            &format!(
                "casting pointers to integers in {}s is unstable",
                item.const_kind(),
            ),
        );
    }
}

/// An access to a (non-thread-local) `static`.
#[derive(Debug)]
pub struct StaticAccess;
impl NonConstOp for StaticAccess {
    fn is_allowed_in_item(&self, item: &Item<'_, '_>) -> bool {
        item.const_kind().is_static()
    }

    fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
        let mut err = struct_span_err!(item.tcx.sess, span, E0013,
                                        "{}s cannot refer to statics, use \
                                        a constant instead", item.const_kind());
        if item.tcx.sess.teach(&err.get_code().unwrap()) {
            err.note(
                "Static and const variables can refer to other const variables. \
                    But a const variable cannot refer to a static variable."
            );
            err.help(
                "To fix this, the value can be extracted as a const and then used."
            );
        }
        err.emit();
    }
}

/// An access to a thread-local `static`.
#[derive(Debug)]
pub struct ThreadLocalAccess;
impl NonConstOp for ThreadLocalAccess {
    const IS_SUPPORTED_IN_MIRI: bool = false;

    fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
        span_err!(item.tcx.sess, span, E0625,
            "thread-local statics cannot be \
            accessed at compile-time");
    }
}

#[derive(Debug)]
pub struct Transmute;
impl NonConstOp for Transmute {
    fn feature_gate(tcx: TyCtxt<'_>) -> Option<bool> {
        Some(tcx.features().const_transmute)
    }

    fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
        emit_feature_err(
            &item.tcx.sess.parse_sess, sym::const_transmute,
            span, GateIssue::Language,
            &format!("The use of std::mem::transmute() \
            is gated in {}s", item.const_kind()));
    }
}

#[derive(Debug)]
pub struct UnionAccess;
impl NonConstOp for UnionAccess {
    fn is_allowed_in_item(&self, item: &Item<'_, '_>) -> bool {
        // Union accesses are stable in all contexts except `const fn`.
        item.const_kind() != ConstKind::ConstFn || Self::feature_gate(item.tcx).unwrap()
    }

    fn feature_gate(tcx: TyCtxt<'_>) -> Option<bool> {
        Some(tcx.features().const_fn_union)
    }

    fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
        emit_feature_err(
            &item.tcx.sess.parse_sess, sym::const_fn_union,
            span, GateIssue::Language,
            "unions in const fn are unstable",
        );
    }
}
<|endoftext|>


<commit_before>use traits::operations::{Transpose, ApproxEq};
use traits::structure::{ColSlice, Eye, Indexable, Diag, SquareMat, BaseFloat};
use traits::geometry::Norm;
use std::cmp::min;
use std::ops::{Mul, Add, Sub};

/// Get the householder matrix corresponding to a reflexion to the hyperplane
/// defined by `vec`. It can be a reflexion contained in a subspace.
///
/// # Arguments
/// * `dim` - the dimension of the space the resulting matrix operates in
/// * `start` - the starting dimension of the subspace of the reflexion
/// * `vec` - the vector defining the reflection.
pub fn householder_matrix<N, V, M>(dim: usize, start: usize, vec: V) -> M
    where N: BaseFloat,
          M: Eye + Indexable<(usize, usize), N>,
          V: Indexable<usize, N> {
    let mut qk : M = Eye::new_identity(dim);
    let subdim = vec.shape();

    let stop = subdim + start;

    assert!(dim >= stop);

    for j in (start .. stop) {
        for i in (start .. stop) {
            unsafe {
                let vv = vec.unsafe_at(i - start) * vec.unsafe_at(j - start);
                let qkij = qk.unsafe_at((i, j));
                qk.unsafe_set((i, j), qkij - vv - vv);
            }
        }
    }
    qk
}

/// QR decomposition using Householder reflections.
///
/// # Arguments
/// * `m` - matrix to decompose
pub fn qr<N, V, M>(m: &M) -> (M, M)
    where N: BaseFloat,
          V: Indexable<usize, N> + Norm<N>,
          M: Copy + Eye + ColSlice<V> + Transpose + Indexable<(usize, usize), N> +
             Mul<M, Output = M> {
    let (rows, cols) = m.shape();
    assert!(rows >= cols);
    let mut q : M = Eye::new_identity(rows);
    let mut r = *m;

    for ite in 0..min(rows - 1, cols) {
        let mut v = r.col_slice(ite, ite, rows);
        let alpha =
            if unsafe { v.unsafe_at(ite) } >= ::zero() {
                -Norm::norm(&v)
            }
            else {
                Norm::norm(&v)
            };
        unsafe {
            let x = v.unsafe_at(0);
            v.unsafe_set(0, x - alpha);
        }
        if !::is_zero(&v.normalize_mut()) {
            let qk: M = householder_matrix(rows, ite, v);
            r = qk * r;
            q = q * Transpose::transpose(&qk);
        }
    }

    (q, r)
}

/// Eigendecomposition of a square matrix using the qr algorithm.
pub fn eigen_qr<N, V, VS, M>(m: &M, eps: &N, niter: usize) -> (M, V)
    where N:  BaseFloat,
          VS: Indexable<usize, N> + Norm<N>,
          M:  Indexable<(usize, usize), N> + SquareMat<N, V> + Add<M, Output = M> +
              Sub<M, Output = M> + ColSlice<VS> +
              ApproxEq<N> + Copy {
    let mut eigenvectors: M = ::one::<M>();
    let mut eigenvalues = *m;
    // let mut shifter: M = Eye::new_identity(rows);

    let mut iter = 0;
    for _ in 0..niter {
        let mut stop = true;

        for j in 0..::dim::<M>() {
            for i in 0..j {
                if unsafe { eigenvalues.unsafe_at((i, j)) }.abs() >= *eps {
                    stop = false;
                    break;
                }
            }

            for i in j + 1..::dim::<M>() {
                if unsafe { eigenvalues.unsafe_at((i, j)) }.abs() >= *eps {
                    stop = false;
                    break;
                }
            }
        }

        if stop {
            break;
        }
        iter = iter + 1;

        let (q, r) = qr(&eigenvalues);;

        eigenvalues  = r * q;
        eigenvectors = eigenvectors * q;
    }

    (eigenvectors, eigenvalues.diag())
}

/// Cholesky decomposition G of a square symmetric positive definite matrix A, such that A = G * G^T
///
/// # Arguments
/// * `m` - square symmetric positive definite matrix to decompose
pub fn cholesky<N, V, VS, M>(m: &M) -> Result<M, &'static str>
    where N:  BaseFloat,
          VS: Indexable<usize, N> + Norm<N>,
          M:  Indexable<(usize, usize), N> + SquareMat<N, V> + Add<M, Output = M> +
              Sub<M, Output = M> + ColSlice<VS> +
              ApproxEq<N> + Copy {

    let mut out = m.clone().transpose();

    if !ApproxEq::approx_eq(&out, &m) {
        return Err("Cholesky: Input matrix is not symmetric");
    }

    for i in 0..out.nrows() {
        for j in 0..(i+1) {

            let mut sum: N = out[(i,j)];

            for k in 0..j {
                sum = sum - out[(i, k)] * out[(j, k)];
            }

            if i > j {
                out[(i, j)] = sum / out[(j, j)];
            }
            else if i < j {
                out[(i,j)] = N::zero();
            }
            else if sum > N::zero() {
                out[(i,i)] = sum.sqrt();
            }
            else {
                return Err("Cholesky: Input matrix is not positive definite to machine precision");
            }
        }
    }

    for i in 0..out.nrows() {
        for j in i+1..out.ncols() {
            out[(i,j)] = N::zero();
        }

    }

    return Ok(out);
}<commit_msg>Removed unused code<commit_after>use traits::operations::{Transpose, ApproxEq};
use traits::structure::{ColSlice, Eye, Indexable, Diag, SquareMat, BaseFloat};
use traits::geometry::Norm;
use std::cmp::min;
use std::ops::{Mul, Add, Sub};

/// Get the householder matrix corresponding to a reflexion to the hyperplane
/// defined by `vec`. It can be a reflexion contained in a subspace.
///
/// # Arguments
/// * `dim` - the dimension of the space the resulting matrix operates in
/// * `start` - the starting dimension of the subspace of the reflexion
/// * `vec` - the vector defining the reflection.
pub fn householder_matrix<N, V, M>(dim: usize, start: usize, vec: V) -> M
    where N: BaseFloat,
          M: Eye + Indexable<(usize, usize), N>,
          V: Indexable<usize, N> {
    let mut qk : M = Eye::new_identity(dim);
    let subdim = vec.shape();

    let stop = subdim + start;

    assert!(dim >= stop);

    for j in (start .. stop) {
        for i in (start .. stop) {
            unsafe {
                let vv = vec.unsafe_at(i - start) * vec.unsafe_at(j - start);
                let qkij = qk.unsafe_at((i, j));
                qk.unsafe_set((i, j), qkij - vv - vv);
            }
        }
    }
    qk
}

/// QR decomposition using Householder reflections.
///
/// # Arguments
/// * `m` - matrix to decompose
pub fn qr<N, V, M>(m: &M) -> (M, M)
    where N: BaseFloat,
          V: Indexable<usize, N> + Norm<N>,
          M: Copy + Eye + ColSlice<V> + Transpose + Indexable<(usize, usize), N> +
             Mul<M, Output = M> {
    let (rows, cols) = m.shape();
    assert!(rows >= cols);
    let mut q : M = Eye::new_identity(rows);
    let mut r = *m;

    for ite in 0..min(rows - 1, cols) {
        let mut v = r.col_slice(ite, ite, rows);
        let alpha =
            if unsafe { v.unsafe_at(ite) } >= ::zero() {
                -Norm::norm(&v)
            }
            else {
                Norm::norm(&v)
            };
        unsafe {
            let x = v.unsafe_at(0);
            v.unsafe_set(0, x - alpha);
        }
        if !::is_zero(&v.normalize_mut()) {
            let qk: M = householder_matrix(rows, ite, v);
            r = qk * r;
            q = q * Transpose::transpose(&qk);
        }
    }

    (q, r)
}

/// Eigendecomposition of a square matrix using the qr algorithm.
pub fn eigen_qr<N, V, VS, M>(m: &M, eps: &N, niter: usize) -> (M, V)
    where N:  BaseFloat,
          VS: Indexable<usize, N> + Norm<N>,
          M:  Indexable<(usize, usize), N> + SquareMat<N, V> + Add<M, Output = M> +
              Sub<M, Output = M> + ColSlice<VS> +
              ApproxEq<N> + Copy {
    let mut eigenvectors: M = ::one::<M>();
    let mut eigenvalues = *m;
    // let mut shifter: M = Eye::new_identity(rows);

    let mut iter = 0;
    for _ in 0..niter {
        let mut stop = true;

        for j in 0..::dim::<M>() {
            for i in 0..j {
                if unsafe { eigenvalues.unsafe_at((i, j)) }.abs() >= *eps {
                    stop = false;
                    break;
                }
            }

            for i in j + 1..::dim::<M>() {
                if unsafe { eigenvalues.unsafe_at((i, j)) }.abs() >= *eps {
                    stop = false;
                    break;
                }
            }
        }

        if stop {
            break;
        }
        iter = iter + 1;

        let (q, r) = qr(&eigenvalues);;

        eigenvalues  = r * q;
        eigenvectors = eigenvectors * q;
    }

    (eigenvectors, eigenvalues.diag())
}

/// Cholesky decomposition G of a square symmetric positive definite matrix A, such that A = G * G^T
///
/// # Arguments
/// * `m` - square symmetric positive definite matrix to decompose
pub fn cholesky<N, V, VS, M>(m: &M) -> Result<M, &'static str>
    where N:  BaseFloat,
          VS: Indexable<usize, N> + Norm<N>,
          M:  Indexable<(usize, usize), N> + SquareMat<N, V> + Add<M, Output = M> +
              Sub<M, Output = M> + ColSlice<VS> +
              ApproxEq<N> + Copy {

    let mut out = m.clone().transpose();

    if !ApproxEq::approx_eq(&out, &m) {
        return Err("Cholesky: Input matrix is not symmetric");
    }

    for i in 0..out.nrows() {
        for j in 0..(i+1) {

            let mut sum: N = out[(i,j)];

            for k in 0..j {
                sum = sum - out[(i, k)] * out[(j, k)];
            }

            if i > j {
                out[(i, j)] = sum / out[(j, j)];
            }
            else if sum > N::zero() {
                out[(i,i)] = sum.sqrt();
            }
            else {
                return Err("Cholesky: Input matrix is not positive definite to machine precision");
            }
        }
    }

    for i in 0..out.nrows() {
        for j in i+1..out.ncols() {
            out[(i,j)] = N::zero();
        }

    }

    return Ok(out);
}<|endoftext|>


<commit_before>pub fn find() -> Option<i32> {
    let n: i32 = 1000;
    for a in 1..n {
        for b in a..n {
            let c = n - a - b;
            if a * a + b * b == c * c {
                return Some(a * b * c);
            }
        }
    }
    None
}
<commit_msg>better: no overflow, all unsigned<commit_after>pub fn find() -> Option<u32> {
    let n: u32 = 1000;
    for a in 1..n {
        for b in 1..a - 1 {
            let c = n - a - b;
            if a * a + b * b == c * c {
                return Some(a * b * c);
            }
        }
    }
    None
}
<|endoftext|>


<commit_before>//! This doc was generate for the upcoming v0.7 of the wayland-client crate.
//! This new version is a complete change of the API. If you are looking for the
//! documentation of the crate currently on crates.io, check
//! [on docs.rs](https://docs.rs/wayland-client/0.6.2/wayland_client/).

#![warn(missing_docs)]

#[macro_use] extern crate bitflags;
#[macro_use] extern crate wayland_sys;
extern crate libc;

pub use generated::client as protocol;

use wayland_sys::client::wl_proxy;
use wayland_sys::common::{wl_interface, wl_argument};

mod display;
mod event_queue;
mod env;

pub use event_queue::{EventQueue, EventQueueHandle, StateGuard};
pub use display::{default_connect, ConnectError, FatalError};
pub use env::{EnvHandler, EnvHandlerInner};

/// Common routines for wayland proxy objects.
///
/// All wayland objects automatically implement this trait
/// as generated by the scanner.
///
/// It is mostly used for internal use by the library, and you
/// should only need these methods for interfacing with C library
/// working on wayland objects.
pub trait Proxy {
    /// Pointer to the underlying wayland proxy object
    fn ptr(&self) -> *mut wl_proxy;
    /// Create an instance from a wayland pointer
    ///
    /// The pointer must refer to a valid wayland proxy
    /// of the appropriate interface, but that have not
    /// yet been seen by the library.
    ///
    /// The library will take control of the object (notably
    /// overwrite its user_data).
    unsafe fn from_ptr_new(*mut wl_proxy) -> Self;
    /// Create an instance from a wayland pointer
    ///
    /// The pointer must refer to a valid wayland proxy
    /// of the appropriate interface, and have already been
    /// initialized by the library (it'll assume this proxy
    /// user_data contains a certain kind of data).
    unsafe fn from_ptr_initialized(*mut wl_proxy) -> Self;
    /// Pointer to the interface representation
    fn interface_ptr() -> *const wl_interface;
    /// Internal wayland name of this interface
    fn interface_name() -> &'static str;
    /// Max version of this interface supported
    fn supported_version() -> u32;
    /// Current version of the interface this proxy is instanciated with
    fn version(&self) -> u32;
    /// Check if the proxt behind this handle is actually still alive
    fn is_alive(&self) -> bool;
}

/// Possible outcome of the call of a request on a proxy
pub enum RequestResult<T> {
    /// Message has been buffered and will be sent to server
    Sent(T),
    /// This proxy is already destroyed, request has been ignored
    Destroyed
}

impl<T> RequestResult<T> {
    /// Assert that result is successfull and extract the value.
    ///
    /// Panics with provided error message if the result was `Destroyed`.
    pub fn expect(self, error: &str) -> T {
        match self {
            RequestResult::Sent(v) => v,
            RequestResult::Destroyed => panic!("{}", error)
        }
    }
}

/// Generic handler trait
///
/// This trait is automatically implemented for objects that implement
/// the appropriate interface-specific `Handler` traits. It represents
/// the hability for a type to handle events directed to a given wayland
/// interface.
///
/// For example, implementing `wl_surface::Handler` for you type will
/// automatically provide it with an implementation of
/// `Handler<WlSurface>` as well. This is the only correct way
/// to implement this trait, and you should not attempt to implement it
/// yourself.
pub unsafe trait Handler<T: Proxy> {
    /// Dispatch a message.
    unsafe fn message(&mut self, evq: &mut EventQueueHandle, proxy: &T, opcode: u32, args: *const wl_argument) -> Result<(),()>;
}

mod generated {
    #![allow(dead_code,non_camel_case_types,unused_unsafe,unused_variables)]
    #![allow(non_upper_case_globals,non_snake_case,unused_imports)]
    #![allow(missing_docs)]

    pub mod interfaces {
        include!(concat!(env!("OUT_DIR"), "/wayland_interfaces.rs"));
    }

    pub mod client {
        //! The wayland core protocol
        //!
        //! This module contains all objects of the core wayland protocol.
        //!
        //! It has been generated from the `wayland.xml` protocol file
        //! using `wayland_scanner`.

        // Imports that need to be available to submodules
        // but should not be in public API.
        // Will be fixable with pub(restricted).
        #[doc(hidden)] pub use {Proxy, Handler, RequestResult};
        #[doc(hidden)] pub use event_queue::EventQueueHandle;
        #[doc(hidden)] pub use super::interfaces;
        include!(concat!(env!("OUT_DIR"), "/wayland_api.rs"));
    }
}

pub mod sys {
    //! Reexports of types and objects from wayland-sys
    pub use wayland_sys::common::*;
    pub use wayland_sys::client::*;
}
<commit_msg>client: crate level documentation.<commit_after>//! Client-side Wayland connector
//!
//! # Overview
//!
//! Connection to the Wayland compositor is achieved by
//! the `default_connect()` function, which provides you
//! with a `WlDisplay` and an `EventQueue`.
//!
//! From the display, you'll retrieve the registry, from
//! which you can instanciate the globals you need.
//!
//! You then register your handlers for events to the
//! event queue, and integrate it in your main event loop.
//!
//! # Handlers and event queues
//!
//! This crate mirrors the callback-oriented design of the
//! Wayland C library by using handler structs: each wayland
//! type defines a `Handler` trait in its module, which one
//! method for each possible event this object can receive.
//!
//! To use it, you need to build a struct (or enum) that will
//! implement all the traits for all the events you are interested
//! in. All methods of handler traits provide a default
//! implementation foing nothing, so you don't need to write
//! empty methods for events you want to ignore. You also need
//! to declare the handler capability for your struct using
//! the `declare_handler!(..)` macro. A single struct can be
//! handler for several wayland interfaces at once.
//!
//! ## Example of handler
//!
//! ```ignore
//! /*  writing a handler for an wl_foo interface */
//! // import the module of this interface
//! use wl_foo;
//!
//! struct MyHandler { /* some fields to store state */ }
//!
//! // implement handerl trait:
//! impl wl_foo::Handler for MyHandler {
//!     fn an_event(&mut self,
//!                 evqh: &mut EventQueueHandle,
//!                 me: &wl_foo::WlFoo,
//!                 arg1, arg2, // the actual args of the event
//!     ) {
//!         /* handle the event */
//!     }
//! }
//!
//! // declare the handler capability
//! // this boring step is necessary because Rust's type system is
//! // not yet magical enough
//! declare_handler!(MyHandler, wl_foo::Handler, wl_foo::WlFoo);
//! ```
//!
//! ## Event Queues and handlers
//!
//! In your initialization code, you'll need to instanciate
//! your handler and give it to the event queue:
//!
//! ```ignore
//! let handler_id = event_queue.add_handler(MyHandler::new());
//! ```
//!
//! Then, you can register your wayland objects to this handler:
//!
//! ```ignore
//! // This type info is necessary for safety, as at registration
//! // time the event_queue will check that the handler you
//! // specified using handler_id has the same type as provided
//! // as argument, and that this type implements the appropriate
//! // handler trait.
//! event_queue.register::<_, MyHandler>(&my_object, handler_id);
//! ```
//!
//! You can have several handlers in the same event queue,
//! but they cannot share their state without synchronisation
//! primitives like `Arc`, `Mutex` and friends, so if two handlers
//! need to share some state, you should consider building them
//! as a single struct.
//!
//! A given wayland object can only be registered to a single
//! handler at a given time, re-registering it to a new handler
//! will overwrite the previous configuration.
//!
//! Handlers can be created, and objects registered to them
//! from within a handler method, using the `&EventQueueHandle`
//! argument.
//!
//! ## Event loop integration
//!
//! Once this setup is done, you can integrate the event queue
//! to the main event loop of your program:
//!
//! ```ignore
//! loop {
//!     // flush events to the server
//!     display.flush().unwrap();
//!     // receive events from the server and dispatch them
//!     // to handlers (might block)
//!     event_queue.dispatch().unwrap();
//! }
//! ```
//!
//! For more precise control of the flow of the event queue
//! (and importantly non-blocking options), see `EventQueue`
//! documentation.
//!
//! # Protocols integration
//!
//! This crate provides the basic primitives as well as the
//! core wayland protocol (in the `protocol` module), but
//! other protocols can be integrated from XML descriptions.
//!
//! The the crate `wayland_scanner` and its documentation for
//! details about how to do so.

#![warn(missing_docs)]

#[macro_use] extern crate bitflags;
#[macro_use] extern crate wayland_sys;
extern crate libc;

pub use generated::client as protocol;

use wayland_sys::client::wl_proxy;
use wayland_sys::common::{wl_interface, wl_argument};

mod display;
mod event_queue;
mod env;

pub use event_queue::{EventQueue, EventQueueHandle, StateGuard};
pub use display::{default_connect, ConnectError, FatalError};
pub use env::{EnvHandler, EnvHandlerInner};

/// Common routines for wayland proxy objects.
///
/// All wayland objects automatically implement this trait
/// as generated by the scanner.
///
/// It is mostly used for internal use by the library, and you
/// should only need these methods for interfacing with C library
/// working on wayland objects.
pub trait Proxy {
    /// Pointer to the underlying wayland proxy object
    fn ptr(&self) -> *mut wl_proxy;
    /// Create an instance from a wayland pointer
    ///
    /// The pointer must refer to a valid wayland proxy
    /// of the appropriate interface, but that have not
    /// yet been seen by the library.
    ///
    /// The library will take control of the object (notably
    /// overwrite its user_data).
    unsafe fn from_ptr_new(*mut wl_proxy) -> Self;
    /// Create an instance from a wayland pointer
    ///
    /// The pointer must refer to a valid wayland proxy
    /// of the appropriate interface, and have already been
    /// initialized by the library (it'll assume this proxy
    /// user_data contains a certain kind of data).
    unsafe fn from_ptr_initialized(*mut wl_proxy) -> Self;
    /// Pointer to the interface representation
    fn interface_ptr() -> *const wl_interface;
    /// Internal wayland name of this interface
    fn interface_name() -> &'static str;
    /// Max version of this interface supported
    fn supported_version() -> u32;
    /// Current version of the interface this proxy is instanciated with
    fn version(&self) -> u32;
    /// Check if the proxt behind this handle is actually still alive
    fn is_alive(&self) -> bool;
}

/// Possible outcome of the call of a request on a proxy
pub enum RequestResult<T> {
    /// Message has been buffered and will be sent to server
    Sent(T),
    /// This proxy is already destroyed, request has been ignored
    Destroyed
}

impl<T> RequestResult<T> {
    /// Assert that result is successfull and extract the value.
    ///
    /// Panics with provided error message if the result was `Destroyed`.
    pub fn expect(self, error: &str) -> T {
        match self {
            RequestResult::Sent(v) => v,
            RequestResult::Destroyed => panic!("{}", error)
        }
    }
}

/// Generic handler trait
///
/// This trait is automatically implemented for objects that implement
/// the appropriate interface-specific `Handler` traits. It represents
/// the hability for a type to handle events directed to a given wayland
/// interface.
///
/// For example, implementing `wl_surface::Handler` for you type will
/// automatically provide it with an implementation of
/// `Handler<WlSurface>` as well. This is the only correct way
/// to implement this trait, and you should not attempt to implement it
/// yourself.
pub unsafe trait Handler<T: Proxy> {
    /// Dispatch a message.
    unsafe fn message(&mut self, evq: &mut EventQueueHandle, proxy: &T, opcode: u32, args: *const wl_argument) -> Result<(),()>;
}

mod generated {
    #![allow(dead_code,non_camel_case_types,unused_unsafe,unused_variables)]
    #![allow(non_upper_case_globals,non_snake_case,unused_imports)]
    #![allow(missing_docs)]

    pub mod interfaces {
        include!(concat!(env!("OUT_DIR"), "/wayland_interfaces.rs"));
    }

    pub mod client {
        //! The wayland core protocol
        //!
        //! This module contains all objects of the core wayland protocol.
        //!
        //! It has been generated from the `wayland.xml` protocol file
        //! using `wayland_scanner`.

        // Imports that need to be available to submodules
        // but should not be in public API.
        // Will be fixable with pub(restricted).
        #[doc(hidden)] pub use {Proxy, Handler, RequestResult};
        #[doc(hidden)] pub use event_queue::EventQueueHandle;
        #[doc(hidden)] pub use super::interfaces;
        include!(concat!(env!("OUT_DIR"), "/wayland_api.rs"));
    }
}

pub mod sys {
    //! Reexports of types and objects from wayland-sys
    pub use wayland_sys::common::*;
    pub use wayland_sys::client::*;
}
<|endoftext|>


<commit_before>/*===============================================================================================*/
// Copyright 2016 Kyle Finlay
//
// 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.
/*===============================================================================================*/

extern crate glob;
extern crate libloading;

use ::engine::App;
use ::engine::backend::{Config, Info, Type};

use self::glob::glob;
use self::libloading::{Library, Symbol};

use std::fs;

/*===============================================================================================*/
/*------MANAGER STRUCT---------------------------------------------------------------------------*/
/*===============================================================================================*/

/// Manages the loading of the various backend systems.
#[derive (Default)]
pub struct Manager {

    // Private
    _config: Config,
    _backend_list: Vec<Info>,
    _ext: String,
}

/*===============================================================================================*/
/*------MANAGER PUBLIC METHODS-------------------------------------------------------------------*/
/*===============================================================================================*/

impl Manager {

    /// Loads the configuration file.
    pub fn load_config (&mut self) {

        // Get a pointer to the config manager
        let cfg_mgr = App::get_config_manager ().unwrap ();
        let cfg_exists = cfg_mgr.borrow ().config_exists ("backend_manager");

        // Check if the config file for the backend manager exists.
        // If so, load it.
        // If not, create it.
        let cfg = {

            if cfg_exists {
                cfg_mgr.borrow ().load_config::<Config> ("backend_manager").unwrap ()
            }

            else {

                cfg_mgr.borrow_mut ().create_config::<Config> ("backend_manager");
                cfg_mgr.borrow ().load_config::<Config> ("backend_manager").unwrap ()
            }
        };

        self._config = cfg;
    }

/*-----------------------------------------------------------------------------------------------*/

    /// Saves the configuration file.
    pub fn save_config (&self) {

        // Get a pointer to the config manager
        let cfg_mgr = App::get_config_manager ().unwrap ();
        let cfg_exists = cfg_mgr.borrow ().config_exists ("backend_manager");

        // Check if the config file for the backend manager exists.
        // If so, save it.
        // If not, create it.
        if cfg_exists {
            cfg_mgr.borrow ().save_config ("backend_manager", &self._config).unwrap ();
        }

        else {

            cfg_mgr.borrow_mut ().create_config::<Config> ("backend_manager");
            cfg_mgr.borrow ().save_config ("backend_manager", &self._config).unwrap ();
        }
    }

/*-----------------------------------------------------------------------------------------------*/

    /// Queries the backend directory for plugins.
    ///
    /// All valid backend plugins are then registered with the manager for loading.
    /// Any plugins with errors are ignored.
    pub fn query_backend_dir (&mut self) {

        // Clear the old backend list
        self._backend_list.clear ();
        info! ("Searching for backend plugins...");

        if !&self._check_backend_dir_exists () {
            return;
        }

        // Recurse through the backend directory, and get all backend plugins
        for path in glob (&format! ("{}/*{}", &self._config.backend_dir, &self._ext)).unwrap ().filter_map (Result::ok) {

            info! ("Found: {:?}", &path.file_name ().unwrap ());

            // Load the library and get the function symbols.
            match Library::new (&path) {

                Ok (lib) => {

                    let get_backend_info: Symbol<unsafe extern fn () -> Info> = unsafe {

                        match lib.get (b"get_backend_info\0") {

                            Ok (l) => l,
                            Err (e) => {

                                warn! ("Could not find function 'get_backend_info' in library {:?}\n{}",
                                       &path.file_name ().unwrap (), e);
                                continue;
                            }
                        }
                    };

                    // Create a new instance of the plugin, and add it to the list
                    unsafe {
                        self._backend_list.push (get_backend_info ());
                    }

                    info! ("Added: {:?}", &path.file_name ().unwrap ());
                },

                Err (e) => {

                    warn! ("Could not load library {:?}\n{}", &path.file_name ().unwrap (), e);
                    continue;
                }
            }
        }

        // If list is empty, print empty
        // Otherwise, print searching complete
        if self._backend_list.is_empty () {
            info! ("No backend plugins found.");
        }

        else {
            info! ("Backend searching complete.");
        }
    }

/*-----------------------------------------------------------------------------------------------*/

    /// Lists all avaliable backends of a given type.
    pub fn list_backends (&self, backend_type: Type) -> Vec<String> {

        let mut return_vec = Vec::<String>::new ();

        for backend in self._backend_list.clone () {

            if backend.b_type == backend_type {
                return_vec.push (backend.name);
            }
        }

        return_vec
    }

/*-----------------------------------------------------------------------------------------------*/

    /// Sets the default backend.
    pub fn set_default_backend (&mut self, backend_name: &str) {

        for b in &self._backend_list {

            if b.name == backend_name {

                self._config.default_backend [b.b_type as usize] = b.name.clone ();
                return;
            }
        }

        warn! ("No backend plugin with name '{}' found.", backend_name);
    }

/*===============================================================================================*/
/*------MANAGER PUBLIC STATIC METHODS------------------------------------------------------------*/
/*===============================================================================================*/

    /// Creates a new instance of the BackendManager.
    ///
    /// # Return value
    /// A new instance of the backend manager.
    pub fn new () -> Manager {

        // Set the platform extension
        let plug_ext = if cfg! (target_os = "windows") {".dll"}
                       else if cfg! (target_os = "linux") {".so"}
                       else if cfg! (target_os = "macos") {".dylib"}
                       else {panic! ("Platform unsupported")};
        Manager {

            _config: Config::default (),
            _backend_list: Vec::new (),
            _ext: plug_ext.to_string ()
        }
    }

/*===============================================================================================*/
/*------MANAGER PRIVATE METHODS------------------------------------------------------------------*/
/*===============================================================================================*/

    // Checks if the backend directory exists.
    // If not, a new one is created.
    fn _check_backend_dir_exists (&self) -> bool {

        if fs::metadata (&self._config.backend_dir).is_err () {

            warn! ("Backend directory does not exist. Creating one now.");

            // Create new directory and check for errors
            match fs::create_dir (&self._config.backend_dir) {

                Ok  (_) => {

                    info! ("Directory creation successful.");
                    info! ("No backend plugins found.");
                    return false;
                },

                Err (e) => {

                    error! ("Failed to create backend directory: {}", e);
                    panic! ();
                }
            }
        }

        true
    }
}
<commit_msg>Added "get_default_backend" method<commit_after>/*===============================================================================================*/
// Copyright 2016 Kyle Finlay
//
// 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.
/*===============================================================================================*/

extern crate glob;
extern crate libloading;

use ::engine::App;
use ::engine::backend::{Config, Info, Type, State};

use self::glob::glob;
use self::libloading::{Library, Symbol};

use std::cell::RefCell;
use std::fs;
use std::rc::Rc;

/*===============================================================================================*/
/*------MANAGER STRUCT---------------------------------------------------------------------------*/
/*===============================================================================================*/

/// Manages the loading of the various backend systems.
#[derive (Default)]
pub struct Manager {

    // Private
    _config: Config,
    _backend_list: Vec<Rc<RefCell<Info>>>,
    _ext: String,
}

/*===============================================================================================*/
/*------MANAGER PUBLIC METHODS-------------------------------------------------------------------*/
/*===============================================================================================*/

impl Manager {

    /// Loads the configuration file.
    pub fn load_config (&mut self) {

        // Get a pointer to the config manager
        let cfg_mgr = App::get_config_manager ().unwrap ();
        let cfg_exists = cfg_mgr.borrow ().config_exists ("backend_manager");

        // Check if the config file for the backend manager exists.
        // If so, load it.
        // If not, create it.
        let cfg = {

            if cfg_exists {
                cfg_mgr.borrow ().load_config::<Config> ("backend_manager").unwrap ()
            }

            else {

                cfg_mgr.borrow_mut ().create_config::<Config> ("backend_manager");
                cfg_mgr.borrow ().load_config::<Config> ("backend_manager").unwrap ()
            }
        };

        self._config = cfg;
    }

/*-----------------------------------------------------------------------------------------------*/

    /// Saves the configuration file.
    pub fn save_config (&self) {

        // Get a pointer to the config manager
        let cfg_mgr = App::get_config_manager ().unwrap ();
        let cfg_exists = cfg_mgr.borrow ().config_exists ("backend_manager");

        // Check if the config file for the backend manager exists.
        // If so, save it.
        // If not, create it.
        if cfg_exists {
            cfg_mgr.borrow ().save_config ("backend_manager", &self._config).unwrap ();
        }

        else {

            cfg_mgr.borrow_mut ().create_config::<Config> ("backend_manager");
            cfg_mgr.borrow ().save_config ("backend_manager", &self._config).unwrap ();
        }
    }

/*-----------------------------------------------------------------------------------------------*/

    /// Queries the backend directory for plugins.
    ///
    /// All valid backend plugins are then registered with the manager for loading.
    /// Any plugins with errors are ignored.
    pub fn query_backend_dir (&mut self) {

        // Clear the old backend list
        self._backend_list.clear ();
        info! ("Searching for backend plugins...");

        if !&self._check_backend_dir_exists () {
            return;
        }

        // Recurse through the backend directory, and get all backend plugins
        for path in glob (&format! ("{}/*{}", &self._config.backend_dir, &self._ext)).unwrap ().filter_map (Result::ok) {

            info! ("Found: {:?}", &path.file_name ().unwrap ());

            // Load the library and get the function symbols.
            match Library::new (&path) {

                Ok (lib) => {

                    let get_backend_info: Symbol<unsafe extern fn () -> Info> = unsafe {

                        match lib.get (b"get_backend_info\0") {

                            Ok (l) => l,
                            Err (e) => {

                                warn! ("Could not find function 'get_backend_info' in library {:?}\n{}",
                                       &path.file_name ().unwrap (), e);
                                continue;
                            }
                        }
                    };

                    // Create a new instance of the plugin, and add it to the list
                    unsafe {
                        self._backend_list.push (Rc::new (RefCell::new (get_backend_info ())));
                    }

                    // Set the path and state of the backend plugin
                    let index = self._backend_list.len () - 1;
                    self._backend_list[index].borrow_mut ().path  = path.to_str ().unwrap ().to_string ();
                    self._backend_list[index].borrow_mut ().state = State::Unloaded;

                    info! ("Added: {:?}", &path.file_name ().unwrap ());
                },

                Err (e) => {

                    warn! ("Could not load library {:?}\n{}", &path.file_name ().unwrap (), e);
                    continue;
                }
            }
        }

        // If list is empty, print empty
        // Otherwise, print searching complete
        if self._backend_list.is_empty () {
            info! ("No backend plugins found.");
        }

        else {
            info! ("Backend searching complete.");
        }
    }

/*-----------------------------------------------------------------------------------------------*/

    /// Lists all avaliable backends of a given type.
    pub fn list_backends (&self, backend_type: Type) -> Vec<String> {

        let mut return_vec = Vec::<String>::new ();

        for backend in &self._backend_list.clone () {

            if backend.borrow ().b_type == backend_type {
                return_vec.push (backend.borrow ().name.clone ());
            }
        }

        return_vec
    }

/*-----------------------------------------------------------------------------------------------*/

    /// Gets the default backend.
    pub fn get_default_backend (&self, backend_type: Type) -> Option<Rc<RefCell<Info>>> {

        let back_name = self._config.default_backend [backend_type as usize].clone ();

        // Check if the backend is the fallback
        if back_name == "fallback" {
            return None;
        }

        // Otherwise return the default backend for that type
        for b in &self._backend_list {

            if b.borrow ().name == back_name {
                return Some (b.clone ());
            }
        }

        None
    }

/*-----------------------------------------------------------------------------------------------*/

    /// Sets the default backend.
    pub fn set_default_backend (&mut self, backend_name: &str) {

        for b in &self._backend_list {

            if b.borrow ().name == backend_name {

                self._config.default_backend [b.borrow ().b_type as usize] = b.borrow ().name.clone ();
                return;
            }
        }

        warn! ("No backend plugin with name '{}' found.", backend_name);
    }

/*===============================================================================================*/
/*------MANAGER PUBLIC STATIC METHODS------------------------------------------------------------*/
/*===============================================================================================*/

    /// Creates a new instance of the BackendManager.
    ///
    /// # Return value
    /// A new instance of the backend manager.
    pub fn new () -> Manager {

        // Set the platform extension
        let plug_ext = if cfg! (target_os = "windows") {".dll"}
                       else if cfg! (target_os = "linux") {".so"}
                       else if cfg! (target_os = "macos") {".dylib"}
                       else {panic! ("Platform unsupported")};
        Manager {

            _config: Config::default (),
            _backend_list: Vec::new (),
            _ext: plug_ext.to_string ()
        }
    }

/*===============================================================================================*/
/*------MANAGER PRIVATE METHODS------------------------------------------------------------------*/
/*===============================================================================================*/

    // Checks if the backend directory exists.
    // If not, a new one is created.
    fn _check_backend_dir_exists (&self) -> bool {

        if fs::metadata (&self._config.backend_dir).is_err () {

            warn! ("Backend directory does not exist. Creating one now.");

            // Create new directory and check for errors
            match fs::create_dir (&self._config.backend_dir) {

                Ok  (_) => {

                    info! ("Directory creation successful.");
                    info! ("No backend plugins found.");
                    return false;
                },

                Err (e) => {

                    error! ("Failed to create backend directory: {}", e);
                    panic! ();
                }
            }
        }

        true
    }
}
<|endoftext|>


<commit_before>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use std::fs::OpenOptions;
use std::path::{Path, PathBuf};
use std::{cmp, panic};

use serde_json::{from_reader, Value};

use devicemapper::{Bytes, Sectors, IEC};

use super::logger::init_logger;
use super::util::clean_up;

use super::super::device::wipe_sectors;

pub struct RealTestDev {
    path: PathBuf,
}

impl RealTestDev {
    /// Construct a new test device for the given path.
    /// Wipe initial MiB to clear metadata.
    pub fn new(path: &Path) -> RealTestDev {
        wipe_sectors(path, Sectors(0), Bytes(IEC::Mi).sectors()).unwrap();
        RealTestDev {
            path: PathBuf::from(path),
        }
    }

    /// Get the device node of the device.
    fn as_path(&self) -> &Path {
        &self.path
    }
}

impl Drop for RealTestDev {
    fn drop(&mut self) {
        wipe_sectors(&self.path, Sectors(0), Bytes(IEC::Mi).sectors()).unwrap();
    }
}

pub enum DeviceLimits {
    Exactly(usize),
    AtLeast(usize),
    Range(usize, usize), // inclusive
}

/// Get a list of counts of devices to use for tests.
/// None of the counts can be greater than avail.
fn get_device_counts(limits: DeviceLimits, avail: usize) -> Vec<usize> {
    // Convert enum to [lower, Option<upper>) values
    let (lower, maybe_upper) = match limits {
        DeviceLimits::Exactly(num) => (num, Some(num + 1)),
        DeviceLimits::AtLeast(num) => (num, None),
        DeviceLimits::Range(lower, upper) => {
            assert!(lower < upper);
            (lower, Some(upper + 1))
        }
    };

    let mut counts = vec![];

    // Check these values against available blockdevs
    if lower > avail {
        return counts;
    }

    counts.push(lower);

    if lower != avail {
        match maybe_upper {
            None => counts.push(avail),
            Some(upper) => {
                if lower + 1 < upper {
                    counts.push(cmp::min(upper - 1, avail))
                }
            }
        }
    }

    counts
}

/// Run test on real devices, using given constraints. Constraints may result
/// in multiple invocations of the test, with differing numbers of block
/// devices.
pub fn test_with_spec<F>(limits: DeviceLimits, test: F) -> ()
where
    F: Fn(&[&Path]) -> () + panic::RefUnwindSafe,
{
    let file = OpenOptions::new()
        .read(true)
        .open("tests/test_config.json")
        .unwrap();
    let config: Value = from_reader(&file).unwrap();
    let devpaths: Vec<_> = config
        .get("ok_to_destroy_dev_array_key")
        .unwrap()
        .as_array()
        .unwrap()
        .iter()
        .map(|x| Path::new(x.as_str().unwrap()))
        .collect();

    let counts = get_device_counts(limits, devpaths.len());

    assert!(!counts.is_empty());

    init_logger();

    let runs = counts
        .iter()
        .map(|num| devpaths.iter().take(*num).collect::<Vec<_>>());

    for run_paths in runs {
        let devices: Vec<_> = run_paths.iter().map(|x| RealTestDev::new(x)).collect();

        clean_up().unwrap();

        let result =
            panic::catch_unwind(|| test(&devices.iter().map(|x| x.as_path()).collect::<Vec<_>>()));
        let tear_down = clean_up();

        result.unwrap();
        tear_down.unwrap();
    }
}
<commit_msg>Comment device limits<commit_after>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use std::fs::OpenOptions;
use std::path::{Path, PathBuf};
use std::{cmp, panic};

use serde_json::{from_reader, Value};

use devicemapper::{Bytes, Sectors, IEC};

use super::logger::init_logger;
use super::util::clean_up;

use super::super::device::wipe_sectors;

pub struct RealTestDev {
    path: PathBuf,
}

impl RealTestDev {
    /// Construct a new test device for the given path.
    /// Wipe initial MiB to clear metadata.
    pub fn new(path: &Path) -> RealTestDev {
        wipe_sectors(path, Sectors(0), Bytes(IEC::Mi).sectors()).unwrap();
        RealTestDev {
            path: PathBuf::from(path),
        }
    }

    /// Get the device node of the device.
    fn as_path(&self) -> &Path {
        &self.path
    }
}

impl Drop for RealTestDev {
    fn drop(&mut self) {
        wipe_sectors(&self.path, Sectors(0), Bytes(IEC::Mi).sectors()).unwrap();
    }
}

/// Shorthand for specifying devices to use for tests
pub enum DeviceLimits {
    /// Use exactly the number of devices specified
    Exactly(usize),
    /// Use at least the number of devices specified, but if there are more
    /// devices available, also use the maximum number of devices.
    AtLeast(usize),
    /// Use exactly the number of devices specified in the first argument,
    /// and the minimum of the number of devices specified and the number
    /// of devices available in the second argument.
    Range(usize, usize),
}

/// Get a list of counts of devices to use for tests.
/// None of the counts can be greater than avail.
fn get_device_counts(limits: DeviceLimits, avail: usize) -> Vec<usize> {
    // Convert enum to [lower, Option<upper>) values
    let (lower, maybe_upper) = match limits {
        DeviceLimits::Exactly(num) => (num, Some(num + 1)),
        DeviceLimits::AtLeast(num) => (num, None),
        DeviceLimits::Range(lower, upper) => {
            assert!(lower < upper);
            (lower, Some(upper + 1))
        }
    };

    let mut counts = vec![];

    // Check these values against available blockdevs
    if lower > avail {
        return counts;
    }

    counts.push(lower);

    if lower != avail {
        match maybe_upper {
            None => counts.push(avail),
            Some(upper) => {
                if lower + 1 < upper {
                    counts.push(cmp::min(upper - 1, avail))
                }
            }
        }
    }

    counts
}

/// Run test on real devices, using given constraints. Constraints may result
/// in multiple invocations of the test, with differing numbers of block
/// devices.
pub fn test_with_spec<F>(limits: DeviceLimits, test: F) -> ()
where
    F: Fn(&[&Path]) -> () + panic::RefUnwindSafe,
{
    let file = OpenOptions::new()
        .read(true)
        .open("tests/test_config.json")
        .unwrap();
    let config: Value = from_reader(&file).unwrap();
    let devpaths: Vec<_> = config
        .get("ok_to_destroy_dev_array_key")
        .unwrap()
        .as_array()
        .unwrap()
        .iter()
        .map(|x| Path::new(x.as_str().unwrap()))
        .collect();

    let counts = get_device_counts(limits, devpaths.len());

    assert!(!counts.is_empty());

    init_logger();

    let runs = counts
        .iter()
        .map(|num| devpaths.iter().take(*num).collect::<Vec<_>>());

    for run_paths in runs {
        let devices: Vec<_> = run_paths.iter().map(|x| RealTestDev::new(x)).collect();

        clean_up().unwrap();

        let result =
            panic::catch_unwind(|| test(&devices.iter().map(|x| x.as_path()).collect::<Vec<_>>()));
        let tear_down = clean_up();

        result.unwrap();
        tear_down.unwrap();
    }
}
<|endoftext|>


<commit_before>extern crate rand;
extern crate timely;
extern crate differential_dataflow;

use rand::{Rng, SeedableRng, StdRng};

use timely::progress::nested::product::Product;
use timely::progress::timestamp::RootTimestamp;

use timely::dataflow::operators::unordered_input::UnorderedInput;

use differential_dataflow::AsCollection;
use differential_dataflow::operators::*;

fn main() {

    let nodes: usize = std::env::args().nth(1).unwrap().parse().unwrap();
    let edges: usize = std::env::args().nth(2).unwrap().parse().unwrap();
    let batch: usize = std::env::args().nth(3).unwrap().parse().unwrap();
    let rounds: usize = std::env::args().nth(4).unwrap().parse().unwrap();

    timely::execute_from_args(std::env::args().skip(5), move |worker| {

        let index = worker.index();
        let peers = worker.peers();

        let (mut root_input, root_cap, mut edge_input, mut edge_cap, probe) =
        worker.dataflow(|scope| {

            let ((root_input, root_cap), roots) = scope.new_unordered_input();
            let ((edge_input, edge_cap), edges) = scope.new_unordered_input();

            let roots = roots.as_collection();
            let edges = edges.as_collection()
                             // .inspect(|x| println!("edge: {:?}", x))
                             ;

            let probe =
            roots.iterate(|inner| {

                let edges = edges.enter(&inner.scope());
                let roots = roots.enter(&inner.scope());

                edges
                    .semijoin(&inner)
                    .map(|(_s,d)| d)
                    .concat(&roots)
                    .distinct()
            })
            .map(|_| ())
            .consolidate()
            .inspect(|x| println!("{:?}\tchanges: {:?}", x.1, x.2))
            .probe();

            (root_input, root_cap, edge_input, edge_cap, probe)
        });

        let seed: &[_] = &[1, 2, 3, index];
        let mut rng1: StdRng = SeedableRng::from_seed(seed);    // rng for edge additions
        let mut rng2: StdRng = SeedableRng::from_seed(seed);    // rng for edge deletions

        let worker_edges = edges / peers + if index < edges % peers { 1 } else { 0 };
        let worker_batch = batch / peers + if index < batch % peers { 1 } else { 0 };

        // load initial root.
        root_input.session(root_cap).give((0, RootTimestamp::new(Product::new(0, 0)), 1));

        // load initial edges
        edge_input
            .session(edge_cap.clone())
            .give_iterator((0 .. worker_edges).map(|_|
                ((rng1.gen_range(0, nodes), rng1.gen_range(0, nodes)),
                    RootTimestamp::new(Product::new(0, 0)), 1)
            ));

        let edge_cap_next = edge_cap.delayed(&RootTimestamp::new(Product::new(1, 0)));

        edge_cap.downgrade(&RootTimestamp::new(Product::new(0, 1)));
        while probe.less_than(edge_cap.time()) {
            worker.step();
        }

        for round in 1 .. rounds {

            edge_input
                .session(edge_cap.clone())
                .give_iterator((0 .. worker_batch).flat_map(|_| {
                    let insert = ((rng1.gen_range(0, nodes), rng1.gen_range(0, nodes)), RootTimestamp::new(Product::new(0, round)), 1);
                    let remove = ((rng2.gen_range(0, nodes), rng2.gen_range(0, nodes)), RootTimestamp::new(Product::new(0, round)),-1);
                    Some(insert).into_iter().chain(Some(remove).into_iter())
                }));

            edge_cap.downgrade(&RootTimestamp::new(Product::new(0, round+1)));
            while probe.less_than(edge_cap.time()) {
                worker.step();
            }
        }

        edge_cap = edge_cap_next;

        edge_input
            .session(edge_cap.clone())
            .give_iterator((0 .. worker_batch).map(|_| {
                ((rng1.gen_range(0, nodes), rng1.gen_range(0, nodes)), RootTimestamp::new(Product::new(1, 0)), 1)
            }));

        edge_cap.downgrade(&RootTimestamp::new(Product::new(2, 0)));
        while probe.less_than(&RootTimestamp::new(Product::new(1, rounds+1))) {
            worker.step();
        }

        edge_input
            .session(edge_cap.clone())
            .give_iterator((0 .. worker_batch).map(|_| {
                ((rng1.gen_range(0, nodes), rng1.gen_range(0, nodes)), RootTimestamp::new(Product::new(2, 3)), 1)
            }));

        edge_cap.downgrade(&RootTimestamp::new(Product::new(3, 0)));
        while probe.less_than(&RootTimestamp::new(Product::new(2, rounds+1))) {
            worker.step();
        }

        edge_input
            .session(edge_cap.clone())
            .give_iterator((0 .. worker_batch).map(|_| {
                ((rng1.gen_range(0, nodes), rng1.gen_range(0, nodes)), RootTimestamp::new(Product::new(3, 1)), 1)
            }));

        edge_cap.downgrade(&RootTimestamp::new(Product::new(4, 0)));
        while probe.less_than(&RootTimestamp::new(Product::new(3, rounds+1))) {
            worker.step();
        }

    }).unwrap();
}<commit_msg>multitemporal example<commit_after>#[macro_use]
extern crate abomonation_derive;
extern crate abomonation;

extern crate rand;
extern crate timely;
extern crate differential_dataflow;

use rand::{Rng, SeedableRng, StdRng};

use timely::dataflow::ProbeHandle;
use timely::progress::timestamp::RootTimestamp;

use timely::dataflow::operators::unordered_input::UnorderedInput;

use differential_dataflow::AsCollection;
use differential_dataflow::operators::*;

use pair::Pair;

fn main() {

    let nodes: usize = std::env::args().nth(1).unwrap().parse().unwrap();
    let edges: usize = std::env::args().nth(2).unwrap().parse().unwrap();
    let batch: usize = std::env::args().nth(3).unwrap().parse().unwrap();
    let rounds: usize = std::env::args().nth(4).unwrap().parse().unwrap();

    timely::execute_from_args(std::env::args().skip(5), move |worker| {

        let index = worker.index();
        let peers = worker.peers();
        let mut probe = ProbeHandle::new();

        let (mut root_input, root_cap, mut edge_input, mut edge_cap) =
        worker.dataflow(|scope| {

            let ((root_input, root_cap), roots) = scope.new_unordered_input();
            let ((edge_input, edge_cap), edges) = scope.new_unordered_input();

            let roots = roots.as_collection();
            let edges = edges.as_collection()
                             // .inspect(|x| println!("edge: {:?}", x))
                             ;

            roots.iterate(|inner| {

                let edges = edges.enter(&inner.scope());
                let roots = roots.enter(&inner.scope());

                edges
                    .semijoin(&inner)
                    .map(|(_s,d)| d)
                    .concat(&roots)
                    .distinct()
            })
            .map(|_| ())
            .consolidate()
            .inspect(|x| println!("{:?}\tchanges: {:?}", x.1, x.2))
            .probe_with(&mut probe);

            (root_input, root_cap, edge_input, edge_cap)
        });

        let seed: &[_] = &[1, 2, 3, index];
        let mut rng1: StdRng = SeedableRng::from_seed(seed);    // rng for edge additions
        let mut rng2: StdRng = SeedableRng::from_seed(seed);    // rng for edge deletions

        let worker_edges = edges / peers + if index < edges % peers { 1 } else { 0 };
        let worker_batch = batch / peers + if index < batch % peers { 1 } else { 0 };

        // load initial root.
        root_input
            .session(root_cap)
            .give((0, RootTimestamp::new(Pair::new(0, 0)), 1));

        // load initial edges
        edge_input
            .session(edge_cap.clone())
            .give_iterator((0 .. worker_edges).map(|_|
                ((rng1.gen_range(0, nodes), rng1.gen_range(0, nodes)),
                    RootTimestamp::new(Pair::new(0, 0)), 1)
            ));

        let edge_cap_next = edge_cap.delayed(&RootTimestamp::new(Pair::new(1, 0)));

        edge_cap.downgrade(&RootTimestamp::new(Pair::new(0, 1)));
        while probe.less_than(edge_cap.time()) {
            worker.step();
        }

        for round in 1 .. rounds {

            edge_input
                .session(edge_cap.clone())
                .give_iterator((0 .. worker_batch).flat_map(|_| {
                    let insert = ((rng1.gen_range(0, nodes), rng1.gen_range(0, nodes)), RootTimestamp::new(Pair::new(0, round)), 1);
                    let remove = ((rng2.gen_range(0, nodes), rng2.gen_range(0, nodes)), RootTimestamp::new(Pair::new(0, round)),-1);
                    Some(insert).into_iter().chain(Some(remove).into_iter())
                }));

            edge_cap.downgrade(&RootTimestamp::new(Pair::new(0, round+1)));
            while probe.less_than(edge_cap.time()) {
                worker.step();
            }
        }

        edge_cap = edge_cap_next;

        edge_input
            .session(edge_cap.clone())
            .give_iterator((0 .. worker_batch).map(|_| {
                ((rng1.gen_range(0, nodes), rng1.gen_range(0, nodes)), RootTimestamp::new(Pair::new(1, 0)), 1)
            }));

        edge_cap.downgrade(&RootTimestamp::new(Pair::new(2, 0)));
        while probe.less_than(&RootTimestamp::new(Pair::new(1, rounds+1))) {
            worker.step();
        }

        edge_input
            .session(edge_cap.clone())
            .give_iterator((0 .. worker_batch).map(|_| {
                ((rng1.gen_range(0, nodes), rng1.gen_range(0, nodes)), RootTimestamp::new(Pair::new(2, 3)), 1)
            }));

        edge_cap.downgrade(&RootTimestamp::new(Pair::new(3, 0)));
        while probe.less_than(&RootTimestamp::new(Pair::new(2, rounds+1))) {
            worker.step();
        }

        edge_input
            .session(edge_cap.clone())
            .give_iterator((0 .. worker_batch).map(|_| {
                ((rng1.gen_range(0, nodes), rng1.gen_range(0, nodes)), RootTimestamp::new(Pair::new(3, 1)), 1)
            }));

        edge_cap.downgrade(&RootTimestamp::new(Pair::new(4, 0)));
        while probe.less_than(&RootTimestamp::new(Pair::new(3, rounds+1))) {
            worker.step();
        }

    }).unwrap();
}

/// This module contains a definition of a new timestamp time, a "pair" or product.
///
/// This is a minimal self-contained implementation, in that it doesn't borrow anything
/// from the rest of the library other than the traits it needs to implement. With this
/// type and its implementations, you can use it as a timestamp type.
mod pair {

    /// A pair of timestamps, partially ordered by the product order.
    #[derive(Debug, Hash, Default, Clone, Eq, PartialEq, Ord, PartialOrd, Abomonation)]
    pub struct Pair<S, T> {
        pub first: S,
        pub second: T,
    }

    impl<S, T> Pair<S, T> {
        /// Create a new pair.
        pub fn new(first: S, second: T) -> Self {
            Pair { first, second }
        }
    }

    // Implement timely dataflow's `PartialOrder` trait.
    use timely::order::PartialOrder;
    impl<S: PartialOrder, T: PartialOrder> PartialOrder for Pair<S, T> {
        fn less_equal(&self, other: &Self) -> bool {
            self.first.less_equal(&other.first) && self.second.less_equal(&other.second)
        }
    }

    // Implement timely dataflow's `PathSummary` trait.
    // This is preparation for the `Timestamp` implementation below.
    use timely::progress::PathSummary;
    // impl<S: Timestamp, T: Timestamp> PathSummary<Pair<S,T>> for Pair<<S as Timestamp>::Summary, <T as Timestamp>::Summary> {
    //     fn results_in(&self, timestamp: &Pair<S, T>) -> Option<Pair<S,T>> {
    //         if let Some(s) = self.first.results_in(&timestamp.first) {
    //             if let Some(t) = self.second.results_in(&timestamp.second) {
    //                 Some(Pair::new(s,t))
    //             }
    //             else { None }
    //         }
    //         else { None }
    //     }
    //     fn followed_by(&self, other: &Self) -> Option<Self> {
    //         if let Some(s) = self.first.followed_by(&other.first) {
    //             if let Some(t) = self.second.followed_by(&other.second) {
    //                 Some(Pair::new(s,t))
    //             }
    //             else { None }
    //         }
    //         else { None }
    //     }
    // }

    impl<S: Timestamp, T: Timestamp> PathSummary<Pair<S,T>> for () {
        fn results_in(&self, timestamp: &Pair<S, T>) -> Option<Pair<S,T>> {
            Some(timestamp.clone())
        }
        fn followed_by(&self, other: &Self) -> Option<Self> {
            Some(other.clone())
        }
    }

    // Implement timely dataflow's `Timestamp` trait.
    use timely::progress::Timestamp;
    impl<S: Timestamp, T: Timestamp> Timestamp for Pair<S, T> {
        type Summary = ();//Pair<<S as Timestamp>::Summary, <T as Timestamp>::Summary>;
    }

    // Implement differential dataflow's `Lattice` trait.
    // This extends the `PartialOrder` implementation with additional structure.
    use differential_dataflow::lattice::Lattice;
    impl<S: Lattice, T: Lattice> Lattice for Pair<S, T> {
        fn minimum() -> Self { Pair { first: S::minimum(), second: T::minimum() }}
        fn maximum() -> Self { Pair { first: S::maximum(), second: T::maximum() }}
        fn join(&self, other: &Self) -> Self {
            Pair {
                first: self.first.join(&other.first),
                second: self.second.join(&other.second),
            }
        }
        fn meet(&self, other: &Self) -> Self {
            Pair {
                first: self.first.meet(&other.first),
                second: self.second.meet(&other.second),
            }
        }
    }
}<|endoftext|>


<commit_before>#[doc = "Random number generation"]

enum rctx {}

#[abi = "cdecl"]
native mod rustrt {
    fn rand_new() -> *rctx;
    fn rand_next(c: *rctx) -> u32;
    fn rand_free(c: *rctx);
}

#[doc = "A random number generator"]
iface rng {
    #[doc = "Return the next random integer"]
    fn next() -> u32;

    #[doc = "Return the next random float"]
    fn next_float() -> float;

    #[doc = "Return a random string composed of A-Z, a-z, 0-9."]
    fn gen_str(len: uint) -> str;

    #[doc = "Return a random byte string."]
    fn gen_bytes(len: uint) -> [u8];
}

resource rand_res(c: *rctx) { rustrt::rand_free(c); }

#[doc = "Create a random number generator"]
fn rng() -> rng {
    impl of rng for @rand_res {
        fn next() -> u32 { ret rustrt::rand_next(**self); }
        fn next_float() -> float {
          let u1 = rustrt::rand_next(**self) as float;
          let u2 = rustrt::rand_next(**self) as float;
          let u3 = rustrt::rand_next(**self) as float;
          let scale = u32::max_value as float;
          ret ((u1 / scale + u2) / scale + u3) / scale;
        }
        fn gen_str(len: uint) -> str {
            let charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
                          "abcdefghijklmnopqrstuvwxyz" +
                          "0123456789";
            let mut s = "";
            let mut i = 0u;
            while (i < len) {
                let n = rustrt::rand_next(**self) as uint %
                    str::len(charset);
                s = s + str::from_char(str::char_at(charset, n));
                i += 1u;
            }
            s
        }
        fn gen_bytes(len: uint) -> [u8] {
            let mut v = [];
            let mut i = 0u;
            while i < len {
                let n = rustrt::rand_next(**self) as uint;
                v += [(n % (u8::max_value as uint)) as u8];
                i += 1u;
            }
            v
        }
    }
    @rand_res(rustrt::rand_new()) as rng
}

#[cfg(test)]
mod tests {

    #[test]
    fn test() {
        let r1: rand::rng = rand::rng();
        log(debug, r1.next());
        log(debug, r1.next());
        {
            let r2 = rand::rng();
            log(debug, r1.next());
            log(debug, r2.next());
            log(debug, r1.next());
            log(debug, r1.next());
            log(debug, r2.next());
            log(debug, r2.next());
            log(debug, r1.next());
            log(debug, r1.next());
            log(debug, r1.next());
            log(debug, r2.next());
            log(debug, r2.next());
            log(debug, r2.next());
        }
        log(debug, r1.next());
        log(debug, r1.next());
    }

    #[test]
    fn genstr() {
        let r: rand::rng = rand::rng();
        log(debug, r.gen_str(10u));
        log(debug, r.gen_str(10u));
        log(debug, r.gen_str(10u));
        assert(str::len(r.gen_str(10u)) == 10u);
        assert(str::len(r.gen_str(16u)) == 16u);
    }
}

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
<commit_msg>core: Docs<commit_after>#[doc = "Random number generation"];

export rng;

enum rctx {}

#[abi = "cdecl"]
native mod rustrt {
    fn rand_new() -> *rctx;
    fn rand_next(c: *rctx) -> u32;
    fn rand_free(c: *rctx);
}

#[doc = "A random number generator"]
iface rng {
    #[doc = "Return the next random integer"]
    fn next() -> u32;

    #[doc = "Return the next random float"]
    fn next_float() -> float;

    #[doc = "Return a random string composed of A-Z, a-z, 0-9."]
    fn gen_str(len: uint) -> str;

    #[doc = "Return a random byte string."]
    fn gen_bytes(len: uint) -> [u8];
}

resource rand_res(c: *rctx) { rustrt::rand_free(c); }

#[doc = "Create a random number generator"]
fn rng() -> rng {
    impl of rng for @rand_res {
        fn next() -> u32 { ret rustrt::rand_next(**self); }
        fn next_float() -> float {
          let u1 = rustrt::rand_next(**self) as float;
          let u2 = rustrt::rand_next(**self) as float;
          let u3 = rustrt::rand_next(**self) as float;
          let scale = u32::max_value as float;
          ret ((u1 / scale + u2) / scale + u3) / scale;
        }
        fn gen_str(len: uint) -> str {
            let charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
                          "abcdefghijklmnopqrstuvwxyz" +
                          "0123456789";
            let mut s = "";
            let mut i = 0u;
            while (i < len) {
                let n = rustrt::rand_next(**self) as uint %
                    str::len(charset);
                s = s + str::from_char(str::char_at(charset, n));
                i += 1u;
            }
            s
        }
        fn gen_bytes(len: uint) -> [u8] {
            let mut v = [];
            let mut i = 0u;
            while i < len {
                let n = rustrt::rand_next(**self) as uint;
                v += [(n % (u8::max_value as uint)) as u8];
                i += 1u;
            }
            v
        }
    }
    @rand_res(rustrt::rand_new()) as rng
}

#[cfg(test)]
mod tests {

    #[test]
    fn test() {
        let r1: rand::rng = rand::rng();
        log(debug, r1.next());
        log(debug, r1.next());
        {
            let r2 = rand::rng();
            log(debug, r1.next());
            log(debug, r2.next());
            log(debug, r1.next());
            log(debug, r1.next());
            log(debug, r2.next());
            log(debug, r2.next());
            log(debug, r1.next());
            log(debug, r1.next());
            log(debug, r1.next());
            log(debug, r2.next());
            log(debug, r2.next());
            log(debug, r2.next());
        }
        log(debug, r1.next());
        log(debug, r1.next());
    }

    #[test]
    fn genstr() {
        let r: rand::rng = rand::rng();
        log(debug, r.gen_str(10u));
        log(debug, r.gen_str(10u));
        log(debug, r.gen_str(10u));
        assert(str::len(r.gen_str(10u)) == 10u);
        assert(str::len(r.gen_str(16u)) == 16u);
    }
}

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
<|endoftext|>