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

//! Implementation of `std::os` functionality for Windows

#![allow(bad_style)]

use prelude::v1::*;
use os::windows::prelude::*;

use error::Error as StdError;
use ffi::{OsString, OsStr};
use fmt;
use io;
use libc::types::os::arch::extra::LPWCH;
use libc::{self, c_int, c_void};
use mem;
use ops::Range;
use os::windows::ffi::EncodeWide;
use path::{self, PathBuf};
use ptr;
use slice;
use sys::c;
use sys::handle::Handle;

use libc::funcs::extra::kernel32::{
    GetEnvironmentStringsW,
    FreeEnvironmentStringsW
};

pub fn errno() -> i32 {
    unsafe { libc::GetLastError() as i32 }
}

/// Gets a detailed string description for the given error number.
pub fn error_string(errnum: i32) -> String {
    use libc::types::os::arch::extra::DWORD;
    use libc::types::os::arch::extra::LPWSTR;
    use libc::types::os::arch::extra::LPVOID;
    use libc::types::os::arch::extra::WCHAR;

    #[link_name = "kernel32"]
    extern "system" {
        fn FormatMessageW(flags: DWORD,
                          lpSrc: LPVOID,
                          msgId: DWORD,
                          langId: DWORD,
                          buf: LPWSTR,
                          nsize: DWORD,
                          args: *const c_void)
                          -> DWORD;
    }

    const FORMAT_MESSAGE_FROM_SYSTEM: DWORD = 0x00001000;
    const FORMAT_MESSAGE_IGNORE_INSERTS: DWORD = 0x00000200;

    // This value is calculated from the macro
    // MAKELANGID(LANG_SYSTEM_DEFAULT, SUBLANG_SYS_DEFAULT)
    let langId = 0x0800 as DWORD;

    let mut buf = [0 as WCHAR; 2048];

    unsafe {
        let res = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM |
                                 FORMAT_MESSAGE_IGNORE_INSERTS,
                                 ptr::null_mut(),
                                 errnum as DWORD,
                                 langId,
                                 buf.as_mut_ptr(),
                                 buf.len() as DWORD,
                                 ptr::null());
        if res == 0 {
            // Sometimes FormatMessageW can fail e.g. system doesn't like langId,
            let fm_err = errno();
            return format!("OS Error {} (FormatMessageW() returned error {})",
                           errnum, fm_err);
        }

        let b = buf.iter().position(|&b| b == 0).unwrap_or(buf.len());
        let msg = String::from_utf16(&buf[..b]);
        match msg {
            Ok(msg) => msg,
            Err(..) => format!("OS Error {} (FormatMessageW() returned \
                                invalid UTF-16)", errnum),
        }
    }
}

pub struct Env {
    base: LPWCH,
    cur: LPWCH,
}

impl Iterator for Env {
    type Item = (OsString, OsString);

    fn next(&mut self) -> Option<(OsString, OsString)> {
        unsafe {
            if *self.cur == 0 { return None }
            let p = &*self.cur;
            let mut len = 0;
            while *(p as *const u16).offset(len) != 0 {
                len += 1;
            }
            let p = p as *const u16;
            let s = slice::from_raw_parts(p, len as usize);
            self.cur = self.cur.offset(len + 1);

            let (k, v) = match s.iter().position(|&b| b == '=' as u16) {
                Some(n) => (&s[..n], &s[n+1..]),
                None => (s, &[][..]),
            };
            Some((OsStringExt::from_wide(k), OsStringExt::from_wide(v)))
        }
    }
}

impl Drop for Env {
    fn drop(&mut self) {
        unsafe { FreeEnvironmentStringsW(self.base); }
    }
}

pub fn env() -> Env {
    unsafe {
        let ch = GetEnvironmentStringsW();
        if ch as usize == 0 {
            panic!("failure getting env string from OS: {}",
                   io::Error::last_os_error());
        }
        Env { base: ch, cur: ch }
    }
}

pub struct SplitPaths<'a> {
    data: EncodeWide<'a>,
    must_yield: bool,
}

pub fn split_paths(unparsed: &OsStr) -> SplitPaths {
    SplitPaths {
        data: unparsed.encode_wide(),
        must_yield: true,
    }
}

impl<'a> Iterator for SplitPaths<'a> {
    type Item = PathBuf;
    fn next(&mut self) -> Option<PathBuf> {
        // On Windows, the PATH environment variable is semicolon separated.
        // Double quotes are used as a way of introducing literal semicolons
        // (since c:\some;dir is a valid Windows path). Double quotes are not
        // themselves permitted in path names, so there is no way to escape a
        // double quote.  Quoted regions can appear in arbitrary locations, so
        //
        //   c:\foo;c:\som"e;di"r;c:\bar
        //
        // Should parse as [c:\foo, c:\some;dir, c:\bar].
        //
        // (The above is based on testing; there is no clear reference available
        // for the grammar.)

        let must_yield = self.must_yield;
        self.must_yield = false;

        let mut in_progress = Vec::new();
        let mut in_quote = false;
        for b in self.data.by_ref() {
            if b == '"' as u16 {
                in_quote = !in_quote;
            } else if b == ';' as u16 && !in_quote {
                self.must_yield = true;
                break
            } else {
                in_progress.push(b)
            }
        }

        if !must_yield && in_progress.is_empty() {
            None
        } else {
            Some(super::os2path(&in_progress))
        }
    }
}

#[derive(Debug)]
pub struct JoinPathsError;

pub fn join_paths<I, T>(paths: I) -> Result<OsString, JoinPathsError>
    where I: Iterator<Item=T>, T: AsRef<OsStr>
{
    let mut joined = Vec::new();
    let sep = b';' as u16;

    for (i, path) in paths.enumerate() {
        let path = path.as_ref();
        if i > 0 { joined.push(sep) }
        let v = path.encode_wide().collect::<Vec<u16>>();
        if v.contains(&(b'"' as u16)) {
            return Err(JoinPathsError)
        } else if v.contains(&sep) {
            joined.push(b'"' as u16);
            joined.push_all(&v[..]);
            joined.push(b'"' as u16);
        } else {
            joined.push_all(&v[..]);
        }
    }

    Ok(OsStringExt::from_wide(&joined[..]))
}

impl fmt::Display for JoinPathsError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        "path segment contains `\"`".fmt(f)
    }
}

impl StdError for JoinPathsError {
    fn description(&self) -> &str { "failed to join paths" }
}

pub fn current_exe() -> io::Result<PathBuf> {
    super::fill_utf16_buf(|buf, sz| unsafe {
        libc::GetModuleFileNameW(ptr::null_mut(), buf, sz)
    }, super::os2path)
}

pub fn getcwd() -> io::Result<PathBuf> {
    super::fill_utf16_buf(|buf, sz| unsafe {
        libc::GetCurrentDirectoryW(sz, buf)
    }, super::os2path)
}

pub fn chdir(p: &path::Path) -> io::Result<()> {
    let p: &OsStr = p.as_ref();
    let mut p = p.encode_wide().collect::<Vec<_>>();
    p.push(0);

    unsafe {
        match libc::SetCurrentDirectoryW(p.as_ptr()) != (0 as libc::BOOL) {
            true => Ok(()),
            false => Err(io::Error::last_os_error()),
        }
    }
}

pub fn getenv(k: &OsStr) -> Option<OsString> {
    let k = super::to_utf16_os(k);
    super::fill_utf16_buf(|buf, sz| unsafe {
        libc::GetEnvironmentVariableW(k.as_ptr(), buf, sz)
    }, |buf| {
        OsStringExt::from_wide(buf)
    }).ok()
}

pub fn setenv(k: &OsStr, v: &OsStr) {
    let k = super::to_utf16_os(k);
    let v = super::to_utf16_os(v);

    unsafe {
        if libc::SetEnvironmentVariableW(k.as_ptr(), v.as_ptr()) == 0 {
            panic!("failed to set env: {}", io::Error::last_os_error());
        }
    }
}

pub fn unsetenv(n: &OsStr) {
    let v = super::to_utf16_os(n);
    unsafe {
        if libc::SetEnvironmentVariableW(v.as_ptr(), ptr::null()) == 0 {
            panic!("failed to unset env: {}", io::Error::last_os_error());
        }
    }
}

pub struct Args {
    range: Range<isize>,
    cur: *mut *mut u16,
}

impl Iterator for Args {
    type Item = OsString;
    fn next(&mut self) -> Option<OsString> {
        self.range.next().map(|i| unsafe {
            let ptr = *self.cur.offset(i);
            let mut len = 0;
            while *ptr.offset(len) != 0 { len += 1; }

            // Push it onto the list.
            let ptr = ptr as *const u16;
            let buf = slice::from_raw_parts(ptr, len as usize);
            OsStringExt::from_wide(buf)
        })
    }
    fn size_hint(&self) -> (usize, Option<usize>) { self.range.size_hint() }
}

impl ExactSizeIterator for Args {
    fn len(&self) -> usize { self.range.len() }
}

impl Drop for Args {
    fn drop(&mut self) {
        // self.cur can be null if CommandLineToArgvW previously failed,
        // but LocalFree ignores NULL pointers
        unsafe { c::LocalFree(self.cur as *mut c_void); }
    }
}

pub fn args() -> Args {
    unsafe {
        let mut nArgs: c_int = 0;
        let lpCmdLine = c::GetCommandLineW();
        let szArgList = c::CommandLineToArgvW(lpCmdLine, &mut nArgs);

        // szArcList can be NULL if CommandLinToArgvW failed,
        // but in that case nArgs is 0 so we won't actually
        // try to read a null pointer
        Args { cur: szArgList, range: 0..(nArgs as isize) }
    }
}

pub fn page_size() -> usize {
    unsafe {
        let mut info = mem::zeroed();
        libc::GetSystemInfo(&mut info);
        return info.dwPageSize as usize;
    }
}

pub fn temp_dir() -> PathBuf {
    super::fill_utf16_buf(|buf, sz| unsafe {
        c::GetTempPathW(sz, buf)
    }, super::os2path).unwrap()
}

pub fn home_dir() -> Option<PathBuf> {
    getenv("HOME".as_ref()).or_else(|| {
        getenv("USERPROFILE".as_ref())
    }).map(PathBuf::from).or_else(|| unsafe {
        let me = c::GetCurrentProcess();
        let mut token = ptr::null_mut();
        if c::OpenProcessToken(me, c::TOKEN_READ, &mut token) == 0 {
            return None
        }
        let _handle = Handle::new(token);
        super::fill_utf16_buf(|buf, mut sz| {
            match c::GetUserProfileDirectoryW(token, buf, &mut sz) {
                0 if libc::GetLastError() != 0 => 0,
                0 => sz,
                n => n as libc::DWORD,
            }
        }, super::os2path).ok()
    })
}

pub fn exit(code: i32) -> ! {
    unsafe { c::ExitProcess(code as libc::c_uint) }
}
<commit_msg>Rollup merge of #27577 - diaphore:trailing-newline-formatmessagew, r=alexcrichton<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Implementation of `std::os` functionality for Windows

#![allow(bad_style)]

use prelude::v1::*;
use os::windows::prelude::*;

use error::Error as StdError;
use ffi::{OsString, OsStr};
use fmt;
use io;
use libc::types::os::arch::extra::LPWCH;
use libc::{self, c_int, c_void};
use mem;
use ops::Range;
use os::windows::ffi::EncodeWide;
use path::{self, PathBuf};
use ptr;
use slice;
use sys::c;
use sys::handle::Handle;

use libc::funcs::extra::kernel32::{
    GetEnvironmentStringsW,
    FreeEnvironmentStringsW
};

pub fn errno() -> i32 {
    unsafe { libc::GetLastError() as i32 }
}

/// Gets a detailed string description for the given error number.
pub fn error_string(errnum: i32) -> String {
    use libc::types::os::arch::extra::DWORD;
    use libc::types::os::arch::extra::LPWSTR;
    use libc::types::os::arch::extra::LPVOID;
    use libc::types::os::arch::extra::WCHAR;

    #[link_name = "kernel32"]
    extern "system" {
        fn FormatMessageW(flags: DWORD,
                          lpSrc: LPVOID,
                          msgId: DWORD,
                          langId: DWORD,
                          buf: LPWSTR,
                          nsize: DWORD,
                          args: *const c_void)
                          -> DWORD;
    }

    const FORMAT_MESSAGE_FROM_SYSTEM: DWORD = 0x00001000;
    const FORMAT_MESSAGE_IGNORE_INSERTS: DWORD = 0x00000200;

    // This value is calculated from the macro
    // MAKELANGID(LANG_SYSTEM_DEFAULT, SUBLANG_SYS_DEFAULT)
    let langId = 0x0800 as DWORD;

    let mut buf = [0 as WCHAR; 2048];

    unsafe {
        let res = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM |
                                 FORMAT_MESSAGE_IGNORE_INSERTS,
                                 ptr::null_mut(),
                                 errnum as DWORD,
                                 langId,
                                 buf.as_mut_ptr(),
                                 buf.len() as DWORD,
                                 ptr::null());
        if res == 0 {
            // Sometimes FormatMessageW can fail e.g. system doesn't like langId,
            let fm_err = errno();
            return format!("OS Error {} (FormatMessageW() returned error {})",
                           errnum, fm_err);
        }

        let b = buf.iter().position(|&b| b == 0).unwrap_or(buf.len());
        match String::from_utf16(&buf[..b]) {
            Ok(mut msg) => {
                // Trim trailing CRLF inserted by FormatMessageW
                let len = msg.trim_right().len();
                msg.truncate(len);
                msg
            },
            Err(..) => format!("OS Error {} (FormatMessageW() returned \
                                invalid UTF-16)", errnum),
        }
    }
}

pub struct Env {
    base: LPWCH,
    cur: LPWCH,
}

impl Iterator for Env {
    type Item = (OsString, OsString);

    fn next(&mut self) -> Option<(OsString, OsString)> {
        unsafe {
            if *self.cur == 0 { return None }
            let p = &*self.cur;
            let mut len = 0;
            while *(p as *const u16).offset(len) != 0 {
                len += 1;
            }
            let p = p as *const u16;
            let s = slice::from_raw_parts(p, len as usize);
            self.cur = self.cur.offset(len + 1);

            let (k, v) = match s.iter().position(|&b| b == '=' as u16) {
                Some(n) => (&s[..n], &s[n+1..]),
                None => (s, &[][..]),
            };
            Some((OsStringExt::from_wide(k), OsStringExt::from_wide(v)))
        }
    }
}

impl Drop for Env {
    fn drop(&mut self) {
        unsafe { FreeEnvironmentStringsW(self.base); }
    }
}

pub fn env() -> Env {
    unsafe {
        let ch = GetEnvironmentStringsW();
        if ch as usize == 0 {
            panic!("failure getting env string from OS: {}",
                   io::Error::last_os_error());
        }
        Env { base: ch, cur: ch }
    }
}

pub struct SplitPaths<'a> {
    data: EncodeWide<'a>,
    must_yield: bool,
}

pub fn split_paths(unparsed: &OsStr) -> SplitPaths {
    SplitPaths {
        data: unparsed.encode_wide(),
        must_yield: true,
    }
}

impl<'a> Iterator for SplitPaths<'a> {
    type Item = PathBuf;
    fn next(&mut self) -> Option<PathBuf> {
        // On Windows, the PATH environment variable is semicolon separated.
        // Double quotes are used as a way of introducing literal semicolons
        // (since c:\some;dir is a valid Windows path). Double quotes are not
        // themselves permitted in path names, so there is no way to escape a
        // double quote.  Quoted regions can appear in arbitrary locations, so
        //
        //   c:\foo;c:\som"e;di"r;c:\bar
        //
        // Should parse as [c:\foo, c:\some;dir, c:\bar].
        //
        // (The above is based on testing; there is no clear reference available
        // for the grammar.)

        let must_yield = self.must_yield;
        self.must_yield = false;

        let mut in_progress = Vec::new();
        let mut in_quote = false;
        for b in self.data.by_ref() {
            if b == '"' as u16 {
                in_quote = !in_quote;
            } else if b == ';' as u16 && !in_quote {
                self.must_yield = true;
                break
            } else {
                in_progress.push(b)
            }
        }

        if !must_yield && in_progress.is_empty() {
            None
        } else {
            Some(super::os2path(&in_progress))
        }
    }
}

#[derive(Debug)]
pub struct JoinPathsError;

pub fn join_paths<I, T>(paths: I) -> Result<OsString, JoinPathsError>
    where I: Iterator<Item=T>, T: AsRef<OsStr>
{
    let mut joined = Vec::new();
    let sep = b';' as u16;

    for (i, path) in paths.enumerate() {
        let path = path.as_ref();
        if i > 0 { joined.push(sep) }
        let v = path.encode_wide().collect::<Vec<u16>>();
        if v.contains(&(b'"' as u16)) {
            return Err(JoinPathsError)
        } else if v.contains(&sep) {
            joined.push(b'"' as u16);
            joined.push_all(&v[..]);
            joined.push(b'"' as u16);
        } else {
            joined.push_all(&v[..]);
        }
    }

    Ok(OsStringExt::from_wide(&joined[..]))
}

impl fmt::Display for JoinPathsError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        "path segment contains `\"`".fmt(f)
    }
}

impl StdError for JoinPathsError {
    fn description(&self) -> &str { "failed to join paths" }
}

pub fn current_exe() -> io::Result<PathBuf> {
    super::fill_utf16_buf(|buf, sz| unsafe {
        libc::GetModuleFileNameW(ptr::null_mut(), buf, sz)
    }, super::os2path)
}

pub fn getcwd() -> io::Result<PathBuf> {
    super::fill_utf16_buf(|buf, sz| unsafe {
        libc::GetCurrentDirectoryW(sz, buf)
    }, super::os2path)
}

pub fn chdir(p: &path::Path) -> io::Result<()> {
    let p: &OsStr = p.as_ref();
    let mut p = p.encode_wide().collect::<Vec<_>>();
    p.push(0);

    unsafe {
        match libc::SetCurrentDirectoryW(p.as_ptr()) != (0 as libc::BOOL) {
            true => Ok(()),
            false => Err(io::Error::last_os_error()),
        }
    }
}

pub fn getenv(k: &OsStr) -> Option<OsString> {
    let k = super::to_utf16_os(k);
    super::fill_utf16_buf(|buf, sz| unsafe {
        libc::GetEnvironmentVariableW(k.as_ptr(), buf, sz)
    }, |buf| {
        OsStringExt::from_wide(buf)
    }).ok()
}

pub fn setenv(k: &OsStr, v: &OsStr) {
    let k = super::to_utf16_os(k);
    let v = super::to_utf16_os(v);

    unsafe {
        if libc::SetEnvironmentVariableW(k.as_ptr(), v.as_ptr()) == 0 {
            panic!("failed to set env: {}", io::Error::last_os_error());
        }
    }
}

pub fn unsetenv(n: &OsStr) {
    let v = super::to_utf16_os(n);
    unsafe {
        if libc::SetEnvironmentVariableW(v.as_ptr(), ptr::null()) == 0 {
            panic!("failed to unset env: {}", io::Error::last_os_error());
        }
    }
}

pub struct Args {
    range: Range<isize>,
    cur: *mut *mut u16,
}

impl Iterator for Args {
    type Item = OsString;
    fn next(&mut self) -> Option<OsString> {
        self.range.next().map(|i| unsafe {
            let ptr = *self.cur.offset(i);
            let mut len = 0;
            while *ptr.offset(len) != 0 { len += 1; }

            // Push it onto the list.
            let ptr = ptr as *const u16;
            let buf = slice::from_raw_parts(ptr, len as usize);
            OsStringExt::from_wide(buf)
        })
    }
    fn size_hint(&self) -> (usize, Option<usize>) { self.range.size_hint() }
}

impl ExactSizeIterator for Args {
    fn len(&self) -> usize { self.range.len() }
}

impl Drop for Args {
    fn drop(&mut self) {
        // self.cur can be null if CommandLineToArgvW previously failed,
        // but LocalFree ignores NULL pointers
        unsafe { c::LocalFree(self.cur as *mut c_void); }
    }
}

pub fn args() -> Args {
    unsafe {
        let mut nArgs: c_int = 0;
        let lpCmdLine = c::GetCommandLineW();
        let szArgList = c::CommandLineToArgvW(lpCmdLine, &mut nArgs);

        // szArcList can be NULL if CommandLinToArgvW failed,
        // but in that case nArgs is 0 so we won't actually
        // try to read a null pointer
        Args { cur: szArgList, range: 0..(nArgs as isize) }
    }
}

pub fn page_size() -> usize {
    unsafe {
        let mut info = mem::zeroed();
        libc::GetSystemInfo(&mut info);
        return info.dwPageSize as usize;
    }
}

pub fn temp_dir() -> PathBuf {
    super::fill_utf16_buf(|buf, sz| unsafe {
        c::GetTempPathW(sz, buf)
    }, super::os2path).unwrap()
}

pub fn home_dir() -> Option<PathBuf> {
    getenv("HOME".as_ref()).or_else(|| {
        getenv("USERPROFILE".as_ref())
    }).map(PathBuf::from).or_else(|| unsafe {
        let me = c::GetCurrentProcess();
        let mut token = ptr::null_mut();
        if c::OpenProcessToken(me, c::TOKEN_READ, &mut token) == 0 {
            return None
        }
        let _handle = Handle::new(token);
        super::fill_utf16_buf(|buf, mut sz| {
            match c::GetUserProfileDirectoryW(token, buf, &mut sz) {
                0 if libc::GetLastError() != 0 => 0,
                0 => sz,
                n => n as libc::DWORD,
            }
        }, super::os2path).ok()
    })
}

pub fn exit(code: i32) -> ! {
    unsafe { c::ExitProcess(code as libc::c_uint) }
}
<|endoftext|>


<commit_before><commit_msg>Add problem #64<commit_after>use core::hashmap::linear::{ LinearSet };

use common::arith::{ isqrt };
use common::calc::{ get_gcd };
use common::problem::{ Problem };

pub static problem: Problem<'static> = Problem {
    id: 64,
    answer: "1322",
    solver: solve
};

fn calc_a(n: int, (p, q, r): (int, int, int)) -> int {
    // a := |f_n(p, q, r)|
    // a <= f_n(p, q, r) < a + 1
    // r a - q <= p sqrt(n) < r (a + 1) - pq
    // (ar - q)^2 <= np^2 < ((a+1)r - q)^2
    fn arq2(a: int, r: int, q: int) -> int {
        let s = a * r - q;
        return s * s;
    }

    let np2 = n * p * p;

    let sqn = isqrt(n as uint) as int;
    let estim_a = (p * sqn + q) / r;
    let mut a = estim_a;
    assert!(arq2(a, r, q) <= np2);
    while arq2(a + 1, r, q) <= np2 {
        a = a + 1;
    }
    assert!(arq2(a, r, q) <= np2);
    return a;
}

// f_n (p, q, r) := (p sqrt(n) + q)/ r
//                = a + (p sqrt(n) + q - ar) / r
// b := q - ar
//                = a + (p sqrt(n) + b) / r
//                = a + (1 / (r / (p sqrt(n) + b)))
//                = a + (1 / (rp sqrt(n) - rb) / (np^2 - b^2))
// (p, q, r) := (rp / m, -rb / m, (np^2 - b^2) / m)
fn each_a(n: int, f: &fn(int, (int, int, int)) -> bool) {
    let mut (p, q, r) = (1, 0, 1);
    loop {
        let a = calc_a(n, (p, q, r));
        if a * a == n || p == 0 {
            p = 0; q = 0; r = 1;
        } else {
            let b = q - a * r;
            let (p2, q2, r2) = (r*p, -r*b, n*p*p - b*b);
            let m = get_gcd(get_gcd(p2 as uint, q2 as uint), r2 as uint) as int;
            p = p2 / m;
            q = q2 / m;
            r = r2 / m;
        }
        if !f(a, (p, q, r)) { break; }
    }
}

// (p sqrt(n) + q) / r
// = a + (p sqrt(n) + j) / r
// = a + 1 / (r / (p sqrt(n) + j))
// = a + 1 / r ((p sqrt(n) - j) / (np^2 - j^2))
// => r(p sqrt(n) - j) / (np^2 - j^2)
fn solve() -> ~str {
    let mut cnt = 0u;
    for int::range(1, 10001) |n| {
        let mut an = ~[];
        let mut set = LinearSet::new();
        for each_a(n) |a, pqr| {
            if set.contains(&(a, pqr)) {
                // 平方数の period は 0
                let period = if a == 0 { 0 } else { set.len() - 1 };
                if period % 2 == 1 { cnt += 1; }
                break;
            }
            set.insert((a, pqr));
            an.push(a);
        }
    }
    return cnt.to_str();
}

<|endoftext|>


<commit_before>use crate::command_prelude::*;

use cargo::ops;

pub fn cli() -> App {
    subcommand("rustc")
        .setting(AppSettings::TrailingVarArg)
        .about("Compile a package and all of its dependencies")
        .arg(opt("quiet", "No output printed to stdout").short("q"))
        .arg(Arg::with_name("args").multiple(true))
        .arg_package("Package to build")
        .arg_jobs()
        .arg_targets_all(
            "Build only this package's library",
            "Build only the specified binary",
            "Build all binaries",
            "Build only the specified example",
            "Build all examples",
            "Build only the specified test target",
            "Build all tests",
            "Build only the specified bench target",
            "Build all benches",
            "Build all targets",
        )
        .arg_release("Build artifacts in release mode, with optimizations")
        .arg_profile("Build artifacts with the specified profile")
        .arg_features()
        .arg_target_triple("Target triple which compiles will be for")
        .arg_target_dir()
        .arg_manifest_path()
        .arg_message_format()
        .after_help(
            "\
The specified target for the current package (or package specified by SPEC if
provided) will be compiled along with all of its dependencies. The specified
<args>... will all be passed to the final compiler invocation, not any of the
dependencies. Note that the compiler will still unconditionally receive
arguments such as -L, --extern, and --crate-type, and the specified <args>...
will simply be added to the compiler invocation.

This command requires that only one target is being compiled. If more than one
target is available for the current package the filters of --lib, --bin, etc,
must be used to select which target is compiled. To pass flags to all compiler
processes spawned by Cargo, use the $RUSTFLAGS environment variable or the
`build.rustflags` configuration option.
",
        )
}

pub fn exec(config: &mut Config, args: &ArgMatches<'_>) -> CliResult {
    let ws = args.workspace(config)?;
    let mode = match args.value_of("profile") {
        Some("dev") | None => CompileMode::Build,
        Some("test") => CompileMode::Test,
        Some("bench") => CompileMode::Bench,
        Some("check") => CompileMode::Check { test: false },
        Some(mode) => {
            let err = anyhow::format_err!(
                "unknown profile: `{}`, use dev,
                                   test, or bench",
                mode
            );
            return Err(CliError::new(err, 101));
        }
    };
    let mut compile_opts = args.compile_options_for_single_package(
        config,
        mode,
        Some(&ws),
        ProfileChecking::Unchecked,
    )?;
    let target_args = values(args, "args");
    compile_opts.target_rustc_args = if target_args.is_empty() {
        None
    } else {
        Some(target_args)
    };
    ops::compile(&ws, &compile_opts)?;
    Ok(())
}
<commit_msg>Modified the help information of cargo-rustc<commit_after>use crate::command_prelude::*;

use cargo::ops;

pub fn cli() -> App {
    subcommand("rustc")
        .setting(AppSettings::TrailingVarArg)
        .about("Compile a package, and pass extra options to the compiler")
        .arg(opt("quiet", "No output printed to stdout").short("q"))
        .arg(Arg::with_name("args").multiple(true).help("Rustc flags"))
        .arg_package("Package to build")
        .arg_jobs()
        .arg_targets_all(
            "Build only this package's library",
            "Build only the specified binary",
            "Build all binaries",
            "Build only the specified example",
            "Build all examples",
            "Build only the specified test target",
            "Build all tests",
            "Build only the specified bench target",
            "Build all benches",
            "Build all targets",
        )
        .arg_release("Build artifacts in release mode, with optimizations")
        .arg_profile("Build artifacts with the specified profile")
        .arg_features()
        .arg_target_triple("Target triple which compiles will be for")
        .arg_target_dir()
        .arg_manifest_path()
        .arg_message_format()
        .after_help(
            "\
The specified target for the current package (or package specified by SPEC if
provided) will be compiled along with all of its dependencies. The specified
<args>... will all be passed to the final compiler invocation, not any of the
dependencies. Note that the compiler will still unconditionally receive
arguments such as -L, --extern, and --crate-type, and the specified <args>...
will simply be added to the compiler invocation.

This command requires that only one target is being compiled. If more than one
target is available for the current package the filters of --lib, --bin, etc,
must be used to select which target is compiled. To pass flags to all compiler
processes spawned by Cargo, use the $RUSTFLAGS environment variable or the
`build.rustflags` configuration option.
",
        )
}

pub fn exec(config: &mut Config, args: &ArgMatches<'_>) -> CliResult {
    let ws = args.workspace(config)?;
    let mode = match args.value_of("profile") {
        Some("dev") | None => CompileMode::Build,
        Some("test") => CompileMode::Test,
        Some("bench") => CompileMode::Bench,
        Some("check") => CompileMode::Check { test: false },
        Some(mode) => {
            let err = anyhow::format_err!(
                "unknown profile: `{}`, use dev,
                                   test, or bench",
                mode
            );
            return Err(CliError::new(err, 101));
        }
    };
    let mut compile_opts = args.compile_options_for_single_package(
        config,
        mode,
        Some(&ws),
        ProfileChecking::Unchecked,
    )?;
    let target_args = values(args, "args");
    compile_opts.target_rustc_args = if target_args.is_empty() {
        None
    } else {
        Some(target_args)
    };
    ops::compile(&ws, &compile_opts)?;
    Ok(())
}
<|endoftext|>


<commit_before><commit_msg>Add a example benchmark for zipped iteration.<commit_after>#![feature(test)]
#![allow(deprecated)]

extern crate test;
use test::{black_box, Bencher};

use ndarray::Zip;
use numpy::{npyiter::NpyMultiIterBuilder, PyArray};
use pyo3::Python;

fn numpy_iter(bencher: &mut Bencher, size: usize) {
    Python::with_gil(|py| {
        let x = PyArray::<f64, _>::zeros(py, size, false);
        let y = PyArray::<f64, _>::zeros(py, size, false);
        let z = PyArray::<f64, _>::zeros(py, size, false);

        let x = x.readonly();
        let y = y.readonly();
        let mut z = z.readwrite();

        bencher.iter(|| {
            let iter = NpyMultiIterBuilder::new()
                .add_readonly(black_box(&x))
                .add_readonly(black_box(&y))
                .add_readwrite(black_box(&mut z))
                .build()
                .unwrap();

            for (x, y, z) in iter {
                *z = x + y;
            }
        });
    });
}

#[bench]
fn numpy_iter_small(bencher: &mut Bencher) {
    numpy_iter(bencher, 2_usize.pow(5));
}

#[bench]
fn numpy_iter_medium(bencher: &mut Bencher) {
    numpy_iter(bencher, 2_usize.pow(10));
}

#[bench]
fn numpy_iter_large(bencher: &mut Bencher) {
    numpy_iter(bencher, 2_usize.pow(15));
}

fn ndarray_iter(bencher: &mut Bencher, size: usize) {
    Python::with_gil(|py| {
        let x = PyArray::<f64, _>::zeros(py, size, false);
        let y = PyArray::<f64, _>::zeros(py, size, false);
        let z = PyArray::<f64, _>::zeros(py, size, false);

        let x = x.readonly();
        let y = y.readonly();
        let mut z = z.readwrite();

        bencher.iter(|| {
            Zip::from(black_box(x.as_array()))
                .and(black_box(y.as_array()))
                .and(black_box(z.as_array_mut()))
                .for_each(|x, y, z| {
                    *z = x + y;
                });
        });
    });
}

#[bench]
fn ndarray_iter_small(bencher: &mut Bencher) {
    ndarray_iter(bencher, 2_usize.pow(5));
}

#[bench]
fn ndarray_iter_medium(bencher: &mut Bencher) {
    ndarray_iter(bencher, 2_usize.pow(10));
}

#[bench]
fn ndarray_iter_large(bencher: &mut Bencher) {
    ndarray_iter(bencher, 2_usize.pow(15));
}
<|endoftext|>


<commit_before><commit_msg>Rollup merge of #89997 - cameron1024:const-str-as-bytes-ice, r=JohnTitor<commit_after>// build-pass

trait Foo {}

struct Bar {
    bytes: &'static [u8],
    func: fn(&Box<dyn Foo>),
}
fn example(_: &Box<dyn Foo>) {}

const BARS: &[Bar] = &[
    Bar {
        bytes: "0".as_bytes(),
        func: example,
    },
    Bar {
        bytes: "0".as_bytes(),
        func: example,
    },
];

fn main() {
    let x = todo!();

    for bar in BARS {
        (bar.func)(&x);
    }
}
<|endoftext|>


<commit_before><commit_msg>add strange example that fails<commit_after>#![feature(target_feature)]

extern crate stdsimd;

use std::env;
use stdsimd::simd;

#[inline(never)]
#[target_feature = "-sse2"]
fn myop(
    (x0, x1, x2, x3): (u64, u64, u64, u64),
    (y0, y1, y2, y3): (u64, u64, u64, u64),
) -> (u64, u64, u64, u64) {
    let x = simd::u64x4::new(x0, x1, x2, x3);
    let y = simd::u64x4::new(y0, y1, y2, y3);
    let r = x * y;
    (r.extract(0), r.extract(1), r.extract(2), r.extract(3))
}

fn main() {
    let x = env::args().nth(1).unwrap().parse().unwrap();
    let y = env::args().nth(1).unwrap().parse().unwrap();
    let r = myop((x, x, x, x), (y, y, y, y));
    println!("{:?}", r);
}
<|endoftext|>


<commit_before><commit_msg>Add description for the help commands.<commit_after><|endoftext|>


<commit_before><commit_msg>Corrected timing on first frame.<commit_after><|endoftext|>


<commit_before><commit_msg>Feature gate summary the var RECORD_SUMMARY<commit_after><|endoftext|>


<commit_before>// Copyright 2013 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.

/*!
An attempt to move all intrinsic declarations to a single place,
as mentioned in #3369
The intrinsics are defined in librustc/middle/trans/foreign.rs.
*/

#[abi = "rust-intrinsic"]
pub extern "rust-intrinsic" {
    pub fn atomic_cxchg(dst: &mut int, old: int, src: int) -> int;
    pub fn atomic_cxchg_acq(dst: &mut int, old: int, src: int) -> int;
    pub fn atomic_cxchg_rel(dst: &mut int, old: int, src: int) -> int;

    #[cfg(not(stage0))]
    pub fn atomic_load(src: &int) -> int;
    #[cfg(not(stage0))]
    pub fn atomic_load_acq(src: &int) -> int;

    #[cfg(not(stage0))]
    pub fn atomic_store(dst: &mut int, val: int);
    #[cfg(not(stage0))]
    pub fn atomic_store_rel(dst: &mut int, val: int);

    pub fn atomic_xchg(dst: &mut int, src: int) -> int;
    pub fn atomic_xchg_acq(dst: &mut int, src: int) -> int;
    pub fn atomic_xchg_rel(dst: &mut int, src: int) -> int;

    pub fn atomic_xadd(dst: &mut int, src: int) -> int;
    pub fn atomic_xadd_acq(dst: &mut int, src: int) -> int;
    pub fn atomic_xadd_rel(dst: &mut int, src: int) -> int;

    pub fn atomic_xsub(dst: &mut int, src: int) -> int;
    pub fn atomic_xsub_acq(dst: &mut int, src: int) -> int;
    pub fn atomic_xsub_rel(dst: &mut int, src: int) -> int;

    pub fn size_of<T>() -> uint;

    pub fn move_val<T>(dst: &mut T, src: T);
    pub fn move_val_init<T>(dst: &mut T, src: T);

    pub fn min_align_of<T>() -> uint;
    pub fn pref_align_of<T>() -> uint;

    pub fn get_tydesc<T>() -> *();

    /// init is unsafe because it returns a zeroed-out datum,
    /// which is unsafe unless T is POD. We don't have a POD
    /// kind yet. (See #4074)
    pub unsafe fn init<T>() -> T;

    #[cfg(not(stage0))]
    pub unsafe fn uninit<T>() -> T;

    /// forget is unsafe because the caller is responsible for
    /// ensuring the argument is deallocated already
    pub unsafe fn forget<T>(_: T) -> ();

    pub fn needs_drop<T>() -> bool;

    // XXX: intrinsic uses legacy modes and has reference to TyDesc
    // and TyVisitor which are in librustc
    //fn visit_tydesc(++td: *TyDesc, &&tv: TyVisitor) -> ();
    // XXX: intrinsic uses legacy modes
    //fn frame_address(f: &once fn(*u8));

    pub fn morestack_addr() -> *();

    pub fn memmove32(dst: *mut u8, src: *u8, size: u32);
    pub fn memmove64(dst: *mut u8, src: *u8, size: u64);

    pub fn sqrtf32(x: f32) -> f32;
    pub fn sqrtf64(x: f64) -> f64;

    pub fn powif32(a: f32, x: i32) -> f32;
    pub fn powif64(a: f64, x: i32) -> f64;

    // the following kill the stack canary without
    // `fixed_stack_segment`. This possibly only affects the f64
    // variants, but it's hard to be sure since it seems to only
    // occur with fairly specific arguments.
    #[fixed_stack_segment]
    pub fn sinf32(x: f32) -> f32;
    #[fixed_stack_segment]
    pub fn sinf64(x: f64) -> f64;

    #[fixed_stack_segment]
    pub fn cosf32(x: f32) -> f32;
    #[fixed_stack_segment]
    pub fn cosf64(x: f64) -> f64;

    #[fixed_stack_segment]
    pub fn powf32(a: f32, x: f32) -> f32;
    #[fixed_stack_segment]
    pub fn powf64(a: f64, x: f64) -> f64;

    #[fixed_stack_segment]
    pub fn expf32(x: f32) -> f32;
    #[fixed_stack_segment]
    pub fn expf64(x: f64) -> f64;

    pub fn exp2f32(x: f32) -> f32;
    pub fn exp2f64(x: f64) -> f64;

    pub fn logf32(x: f32) -> f32;
    pub fn logf64(x: f64) -> f64;

    pub fn log10f32(x: f32) -> f32;
    pub fn log10f64(x: f64) -> f64;

    pub fn log2f32(x: f32) -> f32;
    pub fn log2f64(x: f64) -> f64;

    pub fn fmaf32(a: f32, b: f32, c: f32) -> f32;
    pub fn fmaf64(a: f64, b: f64, c: f64) -> f64;

    pub fn fabsf32(x: f32) -> f32;
    pub fn fabsf64(x: f64) -> f64;

    pub fn floorf32(x: f32) -> f32;
    pub fn floorf64(x: f64) -> f64;

    pub fn ceilf32(x: f32) -> f32;
    pub fn ceilf64(x: f64) -> f64;

    pub fn truncf32(x: f32) -> f32;
    pub fn truncf64(x: f64) -> f64;

    pub fn ctpop8(x: i8) -> i8;
    pub fn ctpop16(x: i16) -> i16;
    pub fn ctpop32(x: i32) -> i32;
    pub fn ctpop64(x: i64) -> i64;

    pub fn ctlz8(x: i8) -> i8;
    pub fn ctlz16(x: i16) -> i16;
    pub fn ctlz32(x: i32) -> i32;
    pub fn ctlz64(x: i64) -> i64;

    pub fn cttz8(x: i8) -> i8;
    pub fn cttz16(x: i16) -> i16;
    pub fn cttz32(x: i32) -> i32;
    pub fn cttz64(x: i64) -> i64;

    pub fn bswap16(x: i16) -> i16;
    pub fn bswap32(x: i32) -> i32;
    pub fn bswap64(x: i64) -> i64;
}
<commit_msg>core: Document some intrinsics<commit_after>// Copyright 2013 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.

/*! rustc compiler intrinsics.

The corresponding definitions are in librustc/middle/trans/foreign.rs.

# Atomics

The atomic intrinsics provide common atomic operations on machine
words, with multiple possible memory orderings. They obey the same
semantics as C++0x. See the LLVM documentation on [[atomics]].

[atomics]: http://llvm.org/docs/Atomics.html

A quick refresher on memory ordering:

* Acquire - a barrier for aquiring a lock. Subsequent reads and writes
  take place after the barrier.
* Release - a barrier for releasing a lock. Preceding reads and writes
  take place before the barrier.
* Sequentially consistent - sequentially consistent operations are
  guaranteed to happen in order. This is the standard mode for working
  with atomic types and is equivalent to Java's `volatile`.

*/

#[abi = "rust-intrinsic"]
pub extern "rust-intrinsic" {

    /// Atomic compare and exchange, sequentially consistent.
    pub fn atomic_cxchg(dst: &mut int, old: int, src: int) -> int;
    /// Atomic compare and exchange, acquire ordering.
    pub fn atomic_cxchg_acq(dst: &mut int, old: int, src: int) -> int;
    /// Atomic compare and exchange, release ordering.
    pub fn atomic_cxchg_rel(dst: &mut int, old: int, src: int) -> int;

    /// Atomic load, sequentially consistent.
    #[cfg(not(stage0))]
    pub fn atomic_load(src: &int) -> int;
    /// Atomic load, acquire ordering.
    #[cfg(not(stage0))]
    pub fn atomic_load_acq(src: &int) -> int;

    /// Atomic store, sequentially consistent.
    #[cfg(not(stage0))]
    pub fn atomic_store(dst: &mut int, val: int);
    /// Atomic store, release ordering.
    #[cfg(not(stage0))]
    pub fn atomic_store_rel(dst: &mut int, val: int);

    /// Atomic exchange, sequentially consistent.
    pub fn atomic_xchg(dst: &mut int, src: int) -> int;
    /// Atomic exchange, acquire ordering.
    pub fn atomic_xchg_acq(dst: &mut int, src: int) -> int;
    /// Atomic exchange, release ordering.
    pub fn atomic_xchg_rel(dst: &mut int, src: int) -> int;

    /// Atomic addition, sequentially consistent.
    pub fn atomic_xadd(dst: &mut int, src: int) -> int;
    /// Atomic addition, acquire ordering.
    pub fn atomic_xadd_acq(dst: &mut int, src: int) -> int;
    /// Atomic addition, release ordering.
    pub fn atomic_xadd_rel(dst: &mut int, src: int) -> int;

    /// Atomic subtraction, sequentially consistent.
    pub fn atomic_xsub(dst: &mut int, src: int) -> int;
    /// Atomic subtraction, acquire ordering.
    pub fn atomic_xsub_acq(dst: &mut int, src: int) -> int;
    /// Atomic subtraction, release ordering.
    pub fn atomic_xsub_rel(dst: &mut int, src: int) -> int;

    /// The size of a type in bytes.
    ///
    /// This is the exact number of bytes in memory taken up by a
    /// value of the given type. In other words, a memset of this size
    /// would *exactly* overwrite a value. When laid out in vectors
    /// and structures there may be additional padding between
    /// elements.
    pub fn size_of<T>() -> uint;

    /// Move a value to a memory location containing a value.
    ///
    /// Drop glue is run on the destination, which must contain a
    /// valid Rust value.
    pub fn move_val<T>(dst: &mut T, src: T);

    /// Move a value to an uninitialized memory location.
    ///
    /// Drop glue is not run on the destination.
    pub fn move_val_init<T>(dst: &mut T, src: T);

    pub fn min_align_of<T>() -> uint;
    pub fn pref_align_of<T>() -> uint;

    /// Get a static pointer to a type descriptor.
    pub fn get_tydesc<T>() -> *();

    /// Create a value initialized to zero.
    ///
    /// `init` is unsafe because it returns a zeroed-out datum,
    /// which is unsafe unless T is POD. We don't have a POD
    /// kind yet. (See #4074).
    pub unsafe fn init<T>() -> T;

    /// Create an uninitialized value.
    #[cfg(not(stage0))]
    pub unsafe fn uninit<T>() -> T;

    /// Move a value out of scope without running drop glue.
    ///
    /// `forget` is unsafe because the caller is responsible for
    /// ensuring the argument is deallocated already.
    pub unsafe fn forget<T>(_: T) -> ();

    /// Returns `true` if a type requires drop glue.
    pub fn needs_drop<T>() -> bool;

    // XXX: intrinsic uses legacy modes and has reference to TyDesc
    // and TyVisitor which are in librustc
    //fn visit_tydesc(++td: *TyDesc, &&tv: TyVisitor) -> ();
    // XXX: intrinsic uses legacy modes
    //fn frame_address(f: &once fn(*u8));

    /// Get the address of the `__morestack` stack growth function.
    pub fn morestack_addr() -> *();

    /// Equivalent to the `llvm.memmove.p0i8.0i8.i32` intrinsic.
    pub fn memmove32(dst: *mut u8, src: *u8, size: u32);
    /// Equivalent to the `llvm.memmove.p0i8.0i8.i64` intrinsic.
    pub fn memmove64(dst: *mut u8, src: *u8, size: u64);

    pub fn sqrtf32(x: f32) -> f32;
    pub fn sqrtf64(x: f64) -> f64;

    pub fn powif32(a: f32, x: i32) -> f32;
    pub fn powif64(a: f64, x: i32) -> f64;

    // the following kill the stack canary without
    // `fixed_stack_segment`. This possibly only affects the f64
    // variants, but it's hard to be sure since it seems to only
    // occur with fairly specific arguments.
    #[fixed_stack_segment]
    pub fn sinf32(x: f32) -> f32;
    #[fixed_stack_segment]
    pub fn sinf64(x: f64) -> f64;

    #[fixed_stack_segment]
    pub fn cosf32(x: f32) -> f32;
    #[fixed_stack_segment]
    pub fn cosf64(x: f64) -> f64;

    #[fixed_stack_segment]
    pub fn powf32(a: f32, x: f32) -> f32;
    #[fixed_stack_segment]
    pub fn powf64(a: f64, x: f64) -> f64;

    #[fixed_stack_segment]
    pub fn expf32(x: f32) -> f32;
    #[fixed_stack_segment]
    pub fn expf64(x: f64) -> f64;

    pub fn exp2f32(x: f32) -> f32;
    pub fn exp2f64(x: f64) -> f64;

    pub fn logf32(x: f32) -> f32;
    pub fn logf64(x: f64) -> f64;

    pub fn log10f32(x: f32) -> f32;
    pub fn log10f64(x: f64) -> f64;

    pub fn log2f32(x: f32) -> f32;
    pub fn log2f64(x: f64) -> f64;

    pub fn fmaf32(a: f32, b: f32, c: f32) -> f32;
    pub fn fmaf64(a: f64, b: f64, c: f64) -> f64;

    pub fn fabsf32(x: f32) -> f32;
    pub fn fabsf64(x: f64) -> f64;

    pub fn floorf32(x: f32) -> f32;
    pub fn floorf64(x: f64) -> f64;

    pub fn ceilf32(x: f32) -> f32;
    pub fn ceilf64(x: f64) -> f64;

    pub fn truncf32(x: f32) -> f32;
    pub fn truncf64(x: f64) -> f64;

    pub fn ctpop8(x: i8) -> i8;
    pub fn ctpop16(x: i16) -> i16;
    pub fn ctpop32(x: i32) -> i32;
    pub fn ctpop64(x: i64) -> i64;

    pub fn ctlz8(x: i8) -> i8;
    pub fn ctlz16(x: i16) -> i16;
    pub fn ctlz32(x: i32) -> i32;
    pub fn ctlz64(x: i64) -> i64;

    pub fn cttz8(x: i8) -> i8;
    pub fn cttz16(x: i16) -> i16;
    pub fn cttz32(x: i32) -> i32;
    pub fn cttz64(x: i64) -> i64;

    pub fn bswap16(x: i16) -> i16;
    pub fn bswap32(x: i32) -> i32;
    pub fn bswap64(x: i64) -> i64;
}
<|endoftext|>


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

use metadata::csearch;
use middle::def::DefFn;
use middle::subst::Subst;
use middle::ty::{TransmuteRestriction, ctxt, ty_bare_fn};
use middle::ty;

use syntax::abi::RustIntrinsic;
use syntax::ast::DefId;
use syntax::ast;
use syntax::ast_map::NodeForeignItem;
use syntax::codemap::Span;
use syntax::parse::token;
use syntax::visit::Visitor;
use syntax::visit;

fn type_size_is_affected_by_type_parameters(tcx: &ty::ctxt, typ: ty::t)
                                            -> bool {
    let mut result = false;
    ty::maybe_walk_ty(typ, |typ| {
        match ty::get(typ).sty {
            ty::ty_box(_) | ty::ty_uniq(_) | ty::ty_ptr(_) |
            ty::ty_rptr(..) | ty::ty_bare_fn(..) | ty::ty_closure(..) => {
                false
            }
            ty::ty_param(_) => {
                result = true;
                // No need to continue; we now know the result.
                false
            }
            ty::ty_enum(did, ref substs) => {
                for enum_variant in (*ty::enum_variants(tcx, did)).iter() {
                    for argument_type in enum_variant.args.iter() {
                        let argument_type = argument_type.subst(tcx, substs);
                        result = result ||
                            type_size_is_affected_by_type_parameters(
                                tcx,
                                argument_type);
                    }
                }

                // Don't traverse substitutions.
                false
            }
            ty::ty_struct(did, ref substs) => {
                for field in ty::struct_fields(tcx, did, substs).iter() {
                    result = result ||
                        type_size_is_affected_by_type_parameters(tcx,
                                                                 field.mt.ty);
                }

                // Don't traverse substitutions.
                false
            }
            _ => true,
        }
    });
    result
}

struct IntrinsicCheckingVisitor<'a> {
    tcx: &'a ctxt,
}

impl<'a> IntrinsicCheckingVisitor<'a> {
    fn def_id_is_transmute(&self, def_id: DefId) -> bool {
        if def_id.krate == ast::LOCAL_CRATE {
            match self.tcx.map.get(def_id.node) {
                NodeForeignItem(ref item) => {
                    token::get_ident(item.ident) ==
                        token::intern_and_get_ident("transmute")
                }
                _ => false,
            }
        } else {
            match csearch::get_item_path(self.tcx, def_id).last() {
                None => false,
                Some(ref last) => {
                    token::get_name(last.name()) ==
                        token::intern_and_get_ident("transmute")
                }
            }
        }
    }

    fn check_transmute(&self, span: Span, from: ty::t, to: ty::t) {
        if type_size_is_affected_by_type_parameters(self.tcx, from) {
            span_err!(self.tcx.sess, span, E0139,
                      "cannot transmute from a type that contains type parameters");
        }
        if type_size_is_affected_by_type_parameters(self.tcx, to) {
            span_err!(self.tcx.sess, span, E0140,
                      "cannot transmute to a type that contains type parameters");
        }

        let restriction = TransmuteRestriction {
            span: span,
            from: from,
            to: to,
        };
        self.tcx.transmute_restrictions.borrow_mut().push(restriction);
    }
}

impl<'a> Visitor<()> for IntrinsicCheckingVisitor<'a> {
    fn visit_expr(&mut self, expr: &ast::Expr, (): ()) {
        match expr.node {
            ast::ExprPath(..) => {
                match ty::resolve_expr(self.tcx, expr) {
                    DefFn(did, _) if self.def_id_is_transmute(did) => {
                        let typ = ty::node_id_to_type(self.tcx, expr.id);
                        match ty::get(typ).sty {
                            ty_bare_fn(ref bare_fn_ty)
                                    if bare_fn_ty.abi == RustIntrinsic => {
                                let from = *bare_fn_ty.sig.inputs.get(0);
                                let to = bare_fn_ty.sig.output;
                                self.check_transmute(expr.span, from, to);
                            }
                            _ => {
                                self.tcx
                                    .sess
                                    .span_bug(expr.span,
                                              "transmute wasn't a bare fn?!");
                            }
                        }
                    }
                    _ => {}
                }
            }
            _ => {}
        }

        visit::walk_expr(self, expr, ());
    }
}

pub fn check_crate(tcx: &ctxt, krate: &ast::Crate) {
    let mut visitor = IntrinsicCheckingVisitor {
        tcx: tcx,
    };

    visit::walk_crate(&mut visitor, krate, ());
}

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

use metadata::csearch;
use middle::def::DefFn;
use middle::subst::Subst;
use middle::ty::{TransmuteRestriction, ctxt, ty_bare_fn};
use middle::ty;

use syntax::abi::RustIntrinsic;
use syntax::ast::DefId;
use syntax::ast;
use syntax::ast_map::NodeForeignItem;
use syntax::codemap::Span;
use syntax::parse::token;
use syntax::visit::Visitor;
use syntax::visit;

fn type_size_is_affected_by_type_parameters(tcx: &ty::ctxt, typ: ty::t)
                                            -> bool {
    let mut result = false;
    ty::maybe_walk_ty(typ, |typ| {
        match ty::get(typ).sty {
            ty::ty_box(_) | ty::ty_uniq(_) | ty::ty_ptr(_) |
            ty::ty_rptr(..) | ty::ty_bare_fn(..) | ty::ty_closure(..) => {
                false
            }
            ty::ty_param(_) => {
                result = true;
                // No need to continue; we now know the result.
                false
            }
            ty::ty_enum(did, ref substs) => {
                for enum_variant in (*ty::enum_variants(tcx, did)).iter() {
                    for argument_type in enum_variant.args.iter() {
                        let argument_type = argument_type.subst(tcx, substs);
                        result = result ||
                            type_size_is_affected_by_type_parameters(
                                tcx,
                                argument_type);
                    }
                }

                // Don't traverse substitutions.
                false
            }
            ty::ty_struct(did, ref substs) => {
                for field in ty::struct_fields(tcx, did, substs).iter() {
                    result = result ||
                        type_size_is_affected_by_type_parameters(tcx,
                                                                 field.mt.ty);
                }

                // Don't traverse substitutions.
                false
            }
            _ => true,
        }
    });
    result
}

struct IntrinsicCheckingVisitor<'a> {
    tcx: &'a ctxt,
}

impl<'a> IntrinsicCheckingVisitor<'a> {
    fn def_id_is_transmute(&self, def_id: DefId) -> bool {
        let intrinsic = match ty::get(ty::lookup_item_type(self.tcx, def_id).ty).sty {
            ty::ty_bare_fn(ref bfty) => bfty.abi == RustIntrinsic,
            _ => return false
        };
        if def_id.krate == ast::LOCAL_CRATE {
            match self.tcx.map.get(def_id.node) {
                NodeForeignItem(ref item) if intrinsic => {
                    token::get_ident(item.ident) ==
                        token::intern_and_get_ident("transmute")
                }
                _ => false,
            }
        } else {
            match csearch::get_item_path(self.tcx, def_id).last() {
                Some(ref last) if intrinsic => {
                    token::get_name(last.name()) ==
                        token::intern_and_get_ident("transmute")
                }
                _ => false,
            }
        }
    }

    fn check_transmute(&self, span: Span, from: ty::t, to: ty::t) {
        if type_size_is_affected_by_type_parameters(self.tcx, from) {
            span_err!(self.tcx.sess, span, E0139,
                      "cannot transmute from a type that contains type parameters");
        }
        if type_size_is_affected_by_type_parameters(self.tcx, to) {
            span_err!(self.tcx.sess, span, E0140,
                      "cannot transmute to a type that contains type parameters");
        }

        let restriction = TransmuteRestriction {
            span: span,
            from: from,
            to: to,
        };
        self.tcx.transmute_restrictions.borrow_mut().push(restriction);
    }
}

impl<'a> Visitor<()> for IntrinsicCheckingVisitor<'a> {
    fn visit_expr(&mut self, expr: &ast::Expr, (): ()) {
        match expr.node {
            ast::ExprPath(..) => {
                match ty::resolve_expr(self.tcx, expr) {
                    DefFn(did, _) if self.def_id_is_transmute(did) => {
                        let typ = ty::node_id_to_type(self.tcx, expr.id);
                        match ty::get(typ).sty {
                            ty_bare_fn(ref bare_fn_ty)
                                    if bare_fn_ty.abi == RustIntrinsic => {
                                let from = *bare_fn_ty.sig.inputs.get(0);
                                let to = bare_fn_ty.sig.output;
                                self.check_transmute(expr.span, from, to);
                            }
                            _ => {
                                self.tcx
                                    .sess
                                    .span_bug(expr.span,
                                              "transmute wasn't a bare fn?!");
                            }
                        }
                    }
                    _ => {}
                }
            }
            _ => {}
        }

        visit::walk_expr(self, expr, ());
    }
}

pub fn check_crate(tcx: &ctxt, krate: &ast::Crate) {
    let mut visitor = IntrinsicCheckingVisitor {
        tcx: tcx,
    };

    visit::walk_crate(&mut visitor, krate, ());
}

<|endoftext|>


<commit_before><commit_msg>Add xfailed test case for #3029<commit_after>// xfail-test
fn fail_then_concat() {
    let x = ~[], y = ~[3];
    fail;
    x += y;
    ~"good" + ~"bye";
}

<|endoftext|>


<commit_before><commit_msg>Add a test to prevent regression<commit_after>// Copyright 2018 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.

pub trait MyIterator {
}

pub struct MyStruct<T>(T);

macro_rules! array_impls {
    ($($N:expr)+) => {
        $(
            impl<'a, T> MyIterator for &'a MyStruct<[T; $N]> {
            }
        )+
    }
}

// @has issue_53812/trait.MyIterator.html '//*[@id="implementors-list"]//h3[1]' 'MyStruct<[T; 0]>'
array_impls! { 10 3 2 1 0 }
<|endoftext|>


<commit_before>use super::mpsc_queue::{Queue};
use alloc::arc::Arc;
use super::mpsc_queue::PopResult::*;

pub enum TryRecvError {
    Empty,
    Disconnected,
}

pub struct Receiver<T> {
    pub queue: Arc<Queue<T>>,
}

impl<T> Receiver<T> {
    fn try_recv(&self, t: T) -> Result<T, TryRecvError> {
        match self.queue.pop() {
            Data(t) => Ok(t),
            _ => Err(TryRecvError::Empty),
        }
    }

    fn recv(&self, t: T) -> Result<T, ()> {
        loop {
            match self.queue.pop() {
                Data(t) => return Ok(t),
                _ => continue,
            }
        }

    }
}

unsafe impl<T: Send> Send for Receiver<T> {}
<commit_msg>Remove unused parameter<commit_after>use super::mpsc_queue::{Queue};
use alloc::arc::Arc;
use super::mpsc_queue::PopResult::*;

pub enum TryRecvError {
    Empty,
    Disconnected,
}

pub struct Receiver<T> {
    pub queue: Arc<Queue<T>>,
}

impl<T> Receiver<T> {
    fn try_recv(&self) -> Result<T, TryRecvError> {
        match self.queue.pop() {
            Data(t) => Ok(t),
            _ => Err(TryRecvError::Empty),
        }
    }

    fn recv(&self) -> Result<T, ()> {
        loop {
            match self.queue.pop() {
                Data(t) => return Ok(t),
                _ => continue,
            }
        }

    }
}

unsafe impl<T: Send> Send for Receiver<T> {}
<|endoftext|>


<commit_before><commit_msg>add test for nasty example<commit_after>// compile-flags: -Zmiri-strict-provenance
#![feature(strict_provenance)]

use std::mem;

// This is the example from
// <https://github.com/rust-lang/unsafe-code-guidelines/issues/286#issuecomment-1085144431>.

unsafe fn deref(left: *const u8, right: *const u8) {
    let left_int: usize = mem::transmute(left); //~ERROR expected initialized plain (non-pointer) bytes
    let right_int: usize = mem::transmute(right);
    if left_int == right_int {
        // The compiler is allowed to replace `left_int` by `right_int` here...
        let left_ptr: *const u8 = mem::transmute(left_int);
        // ...which however means here it could be dereferencing the wrong pointer.
        let _val = *left_ptr;
    }
}

fn main() {
    let ptr1 = &0u8 as *const u8;
    let ptr2 = &1u8 as *const u8;
    unsafe {
        // Two pointers with the same address but different provenance.
        deref(ptr1, ptr2.with_addr(ptr1.addr()));
    }
}
<|endoftext|>


<commit_before><commit_msg>mobs move and change direction randomly<commit_after><|endoftext|>


<commit_before><commit_msg>Fix bug in logging<commit_after><|endoftext|>


<commit_before>//! NEUQUANT Neural-Net quantization algorithm by Anthony Dekker, 1994.
//! See "Kohonen neural networks for optimal colour quantization"
//! in "Network: Computation in Neural Systems" Vol. 5 (1994) pp 351-367.
//! for a discussion of the algorithm.
//! See also  http://www.acm.org/~dekker/NEUQUANT.HTML

/* NeuQuant Neural-Net Quantization Algorithm
 * ------------------------------------------
 *
 * Copyright (c) 1994 Anthony Dekker
 *
 * NEUQUANT Neural-Net quantization algorithm by Anthony Dekker, 1994.
 * See "Kohonen neural networks for optimal colour quantization"
 * in "Network: Computation in Neural Systems" Vol. 5 (1994) pp 351-367.
 * for a discussion of the algorithm.
 * See also  http://www.acm.org/~dekker/NEUQUANT.HTML
 *
 * Any party obtaining a copy of these files from the author, directly or
 * indirectly, is granted, free of charge, a full and unrestricted irrevocable,
 * world-wide, paid up, royalty-free, nonexclusive right and license to deal
 * in this software and documentation files (the "Software"), including without
 * limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons who receive
 * copies from any such party to do so, with the only requirement being
 * that this copyright notice remain intact.
 *
 *
 * Incorporated bugfixes and alpha channel handling from pngnq
 * http://pngnq.sourceforge.net
 *
 */

use std::num::Float;
use std::cmp::{
    max,
    min
};
use super::utils::clamp;

const CHANNELS: usize = 4;

const RADIUS_DEC: i32 = 30; // factor of 1/30 each cycle

const ALPHA_BIASSHIFT: i32 = 10;            // alpha starts at 1
const INIT_ALPHA: i32 = 1 << ALPHA_BIASSHIFT; // biased by 10 bits

const GAMMA: f64 = 1024.0;
const BETA: f64 = 1.0 / GAMMA;
const BETAGAMMA: f64 = BETA * GAMMA;

// four primes near 500 - assume no image has a length so large
// that it is divisible by all four primes
const PRIMES: [usize; 4] = [499, 491, 478, 503];

#[derive(Copy)]
struct Quad<T> {
    r: T,
    g: T,
    b: T,
    a: T,
}

type Neuron = Quad<f64>;
type Color = Quad<i32>;

/// Neural network color quantizer
pub struct NeuQuant {
    network: Vec<Neuron>,
    colormap: Vec<Color>,
    netindex: [usize; 256],
    bias: Vec<f64>, // bias and freq arrays for learning
    freq: Vec<f64>,
    samplefac: i32,
    netsize: usize,
}

impl NeuQuant {
    /// Creates a new neuronal network and trains it with the supplied data
    pub fn new(samplefac: i32, colors: usize, pixels: &[u8]) -> Self {
        let netsize = colors;
        let mut this = NeuQuant {
            network: Vec::with_capacity(netsize),
            colormap: Vec::with_capacity(netsize),
            netindex: [0; 256],
            bias: Vec::with_capacity(netsize),
            freq: Vec::with_capacity(netsize),
            samplefac: samplefac,
            netsize: colors
        };
        this.init(pixels);
        this
    }

    /// Initializes the neuronal network and trains it with the supplied data
    pub fn init(&mut self, pixels: &[u8]) {
        self.network.clear();
        self.colormap.clear();
        self.bias.clear();
        self.freq.clear();
        let freq = (self.netsize as f64).recip();
        for i in 0..self.netsize {
            let tmp = (i as f64) * 256.0 / (self.netsize as f64);
            // Sets alpha values at 0 for dark pixels.
            let a = if i < 16 { i as f64 * 16.0 } else { 255.0 };
            self.network.push(Neuron { r: tmp, g: tmp, b: tmp, a: a});
            self.colormap.push(Color { r: 0, g: 0, b: 0, a: 255 });
            self.freq.push(freq);
            self.bias.push(0.0);
        }
        self.learn(pixels);
        self.build_colormap();
        self.inxbuild();
    }

    /// Maps the pixel in-place to the best-matching color in the color map
    #[inline(always)]
    pub fn map_pixel(&self, pixel: &mut [u8]) {
        match pixel {
            [r, g, b, a] => {
                let i = self.inxsearch(b, g, r, a);
                pixel[0] = self.colormap[i].r as u8;
                pixel[1] = self.colormap[i].g as u8;
                pixel[2] = self.colormap[i].b as u8;
                pixel[3] = self.colormap[i].a as u8;
            }
            _ => panic!()
        }
    }

    /// Finds the best-matching index in the color map for `pixel`
    #[inline(always)]
    pub fn index_of(&self, pixel: &[u8]) -> usize {
        match pixel {
            [r, g, b, a] => {
                self.inxsearch(b, g, r, a)
            }
            _ => panic!()
        }
    }

    /// Move neuron i towards biased (a,b,g,r) by factor alpha
    fn altersingle(&mut self, alpha: f64, i: i32, quad: Quad<f64>) {
        let n = &mut self.network[i as usize];
        n.b -= alpha * (n.b - quad.b);
        n.g -= alpha * (n.g - quad.g);
        n.r -= alpha * (n.r - quad.r);
        n.a -= alpha * (n.a - quad.a);
    }

    /// Move neuron adjacent neurons towards biased (a,b,g,r) by factor alpha
    fn alterneigh(&mut self, alpha: f64, rad: i32, i: i32, quad: Quad<f64>) {
        let lo = max(i - rad, 0);
        let hi = min(i + rad, self.netsize as i32);
        let mut j = i + 1;
        let mut k = i - 1;
        let mut q = 0;

        while (j < hi) || (k > lo) {
            let rad_sq = rad as f64 * rad as f64;
            let alpha = (alpha * (rad_sq - q as f64 * q as f64)) / rad_sq;
            q += 1;
            if j < hi {
                let p = &mut self.network[j as usize];
                p.b -= alpha * (p.b - quad.b);
                p.g -= alpha * (p.g - quad.g);
                p.r -= alpha * (p.r - quad.r);
                p.a -= alpha * (p.a - quad.a);
                j += 1;
            }
            if k > lo {
                let p = &mut self.network[k as usize];
                p.b -= alpha * (p.b - quad.b);
                p.g -= alpha * (p.g - quad.g);
                p.r -= alpha * (p.r - quad.r);
                p.a -= alpha * (p.a - quad.a);
                k -= 1;
            }
        }
    }

    /// Search for biased BGR values
    /// finds closest neuron (min dist) and updates freq
    /// finds best neuron (min dist-bias) and returns position
    /// for frequently chosen neurons, freq[i] is high and bias[i] is negative
    /// bias[i] = gamma*((1/self.netsize)-freq[i])
    fn contest (&mut self, b: f64, g: f64, r: f64, a: f64) -> i32 {
        let mut bestd = Float::max_value();
        let mut bestbiasd: f64 = bestd;
        let mut bestpos = -1;
        let mut bestbiaspos: i32 = bestpos;

        for i in 0..self.netsize {
            let bestbiasd_biased = bestbiasd + self.bias[i];
            let mut dist;
            let n = &self.network[i];
            dist  = (n.b - b).abs();
            dist += (n.r - r).abs();
            if dist < bestd || dist < bestbiasd_biased {
                dist += (n.g - g).abs();
                dist += (n.a - a).abs();
                if dist < bestd {bestd=dist; bestpos=i as i32;}
                let biasdist = dist - self.bias [i];
                if biasdist < bestbiasd {bestbiasd=biasdist; bestbiaspos=i as i32;}
            }
            self.freq[i] -= BETA * self.freq[i];
            self.bias[i] += BETAGAMMA * self.freq[i];
        }
        self.freq[bestpos as usize] += BETA;
        self.bias[bestpos as usize] -= BETAGAMMA;
        return bestbiaspos;
    }

    /// Main learning loop
    /// Note: the number of learning cycles is crucial and the parameters are not
    /// optimized for net sizes < 26 or > 256. 1064 colors seems to work fine
    fn learn(&mut self, pixels: &[u8]) {
        let initrad: i32 = self.netsize as i32/8;   // for 256 cols, radius starts at 32
        let radiusbiasshift: i32 = 6;
        let radiusbias: i32 = 1 << radiusbiasshift;
        let init_bias_radius: i32 = initrad*radiusbias;
        let mut bias_radius = init_bias_radius;
        let alphadec = 30 + ((self.samplefac-1)/3);
        let lengthcount = pixels.len() / CHANNELS;
        let samplepixels = lengthcount / self.samplefac as usize;
        // learning cycles
        let n_cycles = match self.netsize >> 1 { n if n <= 100 => 100, n => n};
        let delta = match samplepixels / n_cycles { 0 => 1, n => n };
        let mut alpha = INIT_ALPHA;

        let mut rad = bias_radius >> radiusbiasshift;
        if rad <= 1 {rad = 0};

        let mut pos = 0;
        let step = *PRIMES.iter()
            .find(|&&prime| lengthcount % prime != 0)
            .unwrap_or(&PRIMES[3]);

        let mut i = 0;
        while i < samplepixels {
            let (r, g, b, a) = {
                let p = &pixels[CHANNELS * pos..][..CHANNELS];
                (p[0] as f64, p[1] as f64, p[2] as f64, p[3] as f64)
            };

            let j =  self.contest (b, g, r, a);

            let alpha_ = (1.0 * alpha as f64) / INIT_ALPHA as f64;
            self.altersingle(alpha_, j, Quad { b: b, g: g, r: r, a: a });
            if rad > 0 {
                self.alterneigh(alpha_, rad, j, Quad { b: b, g: g, r: r, a: a })
            };

            pos += step;
            while pos >= lengthcount { pos -= lengthcount };

            i += 1;
            if i%delta == 0 {
                alpha -= alpha / alphadec;
                bias_radius -= bias_radius / RADIUS_DEC;
                rad = bias_radius >> radiusbiasshift;
                if rad <= 1 {rad = 0};
            }
        }
    }

    /// initializes the color map
    fn build_colormap(&mut self) {
        for i in 0usize..self.netsize {
            self.colormap[i].b = clamp((0.5 + self.network[i].b) as i32, 0, 255);
            self.colormap[i].g = clamp((0.5 + self.network[i].g) as i32, 0, 255);
            self.colormap[i].r = clamp((0.5 + self.network[i].r) as i32, 0, 255);
            self.colormap[i].a = clamp((0.5 + self.network[i].a) as i32, 0, 255);
        }
    }

    /// Insertion sort of network and building of netindex[0..255]
    fn inxbuild(&mut self) {
        let mut previouscol = 0;
        let mut startpos = 0;

        for i in 0..self.netsize {
            let mut p = self.colormap[i];
            let mut q;
            let mut smallpos = i;
            let mut smallval = p.g as usize;            // index on g
            // find smallest in i..netsize-1
            for j in (i + 1)..self.netsize {
                q = self.colormap[j];
                if (q.g as usize) < smallval {      // index on g
                    smallpos = j;
                    smallval = q.g as usize;    // index on g
                }
            }
            q = self.colormap[smallpos];
            // swap p (i) and q (smallpos) entries
            if i != smallpos {
                let mut j;
                j = q;   q = p;   p = j;
                self.colormap[i] = p;
                self.colormap[smallpos] = q;
            }
            // smallval entry is now in position i
            if smallval != previouscol {
                self.netindex[previouscol] = (startpos + i)>>1;
                for j in (previouscol + 1)..smallval {
                    self.netindex[j] = i
                }
                previouscol = smallval;
                startpos = i;
            }
        }
        let max_netpos = self.netsize - 1;
        self.netindex[previouscol] = (startpos + max_netpos)>>1;
        for j in (previouscol + 1)..256 { self.netindex[j] = max_netpos }; // really 256
    }

    /// Search for best matching color
    fn inxsearch(&self, b: u8, g: u8, r: u8, a: u8) -> usize {
        let mut bestd = 1 << 30; // ~ 1_000_000
        let mut best = 0;
        // start at netindex[g] and work outwards
        let mut i = self.netindex[g as usize];
        let mut j = if i > 0 { i - 1 } else { 0 };

        while (i < self.netsize) || (j >  0) {
            if i < self.netsize {
                let p = self.colormap[i];
                let mut e = p.g - g as i32;
                let mut dist = e*e; // inx key
                if dist >= bestd { break }
                else {
                    e = p.b - b as i32;
                    dist += e*e;
                    if dist < bestd {
                        e = p.r - r as i32;
                        dist += e*e;
                        if dist < bestd {
                            e = p.a - a as i32;
                            dist += e*e;
                            if dist < bestd { bestd = dist; best = i;}
                        }
                    }
                    i += 1;
                }
            }
            if j > 0 {
                let p = self.colormap[j];
                let mut e = p.g - g as i32;
                let mut dist = e*e; // inx key
                if dist >= bestd { break }
                else {
                    e = p.b - b as i32;
                    dist += e*e;
                    if dist < bestd {
                        e = p.r - r as i32;
                        dist += e*e;
                        if dist < bestd {
                            e = p.a - a as i32;
                            dist += e*e;
                            if dist < bestd { bestd = dist; best = j; }
                        }
                    }
                    j -= 1;
                }
            }
        }
        best
    }
}
<commit_msg>Shrink struct size<commit_after>//! NEUQUANT Neural-Net quantization algorithm by Anthony Dekker, 1994.
//! See "Kohonen neural networks for optimal colour quantization"
//! in "Network: Computation in Neural Systems" Vol. 5 (1994) pp 351-367.
//! for a discussion of the algorithm.
//! See also  http://www.acm.org/~dekker/NEUQUANT.HTML

/* NeuQuant Neural-Net Quantization Algorithm
 * ------------------------------------------
 *
 * Copyright (c) 1994 Anthony Dekker
 *
 * NEUQUANT Neural-Net quantization algorithm by Anthony Dekker, 1994.
 * See "Kohonen neural networks for optimal colour quantization"
 * in "Network: Computation in Neural Systems" Vol. 5 (1994) pp 351-367.
 * for a discussion of the algorithm.
 * See also  http://www.acm.org/~dekker/NEUQUANT.HTML
 *
 * Any party obtaining a copy of these files from the author, directly or
 * indirectly, is granted, free of charge, a full and unrestricted irrevocable,
 * world-wide, paid up, royalty-free, nonexclusive right and license to deal
 * in this software and documentation files (the "Software"), including without
 * limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons who receive
 * copies from any such party to do so, with the only requirement being
 * that this copyright notice remain intact.
 *
 *
 * Incorporated bugfixes and alpha channel handling from pngnq
 * http://pngnq.sourceforge.net
 *
 */

use std::num::Float;
use std::cmp::{
    max,
    min
};
use super::utils::clamp;

const CHANNELS: usize = 4;

const RADIUS_DEC: i32 = 30; // factor of 1/30 each cycle

const ALPHA_BIASSHIFT: i32 = 10;            // alpha starts at 1
const INIT_ALPHA: i32 = 1 << ALPHA_BIASSHIFT; // biased by 10 bits

const GAMMA: f64 = 1024.0;
const BETA: f64 = 1.0 / GAMMA;
const BETAGAMMA: f64 = BETA * GAMMA;

// four primes near 500 - assume no image has a length so large
// that it is divisible by all four primes
const PRIMES: [usize; 4] = [499, 491, 478, 503];

#[derive(Copy)]
struct Quad<T> {
    r: T,
    g: T,
    b: T,
    a: T,
}

type Neuron = Quad<f64>;
type Color = Quad<i32>;

/// Neural network color quantizer
pub struct NeuQuant {
    network: Vec<Neuron>,
    colormap: Vec<Color>,
    netindex: Vec<usize>,
    bias: Vec<f64>, // bias and freq arrays for learning
    freq: Vec<f64>,
    samplefac: i32,
    netsize: usize,
}

impl NeuQuant {
    /// Creates a new neuronal network and trains it with the supplied data
    pub fn new(samplefac: i32, colors: usize, pixels: &[u8]) -> Self {
        let netsize = colors;
        let mut this = NeuQuant {
            network: Vec::with_capacity(netsize),
            colormap: Vec::with_capacity(netsize),
            netindex: vec![0; 256],
            bias: Vec::with_capacity(netsize),
            freq: Vec::with_capacity(netsize),
            samplefac: samplefac,
            netsize: colors
        };
        this.init(pixels);
        this
    }

    /// Initializes the neuronal network and trains it with the supplied data
    pub fn init(&mut self, pixels: &[u8]) {
        self.network.clear();
        self.colormap.clear();
        self.bias.clear();
        self.freq.clear();
        let freq = (self.netsize as f64).recip();
        for i in 0..self.netsize {
            let tmp = (i as f64) * 256.0 / (self.netsize as f64);
            // Sets alpha values at 0 for dark pixels.
            let a = if i < 16 { i as f64 * 16.0 } else { 255.0 };
            self.network.push(Neuron { r: tmp, g: tmp, b: tmp, a: a});
            self.colormap.push(Color { r: 0, g: 0, b: 0, a: 255 });
            self.freq.push(freq);
            self.bias.push(0.0);
        }
        self.learn(pixels);
        self.build_colormap();
        self.inxbuild();
    }

    /// Maps the pixel in-place to the best-matching color in the color map
    #[inline(always)]
    pub fn map_pixel(&self, pixel: &mut [u8]) {
        match pixel {
            [r, g, b, a] => {
                let i = self.inxsearch(b, g, r, a);
                pixel[0] = self.colormap[i].r as u8;
                pixel[1] = self.colormap[i].g as u8;
                pixel[2] = self.colormap[i].b as u8;
                pixel[3] = self.colormap[i].a as u8;
            }
            _ => panic!()
        }
    }

    /// Finds the best-matching index in the color map for `pixel`
    #[inline(always)]
    pub fn index_of(&self, pixel: &[u8]) -> usize {
        match pixel {
            [r, g, b, a] => {
                self.inxsearch(b, g, r, a)
            }
            _ => panic!()
        }
    }

    /// Move neuron i towards biased (a,b,g,r) by factor alpha
    fn altersingle(&mut self, alpha: f64, i: i32, quad: Quad<f64>) {
        let n = &mut self.network[i as usize];
        n.b -= alpha * (n.b - quad.b);
        n.g -= alpha * (n.g - quad.g);
        n.r -= alpha * (n.r - quad.r);
        n.a -= alpha * (n.a - quad.a);
    }

    /// Move neuron adjacent neurons towards biased (a,b,g,r) by factor alpha
    fn alterneigh(&mut self, alpha: f64, rad: i32, i: i32, quad: Quad<f64>) {
        let lo = max(i - rad, 0);
        let hi = min(i + rad, self.netsize as i32);
        let mut j = i + 1;
        let mut k = i - 1;
        let mut q = 0;

        while (j < hi) || (k > lo) {
            let rad_sq = rad as f64 * rad as f64;
            let alpha = (alpha * (rad_sq - q as f64 * q as f64)) / rad_sq;
            q += 1;
            if j < hi {
                let p = &mut self.network[j as usize];
                p.b -= alpha * (p.b - quad.b);
                p.g -= alpha * (p.g - quad.g);
                p.r -= alpha * (p.r - quad.r);
                p.a -= alpha * (p.a - quad.a);
                j += 1;
            }
            if k > lo {
                let p = &mut self.network[k as usize];
                p.b -= alpha * (p.b - quad.b);
                p.g -= alpha * (p.g - quad.g);
                p.r -= alpha * (p.r - quad.r);
                p.a -= alpha * (p.a - quad.a);
                k -= 1;
            }
        }
    }

    /// Search for biased BGR values
    /// finds closest neuron (min dist) and updates freq
    /// finds best neuron (min dist-bias) and returns position
    /// for frequently chosen neurons, freq[i] is high and bias[i] is negative
    /// bias[i] = gamma*((1/self.netsize)-freq[i])
    fn contest (&mut self, b: f64, g: f64, r: f64, a: f64) -> i32 {
        let mut bestd = Float::max_value();
        let mut bestbiasd: f64 = bestd;
        let mut bestpos = -1;
        let mut bestbiaspos: i32 = bestpos;

        for i in 0..self.netsize {
            let bestbiasd_biased = bestbiasd + self.bias[i];
            let mut dist;
            let n = &self.network[i];
            dist  = (n.b - b).abs();
            dist += (n.r - r).abs();
            if dist < bestd || dist < bestbiasd_biased {
                dist += (n.g - g).abs();
                dist += (n.a - a).abs();
                if dist < bestd {bestd=dist; bestpos=i as i32;}
                let biasdist = dist - self.bias [i];
                if biasdist < bestbiasd {bestbiasd=biasdist; bestbiaspos=i as i32;}
            }
            self.freq[i] -= BETA * self.freq[i];
            self.bias[i] += BETAGAMMA * self.freq[i];
        }
        self.freq[bestpos as usize] += BETA;
        self.bias[bestpos as usize] -= BETAGAMMA;
        return bestbiaspos;
    }

    /// Main learning loop
    /// Note: the number of learning cycles is crucial and the parameters are not
    /// optimized for net sizes < 26 or > 256. 1064 colors seems to work fine
    fn learn(&mut self, pixels: &[u8]) {
        let initrad: i32 = self.netsize as i32/8;   // for 256 cols, radius starts at 32
        let radiusbiasshift: i32 = 6;
        let radiusbias: i32 = 1 << radiusbiasshift;
        let init_bias_radius: i32 = initrad*radiusbias;
        let mut bias_radius = init_bias_radius;
        let alphadec = 30 + ((self.samplefac-1)/3);
        let lengthcount = pixels.len() / CHANNELS;
        let samplepixels = lengthcount / self.samplefac as usize;
        // learning cycles
        let n_cycles = match self.netsize >> 1 { n if n <= 100 => 100, n => n};
        let delta = match samplepixels / n_cycles { 0 => 1, n => n };
        let mut alpha = INIT_ALPHA;

        let mut rad = bias_radius >> radiusbiasshift;
        if rad <= 1 {rad = 0};

        let mut pos = 0;
        let step = *PRIMES.iter()
            .find(|&&prime| lengthcount % prime != 0)
            .unwrap_or(&PRIMES[3]);

        let mut i = 0;
        while i < samplepixels {
            let (r, g, b, a) = {
                let p = &pixels[CHANNELS * pos..][..CHANNELS];
                (p[0] as f64, p[1] as f64, p[2] as f64, p[3] as f64)
            };

            let j =  self.contest (b, g, r, a);

            let alpha_ = (1.0 * alpha as f64) / INIT_ALPHA as f64;
            self.altersingle(alpha_, j, Quad { b: b, g: g, r: r, a: a });
            if rad > 0 {
                self.alterneigh(alpha_, rad, j, Quad { b: b, g: g, r: r, a: a })
            };

            pos += step;
            while pos >= lengthcount { pos -= lengthcount };

            i += 1;
            if i%delta == 0 {
                alpha -= alpha / alphadec;
                bias_radius -= bias_radius / RADIUS_DEC;
                rad = bias_radius >> radiusbiasshift;
                if rad <= 1 {rad = 0};
            }
        }
    }

    /// initializes the color map
    fn build_colormap(&mut self) {
        for i in 0usize..self.netsize {
            self.colormap[i].b = clamp((0.5 + self.network[i].b) as i32, 0, 255);
            self.colormap[i].g = clamp((0.5 + self.network[i].g) as i32, 0, 255);
            self.colormap[i].r = clamp((0.5 + self.network[i].r) as i32, 0, 255);
            self.colormap[i].a = clamp((0.5 + self.network[i].a) as i32, 0, 255);
        }
    }

    /// Insertion sort of network and building of netindex[0..255]
    fn inxbuild(&mut self) {
        let mut previouscol = 0;
        let mut startpos = 0;

        for i in 0..self.netsize {
            let mut p = self.colormap[i];
            let mut q;
            let mut smallpos = i;
            let mut smallval = p.g as usize;            // index on g
            // find smallest in i..netsize-1
            for j in (i + 1)..self.netsize {
                q = self.colormap[j];
                if (q.g as usize) < smallval {      // index on g
                    smallpos = j;
                    smallval = q.g as usize;    // index on g
                }
            }
            q = self.colormap[smallpos];
            // swap p (i) and q (smallpos) entries
            if i != smallpos {
                let mut j;
                j = q;   q = p;   p = j;
                self.colormap[i] = p;
                self.colormap[smallpos] = q;
            }
            // smallval entry is now in position i
            if smallval != previouscol {
                self.netindex[previouscol] = (startpos + i)>>1;
                for j in (previouscol + 1)..smallval {
                    self.netindex[j] = i
                }
                previouscol = smallval;
                startpos = i;
            }
        }
        let max_netpos = self.netsize - 1;
        self.netindex[previouscol] = (startpos + max_netpos)>>1;
        for j in (previouscol + 1)..256 { self.netindex[j] = max_netpos }; // really 256
    }

    /// Search for best matching color
    fn inxsearch(&self, b: u8, g: u8, r: u8, a: u8) -> usize {
        let mut bestd = 1 << 30; // ~ 1_000_000
        let mut best = 0;
        // start at netindex[g] and work outwards
        let mut i = self.netindex[g as usize];
        let mut j = if i > 0 { i - 1 } else { 0 };

        while (i < self.netsize) || (j >  0) {
            if i < self.netsize {
                let p = self.colormap[i];
                let mut e = p.g - g as i32;
                let mut dist = e*e; // inx key
                if dist >= bestd { break }
                else {
                    e = p.b - b as i32;
                    dist += e*e;
                    if dist < bestd {
                        e = p.r - r as i32;
                        dist += e*e;
                        if dist < bestd {
                            e = p.a - a as i32;
                            dist += e*e;
                            if dist < bestd { bestd = dist; best = i;}
                        }
                    }
                    i += 1;
                }
            }
            if j > 0 {
                let p = self.colormap[j];
                let mut e = p.g - g as i32;
                let mut dist = e*e; // inx key
                if dist >= bestd { break }
                else {
                    e = p.b - b as i32;
                    dist += e*e;
                    if dist < bestd {
                        e = p.r - r as i32;
                        dist += e*e;
                        if dist < bestd {
                            e = p.a - a as i32;
                            dist += e*e;
                            if dist < bestd { bestd = dist; best = j; }
                        }
                    }
                    j -= 1;
                }
            }
        }
        best
    }
}
<|endoftext|>