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

use syntax::ast::{self, BindingMode, FieldPat, Pat, PatKind, RangeEnd, RangeSyntax};
use syntax::codemap::{self, BytePos, Span};
use syntax::ptr;

use spanned::Spanned;
use codemap::SpanUtils;
use comment::FindUncommented;
use expr::{can_be_overflowed_expr, rewrite_call_inner, rewrite_pair, rewrite_unary_prefix,
           wrap_struct_field};
use lists::{itemize_list, shape_for_tactic, struct_lit_formatting, struct_lit_shape,
            struct_lit_tactic, write_list, DefinitiveListTactic, SeparatorPlace, SeparatorTactic};
use rewrite::{Rewrite, RewriteContext};
use shape::Shape;
use types::{rewrite_path, PathContext};
use utils::{format_mutability, mk_sp};

impl Rewrite for Pat {
    fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
        match self.node {
            PatKind::Box(ref pat) => rewrite_unary_prefix(context, "box ", &**pat, shape),
            PatKind::Ident(binding_mode, ident, ref sub_pat) => {
                let (prefix, mutability) = match binding_mode {
                    BindingMode::ByRef(mutability) => ("ref ", mutability),
                    BindingMode::ByValue(mutability) => ("", mutability),
                };
                let mut_infix = format_mutability(mutability);
                let id_str = ident.node.to_string();
                let sub_pat = match *sub_pat {
                    Some(ref p) => {
                        // 3 - ` @ `.
                        let width = shape
                            .width
                            .checked_sub(prefix.len() + mut_infix.len() + id_str.len() + 3)?;
                        format!(
                            " @ {}",
                            p.rewrite(context, Shape::legacy(width, shape.indent))?
                        )
                    }
                    None => "".to_owned(),
                };

                Some(format!("{}{}{}{}", prefix, mut_infix, id_str, sub_pat))
            }
            PatKind::Wild => if 1 <= shape.width {
                Some("_".to_owned())
            } else {
                None
            },
            PatKind::Range(ref lhs, ref rhs, ref end_kind) => {
                let infix = match *end_kind {
                    RangeEnd::Included(RangeSyntax::DotDotDot) => "...",
                    RangeEnd::Included(RangeSyntax::DotDotEq) => "..=",
                    RangeEnd::Excluded => "..",
                };
                rewrite_pair(
                    &**lhs,
                    &**rhs,
                    "",
                    infix,
                    "",
                    context,
                    shape,
                    SeparatorPlace::Front,
                )
            }
            PatKind::Ref(ref pat, mutability) => {
                let prefix = format!("&{}", format_mutability(mutability));
                rewrite_unary_prefix(context, &prefix, &**pat, shape)
            }
            PatKind::Tuple(ref items, dotdot_pos) => {
                rewrite_tuple_pat(items, dotdot_pos, None, self.span, context, shape)
            }
            PatKind::Path(ref q_self, ref path) => {
                rewrite_path(context, PathContext::Expr, q_self.as_ref(), path, shape)
            }
            PatKind::TupleStruct(ref path, ref pat_vec, dotdot_pos) => {
                let path_str = rewrite_path(context, PathContext::Expr, None, path, shape)?;
                rewrite_tuple_pat(
                    pat_vec,
                    dotdot_pos,
                    Some(path_str),
                    self.span,
                    context,
                    shape,
                )
            }
            PatKind::Lit(ref expr) => expr.rewrite(context, shape),
            PatKind::Slice(ref prefix, ref slice_pat, ref suffix) => {
                // Rewrite all the sub-patterns.
                let prefix = prefix.iter().map(|p| p.rewrite(context, shape));
                let slice_pat = slice_pat
                    .as_ref()
                    .map(|p| Some(format!("{}..", p.rewrite(context, shape)?)));
                let suffix = suffix.iter().map(|p| p.rewrite(context, shape));

                // Munge them together.
                let pats: Option<Vec<String>> =
                    prefix.chain(slice_pat.into_iter()).chain(suffix).collect();

                // Check that all the rewrites succeeded, and if not return None.
                let pats = pats?;

                // Unwrap all the sub-strings and join them with commas.
                let result = if context.config.spaces_within_square_brackets() {
                    format!("[ {} ]", pats.join(", "))
                } else {
                    format!("[{}]", pats.join(", "))
                };
                Some(result)
            }
            PatKind::Struct(ref path, ref fields, ellipsis) => {
                rewrite_struct_pat(path, fields, ellipsis, self.span, context, shape)
            }
            // FIXME(#819) format pattern macros.
            PatKind::Mac(..) => Some(context.snippet(self.span)),
        }
    }
}

fn rewrite_struct_pat(
    path: &ast::Path,
    fields: &[codemap::Spanned<ast::FieldPat>],
    ellipsis: bool,
    span: Span,
    context: &RewriteContext,
    shape: Shape,
) -> Option<String> {
    // 2 =  ` {`
    let path_shape = shape.sub_width(2)?;
    let path_str = rewrite_path(context, PathContext::Expr, None, path, path_shape)?;

    if fields.is_empty() && !ellipsis {
        return Some(format!("{} {{}}", path_str));
    }

    let (ellipsis_str, terminator) = if ellipsis { (", ..", "..") } else { ("", "}") };

    // 3 = ` { `, 2 = ` }`.
    let (h_shape, v_shape) =
        struct_lit_shape(shape, context, path_str.len() + 3, ellipsis_str.len() + 2)?;

    let items = itemize_list(
        context.codemap,
        fields.iter(),
        terminator,
        |f| f.span.lo(),
        |f| f.span.hi(),
        |f| f.node.rewrite(context, v_shape),
        context.codemap.span_after(span, "{"),
        span.hi(),
        false,
    );
    let item_vec = items.collect::<Vec<_>>();

    let tactic = struct_lit_tactic(h_shape, context, &item_vec);
    let nested_shape = shape_for_tactic(tactic, h_shape, v_shape);
    let fmt = struct_lit_formatting(nested_shape, tactic, context, false);

    let mut fields_str = write_list(&item_vec, &fmt)?;
    let one_line_width = h_shape.map_or(0, |shape| shape.width);

    if ellipsis {
        if fields_str.contains('\n') || fields_str.len() > one_line_width {
            // Add a missing trailing comma.
            if fmt.trailing_separator == SeparatorTactic::Never {
                fields_str.push_str(",");
            }
            fields_str.push_str("\n");
            fields_str.push_str(&nested_shape.indent.to_string(context.config));
            fields_str.push_str("..");
        } else {
            if !fields_str.is_empty() {
                // there are preceding struct fields being matched on
                if fmt.tactic == DefinitiveListTactic::Vertical {
                    // if the tactic is Vertical, write_list already added a trailing ,
                    fields_str.push_str(" ");
                } else {
                    fields_str.push_str(", ");
                }
            }
            fields_str.push_str("..");
        }
    }

    let fields_str = wrap_struct_field(context, &fields_str, shape, v_shape, one_line_width);
    Some(format!("{} {{{}}}", path_str, fields_str))
}

impl Rewrite for FieldPat {
    fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
        let pat = self.pat.rewrite(context, shape);
        if self.is_shorthand {
            pat
        } else {
            let pat_str = pat?;
            let id_str = self.ident.to_string();
            let one_line_width = id_str.len() + 2 + pat_str.len();
            if one_line_width <= shape.width {
                Some(format!("{}: {}", id_str, pat_str))
            } else {
                let nested_shape = shape.block_indent(context.config.tab_spaces());
                let pat_str = self.pat.rewrite(context, nested_shape)?;
                Some(format!(
                    "{}:\n{}{}",
                    id_str,
                    nested_shape.indent.to_string(context.config),
                    pat_str,
                ))
            }
        }
    }
}

pub enum TuplePatField<'a> {
    Pat(&'a ptr::P<ast::Pat>),
    Dotdot(Span),
}

impl<'a> Rewrite for TuplePatField<'a> {
    fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
        match *self {
            TuplePatField::Pat(p) => p.rewrite(context, shape),
            TuplePatField::Dotdot(_) => Some("..".to_string()),
        }
    }
}

impl<'a> Spanned for TuplePatField<'a> {
    fn span(&self) -> Span {
        match *self {
            TuplePatField::Pat(p) => p.span(),
            TuplePatField::Dotdot(span) => span,
        }
    }
}

pub fn can_be_overflowed_pat(context: &RewriteContext, pat: &TuplePatField, len: usize) -> bool {
    match *pat {
        TuplePatField::Pat(pat) => match pat.node {
            ast::PatKind::Path(..) | ast::PatKind::Tuple(..) | ast::PatKind::Struct(..) => {
                context.use_block_indent() && len == 1
            }
            ast::PatKind::Ref(ref p, _) | ast::PatKind::Box(ref p) => {
                can_be_overflowed_pat(context, &TuplePatField::Pat(p), len)
            }
            ast::PatKind::Lit(ref expr) => can_be_overflowed_expr(context, expr, len),
            _ => false,
        },
        TuplePatField::Dotdot(..) => false,
    }
}

fn rewrite_tuple_pat(
    pats: &[ptr::P<ast::Pat>],
    dotdot_pos: Option<usize>,
    path_str: Option<String>,
    span: Span,
    context: &RewriteContext,
    shape: Shape,
) -> Option<String> {
    let mut pat_vec: Vec<_> = pats.into_iter().map(|x| TuplePatField::Pat(x)).collect();

    if let Some(pos) = dotdot_pos {
        let prev = if pos == 0 {
            span.lo()
        } else {
            pats[pos - 1].span().hi()
        };
        let next = if pos + 1 >= pats.len() {
            span.hi()
        } else {
            pats[pos + 1].span().lo()
        };
        let dot_span = mk_sp(prev, next);
        let snippet = context.snippet(dot_span);
        let lo = dot_span.lo() + BytePos(snippet.find_uncommented("..").unwrap() as u32);
        let dotdot = TuplePatField::Dotdot(Span::new(
            lo,
            // 2 == "..".len()
            lo + BytePos(2),
            codemap::NO_EXPANSION,
        ));
        pat_vec.insert(pos, dotdot);
    }

    if pat_vec.is_empty() {
        return Some(format!("{}()", path_str.unwrap_or_default()));
    }

    let wildcard_suffix_len = count_wildcard_suffix_len(context, &pat_vec, span, shape);
    let (pat_vec, span) = if context.config.condense_wildcard_suffixes() && wildcard_suffix_len >= 2
    {
        let new_item_count = 1 + pat_vec.len() - wildcard_suffix_len;
        let sp = pat_vec[new_item_count - 1].span();
        let snippet = context.snippet(sp);
        let lo = sp.lo() + BytePos(snippet.find_uncommented("_").unwrap() as u32);
        pat_vec[new_item_count - 1] = TuplePatField::Dotdot(mk_sp(lo, lo + BytePos(1)));
        (
            &pat_vec[..new_item_count],
            mk_sp(span.lo(), lo + BytePos(1)),
        )
    } else {
        (&pat_vec[..], span)
    };

    // add comma if `(x,)`
    let add_comma = path_str.is_none() && pat_vec.len() == 1 && dotdot_pos.is_none();
    let mut context = context.clone();
    if let Some(&TuplePatField::Dotdot(..)) = pat_vec.last() {
        context.inside_macro = true;
    }
    let path_str = path_str.unwrap_or_default();
    let mut pat_ref_vec = Vec::with_capacity(pat_vec.len());
    for pat in pat_vec {
        pat_ref_vec.push(pat);
    }

    rewrite_call_inner(
        &context,
        &path_str,
        &pat_ref_vec[..],
        span,
        shape,
        shape.width,
        add_comma,
    )
}

fn count_wildcard_suffix_len(
    context: &RewriteContext,
    patterns: &[TuplePatField],
    span: Span,
    shape: Shape,
) -> usize {
    let mut suffix_len = 0;

    let items: Vec<_> = itemize_list(
        context.codemap,
        patterns.iter(),
        ")",
        |item| item.span().lo(),
        |item| item.span().hi(),
        |item| item.rewrite(context, shape),
        context.codemap.span_after(span, "("),
        span.hi() - BytePos(1),
        false,
    ).collect();

    for item in items.iter().rev().take_while(|i| match i.item {
        Some(ref internal_string) if internal_string == "_" => true,
        _ => false,
    }) {
        suffix_len += 1;

        if item.pre_comment.is_some() || item.post_comment.is_some() {
            break;
        }
    }

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

use syntax::ast::{self, BindingMode, FieldPat, Pat, PatKind, RangeEnd, RangeSyntax};
use syntax::codemap::{self, BytePos, Span};
use syntax::ptr;

use spanned::Spanned;
use codemap::SpanUtils;
use comment::FindUncommented;
use expr::{can_be_overflowed_expr, rewrite_call_inner, rewrite_pair, rewrite_unary_prefix,
           wrap_struct_field};
use lists::{itemize_list, shape_for_tactic, struct_lit_formatting, struct_lit_shape,
            struct_lit_tactic, write_list, DefinitiveListTactic, SeparatorPlace, SeparatorTactic};
use rewrite::{Rewrite, RewriteContext};
use shape::Shape;
use types::{rewrite_path, PathContext};
use utils::{format_mutability, mk_sp};

impl Rewrite for Pat {
    fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
        match self.node {
            PatKind::Box(ref pat) => rewrite_unary_prefix(context, "box ", &**pat, shape),
            PatKind::Ident(binding_mode, ident, ref sub_pat) => {
                let (prefix, mutability) = match binding_mode {
                    BindingMode::ByRef(mutability) => ("ref ", mutability),
                    BindingMode::ByValue(mutability) => ("", mutability),
                };
                let mut_infix = format_mutability(mutability);
                let id_str = ident.node.to_string();
                let sub_pat = match *sub_pat {
                    Some(ref p) => {
                        // 3 - ` @ `.
                        let width = shape
                            .width
                            .checked_sub(prefix.len() + mut_infix.len() + id_str.len() + 3)?;
                        format!(
                            " @ {}",
                            p.rewrite(context, Shape::legacy(width, shape.indent))?
                        )
                    }
                    None => "".to_owned(),
                };

                Some(format!("{}{}{}{}", prefix, mut_infix, id_str, sub_pat))
            }
            PatKind::Wild => if 1 <= shape.width {
                Some("_".to_owned())
            } else {
                None
            },
            PatKind::Range(ref lhs, ref rhs, ref end_kind) => {
                let infix = match *end_kind {
                    RangeEnd::Included(RangeSyntax::DotDotDot) => "...",
                    RangeEnd::Included(RangeSyntax::DotDotEq) => "..=",
                    RangeEnd::Excluded => "..",
                };
                rewrite_pair(
                    &**lhs,
                    &**rhs,
                    "",
                    infix,
                    "",
                    context,
                    shape,
                    SeparatorPlace::Front,
                )
            }
            PatKind::Ref(ref pat, mutability) => {
                let prefix = format!("&{}", format_mutability(mutability));
                rewrite_unary_prefix(context, &prefix, &**pat, shape)
            }
            PatKind::Tuple(ref items, dotdot_pos) => {
                rewrite_tuple_pat(items, dotdot_pos, None, self.span, context, shape)
            }
            PatKind::Path(ref q_self, ref path) => {
                rewrite_path(context, PathContext::Expr, q_self.as_ref(), path, shape)
            }
            PatKind::TupleStruct(ref path, ref pat_vec, dotdot_pos) => {
                let path_str = rewrite_path(context, PathContext::Expr, None, path, shape)?;
                rewrite_tuple_pat(
                    pat_vec,
                    dotdot_pos,
                    Some(path_str),
                    self.span,
                    context,
                    shape,
                )
            }
            PatKind::Lit(ref expr) => expr.rewrite(context, shape),
            PatKind::Slice(ref prefix, ref slice_pat, ref suffix) => {
                // Rewrite all the sub-patterns.
                let prefix = prefix.iter().map(|p| p.rewrite(context, shape));
                let slice_pat = slice_pat
                    .as_ref()
                    .map(|p| Some(format!("{}..", p.rewrite(context, shape)?)));
                let suffix = suffix.iter().map(|p| p.rewrite(context, shape));

                // Munge them together.
                let pats: Option<Vec<String>> =
                    prefix.chain(slice_pat.into_iter()).chain(suffix).collect();

                // Check that all the rewrites succeeded, and if not return None.
                let pats = pats?;

                // Unwrap all the sub-strings and join them with commas.
                let result = if context.config.spaces_within_square_brackets() {
                    format!("[ {} ]", pats.join(", "))
                } else {
                    format!("[{}]", pats.join(", "))
                };
                Some(result)
            }
            PatKind::Struct(ref path, ref fields, ellipsis) => {
                rewrite_struct_pat(path, fields, ellipsis, self.span, context, shape)
            }
            // FIXME(#819) format pattern macros.
            PatKind::Mac(..) => Some(context.snippet(self.span)),
        }
    }
}

fn rewrite_struct_pat(
    path: &ast::Path,
    fields: &[codemap::Spanned<ast::FieldPat>],
    ellipsis: bool,
    span: Span,
    context: &RewriteContext,
    shape: Shape,
) -> Option<String> {
    // 2 =  ` {`
    let path_shape = shape.sub_width(2)?;
    let path_str = rewrite_path(context, PathContext::Expr, None, path, path_shape)?;

    if fields.is_empty() && !ellipsis {
        return Some(format!("{} {{}}", path_str));
    }

    let (ellipsis_str, terminator) = if ellipsis { (", ..", "..") } else { ("", "}") };

    // 3 = ` { `, 2 = ` }`.
    let (h_shape, v_shape) =
        struct_lit_shape(shape, context, path_str.len() + 3, ellipsis_str.len() + 2)?;

    let items = itemize_list(
        context.codemap,
        fields.iter(),
        terminator,
        |f| f.span.lo(),
        |f| f.span.hi(),
        |f| f.node.rewrite(context, v_shape),
        context.codemap.span_after(span, "{"),
        span.hi(),
        false,
    );
    let item_vec = items.collect::<Vec<_>>();

    let tactic = struct_lit_tactic(h_shape, context, &item_vec);
    let nested_shape = shape_for_tactic(tactic, h_shape, v_shape);
    let fmt = struct_lit_formatting(nested_shape, tactic, context, false);

    let mut fields_str = write_list(&item_vec, &fmt)?;
    let one_line_width = h_shape.map_or(0, |shape| shape.width);

    if ellipsis {
        if fields_str.contains('\n') || fields_str.len() > one_line_width {
            // Add a missing trailing comma.
            if fmt.trailing_separator == SeparatorTactic::Never {
                fields_str.push_str(",");
            }
            fields_str.push_str("\n");
            fields_str.push_str(&nested_shape.indent.to_string(context.config));
            fields_str.push_str("..");
        } else {
            if !fields_str.is_empty() {
                // there are preceding struct fields being matched on
                if fmt.tactic == DefinitiveListTactic::Vertical {
                    // if the tactic is Vertical, write_list already added a trailing ,
                    fields_str.push_str(" ");
                } else {
                    fields_str.push_str(", ");
                }
            }
            fields_str.push_str("..");
        }
    }

    let fields_str = wrap_struct_field(context, &fields_str, shape, v_shape, one_line_width);
    Some(format!("{} {{{}}}", path_str, fields_str))
}

impl Rewrite for FieldPat {
    fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
        let pat = self.pat.rewrite(context, shape);
        if self.is_shorthand {
            pat
        } else {
            let pat_str = pat?;
            let id_str = self.ident.to_string();
            let one_line_width = id_str.len() + 2 + pat_str.len();
            if one_line_width <= shape.width {
                Some(format!("{}: {}", id_str, pat_str))
            } else {
                let nested_shape = shape.block_indent(context.config.tab_spaces());
                let pat_str = self.pat.rewrite(context, nested_shape)?;
                Some(format!(
                    "{}:\n{}{}",
                    id_str,
                    nested_shape.indent.to_string(context.config),
                    pat_str,
                ))
            }
        }
    }
}

pub enum TuplePatField<'a> {
    Pat(&'a ptr::P<ast::Pat>),
    Dotdot(Span),
}

impl<'a> Rewrite for TuplePatField<'a> {
    fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
        match *self {
            TuplePatField::Pat(p) => p.rewrite(context, shape),
            TuplePatField::Dotdot(_) => Some("..".to_string()),
        }
    }
}

impl<'a> Spanned for TuplePatField<'a> {
    fn span(&self) -> Span {
        match *self {
            TuplePatField::Pat(p) => p.span(),
            TuplePatField::Dotdot(span) => span,
        }
    }
}

pub fn can_be_overflowed_pat(context: &RewriteContext, pat: &TuplePatField, len: usize) -> bool {
    match *pat {
        TuplePatField::Pat(pat) => match pat.node {
            ast::PatKind::Path(..) |
            ast::PatKind::Tuple(..) |
            ast::PatKind::Struct(..) |
            ast::PatKind::TupleStruct(..) => context.use_block_indent() && len == 1,
            ast::PatKind::Ref(ref p, _) | ast::PatKind::Box(ref p) => {
                can_be_overflowed_pat(context, &TuplePatField::Pat(p), len)
            }
            ast::PatKind::Lit(ref expr) => can_be_overflowed_expr(context, expr, len),
            _ => false,
        },
        TuplePatField::Dotdot(..) => false,
    }
}

fn rewrite_tuple_pat(
    pats: &[ptr::P<ast::Pat>],
    dotdot_pos: Option<usize>,
    path_str: Option<String>,
    span: Span,
    context: &RewriteContext,
    shape: Shape,
) -> Option<String> {
    let mut pat_vec: Vec<_> = pats.into_iter().map(|x| TuplePatField::Pat(x)).collect();

    if let Some(pos) = dotdot_pos {
        let prev = if pos == 0 {
            span.lo()
        } else {
            pats[pos - 1].span().hi()
        };
        let next = if pos + 1 >= pats.len() {
            span.hi()
        } else {
            pats[pos + 1].span().lo()
        };
        let dot_span = mk_sp(prev, next);
        let snippet = context.snippet(dot_span);
        let lo = dot_span.lo() + BytePos(snippet.find_uncommented("..").unwrap() as u32);
        let dotdot = TuplePatField::Dotdot(Span::new(
            lo,
            // 2 == "..".len()
            lo + BytePos(2),
            codemap::NO_EXPANSION,
        ));
        pat_vec.insert(pos, dotdot);
    }

    if pat_vec.is_empty() {
        return Some(format!("{}()", path_str.unwrap_or_default()));
    }

    let wildcard_suffix_len = count_wildcard_suffix_len(context, &pat_vec, span, shape);
    let (pat_vec, span) = if context.config.condense_wildcard_suffixes() && wildcard_suffix_len >= 2
    {
        let new_item_count = 1 + pat_vec.len() - wildcard_suffix_len;
        let sp = pat_vec[new_item_count - 1].span();
        let snippet = context.snippet(sp);
        let lo = sp.lo() + BytePos(snippet.find_uncommented("_").unwrap() as u32);
        pat_vec[new_item_count - 1] = TuplePatField::Dotdot(mk_sp(lo, lo + BytePos(1)));
        (
            &pat_vec[..new_item_count],
            mk_sp(span.lo(), lo + BytePos(1)),
        )
    } else {
        (&pat_vec[..], span)
    };

    // add comma if `(x,)`
    let add_comma = path_str.is_none() && pat_vec.len() == 1 && dotdot_pos.is_none();
    let mut context = context.clone();
    if let Some(&TuplePatField::Dotdot(..)) = pat_vec.last() {
        context.inside_macro = true;
    }
    let path_str = path_str.unwrap_or_default();
    let mut pat_ref_vec = Vec::with_capacity(pat_vec.len());
    for pat in pat_vec {
        pat_ref_vec.push(pat);
    }

    rewrite_call_inner(
        &context,
        &path_str,
        &pat_ref_vec[..],
        span,
        shape,
        shape.width,
        add_comma,
    )
}

fn count_wildcard_suffix_len(
    context: &RewriteContext,
    patterns: &[TuplePatField],
    span: Span,
    shape: Shape,
) -> usize {
    let mut suffix_len = 0;

    let items: Vec<_> = itemize_list(
        context.codemap,
        patterns.iter(),
        ")",
        |item| item.span().lo(),
        |item| item.span().hi(),
        |item| item.rewrite(context, shape),
        context.codemap.span_after(span, "("),
        span.hi() - BytePos(1),
        false,
    ).collect();

    for item in items.iter().rev().take_while(|i| match i.item {
        Some(ref internal_string) if internal_string == "_" => true,
        _ => false,
    }) {
        suffix_len += 1;

        if item.pre_comment.is_some() || item.post_comment.is_some() {
            break;
        }
    }

    suffix_len
}
<|endoftext|>


<commit_before>/*!
This module is for platform-specific stuff.
*/

pub use self::inner::{current_time, file_last_modified, get_cache_dir_for};

#[cfg(windows)]
pub mod inner {
    #![allow(non_snake_case)]

    extern crate ole32;
    extern crate shell32;
    extern crate winapi;
    extern crate uuid;

    use std::ffi::OsString;
    use std::fmt;
    use std::fs;
    use std::path::{Path, PathBuf};
    use std::mem;
    use std::os::windows::ffi::OsStringExt;
    use self::uuid::FOLDERID_LocalAppData;
    use error::MainError;

    /**
    Gets the last-modified time of a file, in milliseconds since the UNIX epoch.
    */
    pub fn file_last_modified(file: &fs::File) -> u64 {
        use ::std::os::windows::fs::MetadataExt;

        const MS_BETWEEN_1601_1970: u64 = 11_644_473_600_000;

        let mtime_100ns_1601_utc = file.metadata()
            .map(|md| md.last_write_time())
            .unwrap_or(0);
        let mtime_ms_1601_utc = mtime_100ns_1601_utc / (1000*10);

        // This can obviously underflow... but since files created prior to 1970 are going to be *somewhat rare*, I'm just going to saturate to zero.
        let mtime_ms_1970_utc = mtime_ms_1601_utc.saturating_sub(MS_BETWEEN_1601_1970);
        mtime_ms_1970_utc
    }

    /**
    Gets the current system time, in milliseconds since the UNIX epoch.
    */
    pub fn current_time() -> u64 {
        extern crate time;

        /*
        This is kinda dicey, since *ideally* both this function and `file_last_modified` would be using the same underlying APIs.  They are not, insofar as I know.
        */
        let mut now_1970_utc = time::now_utc().to_timespec();
        if now_1970_utc.sec < 0 || now_1970_utc.nsec < 0 {
            // Fuck it.
            now_1970_utc = time::Timespec::new(0, 0);
        }
        let now_ms_1970_utc = (now_1970_utc.sec as u64 * 1000)
            + (now_1970_utc.nsec as u64 / 1_000_000);
        now_ms_1970_utc
    }

    /**
    Get a directory suitable for storing user- and machine-specific data which may or may not be persisted across sessions.

    On Windows, LocalAppData is where user- and machine- specific data should go, but it *might* be more appropriate to use whatever the official name for "Program Data" is, though.
    */
    pub fn get_cache_dir_for<P>(product: P) -> Result<PathBuf, MainError>
    where P: AsRef<Path> {
        let dir = try!(SHGetKnownFolderPath(&FOLDERID_LocalAppData, 0, ::std::ptr::null_mut())
            .map_err(|e| e.to_string()));
        Ok(Path::new(&dir).to_path_buf().join(product))
    }

    type WinResult<T> = Result<T, WinError>;

    struct WinError(winapi::HRESULT);

    impl fmt::Display for WinError {
        fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
            write!(fmt, "HRESULT({})", self.0)
        }
    }

    // impl From<WinError> for MainError {
    //     fn from(v: WinError) -> MainError {
    //         v.to_string().into()
    //     }
    // }

    fn SHGetKnownFolderPath(rfid: &winapi::KNOWNFOLDERID, dwFlags: winapi::DWORD, hToken: winapi::HANDLE) -> WinResult<OsString> {
        use self::winapi::PWSTR;
        let mut psz_path: PWSTR = unsafe { mem::uninitialized() };
        let hresult = unsafe {
            shell32::SHGetKnownFolderPath(
                rfid,
                dwFlags,
                hToken,
                mem::transmute(&mut psz_path as &mut PWSTR as *mut PWSTR)
            )
        };

        if hresult == winapi::S_OK {
            let r = unsafe { pwstr_to_os_string(psz_path) };
            unsafe { ole32::CoTaskMemFree(psz_path as *mut _) };
            Ok(r)
        } else {
            Err(WinError(hresult))
        }
    }

    unsafe fn pwstr_to_os_string(ptr: winapi::PWSTR) -> OsString {
        OsStringExt::from_wide(::std::slice::from_raw_parts(ptr, pwstr_len(ptr)))
    }

    unsafe fn pwstr_len(mut ptr: winapi::PWSTR) -> usize {
        let mut len = 0;
        while *ptr != 0 {
            len += 1;
            ptr = ptr.offset(1);
        }
        len
    }
}
<commit_msg>Removed some old commented-out code.<commit_after>/*!
This module is for platform-specific stuff.
*/

pub use self::inner::{current_time, file_last_modified, get_cache_dir_for};

#[cfg(windows)]
pub mod inner {
    #![allow(non_snake_case)]

    extern crate ole32;
    extern crate shell32;
    extern crate winapi;
    extern crate uuid;

    use std::ffi::OsString;
    use std::fmt;
    use std::fs;
    use std::path::{Path, PathBuf};
    use std::mem;
    use std::os::windows::ffi::OsStringExt;
    use self::uuid::FOLDERID_LocalAppData;
    use error::MainError;

    /**
    Gets the last-modified time of a file, in milliseconds since the UNIX epoch.
    */
    pub fn file_last_modified(file: &fs::File) -> u64 {
        use ::std::os::windows::fs::MetadataExt;

        const MS_BETWEEN_1601_1970: u64 = 11_644_473_600_000;

        let mtime_100ns_1601_utc = file.metadata()
            .map(|md| md.last_write_time())
            .unwrap_or(0);
        let mtime_ms_1601_utc = mtime_100ns_1601_utc / (1000*10);

        // This can obviously underflow... but since files created prior to 1970 are going to be *somewhat rare*, I'm just going to saturate to zero.
        let mtime_ms_1970_utc = mtime_ms_1601_utc.saturating_sub(MS_BETWEEN_1601_1970);
        mtime_ms_1970_utc
    }

    /**
    Gets the current system time, in milliseconds since the UNIX epoch.
    */
    pub fn current_time() -> u64 {
        extern crate time;

        /*
        This is kinda dicey, since *ideally* both this function and `file_last_modified` would be using the same underlying APIs.  They are not, insofar as I know.
        */
        let mut now_1970_utc = time::now_utc().to_timespec();
        if now_1970_utc.sec < 0 || now_1970_utc.nsec < 0 {
            // Fuck it.
            now_1970_utc = time::Timespec::new(0, 0);
        }
        let now_ms_1970_utc = (now_1970_utc.sec as u64 * 1000)
            + (now_1970_utc.nsec as u64 / 1_000_000);
        now_ms_1970_utc
    }

    /**
    Get a directory suitable for storing user- and machine-specific data which may or may not be persisted across sessions.

    On Windows, LocalAppData is where user- and machine- specific data should go, but it *might* be more appropriate to use whatever the official name for "Program Data" is, though.
    */
    pub fn get_cache_dir_for<P>(product: P) -> Result<PathBuf, MainError>
    where P: AsRef<Path> {
        let dir = try!(SHGetKnownFolderPath(&FOLDERID_LocalAppData, 0, ::std::ptr::null_mut())
            .map_err(|e| e.to_string()));
        Ok(Path::new(&dir).to_path_buf().join(product))
    }

    type WinResult<T> = Result<T, WinError>;

    struct WinError(winapi::HRESULT);

    impl fmt::Display for WinError {
        fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
            write!(fmt, "HRESULT({})", self.0)
        }
    }

    fn SHGetKnownFolderPath(rfid: &winapi::KNOWNFOLDERID, dwFlags: winapi::DWORD, hToken: winapi::HANDLE) -> WinResult<OsString> {
        use self::winapi::PWSTR;
        let mut psz_path: PWSTR = unsafe { mem::uninitialized() };
        let hresult = unsafe {
            shell32::SHGetKnownFolderPath(
                rfid,
                dwFlags,
                hToken,
                mem::transmute(&mut psz_path as &mut PWSTR as *mut PWSTR)
            )
        };

        if hresult == winapi::S_OK {
            let r = unsafe { pwstr_to_os_string(psz_path) };
            unsafe { ole32::CoTaskMemFree(psz_path as *mut _) };
            Ok(r)
        } else {
            Err(WinError(hresult))
        }
    }

    unsafe fn pwstr_to_os_string(ptr: winapi::PWSTR) -> OsString {
        OsStringExt::from_wide(::std::slice::from_raw_parts(ptr, pwstr_len(ptr)))
    }

    unsafe fn pwstr_len(mut ptr: winapi::PWSTR) -> usize {
        let mut len = 0;
        while *ptr != 0 {
            len += 1;
            ptr = ptr.offset(1);
        }
        len
    }
}
<|endoftext|>


<commit_before>use std::io::{self, Write};
use std::old_io;
use ansi_term::Colour::{Red, Yellow};
use driver::codemap::Loc;

#[macro_export]
macro_rules! fatal(
    ($msg:expr, $($args:expr),* ; $stmt:expr) => {
        {
            use assembler::util::fatal;
            fatal(format!($msg, $($args),*), &$stmt.location)
        }
    };

    ($msg:expr ; $stmt:expr) => {
        {
            use std::borrow::ToOwned;
            ::assembler::util::fatal($msg.to_owned(), &$stmt.location)
        }
    };
);

fn is_tty() -> bool {
    old_io::stdio::stderr_raw().isatty()
}

pub fn fatal(msg: String, source: Loc) -> ! {
    let mut stderr = io::stderr();

    if is_tty() {
        writeln!(&mut stderr, "{} in line {}:{}: {}", Red.paint("Error"), source.line, source.col, msg).ok();
    } else {
        writeln!(&mut stderr, "Error in line {}:{}: {}", source.line, source.col, msg).ok();
    }

    old_io::stdio::set_stderr(Box::new(old_io::util::NullWriter));
    panic!();
}

#[macro_export]
macro_rules! warn(
    ($msg:expr, $($args:expr),* ; $stmt:expr ) => {
        ::assembler::util::warn(format!($msg, $($args),*), &$stmt.location)
    }
);

pub fn warn(msg: String, source: Loc) {
    let mut stderr = io::stderr();

    if is_tty() {
        writeln!(&mut stderr, "{} in line {}:{}: {}", Yellow.paint("Warning"), source.line, source.col, msg).ok();
    } else {
        writeln!(&mut stderr, "Warning in line {}:{}: {}", source.line, source.col, msg).ok();
    }
}<commit_msg>Add an abort method for errors without source<commit_after>use std::io::{self, Write};
use std::old_io;
use ansi_term::Colour::{Red, Yellow};
use driver::codemap::Loc;

fn is_tty() -> bool {
    old_io::stdio::stderr_raw().isatty()
}

pub fn abort(msg: String) -> ! {
    let mut stderr = io::stderr();

    if is_tty() {
        writeln!(&mut stderr, "{}: {}", Red.paint("Error"), msg).ok();
    } else {
        writeln!(&mut stderr, "Error: {}", msg).ok();
    }

    old_io::stdio::set_stderr(Box::new(old_io::util::NullWriter));
    panic!();
}

pub fn fatal(msg: String, source: Loc) -> ! {
    let mut stderr = io::stderr();

    if is_tty() {
        writeln!(&mut stderr, "{} in line {}:{}: {}", Red.paint("Error"), source.line, source.col, msg).ok();
    } else {
        writeln!(&mut stderr, "Error in line {}:{}: {}", source.line, source.col, msg).ok();
    }

    old_io::stdio::set_stderr(Box::new(old_io::util::NullWriter));
    panic!();
}

pub fn warn(msg: String, source: Loc) {
    let mut stderr = io::stderr();

    if is_tty() {
        writeln!(&mut stderr, "{} in line {}:{}: {}", Yellow.paint("Warning"), source.line, source.col, msg).ok();
    } else {
        writeln!(&mut stderr, "Warning in line {}:{}: {}", source.line, source.col, msg).ok();
    }
}<|endoftext|>


<commit_before>// Copyright (c) 2017-2018, The rav1e contributors. All rights reserved
//
// This source code is subject to the terms of the BSD 2 Clause License and
// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
// was not distributed with this source code in the LICENSE file, you can
// obtain it at www.aomedia.org/license/software. If the Alliance for Open
// Media Patent License 1.0 was not distributed with this source code in the
// PATENTS file, you can obtain it at www.aomedia.org/license/patent.

#![cfg_attr(feature = "cargo-clippy", allow(cast_lossless))]

use partition::TxSize;

extern {
  static dc_qlookup_Q3: [i16; 256];
  static ac_qlookup_Q3: [i16; 256];
}

fn get_tx_scale(tx_size: TxSize) -> u8 {
  match tx_size {
    TxSize::TX_64X64 => 4,
    TxSize::TX_32X32 => 2,
    _ => 1
  }
}

pub fn dc_q(qindex: usize) -> i16 {
  unsafe { dc_qlookup_Q3[qindex] }
}

pub fn ac_q(qindex: usize) -> i16 {
  unsafe { ac_qlookup_Q3[qindex] }
}

#[derive(Debug, Default, Clone, Copy)]
pub struct QuantizationContext {
    tx_scale: i32,
    dc_quant: u32,
    dc_offset: i32,
    dc_mul_add: (u32, u32, u32),

    ac_quant: u32,
    ac_offset: i32,
    ac_mul_add: (u32, u32, u32),
}

use std::mem;

fn divu_gen(d: u32) -> (u32, u32, u32) {
    let nbits = (mem::size_of_val(&d) as u64) * 8;
    let m = nbits - d.leading_zeros() as u64 - 1;
    if (d & (d - 1)) == 0 {
        (0xFFFFFFFF, 0xFFFFFFFF, m as u32)
    } else {
        let d = d as u64;
        let t = (1u64 << (m + nbits)) / d;
        let r = (t * d + d) & ((1 << nbits) - 1);
        if r <= 1u64 << m {
             (t as u32 + 1, 0u32, m as u32)
        } else {
             (t as u32, t as u32, m as u32)
        }
    }
}

#[inline]
fn divu_pair(x: i32, d: (u32, u32, u32)) -> i32 {
    let y = if x < 0 {-x} else {x} as u64;
    let (a, b, shift) = d;
    let shift = shift as u64;
    let a = a as u64;
    let b = b as u64;

    let y = (((a * y + b) >> 32) >> shift) as i32;
    if x < 0 { -y } else { y }
}

#[cfg(test)]
mod test {
    use super::*;
    #[test]
    fn test_divu_pair() {
        for d in 1..1024 {
            for x in -1000..1000 {
                let ab = divu_gen(d as u32);
                assert_eq!(x/d, divu_pair(x, ab));
            }
        }
    }
    #[test]
    fn gen_divu_table() {
        let b: Vec<(u32, u32, u32)> = dc_qlookup_Q3.iter().map(|&v| {
            divu_gen(v as u32)
        }).collect();

        println!("{:?}", b);
    }
}

impl QuantizationContext {
    pub fn update(&mut self, qindex: usize, tx_size: TxSize) {
      self.tx_scale = get_tx_scale(tx_size) as i32;

      self.dc_quant = dc_q(qindex) as u32;
      self.dc_mul_add = divu_gen(self.dc_quant);

      self.ac_quant = ac_q(qindex) as u32;
      self.ac_mul_add = divu_gen(self.ac_quant);
    }

    #[inline]
    pub fn quantize(&self, coeffs: &mut [i32]) {
      coeffs[0] *= self.tx_scale;
      coeffs[0] += coeffs[0].signum() * self.dc_offset;
      coeffs[0] = divu_pair(coeffs[0], self.dc_mul_add);

      for c in coeffs[1..].iter_mut() {
        *c *= self.tx_scale;
        *c += c.signum() * self.ac_offset;
        *c = divu_pair(*c, self.ac_mul_add);
      }
    }
}

pub fn quantize_in_place(qindex: usize, coeffs: &mut [i32], tx_size: TxSize) {
  let tx_scale = get_tx_scale(tx_size) as i32;

  let dc_quant = dc_q(qindex) as i32;
  let ac_quant = ac_q(qindex) as i32;

  // using 21/64=0.328125 as rounding offset. To be tuned
  let dc_offset = dc_quant * 21 / 64 as i32;
  let ac_offset = ac_quant * 21 / 64 as i32;

  coeffs[0] *= tx_scale;
  coeffs[0] += coeffs[0].signum() * dc_offset;
  coeffs[0] /= dc_quant;

  for c in coeffs[1..].iter_mut() {
    *c *= tx_scale;
    *c += c.signum() * ac_offset;
    *c /= ac_quant;
  }
}

pub fn dequantize(
  qindex: usize, coeffs: &[i32], rcoeffs: &mut [i32], tx_size: TxSize
) {
  let tx_scale = get_tx_scale(tx_size) as i32;

  rcoeffs[0] = (coeffs[0] * dc_q(qindex) as i32) / tx_scale;
  let ac_quant = ac_q(qindex) as i32;

  for (r, &c) in rcoeffs.iter_mut().zip(coeffs.iter()).skip(1) {
    *r = c * ac_quant / tx_scale;
  }
}
<commit_msg>Fix a rebase glitch in quantize<commit_after>// Copyright (c) 2017-2018, The rav1e contributors. All rights reserved
//
// This source code is subject to the terms of the BSD 2 Clause License and
// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
// was not distributed with this source code in the LICENSE file, you can
// obtain it at www.aomedia.org/license/software. If the Alliance for Open
// Media Patent License 1.0 was not distributed with this source code in the
// PATENTS file, you can obtain it at www.aomedia.org/license/patent.

#![cfg_attr(feature = "cargo-clippy", allow(cast_lossless))]

use partition::TxSize;

extern {
  static dc_qlookup_Q3: [i16; 256];
  static ac_qlookup_Q3: [i16; 256];
}

fn get_tx_scale(tx_size: TxSize) -> u8 {
  match tx_size {
    TxSize::TX_64X64 => 4,
    TxSize::TX_32X32 => 2,
    _ => 1
  }
}

pub fn dc_q(qindex: usize) -> i16 {
  unsafe { dc_qlookup_Q3[qindex] }
}

pub fn ac_q(qindex: usize) -> i16 {
  unsafe { ac_qlookup_Q3[qindex] }
}

#[derive(Debug, Default, Clone, Copy)]
pub struct QuantizationContext {
    tx_scale: i32,
    dc_quant: u32,
    dc_offset: i32,
    dc_mul_add: (u32, u32, u32),

    ac_quant: u32,
    ac_offset: i32,
    ac_mul_add: (u32, u32, u32),
}

use std::mem;

fn divu_gen(d: u32) -> (u32, u32, u32) {
    let nbits = (mem::size_of_val(&d) as u64) * 8;
    let m = nbits - d.leading_zeros() as u64 - 1;
    if (d & (d - 1)) == 0 {
        (0xFFFFFFFF, 0xFFFFFFFF, m as u32)
    } else {
        let d = d as u64;
        let t = (1u64 << (m + nbits)) / d;
        let r = (t * d + d) & ((1 << nbits) - 1);
        if r <= 1u64 << m {
             (t as u32 + 1, 0u32, m as u32)
        } else {
             (t as u32, t as u32, m as u32)
        }
    }
}

#[inline]
fn divu_pair(x: i32, d: (u32, u32, u32)) -> i32 {
    let y = if x < 0 {-x} else {x} as u64;
    let (a, b, shift) = d;
    let shift = shift as u64;
    let a = a as u64;
    let b = b as u64;

    let y = (((a * y + b) >> 32) >> shift) as i32;
    if x < 0 { -y } else { y }
}

#[cfg(test)]
mod test {
    use super::*;
    #[test]
    fn test_divu_pair() {
        for d in 1..1024 {
            for x in -1000..1000 {
                let ab = divu_gen(d as u32);
                assert_eq!(x/d, divu_pair(x, ab));
            }
        }
    }
    #[test]
    fn gen_divu_table() {
        let b: Vec<(u32, u32, u32)> = dc_qlookup_Q3.iter().map(|&v| {
            divu_gen(v as u32)
        }).collect();

        println!("{:?}", b);
    }
}

impl QuantizationContext {
    pub fn update(&mut self, qindex: usize, tx_size: TxSize) {
      self.tx_scale = get_tx_scale(tx_size) as i32;

      self.dc_quant = dc_q(qindex) as u32;
      self.dc_mul_add = divu_gen(self.dc_quant);

      self.ac_quant = ac_q(qindex) as u32;
      self.ac_mul_add = divu_gen(self.ac_quant);

      self.dc_offset = self.dc_quant as i32 * 21 / 64;
      self.ac_offset = self.ac_quant as i32 * 21 / 64;
    }

    #[inline]
    pub fn quantize(&self, coeffs: &mut [i32]) {
      coeffs[0] *= self.tx_scale;
      coeffs[0] += coeffs[0].signum() * self.dc_offset;
      coeffs[0] = divu_pair(coeffs[0], self.dc_mul_add);

      for c in coeffs[1..].iter_mut() {
        *c *= self.tx_scale;
        *c += c.signum() * self.ac_offset;
        *c = divu_pair(*c, self.ac_mul_add);
      }
    }
}

pub fn quantize_in_place(qindex: usize, coeffs: &mut [i32], tx_size: TxSize) {
  let tx_scale = get_tx_scale(tx_size) as i32;

  let dc_quant = dc_q(qindex) as i32;
  let ac_quant = ac_q(qindex) as i32;

  // using 21/64=0.328125 as rounding offset. To be tuned
  let dc_offset = dc_quant * 21 / 64 as i32;
  let ac_offset = ac_quant * 21 / 64 as i32;

  coeffs[0] *= tx_scale;
  coeffs[0] += coeffs[0].signum() * dc_offset;
  coeffs[0] /= dc_quant;

  for c in coeffs[1..].iter_mut() {
    *c *= tx_scale;
    *c += c.signum() * ac_offset;
    *c /= ac_quant;
  }
}

pub fn dequantize(
  qindex: usize, coeffs: &[i32], rcoeffs: &mut [i32], tx_size: TxSize
) {
  let tx_scale = get_tx_scale(tx_size) as i32;

  rcoeffs[0] = (coeffs[0] * dc_q(qindex) as i32) / tx_scale;
  let ac_quant = ac_q(qindex) as i32;

  for (r, &c) in rcoeffs.iter_mut().zip(coeffs.iter()).skip(1) {
    *r = c * ac_quant / tx_scale;
  }
}
<|endoftext|>


<commit_before>//! Task execution utilities.
//!
//! In the Tokio execution model, futures are lazy. When a future is created, no
//! work is performed. In order for the work defined by the future to happen,
//! the future must be submitted to an executor. A future that is submitted to
//! an executor is called a "task".
//!
//! The executor is responsible for ensuring that [`Future::poll`] is
//! called whenever the task is [notified]. Notification happens when the
//! internal state of a task transitions from "not ready" to ready. For
//! example, a socket might have received data and a call to `read` will now be
//! able to succeed.
//!
//! The specific strategy used to manage the tasks is left up to the
//! executor. There are two main flavors of executors: single-threaded and
//! multi-threaded. Tokio provides implementation for both of these in the
//! [`runtime`] module.
//!
//! # `Executor` trait.
//!
//! This module provides the [`Executor`] trait (re-exported from
//! [`tokio-executor`]), which describes the API that all executors must
//! implement.
//!
//! A free [`spawn`] function is provided that allows spawning futures onto the
//! default executor (tracked via a thread-local variable) without referencing a
//! handle. It is expected that all executors will set a value for the default
//! executor. This value will often be set to the executor itself, but it is
//! possible that the default executor might be set to a different executor.
//!
//! For example, a single threaded executor might set the default executor to a
//! thread pool instead of itself, allowing futures to spawn new tasks onto the
//! thread pool when those tasks are `Send`.
//!
//! [`Future::poll`]: https://docs.rs/futures/0.1/futures/future/trait.Future.html#tymethod.poll
//! [notified]: https://docs.rs/futures/0.1/futures/executor/trait.Notify.html#tymethod.notify
//! [`runtime`]: ../runtime/index.html
//! [`tokio-executor`]: https://docs.rs/tokio-executor/0.1
//! [`Executor`]: trait.Executor.html
//! [`spawn`]: fn.spawn.html

#[deprecated(
    since = "0.1.8",
    note = "use tokio-current-thread crate or functions in tokio::runtime::current_thread instead",
)]
#[doc(hidden)]
pub mod current_thread;

#[deprecated(since = "0.1.8", note = "use tokio-threadpool crate instead")]
/// Re-exports of [`tokio-threadpool`], deprecated in favor of the crate.
///
/// [`tokio-threadpool`]: https://docs.rs/tokio-threadpool/0.1
pub mod thread_pool {
    pub use tokio_threadpool::{
        Builder,
        Sender,
        Shutdown,
        ThreadPool,
    };
}

pub use tokio_executor::{Executor, DefaultExecutor, SpawnError};

use futures::{Future, IntoFuture};
use futures::future::{self, FutureResult};

/// Return value from the `spawn` function.
///
/// Currently this value doesn't actually provide any functionality. However, it
/// provides a way to add functionality later without breaking backwards
/// compatibility.
///
/// This also implements `IntoFuture` so that it can be used as the return value
/// in a `for_each` loop.
///
/// See [`spawn`] for more details.
///
/// [`spawn`]: fn.spawn.html
#[derive(Debug)]
pub struct Spawn(());

/// Spawns a future on the default executor.
///
/// In order for a future to do work, it must be spawned on an executor. The
/// `spawn` function is the easiest way to do this. It spawns a future on the
/// [default executor] for the current execution context (tracked using a
/// thread-local variable).
///
/// The default executor is **usually** a thread pool.
///
/// # Examples
///
/// In this example, a server is started and `spawn` is used to start a new task
/// that processes each received connection.
///
/// ```rust
/// # extern crate tokio;
/// # extern crate futures;
/// # use futures::{Future, Stream};
/// use tokio::net::TcpListener;
///
/// # fn process<T>(_: T) -> Box<Future<Item = (), Error = ()> + Send> {
/// # unimplemented!();
/// # }
/// # fn dox() {
/// # let addr = "127.0.0.1:8080".parse().unwrap();
/// let listener = TcpListener::bind(&addr).unwrap();
///
/// let server = listener.incoming()
///     .map_err(|e| println!("error = {:?}", e))
///     .for_each(|socket| {
///         tokio::spawn(process(socket))
///     });
///
/// tokio::run(server);
/// # }
/// # pub fn main() {}
/// ```
///
/// [default executor]: struct.DefaultExecutor.html
///
/// # Panics
///
/// This function will panic if the default executor is not set or if spawning
/// onto the default executor returns an error. To avoid the panic, use
/// [`DefaultExecutor`].
///
/// [`DefaultExecutor`]: struct.DefaultExecutor.html
pub fn spawn<F>(f: F) -> Spawn
where F: Future<Item = (), Error = ()> + 'static + Send
{
    ::tokio_executor::spawn(f);
    Spawn(())
}

impl IntoFuture for Spawn {
    type Future = FutureResult<(), ()>;
    type Item = ();
    type Error = ();

    fn into_future(self) -> Self::Future {
        future::ok(())
    }
}
<commit_msg>tokio-executor: hide deprecated tokio-threadpool reexports (#644)<commit_after>//! Task execution utilities.
//!
//! In the Tokio execution model, futures are lazy. When a future is created, no
//! work is performed. In order for the work defined by the future to happen,
//! the future must be submitted to an executor. A future that is submitted to
//! an executor is called a "task".
//!
//! The executor is responsible for ensuring that [`Future::poll`] is
//! called whenever the task is [notified]. Notification happens when the
//! internal state of a task transitions from "not ready" to ready. For
//! example, a socket might have received data and a call to `read` will now be
//! able to succeed.
//!
//! The specific strategy used to manage the tasks is left up to the
//! executor. There are two main flavors of executors: single-threaded and
//! multi-threaded. Tokio provides implementation for both of these in the
//! [`runtime`] module.
//!
//! # `Executor` trait.
//!
//! This module provides the [`Executor`] trait (re-exported from
//! [`tokio-executor`]), which describes the API that all executors must
//! implement.
//!
//! A free [`spawn`] function is provided that allows spawning futures onto the
//! default executor (tracked via a thread-local variable) without referencing a
//! handle. It is expected that all executors will set a value for the default
//! executor. This value will often be set to the executor itself, but it is
//! possible that the default executor might be set to a different executor.
//!
//! For example, a single threaded executor might set the default executor to a
//! thread pool instead of itself, allowing futures to spawn new tasks onto the
//! thread pool when those tasks are `Send`.
//!
//! [`Future::poll`]: https://docs.rs/futures/0.1/futures/future/trait.Future.html#tymethod.poll
//! [notified]: https://docs.rs/futures/0.1/futures/executor/trait.Notify.html#tymethod.notify
//! [`runtime`]: ../runtime/index.html
//! [`tokio-executor`]: https://docs.rs/tokio-executor/0.1
//! [`Executor`]: trait.Executor.html
//! [`spawn`]: fn.spawn.html

#[deprecated(
    since = "0.1.8",
    note = "use tokio-current-thread crate or functions in tokio::runtime::current_thread instead",
)]
#[doc(hidden)]
pub mod current_thread;

#[deprecated(since = "0.1.8", note = "use tokio-threadpool crate instead")]
#[doc(hidden)]
/// Re-exports of [`tokio-threadpool`], deprecated in favor of the crate.
///
/// [`tokio-threadpool`]: https://docs.rs/tokio-threadpool/0.1
pub mod thread_pool {
    pub use tokio_threadpool::{
        Builder,
        Sender,
        Shutdown,
        ThreadPool,
    };
}

pub use tokio_executor::{Executor, DefaultExecutor, SpawnError};

use futures::{Future, IntoFuture};
use futures::future::{self, FutureResult};

/// Return value from the `spawn` function.
///
/// Currently this value doesn't actually provide any functionality. However, it
/// provides a way to add functionality later without breaking backwards
/// compatibility.
///
/// This also implements `IntoFuture` so that it can be used as the return value
/// in a `for_each` loop.
///
/// See [`spawn`] for more details.
///
/// [`spawn`]: fn.spawn.html
#[derive(Debug)]
pub struct Spawn(());

/// Spawns a future on the default executor.
///
/// In order for a future to do work, it must be spawned on an executor. The
/// `spawn` function is the easiest way to do this. It spawns a future on the
/// [default executor] for the current execution context (tracked using a
/// thread-local variable).
///
/// The default executor is **usually** a thread pool.
///
/// # Examples
///
/// In this example, a server is started and `spawn` is used to start a new task
/// that processes each received connection.
///
/// ```rust
/// # extern crate tokio;
/// # extern crate futures;
/// # use futures::{Future, Stream};
/// use tokio::net::TcpListener;
///
/// # fn process<T>(_: T) -> Box<Future<Item = (), Error = ()> + Send> {
/// # unimplemented!();
/// # }
/// # fn dox() {
/// # let addr = "127.0.0.1:8080".parse().unwrap();
/// let listener = TcpListener::bind(&addr).unwrap();
///
/// let server = listener.incoming()
///     .map_err(|e| println!("error = {:?}", e))
///     .for_each(|socket| {
///         tokio::spawn(process(socket))
///     });
///
/// tokio::run(server);
/// # }
/// # pub fn main() {}
/// ```
///
/// [default executor]: struct.DefaultExecutor.html
///
/// # Panics
///
/// This function will panic if the default executor is not set or if spawning
/// onto the default executor returns an error. To avoid the panic, use
/// [`DefaultExecutor`].
///
/// [`DefaultExecutor`]: struct.DefaultExecutor.html
pub fn spawn<F>(f: F) -> Spawn
where F: Future<Item = (), Error = ()> + 'static + Send
{
    ::tokio_executor::spawn(f);
    Spawn(())
}

impl IntoFuture for Spawn {
    type Future = FutureResult<(), ()>;
    type Item = ();
    type Error = ();

    fn into_future(self) -> Self::Future {
        future::ok(())
    }
}
<|endoftext|>


<commit_before>use super::super::{Grid, Coord, FiniteSearchQueue};
use super::*;

#[derive(Clone, Copy)]
struct FieldGrp {
    unmet_num: i32,
    unmet_sum: i32,
    unused: Cand,
}
pub struct Field<'a> {
    dic: &'a Dictionary,
    shape: FieldShape,
    grps: Vec<FieldGrp>,
    val: Vec<i32>,
    cand: Vec<Cand>,
    inconsistent: bool,
    queue: FiniteSearchQueue
}
impl<'a> Field<'a> {
    pub fn new(problem: &Grid<Clue>, dic: &'a Dictionary) -> Field<'a> {
        let n_cells = (problem.height() * problem.width()) as usize;
        let mut has_clue = Grid::new(problem.height(), problem.width(), false);
        for i in 0..n_cells {
            if let Clue::Clue { vertical: _, horizontal: _ } = problem[i] {
                has_clue[i] = true;
            }
        }
        let shape = FieldShape::new(&has_clue);

        let mut grps = vec![FieldGrp {
            unmet_num: 0,
            unmet_sum: 0,
            unused: 0,
        }; shape.group_to_cells.len()];
        let n_groups = grps.len();

        for i in 0..shape.group_to_cells.len() {
            let loc = shape.clue_locations[i];
            let clue_val = match loc {
                ClueLocation::Vertical(v) => match problem[v as usize] {
                    Clue::NoClue => panic!("unexpected condition"),
                    Clue::Clue { vertical: v, horizontal: _ } => v,
                },
                ClueLocation::Horizontal(h) => match problem[h as usize] {
                    Clue::NoClue => panic!("unexpected condition"),
                    Clue::Clue { vertical: _, horizontal: h } => h,
                },
            };
            let mut n_cells = 0;
            for _ in shape.group_to_cells[i] {
                n_cells += 1;
            }
            grps[i] = FieldGrp {
                unmet_num: n_cells,
                unmet_sum: clue_val,
                unused: CAND_ALL,
            };
        }

        Field {
            dic: dic,
            shape: shape,
            grps: grps,
            val: vec![UNDECIDED; n_cells],
            cand: vec![CAND_ALL; n_cells],
            inconsistent: false,
            queue: FiniteSearchQueue::new(n_groups as i32),
        }
    }
    pub fn inconsistent(&self) -> bool {
        self.inconsistent
    }
    pub fn height(&self) -> i32 {
        self.shape.has_clue.height()
    }
    pub fn width(&self) -> i32 {
        self.shape.has_clue.width()
    }
    pub fn val(&self, loc: Coord) -> i32 {
        self.val[self.location(loc)]
    }
    pub fn decide(&mut self, loc: Coord, val: i32) {
        let loc = self.location(loc);

        self.queue.start();
        self.decide_int(loc, val);
        while !self.queue.empty() {
            let g = self.queue.pop();
            self.check_group(g);
        }
        self.queue.finish();

    }
    pub fn check_all(&mut self) {
        self.queue.start();
        for i in 0..(self.grps.len() as i32) {
            self.queue.push(i);
        }
        while !self.queue.empty() {
            let g = self.queue.pop();
            self.check_group(g);
        }
        self.queue.finish();
    }
    fn location(&self, loc: Coord) -> usize {
        self.shape.has_clue.index(loc)
    }
    fn decide_int(&mut self, loc: usize, val: i32) {
        if self.val[loc] != UNDECIDED {
            if self.val[loc] != val {
                self.inconsistent = true;
            }
            return;
        }

        self.val[loc] = val;
        if (self.cand[loc] & (1 << (val - 1))) == 0 {
            self.inconsistent = true;
            return;
        }
        self.cand[loc] = 1 << (val - 1);

        let (g1, g2) = self.shape.cell_to_groups[loc];
        self.grps[g1 as usize].unmet_num -= 1;
        self.grps[g1 as usize].unmet_sum -= val;
        if (self.grps[g1 as usize].unused & (1 << (val - 1) as Cand)) == 0 {
            self.inconsistent = true;
            return;
        }
        self.grps[g1 as usize].unused &= !(1 << (val - 1) as Cand);
        self.grps[g2 as usize].unmet_num -= 1;
        self.grps[g2 as usize].unmet_sum -= val;
        if (self.grps[g2 as usize].unused & (1 << (val - 1) as Cand)) == 0 {
            self.inconsistent = true;
            return;
        }
        self.grps[g2 as usize].unused &= !(1 << (val - 1) as Cand);

        self.eliminate_cand_from_group(g1, val, loc as i32);
        self.eliminate_cand_from_group(g2, val, loc as i32);

        self.queue.push(g1);
        self.queue.push(g2);
    }
    fn eliminate_cand_from_group(&mut self, grp: i32, rem_cand: i32, cur: i32) {
        let cand = !(1 << (rem_cand - 1) as Cand);
        for c in self.shape.group_to_cells[grp as usize] {
            if c != cur {
                self.limit_cand(c as usize, cand);
            }
        }
    }
    fn limit_cand(&mut self, loc: usize, lim: Cand) {
        if self.cand[loc] & lim == self.cand[loc] {
            return;
        }
        self.cand[loc] &= lim;

        let current_cand = self.cand[loc];
        if current_cand == 0 {
            self.inconsistent = true;
            return;
        }
        if current_cand.count_ones() == 1 {
            self.decide_int(loc, (current_cand.trailing_zeros() + 1) as i32);
        }

        let (g1, g2) = self.shape.cell_to_groups[loc];
        self.queue.push(g1);
        self.queue.push(g2);
    }
    fn check_group(&mut self, gid: i32) {
        let grp = self.grps[gid as usize];
        let (imperative, allowed) = self.dic.at(grp.unmet_num, grp.unmet_sum, grp.unused);
        if (imperative, allowed) == dictionary::IMPOSSIBLE {
            self.inconsistent = true;
            return;
        }

        // unique position technique
        if imperative != 0 {
            let mut uniq = 0;
            let mut mult = 0;
            for c in self.shape.group_to_cells[gid as usize] {
                if self.val[c as usize] == UNDECIDED {
                    mult |= uniq & self.cand[c as usize];
                    uniq |= self.cand[c as usize];
                }
            }
            uniq &= imperative & !mult;
            if uniq != 0 {
                for c in self.shape.group_to_cells[gid as usize] {
                    if self.val[c as usize] == UNDECIDED && (self.cand[c as usize] & uniq) != 0 {
                        let val = ((self.cand[c as usize] & uniq).trailing_zeros() + 1) as i32;
                        self.decide_int(c as usize, val);
                    }
                }
            }
        }

        // candidate limitation
        for c in self.shape.group_to_cells[gid as usize] {
            if self.val[c as usize] == UNDECIDED {
                self.limit_cand(c as usize, allowed);
            }
        }

        // two-cells propagation (TODO: improve complexity)
        let grp = self.grps[gid as usize];
        if grp.unmet_num == 2 {
            let mut c1 = -1;
            let mut c2 = -1;
            for c in self.shape.group_to_cells[gid as usize] {
                if self.val[c as usize] == UNDECIDED {
                    if c1 == -1 {
                        c1 = c;
                    } else {
                        c2 = c;
                    }
                }
            }
            for i in 1..(MAX_VAL + 1) {
                if (self.cand[c1 as usize] & (1 << (i - 1) as Cand) == 0) && 1 <= (grp.unmet_sum - i) && (grp.unmet_sum - i) <= MAX_VAL {
                    self.limit_cand(c2 as usize, !(1 << (grp.unmet_sum - i - 1) as Cand));
                }
                if (self.cand[c2 as usize] & (1 << (i - 1) as Cand) == 0) && 1 <= (grp.unmet_sum - i) && (grp.unmet_sum - i) <= MAX_VAL {
                    self.limit_cand(c1 as usize, !(1 << (grp.unmet_sum - i - 1) as Cand));
                }
            }
        }

        // naked pair (TODO: improve complexity)
        for c in self.shape.group_to_cells[gid as usize] {
            if self.val[c as usize] != -1 { continue; }
            for d in self.shape.group_to_cells[gid as usize] {
                if self.val[d as usize] != -1 { continue; }
                if c != d && self.cand[c as usize] == self.cand[d as usize] && self.cand[c as usize].count_ones() == 2 {
                    for e in self.shape.group_to_cells[gid as usize] {
                        if c != e && d != e {
                            let lim = !self.cand[c as usize];
                            self.limit_cand(e as usize, lim);
                        }
                    }
                }
            }
        }

        // min-max method
        let grp = self.grps[gid as usize];
        let mut min_sum = 0;
        let mut max_sum = 0;
        for c in self.shape.group_to_cells[gid as usize] {
            if self.val[c as usize] != -1 { continue; }
            let cand = self.cand[c as usize];
            min_sum += cand.trailing_zeros() + 1;
            max_sum += 32 - cand.leading_zeros();
        }
        for c in self.shape.group_to_cells[gid as usize] {
            if self.val[c as usize] != -1 { continue; }
            let cand = self.cand[c as usize];

            let current_max = grp.unmet_sum - (min_sum - (cand.trailing_zeros() + 1)) as i32;
            let current_min = grp.unmet_sum - (max_sum - (32 - cand.leading_zeros())) as i32;

            let mut lim = CAND_ALL;
            if current_max <= 8 {
                lim &= (1 << current_max as Cand) - 1;
            }
            if current_min >= 2 {
                lim &= !((1 << (current_min as Cand - 1)) - 1);
            }
            if lim != CAND_ALL {
                self.limit_cand(c as usize, lim);
            }
        }
    }
}

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

    #[test]
    fn test_field() {
        let dic = Dictionary::default();
        let mut problem_base = Grid::new(3, 3, Clue::NoClue);
        problem_base[Coord { y: 0, x: 0 }] = Clue::Clue { horizontal: -1, vertical: -1 };
        problem_base[Coord { y: 0, x: 1 }] = Clue::Clue { horizontal: -1, vertical: 3 };
        problem_base[Coord { y: 0, x: 2 }] = Clue::Clue { horizontal: -1, vertical: 8 };
        problem_base[Coord { y: 1, x: 0 }] = Clue::Clue { horizontal: 4, vertical: -1 };
        problem_base[Coord { y: 2, x: 0 }] = Clue::Clue { horizontal: 7, vertical: -1 };

        let mut field = Field::new(&problem_base, &dic);
        field.check_all();

        assert_eq!(field.val(Coord { y: 1, x: 1 }), 1);
        assert_eq!(field.val(Coord { y: 1, x: 2 }), 3);
        assert_eq!(field.val(Coord { y: 2, x: 1 }), 2);
        assert_eq!(field.val(Coord { y: 2, x: 2 }), 5);
        assert_eq!(field.inconsistent(), false);
    }
}
<commit_msg>Kakuro: add a test for inconsistent problem<commit_after>use super::super::{Grid, Coord, FiniteSearchQueue};
use super::*;

#[derive(Clone, Copy)]
struct FieldGrp {
    unmet_num: i32,
    unmet_sum: i32,
    unused: Cand,
}
pub struct Field<'a> {
    dic: &'a Dictionary,
    shape: FieldShape,
    grps: Vec<FieldGrp>,
    val: Vec<i32>,
    cand: Vec<Cand>,
    inconsistent: bool,
    queue: FiniteSearchQueue
}
impl<'a> Field<'a> {
    pub fn new(problem: &Grid<Clue>, dic: &'a Dictionary) -> Field<'a> {
        let n_cells = (problem.height() * problem.width()) as usize;
        let mut has_clue = Grid::new(problem.height(), problem.width(), false);
        for i in 0..n_cells {
            if let Clue::Clue { vertical: _, horizontal: _ } = problem[i] {
                has_clue[i] = true;
            }
        }
        let shape = FieldShape::new(&has_clue);

        let mut grps = vec![FieldGrp {
            unmet_num: 0,
            unmet_sum: 0,
            unused: 0,
        }; shape.group_to_cells.len()];
        let n_groups = grps.len();

        for i in 0..shape.group_to_cells.len() {
            let loc = shape.clue_locations[i];
            let clue_val = match loc {
                ClueLocation::Vertical(v) => match problem[v as usize] {
                    Clue::NoClue => panic!("unexpected condition"),
                    Clue::Clue { vertical: v, horizontal: _ } => v,
                },
                ClueLocation::Horizontal(h) => match problem[h as usize] {
                    Clue::NoClue => panic!("unexpected condition"),
                    Clue::Clue { vertical: _, horizontal: h } => h,
                },
            };
            let mut n_cells = 0;
            for _ in shape.group_to_cells[i] {
                n_cells += 1;
            }
            grps[i] = FieldGrp {
                unmet_num: n_cells,
                unmet_sum: clue_val,
                unused: CAND_ALL,
            };
        }

        Field {
            dic: dic,
            shape: shape,
            grps: grps,
            val: vec![UNDECIDED; n_cells],
            cand: vec![CAND_ALL; n_cells],
            inconsistent: false,
            queue: FiniteSearchQueue::new(n_groups as i32),
        }
    }
    pub fn inconsistent(&self) -> bool {
        self.inconsistent
    }
    pub fn height(&self) -> i32 {
        self.shape.has_clue.height()
    }
    pub fn width(&self) -> i32 {
        self.shape.has_clue.width()
    }
    pub fn val(&self, loc: Coord) -> i32 {
        self.val[self.location(loc)]
    }
    pub fn decide(&mut self, loc: Coord, val: i32) {
        let loc = self.location(loc);

        self.queue.start();
        self.decide_int(loc, val);
        while !self.queue.empty() {
            let g = self.queue.pop();
            self.check_group(g);
        }
        self.queue.finish();

    }
    pub fn check_all(&mut self) {
        self.queue.start();
        for i in 0..(self.grps.len() as i32) {
            self.queue.push(i);
        }
        while !self.queue.empty() {
            let g = self.queue.pop();
            self.check_group(g);
        }
        self.queue.finish();
    }
    fn location(&self, loc: Coord) -> usize {
        self.shape.has_clue.index(loc)
    }
    fn decide_int(&mut self, loc: usize, val: i32) {
        if self.val[loc] != UNDECIDED {
            if self.val[loc] != val {
                self.inconsistent = true;
            }
            return;
        }

        self.val[loc] = val;
        if (self.cand[loc] & (1 << (val - 1))) == 0 {
            self.inconsistent = true;
            return;
        }
        self.cand[loc] = 1 << (val - 1);

        let (g1, g2) = self.shape.cell_to_groups[loc];
        self.grps[g1 as usize].unmet_num -= 1;
        self.grps[g1 as usize].unmet_sum -= val;
        if (self.grps[g1 as usize].unused & (1 << (val - 1) as Cand)) == 0 {
            self.inconsistent = true;
            return;
        }
        self.grps[g1 as usize].unused &= !(1 << (val - 1) as Cand);
        self.grps[g2 as usize].unmet_num -= 1;
        self.grps[g2 as usize].unmet_sum -= val;
        if (self.grps[g2 as usize].unused & (1 << (val - 1) as Cand)) == 0 {
            self.inconsistent = true;
            return;
        }
        self.grps[g2 as usize].unused &= !(1 << (val - 1) as Cand);

        self.eliminate_cand_from_group(g1, val, loc as i32);
        self.eliminate_cand_from_group(g2, val, loc as i32);

        self.queue.push(g1);
        self.queue.push(g2);
    }
    fn eliminate_cand_from_group(&mut self, grp: i32, rem_cand: i32, cur: i32) {
        let cand = !(1 << (rem_cand - 1) as Cand);
        for c in self.shape.group_to_cells[grp as usize] {
            if c != cur {
                self.limit_cand(c as usize, cand);
            }
        }
    }
    fn limit_cand(&mut self, loc: usize, lim: Cand) {
        if self.cand[loc] & lim == self.cand[loc] {
            return;
        }
        self.cand[loc] &= lim;

        let current_cand = self.cand[loc];
        if current_cand == 0 {
            self.inconsistent = true;
            return;
        }
        if current_cand.count_ones() == 1 {
            self.decide_int(loc, (current_cand.trailing_zeros() + 1) as i32);
        }

        let (g1, g2) = self.shape.cell_to_groups[loc];
        self.queue.push(g1);
        self.queue.push(g2);
    }
    fn check_group(&mut self, gid: i32) {
        let grp = self.grps[gid as usize];
        let (imperative, allowed) = self.dic.at(grp.unmet_num, grp.unmet_sum, grp.unused);
        if (imperative, allowed) == dictionary::IMPOSSIBLE {
            self.inconsistent = true;
            return;
        }

        // unique position technique
        if imperative != 0 {
            let mut uniq = 0;
            let mut mult = 0;
            for c in self.shape.group_to_cells[gid as usize] {
                if self.val[c as usize] == UNDECIDED {
                    mult |= uniq & self.cand[c as usize];
                    uniq |= self.cand[c as usize];
                }
            }
            uniq &= imperative & !mult;
            if uniq != 0 {
                for c in self.shape.group_to_cells[gid as usize] {
                    if self.val[c as usize] == UNDECIDED && (self.cand[c as usize] & uniq) != 0 {
                        let val = ((self.cand[c as usize] & uniq).trailing_zeros() + 1) as i32;
                        self.decide_int(c as usize, val);
                    }
                }
            }
        }

        // candidate limitation
        for c in self.shape.group_to_cells[gid as usize] {
            if self.val[c as usize] == UNDECIDED {
                self.limit_cand(c as usize, allowed);
            }
        }

        // two-cells propagation (TODO: improve complexity)
        let grp = self.grps[gid as usize];
        if grp.unmet_num == 2 {
            let mut c1 = -1;
            let mut c2 = -1;
            for c in self.shape.group_to_cells[gid as usize] {
                if self.val[c as usize] == UNDECIDED {
                    if c1 == -1 {
                        c1 = c;
                    } else {
                        c2 = c;
                    }
                }
            }
            for i in 1..(MAX_VAL + 1) {
                if (self.cand[c1 as usize] & (1 << (i - 1) as Cand) == 0) && 1 <= (grp.unmet_sum - i) && (grp.unmet_sum - i) <= MAX_VAL {
                    self.limit_cand(c2 as usize, !(1 << (grp.unmet_sum - i - 1) as Cand));
                }
                if (self.cand[c2 as usize] & (1 << (i - 1) as Cand) == 0) && 1 <= (grp.unmet_sum - i) && (grp.unmet_sum - i) <= MAX_VAL {
                    self.limit_cand(c1 as usize, !(1 << (grp.unmet_sum - i - 1) as Cand));
                }
            }
        }

        // naked pair (TODO: improve complexity)
        for c in self.shape.group_to_cells[gid as usize] {
            if self.val[c as usize] != -1 { continue; }
            for d in self.shape.group_to_cells[gid as usize] {
                if self.val[d as usize] != -1 { continue; }
                if c != d && self.cand[c as usize] == self.cand[d as usize] && self.cand[c as usize].count_ones() == 2 {
                    for e in self.shape.group_to_cells[gid as usize] {
                        if c != e && d != e {
                            let lim = !self.cand[c as usize];
                            self.limit_cand(e as usize, lim);
                        }
                    }
                }
            }
        }

        // min-max method
        let grp = self.grps[gid as usize];
        let mut min_sum = 0;
        let mut max_sum = 0;
        for c in self.shape.group_to_cells[gid as usize] {
            if self.val[c as usize] != -1 { continue; }
            let cand = self.cand[c as usize];
            min_sum += cand.trailing_zeros() + 1;
            max_sum += 32 - cand.leading_zeros();
        }
        for c in self.shape.group_to_cells[gid as usize] {
            if self.val[c as usize] != -1 { continue; }
            let cand = self.cand[c as usize];

            let current_max = grp.unmet_sum - (min_sum - (cand.trailing_zeros() + 1)) as i32;
            let current_min = grp.unmet_sum - (max_sum - (32 - cand.leading_zeros())) as i32;

            let mut lim = CAND_ALL;
            if current_max <= 8 {
                lim &= (1 << current_max as Cand) - 1;
            }
            if current_min >= 2 {
                lim &= !((1 << (current_min as Cand - 1)) - 1);
            }
            if lim != CAND_ALL {
                self.limit_cand(c as usize, lim);
            }
        }
    }
}

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

    #[test]
    fn test_field() {
        let dic = Dictionary::default();
        let mut problem_base = Grid::new(3, 3, Clue::NoClue);
        problem_base[Coord { y: 0, x: 0 }] = Clue::Clue { horizontal: -1, vertical: -1 };
        problem_base[Coord { y: 0, x: 1 }] = Clue::Clue { horizontal: -1, vertical: 3 };
        problem_base[Coord { y: 0, x: 2 }] = Clue::Clue { horizontal: -1, vertical: 8 };
        problem_base[Coord { y: 1, x: 0 }] = Clue::Clue { horizontal: 4, vertical: -1 };
        problem_base[Coord { y: 2, x: 0 }] = Clue::Clue { horizontal: 7, vertical: -1 };

        let mut field = Field::new(&problem_base, &dic);
        field.check_all();

        assert_eq!(field.val(Coord { y: 1, x: 1 }), 1);
        assert_eq!(field.val(Coord { y: 1, x: 2 }), 3);
        assert_eq!(field.val(Coord { y: 2, x: 1 }), 2);
        assert_eq!(field.val(Coord { y: 2, x: 2 }), 5);
        assert_eq!(field.inconsistent(), false);
    }

    #[test]
    fn test_inconsistent_field() {
        let dic = Dictionary::default();
        let mut problem_base = Grid::new(3, 3, Clue::NoClue);
        problem_base[Coord { y: 0, x: 0 }] = Clue::Clue { horizontal: -1, vertical: -1 };
        problem_base[Coord { y: 0, x: 1 }] = Clue::Clue { horizontal: -1, vertical: 3 };
        problem_base[Coord { y: 0, x: 2 }] = Clue::Clue { horizontal: -1, vertical: 6 };
        problem_base[Coord { y: 1, x: 0 }] = Clue::Clue { horizontal: 4, vertical: -1 };
        problem_base[Coord { y: 2, x: 0 }] = Clue::Clue { horizontal: 5, vertical: -1 };

        let mut field = Field::new(&problem_base, &dic);
        field.check_all();

        assert_eq!(field.inconsistent(), true);
    }
}
<|endoftext|>


<commit_before>//! # The Rust core allocation and collections library
//!
//! This library provides smart pointers and collections for managing
//! heap-allocated values.
//!
//! This library, like libcore, normally doesn’t need to be used directly
//! since its contents are re-exported in the [`std` crate](../std/index.html).
//! Crates that use the `#![no_std]` attribute however will typically
//! not depend on `std`, so they’d use this crate instead.
//!
//! ## Boxed values
//!
//! The [`Box`](boxed/index.html) type is a smart pointer type. There can
//! only be one owner of a `Box`, and the owner can decide to mutate the
//! contents, which live on the heap.
//!
//! This type can be sent among threads efficiently as the size of a `Box` value
//! is the same as that of a pointer. Tree-like data structures are often built
//! with boxes because each node often has only one owner, the parent.
//!
//! ## Reference counted pointers
//!
//! The [`Rc`](rc/index.html) type is a non-threadsafe reference-counted pointer
//! type intended for sharing memory within a thread. An `Rc` pointer wraps a
//! type, `T`, and only allows access to `&T`, a shared reference.
//!
//! This type is useful when inherited mutability (such as using `Box`) is too
//! constraining for an application, and is often paired with the `Cell` or
//! `RefCell` types in order to allow mutation.
//!
//! ## Atomically reference counted pointers
//!
//! The [`Arc`](sync/index.html) type is the threadsafe equivalent of the `Rc`
//! type. It provides all the same functionality of `Rc`, except it requires
//! that the contained type `T` is shareable. Additionally, `Arc<T>` is itself
//! sendable while `Rc<T>` is not.
//!
//! This type allows for shared access to the contained data, and is often
//! paired with synchronization primitives such as mutexes to allow mutation of
//! shared resources.
//!
//! ## Collections
//!
//! Implementations of the most common general purpose data structures are
//! defined in this library. They are re-exported through the
//! [standard collections library](../std/collections/index.html).
//!
//! ## Heap interfaces
//!
//! The [`alloc`](alloc/index.html) module defines the low-level interface to the
//! default global allocator. It is not compatible with the libc allocator API.

#![allow(unused_attributes)]
#![stable(feature = "alloc", since = "1.36.0")]
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/",
       issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/",
       test(no_crate_inject, attr(allow(unused_variables), deny(warnings))))]
#![no_std]
#![needs_allocator]

#![warn(deprecated_in_future)]
#![warn(missing_docs)]
#![warn(missing_debug_implementations)]
#![deny(intra_doc_link_resolution_failure)] // rustdoc is run without -D warnings

#![deny(rust_2018_idioms)]
#![allow(explicit_outlives_requirements)]

#![cfg_attr(not(test), feature(generator_trait))]
#![cfg_attr(test, feature(test))]

#![feature(allocator_api)]
#![feature(allow_internal_unstable)]
#![feature(arbitrary_self_types)]
#![feature(box_into_raw_non_null)]
#![feature(box_patterns)]
#![feature(box_syntax)]
#![feature(cfg_target_has_atomic)]
#![feature(coerce_unsized)]
#![feature(dispatch_from_dyn)]
#![feature(core_intrinsics)]
#![feature(dropck_eyepatch)]
#![feature(exact_size_is_empty)]
#![feature(fmt_internals)]
#![feature(fn_traits)]
#![feature(fundamental)]
#![feature(lang_items)]
#![feature(libc)]
#![feature(nll)]
#![feature(optin_builtin_traits)]
#![feature(pattern)]
#![feature(ptr_internals)]
#![feature(ptr_offset_from)]
#![feature(rustc_attrs)]
#![feature(receiver_trait)]
#![feature(specialization)]
#![feature(staged_api)]
#![feature(std_internals)]
#![feature(str_internals)]
#![feature(trusted_len)]
#![feature(try_reserve)]
#![feature(unboxed_closures)]
#![feature(unicode_internals)]
#![feature(unsize)]
#![feature(unsized_locals)]
#![feature(allocator_internals)]
#![feature(on_unimplemented)]
#![feature(rustc_const_unstable)]
#![feature(const_vec_new)]
#![feature(slice_partition_dedup)]
#![feature(maybe_uninit_extra, maybe_uninit_slice, maybe_uninit_array)]
#![feature(alloc_layout_extra)]
#![feature(try_trait)]
#![feature(mem_take)]

// Allow testing this library

#[cfg(test)]
#[macro_use]
extern crate std;
#[cfg(test)]
extern crate test;

// Module with internal macros used by other modules (needs to be included before other modules).
#[macro_use]
mod macros;

// Heaps provided for low-level allocation strategies

pub mod alloc;

// Primitive types using the heaps above

// Need to conditionally define the mod from `boxed.rs` to avoid
// duplicating the lang-items when building in test cfg; but also need
// to allow code to have `use boxed::Box;` declarations.
#[cfg(not(test))]
pub mod boxed;
#[cfg(test)]
mod boxed {
    pub use std::boxed::Box;
}
#[cfg(test)]
mod tests;
pub mod collections;
#[cfg(all(target_has_atomic = "ptr", target_has_atomic = "cas"))]
pub mod sync;
pub mod rc;
pub mod raw_vec;
pub mod prelude;
pub mod borrow;
pub mod fmt;
pub mod slice;
pub mod str;
pub mod string;
pub mod vec;

#[cfg(not(test))]
mod std {
    pub use core::ops; // RangeFull
}
<commit_msg>Add doc links to liballoc crate page<commit_after>//! # The Rust core allocation and collections library
//!
//! This library provides smart pointers and collections for managing
//! heap-allocated values.
//!
//! This library, like libcore, normally doesn’t need to be used directly
//! since its contents are re-exported in the [`std` crate](../std/index.html).
//! Crates that use the `#![no_std]` attribute however will typically
//! not depend on `std`, so they’d use this crate instead.
//!
//! ## Boxed values
//!
//! The [`Box`] type is a smart pointer type. There can only be one owner of a
//! [`Box`], and the owner can decide to mutate the contents, which live on the
//! heap.
//!
//! This type can be sent among threads efficiently as the size of a `Box` value
//! is the same as that of a pointer. Tree-like data structures are often built
//! with boxes because each node often has only one owner, the parent.
//!
//! ## Reference counted pointers
//!
//! The [`Rc`] type is a non-threadsafe reference-counted pointer type intended
//! for sharing memory within a thread. An [`Rc`] pointer wraps a type, `T`, and
//! only allows access to `&T`, a shared reference.
//!
//! This type is useful when inherited mutability (such as using [`Box`]) is too
//! constraining for an application, and is often paired with the [`Cell`] or
//! [`RefCell`] types in order to allow mutation.
//!
//! ## Atomically reference counted pointers
//!
//! The [`Arc`] type is the threadsafe equivalent of the [`Rc`] type. It
//! provides all the same functionality of [`Rc`], except it requires that the
//! contained type `T` is shareable. Additionally, [`Arc<T>`][`Arc`] is itself
//! sendable while [`Rc<T>`][`Rc`] is not.
//!
//! This type allows for shared access to the contained data, and is often
//! paired with synchronization primitives such as mutexes to allow mutation of
//! shared resources.
//!
//! ## Collections
//!
//! Implementations of the most common general purpose data structures are
//! defined in this library. They are re-exported through the
//! [standard collections library](../std/collections/index.html).
//!
//! ## Heap interfaces
//!
//! The [`alloc`](alloc/index.html) module defines the low-level interface to the
//! default global allocator. It is not compatible with the libc allocator API.
//!
//! [`Arc`]: sync/index.html
//! [`Box`]: boxed/index.html
//! [`Cell`]: ../core/cell/index.html
//! [`Rc`]: rc/index.html
//! [`RefCell`]: ../core/cell/index.html

#![allow(unused_attributes)]
#![stable(feature = "alloc", since = "1.36.0")]
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/",
       issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/",
       test(no_crate_inject, attr(allow(unused_variables), deny(warnings))))]
#![no_std]
#![needs_allocator]

#![warn(deprecated_in_future)]
#![warn(missing_docs)]
#![warn(missing_debug_implementations)]
#![deny(intra_doc_link_resolution_failure)] // rustdoc is run without -D warnings

#![deny(rust_2018_idioms)]
#![allow(explicit_outlives_requirements)]

#![cfg_attr(not(test), feature(generator_trait))]
#![cfg_attr(test, feature(test))]

#![feature(allocator_api)]
#![feature(allow_internal_unstable)]
#![feature(arbitrary_self_types)]
#![feature(box_into_raw_non_null)]
#![feature(box_patterns)]
#![feature(box_syntax)]
#![feature(cfg_target_has_atomic)]
#![feature(coerce_unsized)]
#![feature(dispatch_from_dyn)]
#![feature(core_intrinsics)]
#![feature(dropck_eyepatch)]
#![feature(exact_size_is_empty)]
#![feature(fmt_internals)]
#![feature(fn_traits)]
#![feature(fundamental)]
#![feature(lang_items)]
#![feature(libc)]
#![feature(nll)]
#![feature(optin_builtin_traits)]
#![feature(pattern)]
#![feature(ptr_internals)]
#![feature(ptr_offset_from)]
#![feature(rustc_attrs)]
#![feature(receiver_trait)]
#![feature(specialization)]
#![feature(staged_api)]
#![feature(std_internals)]
#![feature(str_internals)]
#![feature(trusted_len)]
#![feature(try_reserve)]
#![feature(unboxed_closures)]
#![feature(unicode_internals)]
#![feature(unsize)]
#![feature(unsized_locals)]
#![feature(allocator_internals)]
#![feature(on_unimplemented)]
#![feature(rustc_const_unstable)]
#![feature(const_vec_new)]
#![feature(slice_partition_dedup)]
#![feature(maybe_uninit_extra, maybe_uninit_slice, maybe_uninit_array)]
#![feature(alloc_layout_extra)]
#![feature(try_trait)]
#![feature(mem_take)]

// Allow testing this library

#[cfg(test)]
#[macro_use]
extern crate std;
#[cfg(test)]
extern crate test;

// Module with internal macros used by other modules (needs to be included before other modules).
#[macro_use]
mod macros;

// Heaps provided for low-level allocation strategies

pub mod alloc;

// Primitive types using the heaps above

// Need to conditionally define the mod from `boxed.rs` to avoid
// duplicating the lang-items when building in test cfg; but also need
// to allow code to have `use boxed::Box;` declarations.
#[cfg(not(test))]
pub mod boxed;
#[cfg(test)]
mod boxed {
    pub use std::boxed::Box;
}
#[cfg(test)]
mod tests;
pub mod collections;
#[cfg(all(target_has_atomic = "ptr", target_has_atomic = "cas"))]
pub mod sync;
pub mod rc;
pub mod raw_vec;
pub mod prelude;
pub mod borrow;
pub mod fmt;
pub mod slice;
pub mod str;
pub mod string;
pub mod vec;

#[cfg(not(test))]
mod std {
    pub use core::ops; // RangeFull
}
<|endoftext|>


<commit_before>use std::cmp::{PartialEq, Eq};
use std::ops::{Neg, Add, Sub, Mul, Div};

#[derive(Copy, Debug)]
pub struct Vector3 {
    pub x: f64,
    pub y: f64,
    pub z: f64,
}

pub const ZERO: Vector3 = Vector3 { x: 0.0, y: 0.0, z: 0.0 };

impl Vector3 {
    pub fn new(_x: f64, _y: f64, _z: f64) -> Vector3 {
        Vector3 { x: _x, y: _y, z: _z }
    }

    pub fn length_square(&self) -> f64 {
        self.x.powi(2) + self.y.powi(2) + self.z.powi(2)
    }

    pub fn length(&self) -> f64 {
        self.length_square().sqrt()
    }

    pub fn normalize(&mut self) {
        let reciprocal_length = 1.0 / self.length();
        self.x *= reciprocal_length;
        self.y *= reciprocal_length;
        self.z *= reciprocal_length;
    }

    pub fn is_normalized(&self) -> bool {
        self.length_square() == 1.0
    }

    pub fn cross(&self, other: &Vector3) -> Vector3 {
        Vector3 {
            x: self.y * other.z - self.z * other.y,
            y: self.z * other.x - self.x * other.z,
            z: self.x * other.y - self.y * other.x,
        }
    }
}

impl Clone for Vector3 {
    fn clone(&self) -> Vector3 {
        Vector3 {
            x: self.x,
            y: self.y,
            z: self.z,
        }
    }
}

impl Neg for Vector3 {
    type Output = Vector3;

    fn neg(self) -> Vector3 {
        Vector3 {
            x: -self.x,
            y: -self.y,
            z: -self.z,
        }
    }
}

impl Add for Vector3 {
    type Output = Vector3;

    fn add(self, other: Vector3) -> Vector3 {
        Vector3 {
            x: self.x + other.x,
            y: self.y + other.y,
            z: self.z + other.z,
        }
    }
}

impl Sub for Vector3 {
    type Output = Vector3;

    fn sub(self, other: Vector3) -> Vector3 {
        Vector3 {
            x: self.x - other.x,
            y: self.y - other.y,
            z: self.z - other.z,
        }
    }
}

impl Mul<f64> for Vector3 {
    type Output = Vector3;

    fn mul(self, other: f64) -> Vector3 {
        Vector3 {
            x: self.x * other,
            y: self.y * other,
            z: self.z * other,
        }
    }
}

impl Mul<Vector3> for f64 {
    type Output = Vector3;

    fn mul(self, other: Vector3) -> Vector3 {
        Vector3 {
            x: self * other.x,
            y: self * other.y,
            z: self * other.z
        }
    }
}

impl Mul for Vector3 {
    type Output = f64;

    fn mul(self, other: Vector3) -> f64 {
        self.x * other.x + self.y * other.y + self.z * other.z
    }
}

impl Div<f64> for Vector3 {
    type Output = Vector3;

    fn div(self, other: f64) -> Vector3 {
        Vector3 {
            x: self.x / other,
            y: self.y / other,
            z: self.z / other,
        }
    }
}

impl PartialEq for Vector3 {
    fn eq(&self, other: &Vector3) -> bool {
        self.x == other.x && self.y == other.y && self.z == other.z
    }
}

impl Eq for Vector3 { }

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

    #[test]
    fn test_length_square() {
        let v = Vector3::new(1.0, 2.0, 3.0);
        assert_eq!(v.length_square(), 14.0);
    }

    #[test]
    fn test_length() {
        let v = Vector3::new(1.0, 2.0, 3.0);
        assert_eq!(v.length(), 14_f64.sqrt());
    }

    #[test]
    fn test_normalize() {
        let mut v = Vector3::new(2.0, 0.0, 0.0);
        v.normalize();
        assert_eq!(v, Vector3::new(1.0, 0.0, 0.0));
    }

    #[test]
    fn test_is_normalized() {
        let v1 = Vector3::new(1.0, 0.0, 0.0);
        let v2 = Vector3::new(1.0, 2.0, 3.0);
        assert!(v1.is_normalized());
        assert!(!v2.is_normalized());
    }

    #[test]
    fn test_cross() {
        let i = Vector3::new(1.0, 0.0, 0.0);
        let j = Vector3::new(0.0, 1.0, 0.0);
        let k = Vector3::new(0.0, 0.0, 1.0);

        assert_eq!(i.cross(&j), k);
        assert_eq!(j.cross(&i), -k);

        assert_eq!(j.cross(&k), i);
        assert_eq!(k.cross(&j), -i);

        assert_eq!(k.cross(&i), j);
        assert_eq!(i.cross(&k), -j);
    }

    #[test]
    fn test_neg() {
        let v = Vector3::new(1.0, 2.0, 3.0);
        assert_eq!(-v, Vector3::new(-1.0, -2.0, -3.0));
    }

    #[test]
    fn test_add() {
        let v1 = Vector3::new(1.0, 2.0, 3.0);
        let v2 = Vector3::new(4.0, 5.0, 6.0);
        let sum = v1 + v2;
        assert_eq!(sum, Vector3::new(5.0, 7.0, 9.0));
    }

    #[test]
    fn test_sub() {
        let v1 = Vector3::new(1.0, 2.0, 3.0);
        let v2 = Vector3::new(4.0, 5.0, 6.0);
        let sub = v2 - v1;
        assert_eq!(sub, Vector3::new(3.0, 3.0, 3.0));
    }

    #[test]
    fn test_mul() {
        let v1 = Vector3::new(1.0, 2.0, 3.0);
        let v2 = Vector3::new(4.0, 5.0, 6.0);
        let v3 = Vector3::new(2.0, 4.0, 6.0);
        assert_eq!(v1 * v2, 32.0);
        assert_eq!(2.0 * v1, v3);
        assert_eq!(v1 * 2.0, v3);
    }

    #[test]
    fn test_div() {
        let v = Vector3::new(2.0, 4.0, 6.0);
        assert_eq!(v / 2.0, Vector3::new(1.0, 2.0, 3.0));
    }

}
<commit_msg>use standard function<commit_after>use std::cmp::{PartialEq, Eq};
use std::ops::{Neg, Add, Sub, Mul, Div};

#[derive(Copy, Debug)]
pub struct Vector3 {
    pub x: f64,
    pub y: f64,
    pub z: f64,
}

pub const ZERO: Vector3 = Vector3 { x: 0.0, y: 0.0, z: 0.0 };

impl Vector3 {
    pub fn new(_x: f64, _y: f64, _z: f64) -> Vector3 {
        Vector3 { x: _x, y: _y, z: _z }
    }

    pub fn length_square(&self) -> f64 {
        self.x.powi(2) + self.y.powi(2) + self.z.powi(2)
    }

    pub fn length(&self) -> f64 {
        self.length_square().sqrt()
    }

    pub fn normalize(&mut self) {
        let reciprocal_length = self.length().recip();
        self.x *= reciprocal_length;
        self.y *= reciprocal_length;
        self.z *= reciprocal_length;
    }

    pub fn is_normalized(&self) -> bool {
        self.length_square() == 1.0
    }

    pub fn cross(&self, other: &Vector3) -> Vector3 {
        Vector3 {
            x: self.y * other.z - self.z * other.y,
            y: self.z * other.x - self.x * other.z,
            z: self.x * other.y - self.y * other.x,
        }
    }
}

impl Clone for Vector3 {
    fn clone(&self) -> Vector3 {
        Vector3 {
            x: self.x,
            y: self.y,
            z: self.z,
        }
    }
}

impl Neg for Vector3 {
    type Output = Vector3;

    fn neg(self) -> Vector3 {
        Vector3 {
            x: -self.x,
            y: -self.y,
            z: -self.z,
        }
    }
}

impl Add for Vector3 {
    type Output = Vector3;

    fn add(self, other: Vector3) -> Vector3 {
        Vector3 {
            x: self.x + other.x,
            y: self.y + other.y,
            z: self.z + other.z,
        }
    }
}

impl Sub for Vector3 {
    type Output = Vector3;

    fn sub(self, other: Vector3) -> Vector3 {
        Vector3 {
            x: self.x - other.x,
            y: self.y - other.y,
            z: self.z - other.z,
        }
    }
}

impl Mul<f64> for Vector3 {
    type Output = Vector3;

    fn mul(self, other: f64) -> Vector3 {
        Vector3 {
            x: self.x * other,
            y: self.y * other,
            z: self.z * other,
        }
    }
}

impl Mul<Vector3> for f64 {
    type Output = Vector3;

    fn mul(self, other: Vector3) -> Vector3 {
        Vector3 {
            x: self * other.x,
            y: self * other.y,
            z: self * other.z
        }
    }
}

impl Mul for Vector3 {
    type Output = f64;

    fn mul(self, other: Vector3) -> f64 {
        self.x * other.x + self.y * other.y + self.z * other.z
    }
}

impl Div<f64> for Vector3 {
    type Output = Vector3;

    fn div(self, other: f64) -> Vector3 {
        Vector3 {
            x: self.x / other,
            y: self.y / other,
            z: self.z / other,
        }
    }
}

impl PartialEq for Vector3 {
    fn eq(&self, other: &Vector3) -> bool {
        self.x == other.x && self.y == other.y && self.z == other.z
    }
}

impl Eq for Vector3 { }

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

    #[test]
    fn test_length_square() {
        let v = Vector3::new(1.0, 2.0, 3.0);
        assert_eq!(v.length_square(), 14.0);
    }

    #[test]
    fn test_length() {
        let v = Vector3::new(1.0, 2.0, 3.0);
        assert_eq!(v.length(), 14_f64.sqrt());
    }

    #[test]
    fn test_normalize() {
        let mut v = Vector3::new(2.0, 0.0, 0.0);
        v.normalize();
        assert_eq!(v, Vector3::new(1.0, 0.0, 0.0));
    }

    #[test]
    fn test_is_normalized() {
        let v1 = Vector3::new(1.0, 0.0, 0.0);
        let v2 = Vector3::new(1.0, 2.0, 3.0);
        assert!(v1.is_normalized());
        assert!(!v2.is_normalized());
    }

    #[test]
    fn test_cross() {
        let i = Vector3::new(1.0, 0.0, 0.0);
        let j = Vector3::new(0.0, 1.0, 0.0);
        let k = Vector3::new(0.0, 0.0, 1.0);

        assert_eq!(i.cross(&j), k);
        assert_eq!(j.cross(&i), -k);

        assert_eq!(j.cross(&k), i);
        assert_eq!(k.cross(&j), -i);

        assert_eq!(k.cross(&i), j);
        assert_eq!(i.cross(&k), -j);
    }

    #[test]
    fn test_neg() {
        let v = Vector3::new(1.0, 2.0, 3.0);
        assert_eq!(-v, Vector3::new(-1.0, -2.0, -3.0));
    }

    #[test]
    fn test_add() {
        let v1 = Vector3::new(1.0, 2.0, 3.0);
        let v2 = Vector3::new(4.0, 5.0, 6.0);
        let sum = v1 + v2;
        assert_eq!(sum, Vector3::new(5.0, 7.0, 9.0));
    }

    #[test]
    fn test_sub() {
        let v1 = Vector3::new(1.0, 2.0, 3.0);
        let v2 = Vector3::new(4.0, 5.0, 6.0);
        let sub = v2 - v1;
        assert_eq!(sub, Vector3::new(3.0, 3.0, 3.0));
    }

    #[test]
    fn test_mul() {
        let v1 = Vector3::new(1.0, 2.0, 3.0);
        let v2 = Vector3::new(4.0, 5.0, 6.0);
        let v3 = Vector3::new(2.0, 4.0, 6.0);
        assert_eq!(v1 * v2, 32.0);
        assert_eq!(2.0 * v1, v3);
        assert_eq!(v1 * 2.0, v3);
    }

    #[test]
    fn test_div() {
        let v = Vector3::new(2.0, 4.0, 6.0);
        assert_eq!(v / 2.0, Vector3::new(1.0, 2.0, 3.0));
    }

}
<|endoftext|>