<commit_before>// struct Point2d {
//     x: f32,
//     y: f32,
// }

fn main() {
    //let pb = Box
}
<commit_msg>modified:   rust/sandbox/src/bin/box.rs<commit_after>use std::mem;

/* https://doc.rust-lang.org/rust-by-example/std/box.html

All values in Rust are stack allocated by default. Values can be boxed (allocated on the heap) by
creating a Box<T>. A box is a smart pointer to a heap allocated value of type T. When a box goes out
of scope, its destructor is called, the inner object is destroyed, and the memory on the heap is freed.
*/

struct Point2d {
    x: f64,
    y: f64,
}

struct BoxCtnr {
    a: Box<Point2d>,
    b: Box<Point2d>,
}

fn main() {
    let point = Point2d { x: 1.0, y: 2.0 };
    let boxed_point: Box<Point2d> = Box::new(Point2d { x: 1.0, y: 2.0 });
    println!("{} {}", (*boxed_point).x, (*boxed_point).y);
    println!("{} {}", boxed_point.x, boxed_point.y); // NOTE the automatic

    let boxed_point2 = boxed_point; // move through a box
    println!("{} {}", boxed_point2.x, boxed_point2.y);

    let boxed_boxed_point: Box<Box<Point2d>> = Box::new(Box::new(Point2d { x: 1.0, y: 2.0 }));
    println!("{} {}", boxed_boxed_point.x, boxed_boxed_point.y); // equivalent

    println!("size_of_val(&point) = {}", mem::size_of_val(&point));
    println!(
        "size_of_val(&boxed_point) = {}",
        mem::size_of_val(&boxed_point2) // 8
    );
    println!(
        "size_of_val(&boxed_boxed_point) = {}",
        mem::size_of_val(&boxed_boxed_point) // 8
    );

    //------------------------------------------

    let box_ctnr = BoxCtnr {
        a: Box::new(Point2d { x: 1.0, y: 2.0 }),
        b: Box::new(Point2d { x: 1.0, y: 2.0 }),
    };
    // rust immutability is DEEP; everything reachable from a immutable reference is immutable
    // box_ctnr.a.x = 3.0;
    println!("{} {}", box_ctnr.a.x, box_ctnr.a.y);
    println!("{} {}", box_ctnr.b.x, box_ctnr.b.y);

    //------------------------------------------

    let mut mut_box_ctnr = BoxCtnr {
        a: Box::new(Point2d { x: 1.0, y: 2.0 }),
        b: Box::new(Point2d { x: 1.0, y: 2.0 }),
    };
    mut_box_ctnr.a.x = 3.0;
    mut_box_ctnr.a.y = 3.0;
    println!("{} {}", mut_box_ctnr.a.x, mut_box_ctnr.a.y);
    println!("{} {}", mut_box_ctnr.b.x, mut_box_ctnr.b.y);
}
<|endoftext|>


<commit_before>#![allow(dead_code,
         non_camel_case_types,
         non_upper_case_globals,
         non_snake_case)]

use core::mem;
use core::ops::{Deref, DerefMut};
pub use core::convert::TryFrom;

use mouros_rust_bindings::CVoid;
use mouros_rust_bindings::mailbox::MailboxRaw;

#[repr(C)]
pub struct message {
    pub msg_type: u32,
    transaction_id: u32,
    pub data: *mut CVoid,
}

#[repr(C)]
pub struct message_handler {
    pub message_name: *const u8,
    pub parsing_func:
        Option<unsafe extern "C" fn(msg_ptr: *mut message, save_ptr: *mut u8) -> bool>,
    pub serialization_func: Option<
        unsafe extern "C" fn(msg_ptr: *const message,
                             output_str: *mut u8,
                             output_str_max_len: u32)
                             -> isize,
    >,
}

#[repr(C)]
pub struct subsystem_message_conf {
    pub subsystem_name: *const u8,
    pub message_handlers: *const message_handler,
    pub num_message_types: u32,
    pub incoming_msg_queue: *mut MailboxRaw,
    pub outgoing_msg_queue: *mut MailboxRaw,
    pub outgoing_err_queue: *mut MailboxRaw,
    pub alloc_message: Option<unsafe extern "C" fn(msg_type_id: u32) -> *mut message>,
    pub free_message: Option<unsafe extern "C" fn(msg: *mut message)>,
}

extern "C" {
    pub fn dispatcher_register_subsystem(conf: *mut subsystem_message_conf) -> bool;
}

pub struct MessageWrapper<T: Wrappable> {
    raw_msg_ptr: *mut message,
    msg: T,
}

pub trait MemManagement {
    fn alloc(msg_type: u32) -> *mut message;
    fn free(msg_ptr: *mut message);
}

pub trait Wrappable: MemManagement + TryFrom<*mut message, Error = ()> {}
impl<T> Wrappable for T
where
    T: MemManagement + TryFrom<*mut message, Error = ()>,
{
}

impl<T> Drop for MessageWrapper<T>
where
    T: Wrappable,
{
    fn drop(&mut self) {
        T::free(self.raw_msg_ptr);
    }
}

impl<T> Deref for MessageWrapper<T>
where
    T: Wrappable,
{
    type Target = T;

    fn deref(&self) -> &Self::Target {
        &self.msg
    }
}

impl<T> DerefMut for MessageWrapper<T>
where
    T: Wrappable,
{
    fn deref_mut(&mut self) -> &mut T {
        &mut self.msg
    }
}

impl<T> Into<*mut message> for MessageWrapper<T>
where
    T: Wrappable,
{
    fn into(self) -> *mut message {
        let raw_msg_ptr = self.raw_msg_ptr;

        // It's the caller's duty ot deallocate the message now.
        mem::forget(self);

        raw_msg_ptr
    }
}

impl<T> TryFrom<*mut message> for MessageWrapper<T>
where
    T: Wrappable,
{
    type Error = ();

    fn try_from(raw_msg_ptr: *mut message) -> Result<Self, Self::Error> {
        unsafe {
            if raw_msg_ptr.is_null() || (*raw_msg_ptr).data.is_null() {
                return Err(());
            }
        };

        Ok(MessageWrapper {
            msg: T::try_from(raw_msg_ptr)?,
            raw_msg_ptr: raw_msg_ptr,
        })
    }
}

impl<T> MessageWrapper<T>
where
    T: Wrappable,
{
    pub fn new(trans_id: u32, msg_type: u32) -> Result<MessageWrapper<T>, ()> {

        if let Ok(msg_wrapper) = MessageWrapper::try_from(T::alloc(msg_type)) {
            unsafe {
                (*msg_wrapper.raw_msg_ptr).transaction_id = trans_id;
            }

            Ok(msg_wrapper)
        } else {
            Err(())
        }
    }

    pub fn get_transaction_id(&self) -> u32 {
        unsafe { (*self.raw_msg_ptr).transaction_id }
    }
}

#[macro_export]
macro_rules! derive_message_wrapper {
    ($type_name:tt<$($lifetime:tt),+>, $msg_id:ident => ( $($parsing_expr:tt)+ ), $alloc_func:expr, $free_func:expr) => (
        derive_message_wrapper!(
            $type_name<$($lifetime),+>,
            [$msg_id => ( $($parsing_expr)+ )],
            $alloc_func, $free_func);
    );

    ($type_name:tt<$($lifetime:tt),+>, [$( $msg_id:ident => ( $($parsing_expr:tt)+ ) ),+], $alloc_func:expr, $free_func:expr) => (
        impl<$($lifetime),+> $crate::bindings::message_dispatcher::TryFrom<*mut $crate::bindings::message_dispatcher::message> for $type_name<$($lifetime),+> {
            derive_message_wrapper!(@try_from_impl
                $type_name<$($lifetime),+>,
                [$( $msg_id => ( $($parsing_expr)+ ) ),+]);
        }

        impl<$($lifetime),+> $crate::bindings::message_dispatcher::MemManagement for $type_name<$($lifetime),+> {
            derive_message_wrapper!(@mem_mgnt_impl $alloc_func, $free_func);
        }
    );

    ($type_name:ty, $msg_id:ident => ( $($parsing_expr:tt)+ ), $alloc_func:expr, $free_func:expr) => (
        derive_message_wrapper!(
            $type_name,
            [$msg_id => ( $($parsing_expr)+ )], $alloc_func, $free_func);
    );

    ($type_name:ty, [$( $msg_id:ident => ( $($parsing_expr:tt)+ ) ),+], $alloc_func:expr, $free_func:expr) => (
        impl $crate::bindings::message_dispatcher::TryFrom<*mut $crate::bindings::message_dispatcher::message> for $type_name {
            derive_message_wrapper!(@try_from_impl
                $type_name,
                [$($msg_id => ( $($parsing_expr)+ ) ),+]);
        }

        impl $crate::bindings::message_dispatcher::MemManagement for $type_name {
            derive_message_wrapper!(@mem_mgnt_impl $alloc_func, $free_func);
        }
    );

    (@try_from_impl $type_name:ty, [$($msg_id:ident => ( $($parsing_expr:tt)+ ) ),+]) => (
        type Error = ();

        fn try_from(raw_ptr: *mut $crate::bindings::message_dispatcher::message) -> Result<$type_name, Self::Error> {
            unsafe {
                if raw_ptr.is_null() {
                    return Err(());
                }

                #[allow(unused_variables)]
                let data_ptr = (*raw_ptr).data;

                match (*raw_ptr).msg_type {
                    $($msg_id => {derive_message_wrapper!(@match_pattern data_ptr, $($parsing_expr)+ )},)+
                    _ => Err(())
                }
            }
        }
    );

    (@match_pattern $_payload_ptr:expr, $type_head:tt$(::$type_tail:tt)* ) => {
        Ok($type_head$(::$type_tail)*)
    };

    (@match_pattern $payload_ptr:expr, $($parsing_expr:tt)+ ) => {
        {
            if $payload_ptr.is_null() {
                return Err(());
            }

            derive_message_wrapper!(@as_expr $($parsing_expr)+)($payload_ptr)
        }
    };

    (@mem_mgnt_impl $alloc_func:expr, $free_func:expr) => {
        fn alloc(msg_type: u32) -> *mut $crate::bindings::message_dispatcher::message {
            #[allow(unused_unsafe)]
            unsafe { $alloc_func(msg_type) }
        }

        fn free(msg_ptr: *mut $crate::bindings::message_dispatcher::message) {
            #[allow(unused_unsafe)]
            unsafe { $free_func(msg_ptr); }
        }
    };

    (@as_expr $e:expr) => {$e};
}

pub struct SyncMemory<T>(T);
unsafe impl<T> Sync for SyncMemory<T> {}

impl<T> SyncMemory<T> {
    pub fn new(item: T) -> SyncMemory<T> {
        SyncMemory(item)
    }
}

impl<T> AsRef<T> for SyncMemory<T> {
    fn as_ref(&self) -> &T {
        &self.0
    }
}

impl<T> AsMut<T> for SyncMemory<T> {
    fn as_mut(&mut self) -> &mut T {
        &mut self.0
    }
}

#[macro_export]
macro_rules! unwrap_or_ret_false {
    ($wrapped:expr) => {
        if let Ok(unwrapped) = $wrapped {
            unwrapped
        } else {
            return false;
        }
    }
}
<commit_msg>Added C-string writer<commit_after>#![allow(dead_code,
         non_camel_case_types,
         non_upper_case_globals,
         non_snake_case)]

use core::mem;
use core::ops::{Deref, DerefMut};
pub use core::convert::TryFrom;

use core::fmt;
use core::ptr;

use mouros_rust_bindings::CVoid;
use mouros_rust_bindings::mailbox::MailboxRaw;

#[repr(C)]
pub struct message {
    pub msg_type: u32,
    transaction_id: u32,
    pub data: *mut CVoid,
}

#[repr(C)]
pub struct message_handler {
    pub message_name: *const u8,
    pub parsing_func:
        Option<unsafe extern "C" fn(msg_ptr: *mut message, save_ptr: *mut u8) -> bool>,
    pub serialization_func: Option<
        unsafe extern "C" fn(msg_ptr: *const message,
                             output_str: *mut u8,
                             output_str_max_len: u32)
                             -> isize,
    >,
}

#[repr(C)]
pub struct subsystem_message_conf {
    pub subsystem_name: *const u8,
    pub message_handlers: *const message_handler,
    pub num_message_types: u32,
    pub incoming_msg_queue: *mut MailboxRaw,
    pub outgoing_msg_queue: *mut MailboxRaw,
    pub outgoing_err_queue: *mut MailboxRaw,
    pub alloc_message: Option<unsafe extern "C" fn(msg_type_id: u32) -> *mut message>,
    pub free_message: Option<unsafe extern "C" fn(msg: *mut message)>,
}

extern "C" {
    pub fn dispatcher_register_subsystem(conf: *mut subsystem_message_conf) -> bool;
}

pub struct MessageWrapper<T: Wrappable> {
    raw_msg_ptr: *mut message,
    msg: T,
}

pub trait MemManagement {
    fn alloc(msg_type: u32) -> *mut message;
    fn free(msg_ptr: *mut message);
}

pub trait Wrappable: MemManagement + TryFrom<*mut message, Error = ()> {}
impl<T> Wrappable for T
where
    T: MemManagement + TryFrom<*mut message, Error = ()>,
{
}

impl<T> Drop for MessageWrapper<T>
where
    T: Wrappable,
{
    fn drop(&mut self) {
        T::free(self.raw_msg_ptr);
    }
}

impl<T> Deref for MessageWrapper<T>
where
    T: Wrappable,
{
    type Target = T;

    fn deref(&self) -> &Self::Target {
        &self.msg
    }
}

impl<T> DerefMut for MessageWrapper<T>
where
    T: Wrappable,
{
    fn deref_mut(&mut self) -> &mut T {
        &mut self.msg
    }
}

impl<T> Into<*mut message> for MessageWrapper<T>
where
    T: Wrappable,
{
    fn into(self) -> *mut message {
        let raw_msg_ptr = self.raw_msg_ptr;

        // It's the caller's duty ot deallocate the message now.
        mem::forget(self);

        raw_msg_ptr
    }
}

impl<T> TryFrom<*mut message> for MessageWrapper<T>
where
    T: Wrappable,
{
    type Error = ();

    fn try_from(raw_msg_ptr: *mut message) -> Result<Self, Self::Error> {
        unsafe {
            if raw_msg_ptr.is_null() || (*raw_msg_ptr).data.is_null() {
                return Err(());
            }
        };

        Ok(MessageWrapper {
            msg: T::try_from(raw_msg_ptr)?,
            raw_msg_ptr: raw_msg_ptr,
        })
    }
}

impl<T> MessageWrapper<T>
where
    T: Wrappable,
{
    pub fn new(trans_id: u32, msg_type: u32) -> Result<MessageWrapper<T>, ()> {

        if let Ok(msg_wrapper) = MessageWrapper::try_from(T::alloc(msg_type)) {
            unsafe {
                (*msg_wrapper.raw_msg_ptr).transaction_id = trans_id;
            }

            Ok(msg_wrapper)
        } else {
            Err(())
        }
    }

    pub fn get_transaction_id(&self) -> u32 {
        unsafe { (*self.raw_msg_ptr).transaction_id }
    }
}

#[macro_export]
macro_rules! derive_message_wrapper {
    ($type_name:tt<$($lifetime:tt),+>, $msg_id:ident => ( $($parsing_expr:tt)+ ), $alloc_func:expr, $free_func:expr) => (
        derive_message_wrapper!(
            $type_name<$($lifetime),+>,
            [$msg_id => ( $($parsing_expr)+ )],
            $alloc_func, $free_func);
    );

    ($type_name:tt<$($lifetime:tt),+>, [$( $msg_id:ident => ( $($parsing_expr:tt)+ ) ),+], $alloc_func:expr, $free_func:expr) => (
        impl<$($lifetime),+> $crate::bindings::message_dispatcher::TryFrom<*mut $crate::bindings::message_dispatcher::message> for $type_name<$($lifetime),+> {
            derive_message_wrapper!(@try_from_impl
                $type_name<$($lifetime),+>,
                [$( $msg_id => ( $($parsing_expr)+ ) ),+]);
        }

        impl<$($lifetime),+> $crate::bindings::message_dispatcher::MemManagement for $type_name<$($lifetime),+> {
            derive_message_wrapper!(@mem_mgnt_impl $alloc_func, $free_func);
        }
    );

    ($type_name:ty, $msg_id:ident => ( $($parsing_expr:tt)+ ), $alloc_func:expr, $free_func:expr) => (
        derive_message_wrapper!(
            $type_name,
            [$msg_id => ( $($parsing_expr)+ )], $alloc_func, $free_func);
    );

    ($type_name:ty, [$( $msg_id:ident => ( $($parsing_expr:tt)+ ) ),+], $alloc_func:expr, $free_func:expr) => (
        impl $crate::bindings::message_dispatcher::TryFrom<*mut $crate::bindings::message_dispatcher::message> for $type_name {
            derive_message_wrapper!(@try_from_impl
                $type_name,
                [$($msg_id => ( $($parsing_expr)+ ) ),+]);
        }

        impl $crate::bindings::message_dispatcher::MemManagement for $type_name {
            derive_message_wrapper!(@mem_mgnt_impl $alloc_func, $free_func);
        }
    );

    (@try_from_impl $type_name:ty, [$($msg_id:ident => ( $($parsing_expr:tt)+ ) ),+]) => (
        type Error = ();

        fn try_from(raw_ptr: *mut $crate::bindings::message_dispatcher::message) -> Result<$type_name, Self::Error> {
            unsafe {
                if raw_ptr.is_null() {
                    return Err(());
                }

                #[allow(unused_variables)]
                let data_ptr = (*raw_ptr).data;

                match (*raw_ptr).msg_type {
                    $($msg_id => {derive_message_wrapper!(@match_pattern data_ptr, $($parsing_expr)+ )},)+
                    _ => Err(())
                }
            }
        }
    );

    (@match_pattern $_payload_ptr:expr, $type_head:tt$(::$type_tail:tt)* ) => {
        Ok($type_head$(::$type_tail)*)
    };

    (@match_pattern $payload_ptr:expr, $($parsing_expr:tt)+ ) => {
        {
            if $payload_ptr.is_null() {
                return Err(());
            }

            derive_message_wrapper!(@as_expr $($parsing_expr)+)($payload_ptr)
        }
    };

    (@mem_mgnt_impl $alloc_func:expr, $free_func:expr) => {
        fn alloc(msg_type: u32) -> *mut $crate::bindings::message_dispatcher::message {
            #[allow(unused_unsafe)]
            unsafe { $alloc_func(msg_type) }
        }

        fn free(msg_ptr: *mut $crate::bindings::message_dispatcher::message) {
            #[allow(unused_unsafe)]
            unsafe { $free_func(msg_ptr); }
        }
    };

    (@as_expr $e:expr) => {$e};
}

pub struct SyncMemory<T>(T);
unsafe impl<T> Sync for SyncMemory<T> {}

impl<T> SyncMemory<T> {
    pub fn new(item: T) -> SyncMemory<T> {
        SyncMemory(item)
    }
}

impl<T> AsRef<T> for SyncMemory<T> {
    fn as_ref(&self) -> &T {
        &self.0
    }
}

impl<T> AsMut<T> for SyncMemory<T> {
    fn as_mut(&mut self) -> &mut T {
        &mut self.0
    }
}

#[macro_export]
macro_rules! unwrap_or_ret_false {
    ($wrapped:expr) => {
        if let Ok(unwrapped) = $wrapped {
            unwrapped
        } else {
            return false;
        }
    }
}

pub struct CStrWriter<'buf> {
    buf: &'buf mut [u8],
    pos: usize,
}

impl<'buf> CStrWriter<'buf> {
    pub fn new(buf: &mut [u8]) -> CStrWriter {
        buf[0] = '\0' as u8;

        CStrWriter { buf: buf, pos: 0 }
    }

    pub fn len(&self) -> usize {
        self.pos
    }
}

impl<'buf> fmt::Write for CStrWriter<'buf> {
    fn write_str(&mut self, s: &str) -> fmt::Result {
        let s_len = s.as_bytes().len();

        if (s_len + 1) > (self.buf.len() - self.pos) {
            return Err(fmt::Error);
        }

        unsafe {
            ptr::copy_nonoverlapping(
                s.as_ptr(),
                self.buf.as_mut_ptr().offset(self.pos as isize),
                s_len,
            );
        }

        self.pos += s_len;
        self.buf[self.pos] = '\0' as u8;

        Ok(())
    }
}
<|endoftext|>


<commit_before>use std::io::BufRead;
use std::io::BufReader;
use std::io::Read;

use common::Solution;

type Coordinate = (usize, usize);

#[derive(Debug, Copy, Clone, Eq, PartialEq)]
enum Direction {
    North,
    South,
    West,
    East,
}

impl Direction {
    pub fn from_char(c: char) -> Self {
        match c {
            '^' => Direction::North,
            '<' => Direction::West,
            '>' => Direction::East,
            'v' => Direction::South,
            _ => panic!("Invalid direction {}", c),
        }
    }
    pub fn clockwise(&self) -> Self {
        match self {
            Direction::North => Direction::East,
            Direction::East => Direction::South,
            Direction::South => Direction::West,
            Direction::West => Direction::North,
        }
    }

    pub fn counter_clockwise(&self) -> Self {
        return self.clockwise().clockwise().clockwise();
    }

    pub fn run(&self, pos: Coordinate) -> Coordinate {
        let (x, y) = pos;
        match self {
            Direction::North => (x, y - 1),
            Direction::South => (x, y + 1),
            Direction::West => (x - 1, y),
            Direction::East => (x + 1, y),
        }
    }
}

#[derive(Default, Debug)]
pub struct Day13 {
    grid: Vec<Vec<char>>,
    carts: Vec<(Coordinate, Direction, usize)>,
    alive: Vec<bool>,
}

impl Day13 {
    pub fn new() -> Self {
        Default::default()
    }

    fn alive(&self) -> usize {
        self.alive.iter().filter(|&&x| x).count()
    }

    fn read_input(&mut self, input: &mut Read) {
        let reader = BufReader::new(input);
        for (y, line) in reader.lines().enumerate() {
            let line = line.unwrap();
            let mut current = Vec::new();
            for (x, c) in line.chars().enumerate() {
                match c {
                    '^' | 'v' => {
                        current.push('|');
                        let direction = Direction::from_char(c);
                        self.carts.push(((x, y), direction, 0));
                    }
                    '>' | '<' => {
                        current.push('-');
                        let direction = Direction::from_char(c);
                        self.carts.push(((x, y), direction, 0));
                    }
                    other => current.push(other),
                }
            }
            self.grid.push(current);
        }
        self.alive.resize(self.carts.len(), true);
    }

    fn simulate(&mut self) -> Option<Coordinate> {
        let mut collision = None;
        for (coordinate, direction, turns) in self.carts.iter_mut() {
            *coordinate = direction.run(*coordinate);
            let &mut(x, y) = coordinate;
            *direction = match self.grid[y][x] {
                '|' | '-' => *direction,
                '+' => {
                    let new_dir = match turns {
                        0 => direction.counter_clockwise(),
                        1 => *direction,
                        2 => direction.clockwise(),
                        _ => unreachable!(),
                    };

                    *turns = (*turns + 1) % 3;
                    new_dir

                },
                '/' => match *direction {
                    Direction::North | Direction::South => direction.clockwise(),
                    Direction::West | Direction::East => direction.counter_clockwise(),
                },
                '\\' => match *direction {
                    Direction::North | Direction::South => direction.counter_clockwise() ,
                    Direction::West | Direction::East => direction.clockwise(),
                },
                val => panic!("Invalid tile to be on: {}", val),
            };
        }

        for i in 0..self.carts.len() {
            for j in (i + 1)..self.carts.len() {
                if !self.alive[i] {
                    break;
                }
                if !self.alive[j] {
                    continue;
                }

                if self.carts[i].0 == self.carts[j].0 {
                    self.alive[i] = false;
                    self.alive[j] = false;
                    collision = Some(self.carts[i].0);
                }
            }
        }

        collision
    }
}

impl Solution for Day13 {
    fn part1(&mut self, input: &mut Read) -> String {
        self.read_input(input);
        let mut collision = None;
        while collision == None {
            collision = self.simulate();
        }
        let (x, y) = collision.unwrap();
        format!("{},{}", x, y)
    }

    fn part2(&mut self, input: &mut Read) -> String {
        self.read_input(input);
        while self.alive() > 1 {
            println!("{}", self.alive());
            self.simulate();
        }

        for (i, ((x, y), _, _)) in self.carts.iter().enumerate() {
            if self.alive[i] {
                return format!("{},{}", x, y)
            }
        }
        unreachable!()
    }
}

#[cfg(test)]
mod tests {
    use common::Solution;
    use day13::Day13;
    use day13::Direction;

    const SAMPLE1_INPUT: &[u8] = include_bytes!("samples/13.1.txt");
    const SAMPLE2_INPUT: &[u8] = include_bytes!("samples/13.2.txt");

    #[test]
    fn test_turning() {
        assert_eq!(Direction::East, Direction::South.counter_clockwise());
    }

    #[test]
    fn sample_part1() {
        let mut instance = Day13::new();
        assert_eq!("7,3", instance.part1(&mut SAMPLE1_INPUT))
    }

    #[test]
    fn sample_part2() {
        let mut instance = Day13::new();
        assert_eq!("6,4", instance.part2(&mut SAMPLE2_INPUT))
    }
}
<commit_msg>Implement a very ugly part 2.<commit_after>use std::io::BufRead;
use std::io::BufReader;
use std::io::Read;

use common::Solution;

type Coordinate = (usize, usize);

#[derive(Debug, Copy, Clone, Eq, PartialEq)]
enum Direction {
    North,
    South,
    West,
    East,
}

impl Direction {
    pub fn from_char(c: char) -> Self {
        match c {
            '^' => Direction::North,
            '<' => Direction::West,
            '>' => Direction::East,
            'v' => Direction::South,
            _ => panic!("Invalid direction {}", c),
        }
    }
    pub fn clockwise(&self) -> Self {
        match self {
            Direction::North => Direction::East,
            Direction::East => Direction::South,
            Direction::South => Direction::West,
            Direction::West => Direction::North,
        }
    }

    pub fn counter_clockwise(&self) -> Self {
        return self.clockwise().clockwise().clockwise();
    }

    pub fn run(&self, pos: Coordinate) -> Coordinate {
        let (x, y) = pos;
        match self {
            Direction::North => (x, y - 1),
            Direction::South => (x, y + 1),
            Direction::West => (x - 1, y),
            Direction::East => (x + 1, y),
        }
    }
}

#[derive(Default, Debug)]
pub struct Day13 {
    grid: Vec<Vec<char>>,
    carts: Vec<(Coordinate, Direction, usize, bool)>,
}

impl Day13 {
    pub fn new() -> Self {
        Default::default()
    }

    fn alive(&self) -> usize {
        self.carts.iter().filter(|(_, _, _, x)| *x).count()
    }

    fn read_input(&mut self, input: &mut Read) {
        let reader = BufReader::new(input);
        for (y, line) in reader.lines().enumerate() {
            let line = line.unwrap();
            let mut current = Vec::new();
            for (x, c) in line.chars().enumerate() {
                match c {
                    '^' | 'v' => {
                        current.push('|');
                        let direction = Direction::from_char(c);
                        self.carts.push(((x, y), direction, 0, true));
                    }
                    '>' | '<' => {
                        current.push('-');
                        let direction = Direction::from_char(c);
                        self.carts.push(((x, y), direction, 0, true));
                    }
                    other => current.push(other),
                }
            }
            self.grid.push(current);
        }
    }

    fn simulate(&mut self) -> Option<Coordinate> {
        let mut collision = None;
        self.carts.sort_unstable_by_key(|&((x, y), _, _ , _)| (y, x));
        for i in 0..self.carts.len() {
            {
                let (coordinate, direction, turns, alive) = self.carts.get_mut(i).unwrap();
                if !*alive {
                    continue;
                }
                *coordinate = direction.run(*coordinate);
                let &mut (x, y) = coordinate;
                *direction = match self.grid[y][x] {
                    '|' | '-' => *direction,
                    '+' => {
                        let new_dir = match turns {
                            0 => direction.counter_clockwise(),
                            1 => *direction,
                            2 => direction.clockwise(),
                            _ => unreachable!(),
                        };

                        *turns = (*turns + 1) % 3;
                        new_dir
                    },
                    '/' => match *direction {
                        Direction::North | Direction::South => direction.clockwise(),
                        Direction::West | Direction::East => direction.counter_clockwise(),
                    },
                    '\\' => match *direction {
                        Direction::North | Direction::South => direction.counter_clockwise(),
                        Direction::West | Direction::East => direction.clockwise(),
                    },
                    val => panic!("Invalid tile to be on: {}", val),
                };
            }
            for j in 0..self.carts.len() {
                if i == j {
                    continue;
                }
                if !self.carts[i].3 {
                    break;
                }
                if !self.carts[j].3 {
                    continue;
                }

                if self.carts[i].0 == self.carts[j].0 {
                    self.carts[i].3 = false;
                    self.carts[j].3 = false;
                    collision = Some(self.carts[i].0);
                }
            }
        }

        collision
    }
}

impl Solution for Day13 {
    fn part1(&mut self, input: &mut Read) -> String {
        self.read_input(input);
        let mut collision = None;
        while collision == None {
            collision = self.simulate();
        }
        let (x, y) = collision.unwrap();
        format!("{},{}", x, y)
    }

    fn part2(&mut self, input: &mut Read) -> String {
        self.read_input(input);
        while self.alive() > 1 {
            self.simulate();
        }

        for &((x, y), _, _, alive) in &self.carts {
            if alive {
                return format!("{},{}", x, y)
            }
        }
        unreachable!()
    }
}

#[cfg(test)]
mod tests {
    use common::Solution;
    use day13::Day13;
    use day13::Direction;

    const SAMPLE1_INPUT: &[u8] = include_bytes!("samples/13.1.txt");
    const SAMPLE2_INPUT: &[u8] = include_bytes!("samples/13.2.txt");

    #[test]
    fn test_turning() {
        assert_eq!(Direction::East, Direction::South.counter_clockwise());
    }

    #[test]
    fn sample_part1() {
        let mut instance = Day13::new();
        assert_eq!("7,3", instance.part1(&mut SAMPLE1_INPUT))
    }

    #[test]
    fn sample_part2() {
        let mut instance = Day13::new();
        assert_eq!("6,4", instance.part2(&mut SAMPLE2_INPUT))
    }
}
<|endoftext|>


<commit_before>extern crate neat;
extern crate rand;
extern crate graph_neighbor_matching;
extern crate graph_io_gml as gml;
extern crate closed01;
extern crate petgraph;
extern crate cppn;

use neat::population::{Population, Unrated, Runner};
use neat::genomes::network::{NetworkGenome, NetworkGenomeDistance, NodeType, Environment, ElementStrategy};
use neat::fitness::Fitness;
use neat::traits::Mate;
use neat::crossover::ProbabilisticCrossover;
use neat::prob::is_probable;
use graph_neighbor_matching::{SimilarityMatrix, ScoreNorm, NodeColorMatching, Graph};
use graph_neighbor_matching::graph::{OwnedGraph, GraphBuilder};
use rand::{Rng, Closed01};
use std::marker::PhantomData;
use std::fmt::Debug;
use neat::mutate::{MutateMethod, MutateMethodWeighting};
use petgraph::Graph as PetGraph;
use petgraph::{Directed, EdgeDirection};
use petgraph::graph::NodeIndex;
use std::collections::BTreeMap;
use cppn::bipolar::{Linear, Gaussian, Sigmoid, Sine};
use cppn::{Identity, ActivationFunction};
use cppn::cppn::{Cppn, CppnGraph, CppnNodeType};

fn node_type_from_str(s: &str) -> NodeType {
    match s {
        "input" => NodeType::Input,
        "output" => NodeType::Output,
        "hidden" => NodeType::Hidden { activation_function: 0 }, // XXX
        _ => panic!("Invalid node type/weight"),
    }
}

fn neuron_type_from_str(s: &str) -> NeuronType {
    match s {
        "input" => NeuronType::Input,
        "output" => NeuronType::Output,
        "hidden" => NeuronType::Hidden,
        _ => panic!("Invalid node type/weight"),
    }
}

// NT is the returned node type
fn load_graph<NT, F>(graph_file: &str, node_weight_fn: &F) -> OwnedGraph<NT>
    where F: Fn(&str) -> NT,
          NT: Clone + Debug
{
    use std::fs::File;
    use std::io::Read;

    let graph_s = {
        let mut graph_file = File::open(graph_file).unwrap();
        let mut graph_s = String::new();
        let _ = graph_file.read_to_string(&mut graph_s).unwrap();
        graph_s
    };

    let graph = gml::parse_gml(&graph_s,
                               &|sexp| -> Option<NT> {
                                   sexp.and_then(|se| se.get_str().map(|s| node_weight_fn(s)))
                               },
                               &|_| -> Option<()> { Some(()) })
                    .unwrap();
    OwnedGraph::from_petgraph(&graph)
}

fn genome_to_graph(genome: &NetworkGenome) -> OwnedGraph<NodeType> {
    let mut builder = GraphBuilder::new();

    for (&innov, node) in genome.node_genes.map.iter() {
        // make sure the node exists, even if there are no connection to it.
        let _ = builder.add_node(innov.get(), node.node_type);
    }

    for link in genome.link_genes.map.values() {
        if link.active {
            builder.add_edge(link.source_node_gene.get(),
                             link.target_node_gene.get(),
                             closed01::Closed01::new(link.weight as f32));
        }
    }

    return builder.graph();
}

fn make_activation_function(f: u32) -> Box<ActivationFunction> {
    match f {
        0 => Box::new(Identity),
        1 => Box::new(Linear),
        2 => Box::new(Gaussian),
        3 => Box::new(Sigmoid),
        4 => Box::new(Sine),
        _ => {
            panic!("invalid activation function");
        }
    }
}

// Represents a position within the substrate.
trait Position {
    fn as_slice(&self) -> &[f64];
}

struct Position2d([f64; 2]);

impl Position for Position2d {
    fn as_slice(&self) -> &[f64] {
        &self.0
    }
}

#[derive(Debug, Copy, Clone, PartialEq, Eq)]
enum NeuronType {
    Input,
    Output,
    Hidden,
}

struct Neuron<P: Position> {
    neuron_type: NeuronType,
    position: P,
}

struct Substrate<P: Position> {
    neurons: Vec<Neuron<P>>,
}

impl<P: Position> Substrate<P> {
    fn new() -> Substrate<P> {
        Substrate { neurons: Vec::new() }
    }

    fn add_neuron(&mut self, neuron: Neuron<P>) {
        self.neurons.push(neuron);
    }

    fn develop_edgelist(&self, cppn: &mut Cppn) -> Vec<(usize, usize, f64)> {
        let mut edge_list = Vec::new();
        for (i, neuron_i) in self.neurons.iter().enumerate() {
            for (j, neuron_j) in self.neurons.iter().enumerate() {
                if i != j {
                    // XXX: limit based on distance
                    // evalute cppn for coordinates of neuron_i and neuron_j
                    let inputs = [neuron_i.position.as_slice(), neuron_j.position.as_slice()];

                    let outputs = cppn.calculate(&inputs);
                    assert!(outputs.len() == 1);
                    let weight = outputs[0];
                    // XXX: cut off weight. direction
                    if weight >= 0.0 && weight <= 1.0 {
                        edge_list.push((i, j, weight));
                    }
                }
            }
        }
        edge_list
    }

    fn develop_graph(&self, cppn: &mut Cppn) -> OwnedGraph<NeuronType> {
        let mut builder = GraphBuilder::new();

        for (i, neuron_i) in self.neurons.iter().enumerate() {
            let _ = builder.add_node(i, neuron_i.neuron_type);
        }

        let edgelist = self.develop_edgelist(cppn);
        for (source, target, weight) in edgelist {
            let w = if weight > 1.0 {
                1.0
            } else if weight < 0.0 {
                0.0
            } else {
                weight
            };
            builder.add_edge(source, target, closed01::Closed01::new(w as f32));
        }

        let graph = builder.graph();
        // println!("graph: {:#?}", graph);

        return graph;
    }
}

// Treats the graph as CPPN and constructs a graph.
fn genome_to_cppn(genome: &NetworkGenome) -> Cppn {
    let mut node_map = BTreeMap::new();
    let mut g = CppnGraph::new();

    for (&innov, node) in genome.node_genes.map.iter() {
        // make sure the node exists, even if there are no connection to it.
        let node_idx = match node.node_type {
            NodeType::Input => g.add_node(CppnNodeType::Input, make_activation_function(0)),
            NodeType::Output => g.add_node(CppnNodeType::Output, make_activation_function(0)),
            NodeType::Hidden{activation_function} => {
                g.add_node(CppnNodeType::Hidden,
                           make_activation_function(activation_function))
            }
        };

        node_map.insert(innov.get(), node_idx);
    }

    for link in genome.link_genes.map.values() {
        if link.active {
            g.add_link(node_map[&link.source_node_gene.get()],
                       node_map[&link.target_node_gene.get()],
                       link.weight);
        }
    }

    Cppn::new(g)
}

#[derive(Debug)]
struct NodeColors;

impl NodeColorMatching<NodeType> for NodeColors {
    fn node_color_matching(&self,
                           node_i_value: &NodeType,
                           node_j_value: &NodeType)
                           -> closed01::Closed01<f32> {

        // Treat nodes as equal regardless of their activation function or input/output number.
        let eq = match (node_i_value, node_j_value) {
            (&NodeType::Input, &NodeType::Input) => true,
            (&NodeType::Output, &NodeType::Output) => true,
            (&NodeType::Hidden{..}, &NodeType::Hidden{..}) => true,
            _ => false,
        };

        if eq {
            closed01::Closed01::one()
        } else {
            closed01::Closed01::zero()
        }
    }
}

impl NodeColorMatching<NeuronType> for NodeColors {
    fn node_color_matching(&self,
                           node_i_value: &NeuronType,
                           node_j_value: &NeuronType)
                           -> closed01::Closed01<f32> {
        if node_i_value == node_j_value {
            closed01::Closed01::one()
        } else {
            closed01::Closed01::zero()
        }
    }
}

#[derive(Debug)]
struct FitnessEvaluator {
    target_graph: OwnedGraph<NodeType>,
}

impl FitnessEvaluator {
    // A larger fitness means "better"
    fn fitness(&self, genome: &NetworkGenome) -> f32 {
        let graph = genome_to_graph(genome);
        let mut s = SimilarityMatrix::new(&graph, &self.target_graph, NodeColors);
        s.iterate(50, 0.01);
        s.score_optimal_sum_norm(None, ScoreNorm::MaxDegree).get()
    }
}

#[derive(Debug)]
struct FitnessEvaluatorCppn {
    target_graph: OwnedGraph<NeuronType>,
}

impl FitnessEvaluatorCppn {
    // A larger fitness means "better"
    fn fitness(&self, genome: &NetworkGenome) -> f32 {
        let mut cppn = genome_to_cppn(genome);

        let mut substrate = Substrate::new();
        substrate.add_neuron(Neuron {
            neuron_type: NeuronType::Input,
            position: Position2d([-1.0, -1.0]),
        });
        substrate.add_neuron(Neuron {
            neuron_type: NeuronType::Input,
            position: Position2d([-1.0, 1.0]),
        });

        substrate.add_neuron(Neuron {
            neuron_type: NeuronType::Output,
            position: Position2d([-1.0, 1.0]),
        });
        substrate.add_neuron(Neuron {
            neuron_type: NeuronType::Output,
            position: Position2d([0.0, 1.0]),
        });
        substrate.add_neuron(Neuron {
            neuron_type: NeuronType::Output,
            position: Position2d([1.0, 1.0]),
        });

        let graph = substrate.develop_graph(&mut cppn);

        let mut s = SimilarityMatrix::new(&graph, &self.target_graph, NodeColors);
        s.iterate(50, 0.01);
        s.score_optimal_sum_norm(None, ScoreNorm::MaxDegree).get()
    }
}

struct ES;

impl ElementStrategy for ES {
    fn random_link_weight<R: Rng>(rng: &mut R) -> f64 {
        // XXX Choose a weight between -1 and 1?
        rng.gen()
    }
    fn random_activation_function<R: Rng>(rng: &mut R) -> u32 {
        rng.gen_range(0, 5)
    }
}

const POP_SIZE: usize = 100;
const INPUTS: usize = 2;
const OUTPUTS: usize = 3;

struct Mater<'a, T: ElementStrategy + 'a> {
    // probability for crossover. P_mutate = 1.0 - p_crossover
    p_crossover: Closed01<f32>,
    p_crossover_detail: ProbabilisticCrossover,
    mutate_weights: MutateMethodWeighting,
    env: &'a mut Environment<T>,
}

impl<'a, T: ElementStrategy> Mate<NetworkGenome> for Mater<'a, T> {
    // Add an argument that descibes whether both genomes are of equal fitness.
    // Pass individual, which includes the fitness.
    fn mate<R: Rng>(&mut self,
                    parent_left: &NetworkGenome,
                    parent_right: &NetworkGenome,
                    prefer_mutate: bool,
                    rng: &mut R)
                    -> NetworkGenome {
        if prefer_mutate == false && is_probable(&self.p_crossover, rng) {
            NetworkGenome::crossover(parent_left, parent_right, &self.p_crossover_detail, rng)
        } else {
            // mutate
            let mutate_method = MutateMethod::random_with(&self.mutate_weights, rng);
            self.env
                .mutate(parent_left, mutate_method, rng)
                .or_else(|| self.env.mutate(parent_right, mutate_method, rng))
                .unwrap_or_else(|| parent_left.clone())
        }
    }
}

fn main() {
    let mut rng = rand::thread_rng();

    // let fitness_evaluator = FitnessEvaluator {
    // target_graph: load_graph("examples/jeffress.gml", &node_type_from_str),
    // };
    //

    let fitness_evaluator = FitnessEvaluatorCppn {
        target_graph: load_graph("examples/jeffress.gml", &neuron_type_from_str),
    };

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

    // start with minimal random topology.
    let mut env: Environment<ES> = Environment::new();

    // let template_genome = env.generate_genome(INPUTS, OUTPUTS);
    // 4 inputs for 2xcoordinate pairs.
    let template_genome = env.generate_genome(4, 1);

    println!("{:#?}", template_genome);

    let mut initial_pop = Population::<_, Unrated>::new();

    for _ in 0..POP_SIZE {
        // Add a single link gene! This is required, otherwise we can't determine
        // correctly an InnovationRange.
        let genome = env.mutate_add_connection(&template_genome, &mut rng).unwrap();

        initial_pop.add_genome(Box::new(genome));
    }
    assert!(initial_pop.len() == POP_SIZE);

    let mut mater = Mater {
        p_crossover: Closed01(0.5),
        p_crossover_detail: ProbabilisticCrossover {
            prob_match_left: Closed01(0.5), /* NEAT always selects a random parent for matching genes */
            prob_disjoint_left: Closed01(0.9),
            prob_excess_left: Closed01(0.9),
            prob_disjoint_right: Closed01(0.15),
            prob_excess_right: Closed01(0.15),
        },
        mutate_weights: MutateMethodWeighting {
            w_modify_weight: 1,
            w_add_node: 1,
            w_add_connection: 1,
        },

        env: &mut env,
    };

    let compatibility = NetworkGenomeDistance {
        excess: 1.0,
        disjoint: 1.0,
        weight: 0.0,
    };

    let mut runner = Runner {
        pop_size: POP_SIZE,
        elite_percentage: Closed01(0.05),
        selection_percentage: Closed01(0.2),
        tournament_k: 3,
        compatibility_threshold: 1.0,
        compatibility: &compatibility,
        mate: &mut mater,
        fitness: &|genome| Fitness::new(fitness_evaluator.fitness(genome) as f64),
        _marker: PhantomData,
    };

    let (iter, new_pop) = runner.run(initial_pop,
                                     &|iter, pop| {
                                         iter >= 100 || pop.max_fitness().unwrap().get() > 0.99
                                     },
                                     &mut rng);

    let new_pop = new_pop.sort();

    println!("iter: {}", iter);
    println!("{:#?}", new_pop);
}
<commit_msg>Remove unused code from net.rs<commit_after>extern crate neat;
extern crate rand;
extern crate graph_neighbor_matching;
extern crate graph_io_gml as gml;
extern crate closed01;
extern crate petgraph;

use neat::population::{Population, Unrated, Runner};
use neat::genomes::network::{NetworkGenome, NetworkGenomeDistance, NodeType, Environment, ElementStrategy};
use neat::fitness::Fitness;
use neat::traits::Mate;
use neat::crossover::ProbabilisticCrossover;
use neat::prob::is_probable;
use graph_neighbor_matching::{SimilarityMatrix, ScoreNorm, NodeColorMatching};
use graph_neighbor_matching::graph::{OwnedGraph, GraphBuilder};
use rand::{Rng, Closed01};
use std::marker::PhantomData;
use std::fmt::Debug;
use neat::mutate::{MutateMethod, MutateMethodWeighting};

fn node_type_from_str(s: &str) -> NodeType {
    match s {
        "input" => NodeType::Input,
        "output" => NodeType::Output,
        "hidden" => NodeType::Hidden { activation_function: 0 }, // XXX
        _ => panic!("Invalid node type/weight"),
    }
}

// NT is the returned node type
fn load_graph<NT, F>(graph_file: &str, node_weight_fn: &F) -> OwnedGraph<NT>
    where F: Fn(&str) -> NT,
          NT: Clone + Debug
{
    use std::fs::File;
    use std::io::Read;

    let graph_s = {
        let mut graph_file = File::open(graph_file).unwrap();
        let mut graph_s = String::new();
        let _ = graph_file.read_to_string(&mut graph_s).unwrap();
        graph_s
    };

    let graph = gml::parse_gml(&graph_s,
                               &|sexp| -> Option<NT> {
                                   sexp.and_then(|se| se.get_str().map(|s| node_weight_fn(s)))
                               },
                               &|_| -> Option<()> { Some(()) })
                    .unwrap();
    OwnedGraph::from_petgraph(&graph)
}

fn genome_to_graph(genome: &NetworkGenome) -> OwnedGraph<NodeType> {
    let mut builder = GraphBuilder::new();

    for (&innov, node) in genome.node_genes.map.iter() {
        // make sure the node exists, even if there are no connection to it.
        let _ = builder.add_node(innov.get(), node.node_type);
    }

    for link in genome.link_genes.map.values() {
        if link.active {
            builder.add_edge(link.source_node_gene.get(),
                             link.target_node_gene.get(),
                             closed01::Closed01::new(link.weight as f32));
        }
    }

    return builder.graph();
}

#[derive(Debug)]
struct NodeColors;

impl NodeColorMatching<NodeType> for NodeColors {
    fn node_color_matching(&self,
                           node_i_value: &NodeType,
                           node_j_value: &NodeType)
                           -> closed01::Closed01<f32> {

        // Treat nodes as equal regardless of their activation function or input/output number.
        let eq = match (node_i_value, node_j_value) {
            (&NodeType::Input, &NodeType::Input) => true,
            (&NodeType::Output, &NodeType::Output) => true,
            (&NodeType::Hidden{..}, &NodeType::Hidden{..}) => true,
            _ => false,
        };

        if eq {
            closed01::Closed01::one()
        } else {
            closed01::Closed01::zero()
        }
    }
}

#[derive(Debug)]
struct FitnessEvaluator {
    target_graph: OwnedGraph<NodeType>,
}

impl FitnessEvaluator {
    // A larger fitness means "better"
    fn fitness(&self, genome: &NetworkGenome) -> f32 {
        let graph = genome_to_graph(genome);
        let mut s = SimilarityMatrix::new(&graph, &self.target_graph, NodeColors);
        s.iterate(50, 0.01);
        s.score_optimal_sum_norm(None, ScoreNorm::MaxDegree).get()
    }
}

struct ES;

impl ElementStrategy for ES {
    fn random_link_weight<R: Rng>(rng: &mut R) -> f64 {
        // XXX Choose a weight between -1 and 1?
        rng.gen()
    }
    fn random_activation_function<R: Rng>(rng: &mut R) -> u32 {
        rng.gen_range(0, 5)
    }
}

const POP_SIZE: usize = 100;
const INPUTS: usize = 2;
const OUTPUTS: usize = 3;

struct Mater<'a, T: ElementStrategy + 'a> {
    // probability for crossover. P_mutate = 1.0 - p_crossover
    p_crossover: Closed01<f32>,
    p_crossover_detail: ProbabilisticCrossover,
    mutate_weights: MutateMethodWeighting,
    env: &'a mut Environment<T>,
}

impl<'a, T: ElementStrategy> Mate<NetworkGenome> for Mater<'a, T> {
    // Add an argument that descibes whether both genomes are of equal fitness.
    // Pass individual, which includes the fitness.
    fn mate<R: Rng>(&mut self,
                    parent_left: &NetworkGenome,
                    parent_right: &NetworkGenome,
                    prefer_mutate: bool,
                    rng: &mut R)
                    -> NetworkGenome {
        if prefer_mutate == false && is_probable(&self.p_crossover, rng) {
            NetworkGenome::crossover(parent_left, parent_right, &self.p_crossover_detail, rng)
        } else {
            // mutate
            let mutate_method = MutateMethod::random_with(&self.mutate_weights, rng);
            self.env
                .mutate(parent_left, mutate_method, rng)
                .or_else(|| self.env.mutate(parent_right, mutate_method, rng))
                .unwrap_or_else(|| parent_left.clone())
        }
    }
}

fn main() {
    let mut rng = rand::thread_rng();

    let fitness_evaluator = FitnessEvaluator {
        target_graph: load_graph("examples/jeffress.gml", &node_type_from_str),
    };

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

    // start with minimal random topology.
    let mut env: Environment<ES> = Environment::new();

    let template_genome = env.generate_genome(INPUTS, OUTPUTS);

    println!("{:#?}", template_genome);

    let mut initial_pop = Population::<_, Unrated>::new();

    for _ in 0..POP_SIZE {
        // Add a single link gene! This is required, otherwise we can't determine
        // correctly an InnovationRange.
        let genome = env.mutate_add_connection(&template_genome, &mut rng).unwrap();

        initial_pop.add_genome(Box::new(genome));
    }
    assert!(initial_pop.len() == POP_SIZE);

    let mut mater = Mater {
        p_crossover: Closed01(0.5),
        p_crossover_detail: ProbabilisticCrossover {
            prob_match_left: Closed01(0.5), /* NEAT always selects a random parent for matching genes */
            prob_disjoint_left: Closed01(0.9),
            prob_excess_left: Closed01(0.9),
            prob_disjoint_right: Closed01(0.15),
            prob_excess_right: Closed01(0.15),
        },
        mutate_weights: MutateMethodWeighting {
            w_modify_weight: 1,
            w_add_node: 1,
            w_add_connection: 1,
        },

        env: &mut env,
    };

    let compatibility = NetworkGenomeDistance {
        excess: 1.0,
        disjoint: 1.0,
        weight: 0.0,
    };

    let mut runner = Runner {
        pop_size: POP_SIZE,
        elite_percentage: Closed01(0.05),
        selection_percentage: Closed01(0.2),
        tournament_k: 3,
        compatibility_threshold: 1.0,
        compatibility: &compatibility,
        mate: &mut mater,
        fitness: &|genome| Fitness::new(fitness_evaluator.fitness(genome) as f64),
        _marker: PhantomData,
    };

    let (iter, new_pop) = runner.run(initial_pop,
                                     &|iter, pop| {
                                         iter >= 100 || pop.max_fitness().unwrap().get() > 0.99
                                     },
                                     &mut rng);

    let new_pop = new_pop.sort();

    println!("iter: {}", iter);
    println!("{:#?}", new_pop);
}
<|endoftext|>


<commit_before>
extern crate gltf;
extern crate three;

fn load_mesh(mesh: gltf::mesh::Mesh, factory: &mut three::Factory) -> three::Mesh {
    let primitive = mesh.primitives().nth(0).unwrap();
    let mut faces = vec![];
    match primitive.indices().unwrap() {
        gltf::mesh::Indices::U8(mut i) => {
            while let (Some(a), Some(b), Some(c)) = (i.next(), i.next(), i.next()) {
                faces.push([a as u32, b as u32, c as u32])
            }
        },
        gltf::mesh::Indices::U16(mut i) => {
            while let (Some(a), Some(b), Some(c)) = (i.next(), i.next(), i.next()) {
                faces.push([a as u32, b as u32, c as u32])
            }
        },
        gltf::mesh::Indices::U32(mut i) => {
            while let (Some(a), Some(b), Some(c)) = (i.next(), i.next(), i.next()) {
                faces.push([a, b, c]);
            }
        },
    };
    let vertices = primitive.positions().unwrap().map(|x| x.into()).collect();
    let normals = primitive.normals().unwrap().map(|x| x.into()).collect();
    let tangents = primitive.tangents().unwrap().map(|x| x.into()).collect();
    let mut tex_coords = vec![];
    match primitive.tex_coords(0).unwrap() {
        gltf::mesh::TexCoords::U8(iter) => {
            for x in iter {
                let y = [x[0] as f32 / 255.0, x[1] as f32 / -255.0];
                tex_coords.push(y.into());
            }
        },
        gltf::mesh::TexCoords::U16(iter) => {
            for x in iter {
                let y = [x[0] as f32 / 65535.0, x[1] as f32 / -65535.0];
                tex_coords.push(y.into());
            }
        },
        gltf::mesh::TexCoords::F32(iter) => {
            for x in iter {
                tex_coords.push([x[0], -x[1]].into());
            }
        },
    }
    println!("{:?}", tex_coords);
    let geometry = three::Geometry {
        base_shape: three::GeometryShape {
            vertices: vertices,
            normals: normals,
            tangents: tangents,
            tex_coords: tex_coords,
        },
        faces: faces,
        .. three::Geometry::empty()
    };
    let material = {
        let mat = primitive.material().unwrap();
        let pbr = mat.pbr_metallic_roughness().unwrap();
        let mut load = |texture: &gltf::texture::Texture| {
            let image = texture.source().data().flipv().to_rgba();
            let (width, height) = (image.width() as u16, image.height() as u16);
            factory.load_texture_from_memory(width, height, &image)
        };
        three::Material::MeshPbr {
            base_color_factor: pbr.base_color_factor(),
            metallic_roughness: [pbr.metallic_factor(), pbr.roughness_factor()],
            occlusion_strength: mat.occlusion_texture().map_or(1.0, |t| t.strength()),
            emissive_factor: mat.emissive_factor(),
            normal_scale: mat.normal_texture().map_or(1.0, |t| t.scale()),

            base_color_map: pbr.base_color_texture().map(|t| load(&t)),
            normal_map: mat.normal_texture().map(|t| load(&t)),
            emissive_map: mat.emissive_texture().map(|t| load(&t)),
            metallic_roughness_map: pbr.metallic_roughness_texture().map(|t| load(&t)),
            occlusion_map: mat.occlusion_texture().map(|t| load(&t)),
        }
    };
    factory.mesh(geometry, material)
}

fn import(path_str: &str, factory: &mut three::Factory) -> three::Mesh {
    let gltf = gltf::Import::from_path(path_str).sync().unwrap();
    let mesh = gltf.meshes().nth(0).unwrap();
    load_mesh(mesh, factory)
}

fn main() {
    let mut win = three::Window::new("Three-rs PBR example", "data/shaders").build();
    let mut cam = win.factory.perspective_camera(75.0, 0.01, 100.0);
    let mut yaw: f32 = 0.0;
    let mut distance: f32 = 0.2;
    cam.set_position([distance * yaw.cos(), 0.0, distance * yaw.sin()]);

    let mut light = win.factory.directional_light(0xFFFFFF, 7.0);
    light.look_at([1.0, 1.0, -1.0], [0.0, 0.0, 0.0], Some([0.0, 1.0, 0.0].into()));
    win.scene.add(&light);
    win.scene.background = three::Background::Color(0xC6F0FF);

    let path = std::env::args().nth(1).unwrap_or(format!("test_data/Avocado.gltf"));
    let mesh = import(&path, &mut win.factory);
    win.scene.add(&mesh);

    while win.update() && !three::KEY_ESCAPE.is_hit(&win.input) {
        if three::Button::Key(three::Key::Left).is_hit(&win.input) {
            yaw -= 0.1;
        }
        if three::Button::Key(three::Key::Right).is_hit(&win.input) {
            yaw += 0.1;
        }
        if three::Button::Key(three::Key::Up).is_hit(&win.input) {
            distance -= 0.1;
        }
        if three::Button::Key(three::Key::Down).is_hit(&win.input) {
            distance += 0.1;
        }
        let (x, y, z) = (yaw.sin(), 0.0, yaw.cos());
        cam.look_at(
            [distance * x, y, distance * z],
            [0.0, 0.0, 0.0],
            Some([0.0, 1.0, 0.0].into()),
        );
        win.render(&cam);
    }
}
<commit_msg>Render SciFiHelmet by default<commit_after>
extern crate gltf;
extern crate three;

fn load_mesh(mesh: gltf::mesh::Mesh, factory: &mut three::Factory) -> three::Mesh {
    let primitive = mesh.primitives().nth(0).unwrap();
    let mut faces = vec![];
    match primitive.indices().unwrap() {
        gltf::mesh::Indices::U8(mut i) => {
            while let (Some(a), Some(b), Some(c)) = (i.next(), i.next(), i.next()) {
                faces.push([a as u32, b as u32, c as u32])
            }
        },
        gltf::mesh::Indices::U16(mut i) => {
            while let (Some(a), Some(b), Some(c)) = (i.next(), i.next(), i.next()) {
                faces.push([a as u32, b as u32, c as u32])
            }
        },
        gltf::mesh::Indices::U32(mut i) => {
            while let (Some(a), Some(b), Some(c)) = (i.next(), i.next(), i.next()) {
                faces.push([a, b, c]);
            }
        },
    };
    let vertices = primitive.positions().unwrap().map(|x| x.into()).collect();
    let normals = primitive.normals().unwrap().map(|x| x.into()).collect();
    let tangents = primitive.tangents().unwrap().map(|x| x.into()).collect();
    let mut tex_coords = vec![];
    match primitive.tex_coords(0).unwrap() {
        gltf::mesh::TexCoords::U8(iter) => {
            for x in iter {
                let y = [(x[0] as f32).abs() / 255.0, (x[1] as f32).abs() / 255.0];
                tex_coords.push(y.into());
            }
        },
        gltf::mesh::TexCoords::U16(iter) => {
            for x in iter {
                let y = [(x[0] as f32).abs() / 65535.0, (x[1] as f32).abs() / 65535.0];
                tex_coords.push(y.into());
            }
        },
        gltf::mesh::TexCoords::F32(iter) => {
            for x in iter {
                let y = [x[0].abs(), x[1].abs()];
                tex_coords.push(y.into());
            }
        },
    }
    let geometry = three::Geometry {
        base_shape: three::GeometryShape {
            vertices: vertices,
            normals: normals,
            tangents: tangents,
            tex_coords: tex_coords,
        },
        faces: faces,
        .. three::Geometry::empty()
    };
    let material = {
        let mat = primitive.material().unwrap();
        let pbr = mat.pbr_metallic_roughness().unwrap();
        let mut load = |texture: &gltf::texture::Texture| {
            let image = texture.source().data().to_rgba();
            let (width, height) = (image.width() as u16, image.height() as u16);
            factory.load_texture_from_memory(width, height, &image)
        };
        three::Material::MeshPbr {
            base_color_factor: pbr.base_color_factor(),
            metallic_roughness: [pbr.metallic_factor(), pbr.roughness_factor()],
            occlusion_strength: mat.occlusion_texture().map_or(1.0, |t| t.strength()),
            emissive_factor: mat.emissive_factor(),
            normal_scale: mat.normal_texture().map_or(1.0, |t| t.scale()),

            base_color_map: pbr.base_color_texture().map(|t| load(&t)),
            normal_map: mat.normal_texture().map(|t| load(&t)),
            emissive_map: mat.emissive_texture().map(|t| load(&t)),
            metallic_roughness_map: pbr.metallic_roughness_texture().map(|t| load(&t)),
            occlusion_map: mat.occlusion_texture().map(|t| load(&t)),
        }
    };
    factory.mesh(geometry, material)
}

fn import(path_str: &str, factory: &mut three::Factory) -> three::Mesh {
    let gltf = gltf::Import::from_path(path_str).sync().unwrap();
    let mesh = gltf.meshes().nth(0).unwrap();
    load_mesh(mesh, factory)
}

fn main() {
    let mut win = three::Window::new("Three-rs PBR example", "data/shaders").build();
    let mut cam = win.factory.perspective_camera(75.0, 0.01, 100.0);
    let mut yaw: f32 = 0.8;
    let mut distance: f32 = 3.9;
    cam.set_position([distance * yaw.cos(), 0.0, distance * yaw.sin()]);

    let mut light = win.factory.directional_light(0xFFFFFF, 7.0);
    light.look_at([1.0, 1.0, 1.0], [0.0, 0.0, 0.0], Some([0.0, 1.0, 0.0].into()));
    win.scene.add(&light);
    win.scene.background = three::Background::Color(0xC6F0FF);

    let path = std::env::args().nth(1).unwrap_or(format!("test_data/Avocado.gltf"));
    let mesh = import(&path, &mut win.factory);
    win.scene.add(&mesh);

    while win.update() && !three::KEY_ESCAPE.is_hit(&win.input) {
        if three::Button::Key(three::Key::Left).is_hit(&win.input) {
            yaw -= 0.05;
        }
        if three::Button::Key(three::Key::Right).is_hit(&win.input) {
            yaw += 0.05;
        }
        if three::Button::Key(three::Key::Up).is_hit(&win.input) {
            distance -= 0.05;
        }
        if three::Button::Key(three::Key::Down).is_hit(&win.input) {
            distance += 0.05;
        }
        if three::Button::Key(three::Key::P).is_hit(&win.input) {
            println!("yaw: {}, distance: {}", yaw, distance);
        }
        let (x, y, z) = (yaw.sin(), 0.0, yaw.cos());
        cam.look_at(
            [distance * x, y, distance * z],
            [0.0, 0.0, 0.0],
            Some([0.0, 1.0, 0.0].into()),
        );
        win.render(&cam);
    }
}
<|endoftext|>


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

// GetLastError doesn't seem to work with stack switching
// xfail-test

#[cfg(target_os = "win32")]
extern "stdcall" mod kernel32 {
    fn SetLastError(err: uint);
    fn GetLastError() -> uint;
}

#[cfg(target_os = "win32")]
fn main() {
    let expected = 1234u;
    kernel32::SetLastError(expected);
    let actual = kernel32::GetLastError();
    log(error, actual);
    assert (expected == actual);
}

#[cfg(target_os = "macos")]
#[cfg(target_os = "linux")]
#[cfg(target_os = "freebsd")]
fn main() { }
<commit_msg>test: fix x86stdcall test, r=burningtree.<commit_after>// Copyright 2012 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.

// GetLastError doesn't seem to work with stack switching
// xfail-test

#[cfg(target_os = "win32")]
extern "stdcall" mod kernel32 {
    fn SetLastError(err: uint);
    fn GetLastError() -> uint;
}

#[cfg(target_os = "win32")]
fn main() {
    unsafe {
        let expected = 1234u;
        kernel32::SetLastError(expected);
        let actual = kernel32::GetLastError();
        log(error, actual);
        assert (expected == actual);
    }
}

#[cfg(target_os = "macos")]
#[cfg(target_os = "linux")]
#[cfg(target_os = "freebsd")]
fn main() { }
<|endoftext|>


<commit_before>use super::*;

pub(super) const PATTERN_FIRST: TokenSet = expressions::LITERAL_FIRST
    .union(paths::PATH_FIRST)
    .union(token_set![BOX_KW, REF_KW, MUT_KW, L_PAREN, L_BRACK, AMP, UNDERSCORE, MINUS, DOT]);

pub(crate) fn pattern(p: &mut Parser) {
    pattern_r(p, PAT_RECOVERY_SET);
}

/// Parses a pattern list separated by pipes `|`
pub(super) fn pattern_list(p: &mut Parser) {
    pattern_list_r(p, PAT_RECOVERY_SET)
}

/// Parses a pattern list separated by pipes `|`
/// using the given `recovery_set`
pub(super) fn pattern_list_r(p: &mut Parser, recovery_set: TokenSet) {
    p.eat(T![|]);
    pattern_r(p, recovery_set);

    while p.eat(T![|]) {
        pattern_r(p, recovery_set);
    }
}

pub(super) fn pattern_r(p: &mut Parser, recovery_set: TokenSet) {
    if let Some(lhs) = atom_pat(p, recovery_set) {
        // test range_pat
        // fn main() {
        //     match 92 {
        //         0 ... 100 => (),
        //         101 ..= 200 => (),
        //         200 .. 301=> (),
        //     }
        // }
        for &range_op in [T![...], T![..=], T![..]].iter() {
            if p.at(range_op) {
                let m = lhs.precede(p);
                p.bump(range_op);
                atom_pat(p, recovery_set);
                m.complete(p, RANGE_PAT);
                return;
            }
        }
        // test marco_pat
        // fn main() {
        //     let m!(x) = 0;
        // }
        if lhs.kind() == PATH_PAT && p.at(T![!]) {
            let m = lhs.precede(p);
            items::macro_call_after_excl(p);
            m.complete(p, MACRO_CALL);
        }
    }
}

const PAT_RECOVERY_SET: TokenSet =
    token_set![LET_KW, IF_KW, WHILE_KW, LOOP_KW, MATCH_KW, R_PAREN, COMMA];

fn atom_pat(p: &mut Parser, recovery_set: TokenSet) -> Option<CompletedMarker> {
    let m = match p.nth(0) {
        T![box] => box_pat(p),
        T![ref] | T![mut] => bind_pat(p, true),
        IDENT => match p.nth(1) {
            // Checks the token after an IDENT to see if a pattern is a path (Struct { .. }) or macro
            // (T![x]).
            T!['('] | T!['{'] | T![!] => path_pat(p),
            T![:] if p.nth_at(1, T![::]) => path_pat(p),
            _ => bind_pat(p, true),
        },

        _ if paths::is_use_path_start(p) => path_pat(p),
        _ if is_literal_pat_start(p) => literal_pat(p),

        T![.] if p.at(T![..]) => dot_dot_pat(p),
        T![_] => placeholder_pat(p),
        T![&] => ref_pat(p),
        T!['('] => tuple_pat(p),
        T!['['] => slice_pat(p),

        _ => {
            p.err_recover("expected pattern", recovery_set);
            return None;
        }
    };

    Some(m)
}

fn is_literal_pat_start(p: &Parser) -> bool {
    p.at(T![-]) && (p.nth(1) == INT_NUMBER || p.nth(1) == FLOAT_NUMBER)
        || p.at_ts(expressions::LITERAL_FIRST)
}

// test literal_pattern
// fn main() {
//     match () {
//         -1 => (),
//         92 => (),
//         'c' => (),
//         "hello" => (),
//     }
// }
fn literal_pat(p: &mut Parser) -> CompletedMarker {
    assert!(is_literal_pat_start(p));
    let m = p.start();
    if p.at(T![-]) {
        p.bump(T![-]);
    }
    expressions::literal(p);
    m.complete(p, LITERAL_PAT)
}

// test path_part
// fn foo() {
//     let foo::Bar = ();
//     let ::Bar = ();
//     let Bar { .. } = ();
//     let Bar(..) = ();
// }
fn path_pat(p: &mut Parser) -> CompletedMarker {
    assert!(paths::is_use_path_start(p));
    let m = p.start();
    paths::expr_path(p);
    let kind = match p.current() {
        T!['('] => {
            tuple_pat_fields(p);
            TUPLE_STRUCT_PAT
        }
        T!['{'] => {
            record_field_pat_list(p);
            RECORD_PAT
        }
        _ => PATH_PAT,
    };
    m.complete(p, kind)
}

// test tuple_pat_fields
// fn foo() {
//     let S() = ();
//     let S(_) = ();
//     let S(_,) = ();
//     let S(_, .. , x) = ();
// }
fn tuple_pat_fields(p: &mut Parser) {
    assert!(p.at(T!['(']));
    p.bump(T!['(']);
    pat_list(p, T![')']);
    p.expect(T![')']);
}

// test record_field_pat_list
// fn foo() {
//     let S {} = ();
//     let S { f, ref mut g } = ();
//     let S { h: _, ..} = ();
//     let S { h: _, } = ();
// }
fn record_field_pat_list(p: &mut Parser) {
    assert!(p.at(T!['{']));
    let m = p.start();
    p.bump(T!['{']);
    while !p.at(EOF) && !p.at(T!['}']) {
        match p.current() {
            // A trailing `..` is *not* treated as a DOT_DOT_PAT.
            T![.] if p.at(T![..]) => p.bump(T![..]),

            IDENT if p.nth(1) == T![:] => record_field_pat(p),
            INT_NUMBER if p.nth(1) == T![:] => record_field_pat(p),
            T!['{'] => error_block(p, "expected ident"),
            T![box] => {
                box_pat(p);
            }
            _ => {
                bind_pat(p, false);
            }
        }
        if !p.at(T!['}']) {
            p.expect(T![,]);
        }
    }
    p.expect(T!['}']);
    m.complete(p, RECORD_FIELD_PAT_LIST);
}

// test record_field_pat
// fn foo() {
//     let S { 0: 1 } = ();
//     let S { x: 1 } = ();
// }
fn record_field_pat(p: &mut Parser) {
    assert!(p.at(IDENT) || p.at(INT_NUMBER));
    assert!(p.nth(1) == T![:]);

    let m = p.start();

    if !p.eat(INT_NUMBER) {
        name(p)
    }

    p.bump_any();
    pattern(p);
    m.complete(p, RECORD_FIELD_PAT);
}

// test placeholder_pat
// fn main() { let _ = (); }
fn placeholder_pat(p: &mut Parser) -> CompletedMarker {
    assert!(p.at(T![_]));
    let m = p.start();
    p.bump(T![_]);
    m.complete(p, PLACEHOLDER_PAT)
}

// test dot_dot_pat
// fn main() {
//     let .. = ();
//     //
//     // Tuples
//     //
//     let (a, ..) = ();
//     let (a, ..,) = ();
//     let Tuple(a, ..) = ();
//     let Tuple(a, ..,) = ();
//     let (.., ..) = ();
//     let Tuple(.., ..) = ();
//     let (.., a, ..) = ();
//     let Tuple(.., a, ..) = ();
//     //
//     // Slices
//     //
//     let [..] = ();
//     let [head, ..] = ();
//     let [head, tail @ ..] = ();
//     let [head, .., cons] = ();
//     let [head, mid @ .., cons] = ();
//     let [head, .., .., cons] = ();
//     let [head, .., mid, tail @ ..] = ();
//     let [head, .., mid, .., cons] = ();
// }
fn dot_dot_pat(p: &mut Parser) -> CompletedMarker {
    assert!(p.at(T![..]));
    let m = p.start();
    p.bump(T![..]);
    m.complete(p, DOT_DOT_PAT)
}

// test ref_pat
// fn main() {
//     let &a = ();
//     let &mut b = ();
// }
fn ref_pat(p: &mut Parser) -> CompletedMarker {
    assert!(p.at(T![&]));
    let m = p.start();
    p.bump(T![&]);
    p.eat(T![mut]);
    pattern(p);
    m.complete(p, REF_PAT)
}

// test tuple_pat
// fn main() {
//     let (a, b, ..) = ();
// }
fn tuple_pat(p: &mut Parser) -> CompletedMarker {
    assert!(p.at(T!['(']));
    let m = p.start();
    tuple_pat_fields(p);
    m.complete(p, TUPLE_PAT)
}

// test slice_pat
// fn main() {
//     let [a, b, ..] = [];
// }
fn slice_pat(p: &mut Parser) -> CompletedMarker {
    assert!(p.at(T!['[']));
    let m = p.start();
    p.bump(T!['[']);
    pat_list(p, T![']']);
    p.expect(T![']']);
    m.complete(p, SLICE_PAT)
}

fn pat_list(p: &mut Parser, ket: SyntaxKind) {
    while !p.at(EOF) && !p.at(ket) {
        if !p.at_ts(PATTERN_FIRST) {
            p.error("expected a pattern");
            break;
        }

        pattern(p);
        if !p.at(ket) {
            p.expect(T![,]);
        }
    }
}

// test bind_pat
// fn main() {
//     let a = ();
//     let mut b = ();
//     let ref c = ();
//     let ref mut d = ();
//     let e @ _ = ();
//     let ref mut f @ g @ _ = ();
// }
fn bind_pat(p: &mut Parser, with_at: bool) -> CompletedMarker {
    let m = p.start();
    p.eat(T![ref]);
    p.eat(T![mut]);
    name(p);
    if with_at && p.eat(T![@]) {
        pattern(p);
    }
    m.complete(p, BIND_PAT)
}

// test box_pat
// fn main() {
//     let box i = ();
//     let box Outer { box i, j: box Inner(box &x) } = ();
//     let box ref mut i = ();
// }
fn box_pat(p: &mut Parser) -> CompletedMarker {
    assert!(p.at(T![box]));
    let m = p.start();
    p.bump(T![box]);
    pattern(p);
    m.complete(p, BOX_PAT)
}
<commit_msg>Simplify match arm<commit_after>use super::*;

pub(super) const PATTERN_FIRST: TokenSet = expressions::LITERAL_FIRST
    .union(paths::PATH_FIRST)
    .union(token_set![BOX_KW, REF_KW, MUT_KW, L_PAREN, L_BRACK, AMP, UNDERSCORE, MINUS, DOT]);

pub(crate) fn pattern(p: &mut Parser) {
    pattern_r(p, PAT_RECOVERY_SET);
}

/// Parses a pattern list separated by pipes `|`
pub(super) fn pattern_list(p: &mut Parser) {
    pattern_list_r(p, PAT_RECOVERY_SET)
}

/// Parses a pattern list separated by pipes `|`
/// using the given `recovery_set`
pub(super) fn pattern_list_r(p: &mut Parser, recovery_set: TokenSet) {
    p.eat(T![|]);
    pattern_r(p, recovery_set);

    while p.eat(T![|]) {
        pattern_r(p, recovery_set);
    }
}

pub(super) fn pattern_r(p: &mut Parser, recovery_set: TokenSet) {
    if let Some(lhs) = atom_pat(p, recovery_set) {
        // test range_pat
        // fn main() {
        //     match 92 {
        //         0 ... 100 => (),
        //         101 ..= 200 => (),
        //         200 .. 301=> (),
        //     }
        // }
        for &range_op in [T![...], T![..=], T![..]].iter() {
            if p.at(range_op) {
                let m = lhs.precede(p);
                p.bump(range_op);
                atom_pat(p, recovery_set);
                m.complete(p, RANGE_PAT);
                return;
            }
        }
        // test marco_pat
        // fn main() {
        //     let m!(x) = 0;
        // }
        if lhs.kind() == PATH_PAT && p.at(T![!]) {
            let m = lhs.precede(p);
            items::macro_call_after_excl(p);
            m.complete(p, MACRO_CALL);
        }
    }
}

const PAT_RECOVERY_SET: TokenSet =
    token_set![LET_KW, IF_KW, WHILE_KW, LOOP_KW, MATCH_KW, R_PAREN, COMMA];

fn atom_pat(p: &mut Parser, recovery_set: TokenSet) -> Option<CompletedMarker> {
    let m = match p.nth(0) {
        T![box] => box_pat(p),
        T![ref] | T![mut] => bind_pat(p, true),
        IDENT => match p.nth(1) {
            // Checks the token after an IDENT to see if a pattern is a path (Struct { .. }) or macro
            // (T![x]).
            T!['('] | T!['{'] | T![!] => path_pat(p),
            T![:] if p.nth_at(1, T![::]) => path_pat(p),
            _ => bind_pat(p, true),
        },

        _ if paths::is_use_path_start(p) => path_pat(p),
        _ if is_literal_pat_start(p) => literal_pat(p),

        T![.] if p.at(T![..]) => dot_dot_pat(p),
        T![_] => placeholder_pat(p),
        T![&] => ref_pat(p),
        T!['('] => tuple_pat(p),
        T!['['] => slice_pat(p),

        _ => {
            p.err_recover("expected pattern", recovery_set);
            return None;
        }
    };

    Some(m)
}

fn is_literal_pat_start(p: &Parser) -> bool {
    p.at(T![-]) && (p.nth(1) == INT_NUMBER || p.nth(1) == FLOAT_NUMBER)
        || p.at_ts(expressions::LITERAL_FIRST)
}

// test literal_pattern
// fn main() {
//     match () {
//         -1 => (),
//         92 => (),
//         'c' => (),
//         "hello" => (),
//     }
// }
fn literal_pat(p: &mut Parser) -> CompletedMarker {
    assert!(is_literal_pat_start(p));
    let m = p.start();
    if p.at(T![-]) {
        p.bump(T![-]);
    }
    expressions::literal(p);
    m.complete(p, LITERAL_PAT)
}

// test path_part
// fn foo() {
//     let foo::Bar = ();
//     let ::Bar = ();
//     let Bar { .. } = ();
//     let Bar(..) = ();
// }
fn path_pat(p: &mut Parser) -> CompletedMarker {
    assert!(paths::is_use_path_start(p));
    let m = p.start();
    paths::expr_path(p);
    let kind = match p.current() {
        T!['('] => {
            tuple_pat_fields(p);
            TUPLE_STRUCT_PAT
        }
        T!['{'] => {
            record_field_pat_list(p);
            RECORD_PAT
        }
        _ => PATH_PAT,
    };
    m.complete(p, kind)
}

// test tuple_pat_fields
// fn foo() {
//     let S() = ();
//     let S(_) = ();
//     let S(_,) = ();
//     let S(_, .. , x) = ();
// }
fn tuple_pat_fields(p: &mut Parser) {
    assert!(p.at(T!['(']));
    p.bump(T!['(']);
    pat_list(p, T![')']);
    p.expect(T![')']);
}

// test record_field_pat_list
// fn foo() {
//     let S {} = ();
//     let S { f, ref mut g } = ();
//     let S { h: _, ..} = ();
//     let S { h: _, } = ();
// }
fn record_field_pat_list(p: &mut Parser) {
    assert!(p.at(T!['{']));
    let m = p.start();
    p.bump(T!['{']);
    while !p.at(EOF) && !p.at(T!['}']) {
        match p.current() {
            // A trailing `..` is *not* treated as a DOT_DOT_PAT.
            T![.] if p.at(T![..]) => p.bump(T![..]),

            IDENT | INT_NUMBER if p.nth(1) == T![:] => record_field_pat(p),
            T!['{'] => error_block(p, "expected ident"),
            T![box] => {
                box_pat(p);
            }
            _ => {
                bind_pat(p, false);
            }
        }
        if !p.at(T!['}']) {
            p.expect(T![,]);
        }
    }
    p.expect(T!['}']);
    m.complete(p, RECORD_FIELD_PAT_LIST);
}

// test record_field_pat
// fn foo() {
//     let S { 0: 1 } = ();
//     let S { x: 1 } = ();
// }
fn record_field_pat(p: &mut Parser) {
    assert!(p.at(IDENT) || p.at(INT_NUMBER));
    assert!(p.nth(1) == T![:]);

    let m = p.start();

    if !p.eat(INT_NUMBER) {
        name(p)
    }

    p.bump_any();
    pattern(p);
    m.complete(p, RECORD_FIELD_PAT);
}

// test placeholder_pat
// fn main() { let _ = (); }
fn placeholder_pat(p: &mut Parser) -> CompletedMarker {
    assert!(p.at(T![_]));
    let m = p.start();
    p.bump(T![_]);
    m.complete(p, PLACEHOLDER_PAT)
}

// test dot_dot_pat
// fn main() {
//     let .. = ();
//     //
//     // Tuples
//     //
//     let (a, ..) = ();
//     let (a, ..,) = ();
//     let Tuple(a, ..) = ();
//     let Tuple(a, ..,) = ();
//     let (.., ..) = ();
//     let Tuple(.., ..) = ();
//     let (.., a, ..) = ();
//     let Tuple(.., a, ..) = ();
//     //
//     // Slices
//     //
//     let [..] = ();
//     let [head, ..] = ();
//     let [head, tail @ ..] = ();
//     let [head, .., cons] = ();
//     let [head, mid @ .., cons] = ();
//     let [head, .., .., cons] = ();
//     let [head, .., mid, tail @ ..] = ();
//     let [head, .., mid, .., cons] = ();
// }
fn dot_dot_pat(p: &mut Parser) -> CompletedMarker {
    assert!(p.at(T![..]));
    let m = p.start();
    p.bump(T![..]);
    m.complete(p, DOT_DOT_PAT)
}

// test ref_pat
// fn main() {
//     let &a = ();
//     let &mut b = ();
// }
fn ref_pat(p: &mut Parser) -> CompletedMarker {
    assert!(p.at(T![&]));
    let m = p.start();
    p.bump(T![&]);
    p.eat(T![mut]);
    pattern(p);
    m.complete(p, REF_PAT)
}

// test tuple_pat
// fn main() {
//     let (a, b, ..) = ();
// }
fn tuple_pat(p: &mut Parser) -> CompletedMarker {
    assert!(p.at(T!['(']));
    let m = p.start();
    tuple_pat_fields(p);
    m.complete(p, TUPLE_PAT)
}

// test slice_pat
// fn main() {
//     let [a, b, ..] = [];
// }
fn slice_pat(p: &mut Parser) -> CompletedMarker {
    assert!(p.at(T!['[']));
    let m = p.start();
    p.bump(T!['[']);
    pat_list(p, T![']']);
    p.expect(T![']']);
    m.complete(p, SLICE_PAT)
}

fn pat_list(p: &mut Parser, ket: SyntaxKind) {
    while !p.at(EOF) && !p.at(ket) {
        if !p.at_ts(PATTERN_FIRST) {
            p.error("expected a pattern");
            break;
        }

        pattern(p);
        if !p.at(ket) {
            p.expect(T![,]);
        }
    }
}

// test bind_pat
// fn main() {
//     let a = ();
//     let mut b = ();
//     let ref c = ();
//     let ref mut d = ();
//     let e @ _ = ();
//     let ref mut f @ g @ _ = ();
// }
fn bind_pat(p: &mut Parser, with_at: bool) -> CompletedMarker {
    let m = p.start();
    p.eat(T![ref]);
    p.eat(T![mut]);
    name(p);
    if with_at && p.eat(T![@]) {
        pattern(p);
    }
    m.complete(p, BIND_PAT)
}

// test box_pat
// fn main() {
//     let box i = ();
//     let box Outer { box i, j: box Inner(box &x) } = ();
//     let box ref mut i = ();
// }
fn box_pat(p: &mut Parser) -> CompletedMarker {
    assert!(p.at(T![box]));
    let m = p.start();
    p.bump(T![box]);
    pattern(p);
    m.complete(p, BOX_PAT)
}
<|endoftext|>


<commit_before>//! This module implements minimal run-time feature detection for x86.
//!
//! The features are detected using the `detect_features` function below.
//! This function uses the CPUID instruction to read the feature flags from the
//! CPU and encodes them in an `usize` where each bit position represents
//! whether a feature is available (bit is set) or unavaiable (bit is cleared).
//!
//! The enum `Feature` is used to map bit positions to feature names, and the
//! the `__crate::detect::check_for!` macro is used to map string literals (e.g.,
//! "avx") to these bit positions (e.g., `Feature::avx`).
//!
//! The run-time feature detection is performed by the
//! `__crate::detect::check_for(Feature) -> bool` function. On its first call,
//! this functions queries the CPU for the available features and stores them
//! in a global `AtomicUsize` variable. The query is performed by just checking
//! whether the feature bit in this global variable is set or cleared.

features! {
    @TARGET: x86;
    @MACRO_NAME: is_x86_feature_detected;
    @MACRO_ATTRS:
    /// A macro to test at *runtime* whether a CPU feature is available on
    /// x86/x86-64 platforms.
    ///
    /// This macro is provided in the standard library and will detect at runtime
    /// whether the specified CPU feature is detected. This does **not** resolve at
    /// compile time unless the specified feature is already enabled for the entire
    /// crate. Runtime detection currently relies mostly on the `cpuid` instruction.
    ///
    /// This macro only takes one argument which is a string literal of the feature
    /// being tested for. The feature names supported are the lowercase versions of
    /// the ones defined by Intel in [their documentation][docs].
    ///
    /// ## Supported arguments
    ///
    /// This macro supports the same names that `#[target_feature]` supports. Unlike
    /// `#[target_feature]`, however, this macro does not support names separated
    /// with a comma. Instead testing for multiple features must be done through
    /// separate macro invocations for now.
    ///
    /// Supported arguments are:
    ///
    /// * `"aes"`
    /// * `"pclmulqdq"`
    /// * `"rdrand"`
    /// * `"rdseed"`
    /// * `"tsc"`
    /// * `"mmx"`
    /// * `"sse"`
    /// * `"sse2"`
    /// * `"sse3"`
    /// * `"ssse3"`
    /// * `"sse4.1"`
    /// * `"sse4.2"`
    /// * `"sse4a"`
    /// * `"sha"`
    /// * `"avx"`
    /// * `"avx2"`
    /// * `"avx512f"`
    /// * `"avx512cd"`
    /// * `"avx512er"`
    /// * `"avx512pf"`
    /// * `"avx512bw"`
    /// * `"avx512dq"`
    /// * `"avx512vl"`
    /// * `"avx512ifma"`
    /// * `"avx512vbmi"`
    /// * `"avx512vpopcntdq"`
    /// * `"avx512vbmi2"`
    /// * `"avx512gfni"`
    /// * `"avx512vaes"`
    /// * `"avx512vpclmulqdq"`
    /// * `"avx512vnni"`
    /// * `"avx512bitalg"`
    /// * `"avx512bf16"`
    /// * `"avx512vp2intersect"`
    /// * `"f16c"`
    /// * `"fma"`
    /// * `"bmi1"`
    /// * `"bmi2"`
    /// * `"abm"`
    /// * `"lzcnt"`
    /// * `"tbm"`
    /// * `"popcnt"`
    /// * `"fxsr"`
    /// * `"xsave"`
    /// * `"xsaveopt"`
    /// * `"xsaves"`
    /// * `"xsavec"`
    /// * `"cmpxchg16b"`
    /// * `"adx"`
    /// * `"rtm"`
    ///
    /// [docs]: https://software.intel.com/sites/landingpage/IntrinsicsGuide
    #[stable(feature = "simd_x86", since = "1.27.0")]
    @BIND_FEATURE_NAME: "abm"; "lzcnt"; // abm is a synonym for lzcnt
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] aes: "aes";
    /// AES (Advanced Encryption Standard New Instructions AES-NI)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] pclmulqdq: "pclmulqdq";
    /// CLMUL (Carry-less Multiplication)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] rdrand: "rdrand";
    /// RDRAND
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] rdseed: "rdseed";
    /// RDSEED
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] tsc: "tsc";
    /// TSC (Time Stamp Counter)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] mmx: "mmx";
    /// MMX (MultiMedia eXtensions)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] sse: "sse";
    /// SSE (Streaming SIMD Extensions)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] sse2: "sse2";
    /// SSE2 (Streaming SIMD Extensions 2)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] sse3: "sse3";
    /// SSE3 (Streaming SIMD Extensions 3)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] ssse3: "ssse3";
    /// SSSE3 (Supplemental Streaming SIMD Extensions 3)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] sse4_1: "sse4.1";
    /// SSE4.1 (Streaming SIMD Extensions 4.1)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] sse4_2: "sse4.2";
    /// SSE4.2 (Streaming SIMD Extensions 4.2)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] sse4a: "sse4a";
    /// SSE4a (Streaming SIMD Extensions 4a)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] sha: "sha";
    /// SHA
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] avx: "avx";
    /// AVX (Advanced Vector Extensions)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] avx2: "avx2";
    /// AVX2 (Advanced Vector Extensions 2)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] avx512f: "avx512f" ;
    /// AVX-512 F (Foundation)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] avx512cd: "avx512cd" ;
    /// AVX-512 CD (Conflict Detection Instructions)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] avx512er: "avx512er";
    /// AVX-512 ER (Expo nential and Reciprocal Instructions)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] avx512pf: "avx512pf";
    /// AVX-512 PF (Prefetch Instructions)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] avx512bw: "avx512bw";
    /// AVX-512 BW (Byte and Word Instructions)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] avx512dq: "avx512dq";
    /// AVX-512 DQ (Doubleword and Quadword)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] avx512vl: "avx512vl";
    /// AVX-512 VL (Vector Length Extensions)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] avx512ifma: "avx512ifma";
    /// AVX-512 IFMA (Integer Fused Multiply Add)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] avx512vbmi: "avx512vbmi";
    /// AVX-512 VBMI (Vector Byte Manipulation Instructions)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] avx512vpopcntdq: "avx512vpopcntdq";
    /// AVX-512 VPOPCNTDQ (Vector Population Count Doubleword and
    /// Quadword)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] avx512vbmi2: "avx512vbmi2";
    /// AVX-512 VBMI2 (Additional byte, word, dword and qword capabilities)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] avx512gfni: "avx512gfni";
    /// AVX-512 GFNI (Galois Field New Instruction)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] avx512vaes: "avx512vaes";
    /// AVX-512 VAES (Vector AES instruction)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] avx512vpclmulqdq: "avx512vpclmulqdq";
    /// AVX-512 VPCLMULQDQ (Vector PCLMULQDQ instructions)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] avx512vnni: "avx512vnni";
    /// AVX-512 VNNI (Vector Neural Network Instructions)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] avx512bitalg: "avx512bitalg";
    /// AVX-512 BITALG (Support for VPOPCNT[B,W] and VPSHUFBITQMB)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] avx512bf16: "avx512bf16";
    /// AVX-512 BF16 (BFLOAT16 instructions)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] avx512vp2intersect: "avx512vp2intersect";
    /// AVX-512 P2INTERSECT
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] f16c: "f16c";
    /// F16C (Conversions between IEEE-754 `binary16` and `binary32` formats)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] fma: "fma";
    /// FMA (Fused Multiply Add)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] bmi1: "bmi1" ;
    /// BMI1 (Bit Manipulation Instructions 1)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] bmi2: "bmi2" ;
    /// BMI2 (Bit Manipulation Instructions 2)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] lzcnt: "lzcnt";
    /// ABM (Advanced Bit Manipulation) / LZCNT (Leading Zero Count)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] tbm: "tbm";
    /// TBM (Trailing Bit Manipulation)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] popcnt: "popcnt";
    /// POPCNT (Population Count)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] fxsr: "fxsr";
    /// FXSR (Floating-point context fast save and restor)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] xsave: "xsave";
    /// XSAVE (Save Processor Extended States)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] xsaveopt: "xsaveopt";
    /// XSAVEOPT (Save Processor Extended States Optimized)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] xsaves: "xsaves";
    /// XSAVES (Save Processor Extended States Supervisor)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] xsavec: "xsavec";
    /// XSAVEC (Save Processor Extended States Compacted)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] cmpxchg16b: "cmpxchg16b";
    /// CMPXCH16B (16-byte compare-and-swap instruction)
    @FEATURE: #[stable(feature = "simd_x86_adx", since = "1.33.0")] adx: "adx";
    /// ADX, Intel ADX (Multi-Precision Add-Carry Instruction Extensions)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] rtm: "rtm";
    /// RTM, Intel (Restricted Transactional Memory)
}
<commit_msg>Fix false rustdoc broken_intra_link detection (#984)<commit_after>//! This module implements minimal run-time feature detection for x86.
//!
//! The features are detected using the `detect_features` function below.
//! This function uses the CPUID instruction to read the feature flags from the
//! CPU and encodes them in an `usize` where each bit position represents
//! whether a feature is available (bit is set) or unavaiable (bit is cleared).
//!
//! The enum `Feature` is used to map bit positions to feature names, and the
//! the `__crate::detect::check_for!` macro is used to map string literals (e.g.,
//! "avx") to these bit positions (e.g., `Feature::avx`).
//!
//! The run-time feature detection is performed by the
//! `__crate::detect::check_for(Feature) -> bool` function. On its first call,
//! this functions queries the CPU for the available features and stores them
//! in a global `AtomicUsize` variable. The query is performed by just checking
//! whether the feature bit in this global variable is set or cleared.

features! {
    @TARGET: x86;
    @MACRO_NAME: is_x86_feature_detected;
    @MACRO_ATTRS:
    /// A macro to test at *runtime* whether a CPU feature is available on
    /// x86/x86-64 platforms.
    ///
    /// This macro is provided in the standard library and will detect at runtime
    /// whether the specified CPU feature is detected. This does **not** resolve at
    /// compile time unless the specified feature is already enabled for the entire
    /// crate. Runtime detection currently relies mostly on the `cpuid` instruction.
    ///
    /// This macro only takes one argument which is a string literal of the feature
    /// being tested for. The feature names supported are the lowercase versions of
    /// the ones defined by Intel in [their documentation][docs].
    ///
    /// ## Supported arguments
    ///
    /// This macro supports the same names that `#[target_feature]` supports. Unlike
    /// `#[target_feature]`, however, this macro does not support names separated
    /// with a comma. Instead testing for multiple features must be done through
    /// separate macro invocations for now.
    ///
    /// Supported arguments are:
    ///
    /// * `"aes"`
    /// * `"pclmulqdq"`
    /// * `"rdrand"`
    /// * `"rdseed"`
    /// * `"tsc"`
    /// * `"mmx"`
    /// * `"sse"`
    /// * `"sse2"`
    /// * `"sse3"`
    /// * `"ssse3"`
    /// * `"sse4.1"`
    /// * `"sse4.2"`
    /// * `"sse4a"`
    /// * `"sha"`
    /// * `"avx"`
    /// * `"avx2"`
    /// * `"avx512f"`
    /// * `"avx512cd"`
    /// * `"avx512er"`
    /// * `"avx512pf"`
    /// * `"avx512bw"`
    /// * `"avx512dq"`
    /// * `"avx512vl"`
    /// * `"avx512ifma"`
    /// * `"avx512vbmi"`
    /// * `"avx512vpopcntdq"`
    /// * `"avx512vbmi2"`
    /// * `"avx512gfni"`
    /// * `"avx512vaes"`
    /// * `"avx512vpclmulqdq"`
    /// * `"avx512vnni"`
    /// * `"avx512bitalg"`
    /// * `"avx512bf16"`
    /// * `"avx512vp2intersect"`
    /// * `"f16c"`
    /// * `"fma"`
    /// * `"bmi1"`
    /// * `"bmi2"`
    /// * `"abm"`
    /// * `"lzcnt"`
    /// * `"tbm"`
    /// * `"popcnt"`
    /// * `"fxsr"`
    /// * `"xsave"`
    /// * `"xsaveopt"`
    /// * `"xsaves"`
    /// * `"xsavec"`
    /// * `"cmpxchg16b"`
    /// * `"adx"`
    /// * `"rtm"`
    ///
    /// [docs]: https://software.intel.com/sites/landingpage/IntrinsicsGuide
    #[stable(feature = "simd_x86", since = "1.27.0")]
    @BIND_FEATURE_NAME: "abm"; "lzcnt"; // abm is a synonym for lzcnt
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] aes: "aes";
    /// AES (Advanced Encryption Standard New Instructions AES-NI)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] pclmulqdq: "pclmulqdq";
    /// CLMUL (Carry-less Multiplication)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] rdrand: "rdrand";
    /// RDRAND
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] rdseed: "rdseed";
    /// RDSEED
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] tsc: "tsc";
    /// TSC (Time Stamp Counter)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] mmx: "mmx";
    /// MMX (MultiMedia eXtensions)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] sse: "sse";
    /// SSE (Streaming SIMD Extensions)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] sse2: "sse2";
    /// SSE2 (Streaming SIMD Extensions 2)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] sse3: "sse3";
    /// SSE3 (Streaming SIMD Extensions 3)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] ssse3: "ssse3";
    /// SSSE3 (Supplemental Streaming SIMD Extensions 3)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] sse4_1: "sse4.1";
    /// SSE4.1 (Streaming SIMD Extensions 4.1)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] sse4_2: "sse4.2";
    /// SSE4.2 (Streaming SIMD Extensions 4.2)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] sse4a: "sse4a";
    /// SSE4a (Streaming SIMD Extensions 4a)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] sha: "sha";
    /// SHA
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] avx: "avx";
    /// AVX (Advanced Vector Extensions)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] avx2: "avx2";
    /// AVX2 (Advanced Vector Extensions 2)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] avx512f: "avx512f" ;
    /// AVX-512 F (Foundation)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] avx512cd: "avx512cd" ;
    /// AVX-512 CD (Conflict Detection Instructions)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] avx512er: "avx512er";
    /// AVX-512 ER (Expo nential and Reciprocal Instructions)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] avx512pf: "avx512pf";
    /// AVX-512 PF (Prefetch Instructions)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] avx512bw: "avx512bw";
    /// AVX-512 BW (Byte and Word Instructions)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] avx512dq: "avx512dq";
    /// AVX-512 DQ (Doubleword and Quadword)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] avx512vl: "avx512vl";
    /// AVX-512 VL (Vector Length Extensions)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] avx512ifma: "avx512ifma";
    /// AVX-512 IFMA (Integer Fused Multiply Add)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] avx512vbmi: "avx512vbmi";
    /// AVX-512 VBMI (Vector Byte Manipulation Instructions)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] avx512vpopcntdq: "avx512vpopcntdq";
    /// AVX-512 VPOPCNTDQ (Vector Population Count Doubleword and
    /// Quadword)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] avx512vbmi2: "avx512vbmi2";
    /// AVX-512 VBMI2 (Additional byte, word, dword and qword capabilities)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] avx512gfni: "avx512gfni";
    /// AVX-512 GFNI (Galois Field New Instruction)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] avx512vaes: "avx512vaes";
    /// AVX-512 VAES (Vector AES instruction)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] avx512vpclmulqdq: "avx512vpclmulqdq";
    /// AVX-512 VPCLMULQDQ (Vector PCLMULQDQ instructions)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] avx512vnni: "avx512vnni";
    /// AVX-512 VNNI (Vector Neural Network Instructions)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] avx512bitalg: "avx512bitalg";
    /// AVX-512 BITALG (Support for VPOPCNT\[B,W\] and VPSHUFBITQMB)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] avx512bf16: "avx512bf16";
    /// AVX-512 BF16 (BFLOAT16 instructions)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] avx512vp2intersect: "avx512vp2intersect";
    /// AVX-512 P2INTERSECT
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] f16c: "f16c";
    /// F16C (Conversions between IEEE-754 `binary16` and `binary32` formats)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] fma: "fma";
    /// FMA (Fused Multiply Add)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] bmi1: "bmi1" ;
    /// BMI1 (Bit Manipulation Instructions 1)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] bmi2: "bmi2" ;
    /// BMI2 (Bit Manipulation Instructions 2)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] lzcnt: "lzcnt";
    /// ABM (Advanced Bit Manipulation) / LZCNT (Leading Zero Count)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] tbm: "tbm";
    /// TBM (Trailing Bit Manipulation)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] popcnt: "popcnt";
    /// POPCNT (Population Count)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] fxsr: "fxsr";
    /// FXSR (Floating-point context fast save and restor)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] xsave: "xsave";
    /// XSAVE (Save Processor Extended States)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] xsaveopt: "xsaveopt";
    /// XSAVEOPT (Save Processor Extended States Optimized)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] xsaves: "xsaves";
    /// XSAVES (Save Processor Extended States Supervisor)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] xsavec: "xsavec";
    /// XSAVEC (Save Processor Extended States Compacted)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] cmpxchg16b: "cmpxchg16b";
    /// CMPXCH16B (16-byte compare-and-swap instruction)
    @FEATURE: #[stable(feature = "simd_x86_adx", since = "1.33.0")] adx: "adx";
    /// ADX, Intel ADX (Multi-Precision Add-Carry Instruction Extensions)
    @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] rtm: "rtm";
    /// RTM, Intel (Restricted Transactional Memory)
}
<|endoftext|>