<commit_before>//! Waking mechanism for threads blocked on channel operations.

use std::sync::atomic::{AtomicBool, Ordering};
use std::thread::{self, ThreadId};

use crate::context::Context;
use crate::select::{Operation, Selected};
use crate::utils::Spinlock;

/// Represents a thread blocked on a specific channel operation.
pub(crate) struct Entry {
    /// The operation.
    pub(crate) oper: Operation,

    /// Optional packet.
    pub(crate) packet: usize,

    /// Context associated with the thread owning this operation.
    pub(crate) cx: Context,
}

/// A queue of threads blocked on channel operations.
///
/// This data structure is used by threads to register blocking operations and get woken up once
/// an operation becomes ready.
pub(crate) struct Waker {
    /// A list of select operations.
    selectors: Vec<Entry>,

    /// A list of operations waiting to be ready.
    observers: Vec<Entry>,
}

impl Waker {
    /// Creates a new `Waker`.
    #[inline]
    pub(crate) fn new() -> Self {
        Waker {
            selectors: Vec::new(),
            observers: Vec::new(),
        }
    }

    /// Registers a select operation.
    #[inline]
    pub(crate) fn register(&mut self, oper: Operation, cx: &Context) {
        self.register_with_packet(oper, 0, cx);
    }

    /// Registers a select operation and a packet.
    #[inline]
    pub(crate) fn register_with_packet(&mut self, oper: Operation, packet: usize, cx: &Context) {
        self.selectors.push(Entry {
            oper,
            packet,
            cx: cx.clone(),
        });
    }

    /// Unregisters a select operation.
    #[inline]
    pub(crate) fn unregister(&mut self, oper: Operation) -> Option<Entry> {
        if let Some((i, _)) = self
            .selectors
            .iter()
            .enumerate()
            .find(|&(_, entry)| entry.oper == oper)
        {
            let entry = self.selectors.remove(i);
            Some(entry)
        } else {
            None
        }
    }

    /// Attempts to find another thread's entry, select the operation, and wake it up.
    #[inline]
    pub(crate) fn try_select(&mut self) -> Option<Entry> {
        let mut entry = None;

        if !self.selectors.is_empty() {
            let thread_id = current_thread_id();

            for i in 0..self.selectors.len() {
                // Does the entry belong to a different thread?
                if self.selectors[i].cx.thread_id() != thread_id {
                    // Try selecting this operation.
                    let sel = Selected::Operation(self.selectors[i].oper);
                    let res = self.selectors[i].cx.try_select(sel);

                    if res.is_ok() {
                        // Provide the packet.
                        self.selectors[i].cx.store_packet(self.selectors[i].packet);
                        // Wake the thread up.
                        self.selectors[i].cx.unpark();

                        // Remove the entry from the queue to keep it clean and improve
                        // performance.
                        entry = Some(self.selectors.remove(i));
                        break;
                    }
                }
            }
        }

        entry
    }

    /// Returns `true` if there is an entry which can be selected by the current thread.
    #[inline]
    pub(crate) fn can_select(&self) -> bool {
        if self.selectors.is_empty() {
            false
        } else {
            let thread_id = current_thread_id();

            self.selectors.iter().any(|entry| {
                entry.cx.thread_id() != thread_id && entry.cx.selected() == Selected::Waiting
            })
        }
    }

    /// Registers an operation waiting to be ready.
    #[inline]
    pub(crate) fn watch(&mut self, oper: Operation, cx: &Context) {
        self.observers.push(Entry {
            oper,
            packet: 0,
            cx: cx.clone(),
        });
    }

    /// Unregisters an operation waiting to be ready.
    #[inline]
    pub(crate) fn unwatch(&mut self, oper: Operation) {
        self.observers.retain(|e| e.oper != oper);
    }

    /// Notifies all operations waiting to be ready.
    #[inline]
    pub(crate) fn notify(&mut self) {
        for entry in self.observers.drain(..) {
            if entry.cx.try_select(Selected::Operation(entry.oper)).is_ok() {
                entry.cx.unpark();
            }
        }
    }

    /// Notifies all registered operations that the channel is disconnected.
    #[inline]
    pub(crate) fn disconnect(&mut self) {
        for entry in self.selectors.iter() {
            if entry.cx.try_select(Selected::Disconnected).is_ok() {
                // Wake the thread up.
                //
                // Here we don't remove the entry from the queue. Registered threads must
                // unregister from the waker by themselves. They might also want to recover the
                // packet value and destroy it, if necessary.
                entry.cx.unpark();
            }
        }

        self.notify();
    }
}

impl Drop for Waker {
    #[inline]
    fn drop(&mut self) {
        debug_assert_eq!(self.selectors.len(), 0);
        debug_assert_eq!(self.observers.len(), 0);
    }
}

/// A waker that can be shared among threads without locking.
///
/// This is a simple wrapper around `Waker` that internally uses a mutex for synchronization.
pub(crate) struct SyncWaker {
    /// The inner `Waker`.
    inner: Spinlock<Waker>,

    /// `true` if the waker is empty.
    is_empty: AtomicBool,
}

impl SyncWaker {
    /// Creates a new `SyncWaker`.
    #[inline]
    pub(crate) fn new() -> Self {
        SyncWaker {
            inner: Spinlock::new(Waker::new()),
            is_empty: AtomicBool::new(true),
        }
    }

    /// Registers the current thread with an operation.
    #[inline]
    pub(crate) fn register(&self, oper: Operation, cx: &Context) {
        let mut inner = self.inner.lock();
        inner.register(oper, cx);
        self.is_empty.store(
            inner.selectors.is_empty() && inner.observers.is_empty(),
            Ordering::SeqCst,
        );
    }

    /// Unregisters an operation previously registered by the current thread.
    #[inline]
    pub(crate) fn unregister(&self, oper: Operation) -> Option<Entry> {
        let mut inner = self.inner.lock();
        let entry = inner.unregister(oper);
        self.is_empty.store(
            inner.selectors.is_empty() && inner.observers.is_empty(),
            Ordering::SeqCst,
        );
        entry
    }

    /// Attempts to find one thread (not the current one), select its operation, and wake it up.
    #[inline]
    pub(crate) fn notify(&self) {
        if !self.is_empty.load(Ordering::SeqCst) {
            let mut inner = self.inner.lock();
            if !self.is_empty.load(Ordering::SeqCst) {
                inner.try_select();
                inner.notify();
                self.is_empty.store(
                    inner.selectors.is_empty() && inner.observers.is_empty(),
                    Ordering::SeqCst,
                );
            }
        }
    }

    /// Registers an operation waiting to be ready.
    #[inline]
    pub(crate) fn watch(&self, oper: Operation, cx: &Context) {
        let mut inner = self.inner.lock();
        inner.watch(oper, cx);
        self.is_empty.store(
            inner.selectors.is_empty() && inner.observers.is_empty(),
            Ordering::SeqCst,
        );
    }

    /// Unregisters an operation waiting to be ready.
    #[inline]
    pub(crate) fn unwatch(&self, oper: Operation) {
        let mut inner = self.inner.lock();
        inner.unwatch(oper);
        self.is_empty.store(
            inner.selectors.is_empty() && inner.observers.is_empty(),
            Ordering::SeqCst,
        );
    }

    /// Notifies all threads that the channel is disconnected.
    #[inline]
    pub(crate) fn disconnect(&self) {
        let mut inner = self.inner.lock();
        inner.disconnect();
        self.is_empty.store(
            inner.selectors.is_empty() && inner.observers.is_empty(),
            Ordering::SeqCst,
        );
    }
}

impl Drop for SyncWaker {
    #[inline]
    fn drop(&mut self) {
        debug_assert_eq!(self.is_empty.load(Ordering::SeqCst), true);
    }
}

/// Returns the id of the current thread.
#[inline]
fn current_thread_id() -> ThreadId {
    thread_local! {
        /// Cached thread-local id.
        static THREAD_ID: ThreadId = thread::current().id();
    }

    THREAD_ID
        .try_with(|id| *id)
        .unwrap_or_else(|_| thread::current().id())
}
<commit_msg>avoid bounds check in Waker::try_select method<commit_after>//! Waking mechanism for threads blocked on channel operations.

use std::sync::atomic::{AtomicBool, Ordering};
use std::thread::{self, ThreadId};

use crate::context::Context;
use crate::select::{Operation, Selected};
use crate::utils::Spinlock;

/// Represents a thread blocked on a specific channel operation.
pub(crate) struct Entry {
    /// The operation.
    pub(crate) oper: Operation,

    /// Optional packet.
    pub(crate) packet: usize,

    /// Context associated with the thread owning this operation.
    pub(crate) cx: Context,
}

/// A queue of threads blocked on channel operations.
///
/// This data structure is used by threads to register blocking operations and get woken up once
/// an operation becomes ready.
pub(crate) struct Waker {
    /// A list of select operations.
    selectors: Vec<Entry>,

    /// A list of operations waiting to be ready.
    observers: Vec<Entry>,
}

impl Waker {
    /// Creates a new `Waker`.
    #[inline]
    pub(crate) fn new() -> Self {
        Waker {
            selectors: Vec::new(),
            observers: Vec::new(),
        }
    }

    /// Registers a select operation.
    #[inline]
    pub(crate) fn register(&mut self, oper: Operation, cx: &Context) {
        self.register_with_packet(oper, 0, cx);
    }

    /// Registers a select operation and a packet.
    #[inline]
    pub(crate) fn register_with_packet(&mut self, oper: Operation, packet: usize, cx: &Context) {
        self.selectors.push(Entry {
            oper,
            packet,
            cx: cx.clone(),
        });
    }

    /// Unregisters a select operation.
    #[inline]
    pub(crate) fn unregister(&mut self, oper: Operation) -> Option<Entry> {
        if let Some((i, _)) = self
            .selectors
            .iter()
            .enumerate()
            .find(|&(_, entry)| entry.oper == oper)
        {
            let entry = self.selectors.remove(i);
            Some(entry)
        } else {
            None
        }
    }

    /// Attempts to find another thread's entry, select the operation, and wake it up.
    #[inline]
    pub(crate) fn try_select(&mut self) -> Option<Entry> {
        self.selectors
            .iter()
            .position(|selector| {
                // Does the entry belong to a different thread?
                selector.cx.thread_id() != current_thread_id()
                    && selector // Try selecting this operation.
                        .cx
                        .try_select(Selected::Operation(selector.oper))
                        .is_ok()
                    && {
                        // Provide the packet.
                        selector.cx.store_packet(selector.packet);
                        // Wake the thread up.
                        selector.cx.unpark();
                        true
                    }
            })
            // Remove the entry from the queue to keep it clean and improve
            // performance.
            .map(|pos| self.selectors.remove(pos))
    }

    /// Returns `true` if there is an entry which can be selected by the current thread.
    #[inline]
    pub(crate) fn can_select(&self) -> bool {
        if self.selectors.is_empty() {
            false
        } else {
            let thread_id = current_thread_id();

            self.selectors.iter().any(|entry| {
                entry.cx.thread_id() != thread_id && entry.cx.selected() == Selected::Waiting
            })
        }
    }

    /// Registers an operation waiting to be ready.
    #[inline]
    pub(crate) fn watch(&mut self, oper: Operation, cx: &Context) {
        self.observers.push(Entry {
            oper,
            packet: 0,
            cx: cx.clone(),
        });
    }

    /// Unregisters an operation waiting to be ready.
    #[inline]
    pub(crate) fn unwatch(&mut self, oper: Operation) {
        self.observers.retain(|e| e.oper != oper);
    }

    /// Notifies all operations waiting to be ready.
    #[inline]
    pub(crate) fn notify(&mut self) {
        for entry in self.observers.drain(..) {
            if entry.cx.try_select(Selected::Operation(entry.oper)).is_ok() {
                entry.cx.unpark();
            }
        }
    }

    /// Notifies all registered operations that the channel is disconnected.
    #[inline]
    pub(crate) fn disconnect(&mut self) {
        for entry in self.selectors.iter() {
            if entry.cx.try_select(Selected::Disconnected).is_ok() {
                // Wake the thread up.
                //
                // Here we don't remove the entry from the queue. Registered threads must
                // unregister from the waker by themselves. They might also want to recover the
                // packet value and destroy it, if necessary.
                entry.cx.unpark();
            }
        }

        self.notify();
    }
}

impl Drop for Waker {
    #[inline]
    fn drop(&mut self) {
        debug_assert_eq!(self.selectors.len(), 0);
        debug_assert_eq!(self.observers.len(), 0);
    }
}

/// A waker that can be shared among threads without locking.
///
/// This is a simple wrapper around `Waker` that internally uses a mutex for synchronization.
pub(crate) struct SyncWaker {
    /// The inner `Waker`.
    inner: Spinlock<Waker>,

    /// `true` if the waker is empty.
    is_empty: AtomicBool,
}

impl SyncWaker {
    /// Creates a new `SyncWaker`.
    #[inline]
    pub(crate) fn new() -> Self {
        SyncWaker {
            inner: Spinlock::new(Waker::new()),
            is_empty: AtomicBool::new(true),
        }
    }

    /// Registers the current thread with an operation.
    #[inline]
    pub(crate) fn register(&self, oper: Operation, cx: &Context) {
        let mut inner = self.inner.lock();
        inner.register(oper, cx);
        self.is_empty.store(
            inner.selectors.is_empty() && inner.observers.is_empty(),
            Ordering::SeqCst,
        );
    }

    /// Unregisters an operation previously registered by the current thread.
    #[inline]
    pub(crate) fn unregister(&self, oper: Operation) -> Option<Entry> {
        let mut inner = self.inner.lock();
        let entry = inner.unregister(oper);
        self.is_empty.store(
            inner.selectors.is_empty() && inner.observers.is_empty(),
            Ordering::SeqCst,
        );
        entry
    }

    /// Attempts to find one thread (not the current one), select its operation, and wake it up.
    #[inline]
    pub(crate) fn notify(&self) {
        if !self.is_empty.load(Ordering::SeqCst) {
            let mut inner = self.inner.lock();
            if !self.is_empty.load(Ordering::SeqCst) {
                inner.try_select();
                inner.notify();
                self.is_empty.store(
                    inner.selectors.is_empty() && inner.observers.is_empty(),
                    Ordering::SeqCst,
                );
            }
        }
    }

    /// Registers an operation waiting to be ready.
    #[inline]
    pub(crate) fn watch(&self, oper: Operation, cx: &Context) {
        let mut inner = self.inner.lock();
        inner.watch(oper, cx);
        self.is_empty.store(
            inner.selectors.is_empty() && inner.observers.is_empty(),
            Ordering::SeqCst,
        );
    }

    /// Unregisters an operation waiting to be ready.
    #[inline]
    pub(crate) fn unwatch(&self, oper: Operation) {
        let mut inner = self.inner.lock();
        inner.unwatch(oper);
        self.is_empty.store(
            inner.selectors.is_empty() && inner.observers.is_empty(),
            Ordering::SeqCst,
        );
    }

    /// Notifies all threads that the channel is disconnected.
    #[inline]
    pub(crate) fn disconnect(&self) {
        let mut inner = self.inner.lock();
        inner.disconnect();
        self.is_empty.store(
            inner.selectors.is_empty() && inner.observers.is_empty(),
            Ordering::SeqCst,
        );
    }
}

impl Drop for SyncWaker {
    #[inline]
    fn drop(&mut self) {
        debug_assert_eq!(self.is_empty.load(Ordering::SeqCst), true);
    }
}

/// Returns the id of the current thread.
#[inline]
fn current_thread_id() -> ThreadId {
    thread_local! {
        /// Cached thread-local id.
        static THREAD_ID: ThreadId = thread::current().id();
    }

    THREAD_ID
        .try_with(|id| *id)
        .unwrap_or_else(|_| thread::current().id())
}
<|endoftext|>


<commit_before>mod atom;

pub(crate) use self::atom::match_arm_list;
pub(super) use self::atom::{literal, LITERAL_FIRST};
use super::*;

const EXPR_FIRST: TokenSet = LHS_FIRST;

pub(super) fn expr(p: &mut Parser) -> BlockLike {
    let r = Restrictions {
        forbid_structs: false,
        prefer_stmt: false,
    };
    expr_bp(p, r, 1)
}

pub(super) fn expr_stmt(p: &mut Parser) -> BlockLike {
    let r = Restrictions {
        forbid_structs: false,
        prefer_stmt: true,
    };
    expr_bp(p, r, 1)
}

fn expr_no_struct(p: &mut Parser) {
    let r = Restrictions {
        forbid_structs: true,
        prefer_stmt: false,
    };
    expr_bp(p, r, 1);
}

// test block
// fn a() {}
// fn b() { let _ = 1; }
// fn c() { 1; 2; }
// fn d() { 1; 2 }
pub(crate) fn block(p: &mut Parser) {
    if !p.at(L_CURLY) {
        p.error("expected a block");
        return;
    }
    let m = p.start();
    p.bump();
    while !p.at(EOF) && !p.at(R_CURLY) {
        match p.current() {
            LET_KW => let_stmt(p),
            _ => {
                // test block_items
                // fn a() { fn b() {} }
                let m = p.start();
                match items::maybe_item(p, items::ItemFlavor::Mod) {
                    items::MaybeItem::Item(kind) => {
                        m.complete(p, kind);
                    }
                    items::MaybeItem::Modifiers => {
                        m.abandon(p);
                        p.error("expected an item");
                    }
                    // test pub_expr
                    // fn foo() { pub 92; } //FIXME
                    items::MaybeItem::None => {
                        let is_blocklike = expressions::expr_stmt(p) == BlockLike::Block;
                        if p.at(R_CURLY) {
                            m.abandon(p);
                        } else {
                            // test no_semi_after_block
                            // fn foo() {
                            //     if true {}
                            //     loop {}
                            //     match () {}
                            //     while true {}
                            //     for _ in () {}
                            //     {}
                            //     {}
                            //     macro_rules! test {
                            //          () => {}
                            //     }
                            //     test!{}
                            // }
                            if is_blocklike {
                                p.eat(SEMI);
                            } else {
                                p.expect(SEMI);
                            }
                            m.complete(p, EXPR_STMT);
                        }
                    }
                }
            }
        }
    }
    p.expect(R_CURLY);
    m.complete(p, BLOCK);

    // test let_stmt;
    // fn foo() {
    //     let a;
    //     let b: i32;
    //     let c = 92;
    //     let d: i32 = 92;
    // }
    fn let_stmt(p: &mut Parser) {
        assert!(p.at(LET_KW));
        let m = p.start();
        p.bump();
        patterns::pattern(p);
        if p.at(COLON) {
            types::ascription(p);
        }
        if p.eat(EQ) {
            expressions::expr(p);
        }
        p.expect(SEMI);
        m.complete(p, LET_STMT);
    }
}

#[derive(Clone, Copy)]
struct Restrictions {
    forbid_structs: bool,
    prefer_stmt: bool,
}

enum Op {
    Simple,
    Composite(SyntaxKind, u8),
}

fn current_op(p: &Parser) -> (u8, Op) {
    if let Some(t) = p.next3() {
        match t {
            (L_ANGLE, L_ANGLE, EQ) => return (1, Op::Composite(SHLEQ, 3)),
            (R_ANGLE, R_ANGLE, EQ) => return (1, Op::Composite(SHREQ, 3)),
            _ => (),
        }
    }

    if let Some(t) = p.next2() {
        match t {
            (PLUS, EQ) => return (1, Op::Composite(PLUSEQ, 2)),
            (MINUS, EQ) => return (1, Op::Composite(MINUSEQ, 2)),
            (STAR, EQ) => return (1, Op::Composite(STAREQ, 2)),
            (SLASH, EQ) => return (1, Op::Composite(SLASHEQ, 2)),
            (PIPE, EQ) => return (1, Op::Composite(PIPEEQ, 2)),
            (AMP, EQ) => return (1, Op::Composite(AMPEQ, 2)),
            (CARET, EQ) => return (1, Op::Composite(CARETEQ, 2)),
            (PIPE, PIPE) => return (3, Op::Composite(PIPEPIPE, 2)),
            (AMP, AMP) => return (4, Op::Composite(AMPAMP, 2)),
            (L_ANGLE, EQ) => return (5, Op::Composite(LTEQ, 2)),
            (R_ANGLE, EQ) => return (5, Op::Composite(GTEQ, 2)),
            (L_ANGLE, L_ANGLE) => return (9, Op::Composite(SHL, 2)),
            (R_ANGLE, R_ANGLE) => return (9, Op::Composite(SHR, 2)),
            _ => (),
        }
    }

    let bp = match p.current() {
        EQ => 1,
        DOTDOT | DOTDOTEQ => 2,
        EQEQ | NEQ | L_ANGLE | R_ANGLE => 5,
        PIPE => 6,
        CARET => 7,
        AMP => 8,
        MINUS | PLUS => 10,
        STAR | SLASH | PERCENT => 11,
        _ => 0,
    };
    (bp, Op::Simple)
}

// Parses expression with binding power of at least bp.
fn expr_bp(p: &mut Parser, r: Restrictions, bp: u8) -> BlockLike {
    let mut lhs = match lhs(p, r) {
        Some((lhs, blocklike)) => {
            // test stmt_bin_expr_ambiguity
            // fn foo() {
            //     let _ = {1} & 2;
            //     {1} &2;
            // }
            if r.prefer_stmt && blocklike.is_block() {
                return BlockLike::Block;
            }
            lhs
        }
        None => return BlockLike::NotBlock,
    };

    loop {
        let is_range = p.current() == DOTDOT || p.current() == DOTDOTEQ;
        let (op_bp, op) = current_op(p);
        if op_bp < bp {
            break;
        }
        let m = lhs.precede(p);
        match op {
            Op::Simple => p.bump(),
            Op::Composite(kind, n) => {
                p.bump_compound(kind, n);
            }
        }
        expr_bp(p, r, op_bp + 1);
        lhs = m.complete(p, if is_range { RANGE_EXPR } else { BIN_EXPR });
    }
    BlockLike::NotBlock
}

const LHS_FIRST: TokenSet = token_set_union![
    token_set![AMP, STAR, EXCL, DOTDOT, DOTDOTEQ, MINUS],
    atom::ATOM_EXPR_FIRST,
];

fn lhs(p: &mut Parser, r: Restrictions) -> Option<(CompletedMarker, BlockLike)> {
    let m;
    let kind = match p.current() {
        // test ref_expr
        // fn foo() {
        //     let _ = &1;
        //     let _ = &mut &f();
        // }
        AMP => {
            m = p.start();
            p.bump();
            p.eat(MUT_KW);
            REF_EXPR
        }
        // test unary_expr
        // fn foo() {
        //     **&1;
        //     !!true;
        //     --1;
        // }
        STAR | EXCL | MINUS => {
            m = p.start();
            p.bump();
            PREFIX_EXPR
        }
        // test full_range_expr
        // fn foo() { xs[..]; }
        DOTDOT | DOTDOTEQ => {
            m = p.start();
            p.bump();
            if p.at_ts(EXPR_FIRST) {
                expr_bp(p, r, 2);
            }
            return Some((m.complete(p, RANGE_EXPR), BlockLike::NotBlock));
        }
        _ => {
            let (lhs, blocklike) = atom::atom_expr(p, r)?;
            return Some((
                postfix_expr(p, lhs, !(r.prefer_stmt && blocklike.is_block())),
                blocklike,
            ));
        }
    };
    expr_bp(p, r, 255);
    Some((m.complete(p, kind), BlockLike::NotBlock))
}

fn postfix_expr(
    p: &mut Parser,
    mut lhs: CompletedMarker,
    // Calls are disallowed if the type is a block and we prefer statements because the call cannot be disambiguated from a tuple
    // E.g. `while true {break}();` is parsed as
    // `while true {break}; ();`
    mut allow_calls: bool,
) -> CompletedMarker {
    loop {
        lhs = match p.current() {
            // test stmt_postfix_expr_ambiguity
            // fn foo() {
            //     match () {
            //         _ => {}
            //         () => {}
            //         [] => {}
            //     }
            // }
            L_PAREN if allow_calls => call_expr(p, lhs),
            L_BRACK if allow_calls => index_expr(p, lhs),
            DOT if p.nth(1) == IDENT => {
                if p.nth(2) == L_PAREN || p.nth(2) == COLONCOLON {
                    method_call_expr(p, lhs)
                } else {
                    field_expr(p, lhs)
                }
            }
            DOT if p.nth(1) == INT_NUMBER => field_expr(p, lhs),
            // test postfix_range
            // fn foo() { let x = 1..; }
            DOTDOT | DOTDOTEQ if !EXPR_FIRST.contains(p.nth(1)) => {
                let m = lhs.precede(p);
                p.bump();
                m.complete(p, RANGE_EXPR)
            }
            QUESTION => try_expr(p, lhs),
            AS_KW => cast_expr(p, lhs),
            _ => break,
        };
        allow_calls = true
    }
    lhs
}

// test call_expr
// fn foo() {
//     let _ = f();
//     let _ = f()(1)(1, 2,);
// }
fn call_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
    assert!(p.at(L_PAREN));
    let m = lhs.precede(p);
    arg_list(p);
    m.complete(p, CALL_EXPR)
}

// test index_expr
// fn foo() {
//     x[1][2];
// }
fn index_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
    assert!(p.at(L_BRACK));
    let m = lhs.precede(p);
    p.bump();
    expr(p);
    p.expect(R_BRACK);
    m.complete(p, INDEX_EXPR)
}

// test method_call_expr
// fn foo() {
//     x.foo();
//     y.bar::<T>(1, 2,);
// }
fn method_call_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
    assert!(p.at(DOT) && p.nth(1) == IDENT && (p.nth(2) == L_PAREN || p.nth(2) == COLONCOLON));
    let m = lhs.precede(p);
    p.bump();
    name_ref(p);
    type_args::opt_type_arg_list(p, true);
    if p.at(L_PAREN) {
        arg_list(p);
    }
    m.complete(p, METHOD_CALL_EXPR)
}

// test field_expr
// fn foo() {
//     x.foo;
//     x.0.bar;
// }
fn field_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
    assert!(p.at(DOT) && (p.nth(1) == IDENT || p.nth(1) == INT_NUMBER));
    let m = lhs.precede(p);
    p.bump();
    if p.at(IDENT) {
        name_ref(p)
    } else {
        p.bump()
    }
    m.complete(p, FIELD_EXPR)
}

// test try_expr
// fn foo() {
//     x?;
// }
fn try_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
    assert!(p.at(QUESTION));
    let m = lhs.precede(p);
    p.bump();
    m.complete(p, TRY_EXPR)
}

// test cast_expr
// fn foo() {
//     82 as i32;
//     81 as i8 + 1;
//     79 as i16 - 1;
// }
fn cast_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
    assert!(p.at(AS_KW));
    let m = lhs.precede(p);
    p.bump();
    // Use type_no_bounds(), because cast expressions are not
    // allowed to have bounds.
    types::type_no_bounds(p);
    m.complete(p, CAST_EXPR)
}

fn arg_list(p: &mut Parser) {
    assert!(p.at(L_PAREN));
    let m = p.start();
    p.bump();
    while !p.at(R_PAREN) && !p.at(EOF) {
        if !p.at_ts(EXPR_FIRST) {
            p.error("expected expression");
            break;
        }
        expr(p);
        if !p.at(R_PAREN) && !p.expect(COMMA) {
            break;
        }
    }
    p.eat(R_PAREN);
    m.complete(p, ARG_LIST);
}

// test path_expr
// fn foo() {
//     let _ = a;
//     let _ = a::b;
//     let _ = ::a::<b>;
//     let _ = format!();
// }
fn path_expr(p: &mut Parser, r: Restrictions) -> (CompletedMarker, BlockLike) {
    assert!(paths::is_path_start(p) || p.at(L_ANGLE));
    let m = p.start();
    paths::expr_path(p);
    match p.current() {
        L_CURLY if !r.forbid_structs => {
            named_field_list(p);
            (m.complete(p, STRUCT_LIT), BlockLike::Block)
        }
        EXCL => {
            let block_like = items::macro_call_after_excl(p);
            return (m.complete(p, MACRO_CALL), block_like);
        }
        _ => (m.complete(p, PATH_EXPR), BlockLike::NotBlock),
    }
}

// test struct_lit
// fn foo() {
//     S {};
//     S { x, y: 32, };
//     S { x, y: 32, ..Default::default() };
// }
pub(crate) fn named_field_list(p: &mut Parser) {
    assert!(p.at(L_CURLY));
    let m = p.start();
    p.bump();
    while !p.at(EOF) && !p.at(R_CURLY) {
        match p.current() {
            IDENT => {
                let m = p.start();
                name_ref(p);
                if p.eat(COLON) {
                    expr(p);
                }
                m.complete(p, NAMED_FIELD);
            }
            DOTDOT => {
                p.bump();
                expr(p);
            }
            L_CURLY => error_block(p, "expected a field"),
            _ => p.err_and_bump("expected identifier"),
        }
        if !p.at(R_CURLY) {
            p.expect(COMMA);
        }
    }
    p.expect(R_CURLY);
    m.complete(p, NAMED_FIELD_LIST);
}
<commit_msg>Support a blank expression before a semicolon<commit_after>mod atom;

pub(crate) use self::atom::match_arm_list;
pub(super) use self::atom::{literal, LITERAL_FIRST};
use super::*;

const EXPR_FIRST: TokenSet = LHS_FIRST;

pub(super) fn expr(p: &mut Parser) -> BlockLike {
    let r = Restrictions {
        forbid_structs: false,
        prefer_stmt: false,
    };
    expr_bp(p, r, 1)
}

pub(super) fn expr_stmt(p: &mut Parser) -> BlockLike {
    let r = Restrictions {
        forbid_structs: false,
        prefer_stmt: true,
    };
    expr_bp(p, r, 1)
}

fn expr_no_struct(p: &mut Parser) {
    let r = Restrictions {
        forbid_structs: true,
        prefer_stmt: false,
    };
    expr_bp(p, r, 1);
}

// test block
// fn a() {}
// fn b() { let _ = 1; }
// fn c() { 1; 2; }
// fn d() { 1; 2 }
pub(crate) fn block(p: &mut Parser) {
    if !p.at(L_CURLY) {
        p.error("expected a block");
        return;
    }
    let m = p.start();
    p.bump();
    // test nocontentexpr
    // fn foo(){
    //     ;;;some_expr();;;;{;;;};;;;Ok(())
    // }
    while p.eat(SEMI) {}
    while !p.at(EOF) && !p.at(R_CURLY) {
        match p.current() {
            LET_KW => let_stmt(p),
            _ => {
                // test block_items
                // fn a() { fn b() {} }
                let m = p.start();
                match items::maybe_item(p, items::ItemFlavor::Mod) {
                    items::MaybeItem::Item(kind) => {
                        m.complete(p, kind);
                    }
                    items::MaybeItem::Modifiers => {
                        m.abandon(p);
                        p.error("expected an item");
                    }
                    // test pub_expr
                    // fn foo() { pub 92; } //FIXME
                    items::MaybeItem::None => {
                        let is_blocklike = expressions::expr_stmt(p) == BlockLike::Block;
                        if p.at(R_CURLY) {
                            m.abandon(p);
                        } else {
                            // test no_semi_after_block
                            // fn foo() {
                            //     if true {}
                            //     loop {}
                            //     match () {}
                            //     while true {}
                            //     for _ in () {}
                            //     {}
                            //     {}
                            //     macro_rules! test {
                            //          () => {}
                            //     }
                            //     test!{}
                            // }
                            if is_blocklike {
                                p.eat(SEMI);
                            } else {
                                p.expect(SEMI);
                            }
                            m.complete(p, EXPR_STMT);
                        }
                    }
                }
            }
        }
        while p.eat(SEMI) {}
    }
    p.expect(R_CURLY);
    m.complete(p, BLOCK);

    // test let_stmt;
    // fn foo() {
    //     let a;
    //     let b: i32;
    //     let c = 92;
    //     let d: i32 = 92;
    // }
    fn let_stmt(p: &mut Parser) {
        assert!(p.at(LET_KW));
        let m = p.start();
        p.bump();
        patterns::pattern(p);
        if p.at(COLON) {
            types::ascription(p);
        }
        if p.eat(EQ) {
            expressions::expr(p);
        }
        p.expect(SEMI);
        m.complete(p, LET_STMT);
    }
}

#[derive(Clone, Copy)]
struct Restrictions {
    forbid_structs: bool,
    prefer_stmt: bool,
}

enum Op {
    Simple,
    Composite(SyntaxKind, u8),
}

fn current_op(p: &Parser) -> (u8, Op) {
    if let Some(t) = p.next3() {
        match t {
            (L_ANGLE, L_ANGLE, EQ) => return (1, Op::Composite(SHLEQ, 3)),
            (R_ANGLE, R_ANGLE, EQ) => return (1, Op::Composite(SHREQ, 3)),
            _ => (),
        }
    }

    if let Some(t) = p.next2() {
        match t {
            (PLUS, EQ) => return (1, Op::Composite(PLUSEQ, 2)),
            (MINUS, EQ) => return (1, Op::Composite(MINUSEQ, 2)),
            (STAR, EQ) => return (1, Op::Composite(STAREQ, 2)),
            (SLASH, EQ) => return (1, Op::Composite(SLASHEQ, 2)),
            (PIPE, EQ) => return (1, Op::Composite(PIPEEQ, 2)),
            (AMP, EQ) => return (1, Op::Composite(AMPEQ, 2)),
            (CARET, EQ) => return (1, Op::Composite(CARETEQ, 2)),
            (PIPE, PIPE) => return (3, Op::Composite(PIPEPIPE, 2)),
            (AMP, AMP) => return (4, Op::Composite(AMPAMP, 2)),
            (L_ANGLE, EQ) => return (5, Op::Composite(LTEQ, 2)),
            (R_ANGLE, EQ) => return (5, Op::Composite(GTEQ, 2)),
            (L_ANGLE, L_ANGLE) => return (9, Op::Composite(SHL, 2)),
            (R_ANGLE, R_ANGLE) => return (9, Op::Composite(SHR, 2)),
            _ => (),
        }
    }

    let bp = match p.current() {
        EQ => 1,
        DOTDOT | DOTDOTEQ => 2,
        EQEQ | NEQ | L_ANGLE | R_ANGLE => 5,
        PIPE => 6,
        CARET => 7,
        AMP => 8,
        MINUS | PLUS => 10,
        STAR | SLASH | PERCENT => 11,
        _ => 0,
    };
    (bp, Op::Simple)
}

// Parses expression with binding power of at least bp.
fn expr_bp(p: &mut Parser, r: Restrictions, bp: u8) -> BlockLike {
    let mut lhs = match lhs(p, r) {
        Some((lhs, blocklike)) => {
            // test stmt_bin_expr_ambiguity
            // fn foo() {
            //     let _ = {1} & 2;
            //     {1} &2;
            // }
            if r.prefer_stmt && blocklike.is_block() {
                return BlockLike::Block;
            }
            lhs
        }
        None => return BlockLike::NotBlock,
    };

    loop {
        let is_range = p.current() == DOTDOT || p.current() == DOTDOTEQ;
        let (op_bp, op) = current_op(p);
        if op_bp < bp {
            break;
        }
        let m = lhs.precede(p);
        match op {
            Op::Simple => p.bump(),
            Op::Composite(kind, n) => {
                p.bump_compound(kind, n);
            }
        }
        expr_bp(p, r, op_bp + 1);
        lhs = m.complete(p, if is_range { RANGE_EXPR } else { BIN_EXPR });
    }
    BlockLike::NotBlock
}

const LHS_FIRST: TokenSet = token_set_union![
    token_set![AMP, STAR, EXCL, DOTDOT, DOTDOTEQ, MINUS],
    atom::ATOM_EXPR_FIRST,
];

fn lhs(p: &mut Parser, r: Restrictions) -> Option<(CompletedMarker, BlockLike)> {
    let m;
    let kind = match p.current() {
        // test ref_expr
        // fn foo() {
        //     let _ = &1;
        //     let _ = &mut &f();
        // }
        AMP => {
            m = p.start();
            p.bump();
            p.eat(MUT_KW);
            REF_EXPR
        }
        // test unary_expr
        // fn foo() {
        //     **&1;
        //     !!true;
        //     --1;
        // }
        STAR | EXCL | MINUS => {
            m = p.start();
            p.bump();
            PREFIX_EXPR
        }
        // test full_range_expr
        // fn foo() { xs[..]; }
        DOTDOT | DOTDOTEQ => {
            m = p.start();
            p.bump();
            if p.at_ts(EXPR_FIRST) {
                expr_bp(p, r, 2);
            }
            return Some((m.complete(p, RANGE_EXPR), BlockLike::NotBlock));
        }
        _ => {
            let (lhs, blocklike) = atom::atom_expr(p, r)?;
            return Some((
                postfix_expr(p, lhs, !(r.prefer_stmt && blocklike.is_block())),
                blocklike,
            ));
        }
    };
    expr_bp(p, r, 255);
    Some((m.complete(p, kind), BlockLike::NotBlock))
}

fn postfix_expr(
    p: &mut Parser,
    mut lhs: CompletedMarker,
    // Calls are disallowed if the type is a block and we prefer statements because the call cannot be disambiguated from a tuple
    // E.g. `while true {break}();` is parsed as
    // `while true {break}; ();`
    mut allow_calls: bool,
) -> CompletedMarker {
    loop {
        lhs = match p.current() {
            // test stmt_postfix_expr_ambiguity
            // fn foo() {
            //     match () {
            //         _ => {}
            //         () => {}
            //         [] => {}
            //     }
            // }
            L_PAREN if allow_calls => call_expr(p, lhs),
            L_BRACK if allow_calls => index_expr(p, lhs),
            DOT if p.nth(1) == IDENT => {
                if p.nth(2) == L_PAREN || p.nth(2) == COLONCOLON {
                    method_call_expr(p, lhs)
                } else {
                    field_expr(p, lhs)
                }
            }
            DOT if p.nth(1) == INT_NUMBER => field_expr(p, lhs),
            // test postfix_range
            // fn foo() { let x = 1..; }
            DOTDOT | DOTDOTEQ if !EXPR_FIRST.contains(p.nth(1)) => {
                let m = lhs.precede(p);
                p.bump();
                m.complete(p, RANGE_EXPR)
            }
            QUESTION => try_expr(p, lhs),
            AS_KW => cast_expr(p, lhs),
            _ => break,
        };
        allow_calls = true
    }
    lhs
}

// test call_expr
// fn foo() {
//     let _ = f();
//     let _ = f()(1)(1, 2,);
// }
fn call_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
    assert!(p.at(L_PAREN));
    let m = lhs.precede(p);
    arg_list(p);
    m.complete(p, CALL_EXPR)
}

// test index_expr
// fn foo() {
//     x[1][2];
// }
fn index_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
    assert!(p.at(L_BRACK));
    let m = lhs.precede(p);
    p.bump();
    expr(p);
    p.expect(R_BRACK);
    m.complete(p, INDEX_EXPR)
}

// test method_call_expr
// fn foo() {
//     x.foo();
//     y.bar::<T>(1, 2,);
// }
fn method_call_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
    assert!(p.at(DOT) && p.nth(1) == IDENT && (p.nth(2) == L_PAREN || p.nth(2) == COLONCOLON));
    let m = lhs.precede(p);
    p.bump();
    name_ref(p);
    type_args::opt_type_arg_list(p, true);
    if p.at(L_PAREN) {
        arg_list(p);
    }
    m.complete(p, METHOD_CALL_EXPR)
}

// test field_expr
// fn foo() {
//     x.foo;
//     x.0.bar;
// }
fn field_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
    assert!(p.at(DOT) && (p.nth(1) == IDENT || p.nth(1) == INT_NUMBER));
    let m = lhs.precede(p);
    p.bump();
    if p.at(IDENT) {
        name_ref(p)
    } else {
        p.bump()
    }
    m.complete(p, FIELD_EXPR)
}

// test try_expr
// fn foo() {
//     x?;
// }
fn try_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
    assert!(p.at(QUESTION));
    let m = lhs.precede(p);
    p.bump();
    m.complete(p, TRY_EXPR)
}

// test cast_expr
// fn foo() {
//     82 as i32;
//     81 as i8 + 1;
//     79 as i16 - 1;
// }
fn cast_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
    assert!(p.at(AS_KW));
    let m = lhs.precede(p);
    p.bump();
    // Use type_no_bounds(), because cast expressions are not
    // allowed to have bounds.
    types::type_no_bounds(p);
    m.complete(p, CAST_EXPR)
}

fn arg_list(p: &mut Parser) {
    assert!(p.at(L_PAREN));
    let m = p.start();
    p.bump();
    while !p.at(R_PAREN) && !p.at(EOF) {
        if !p.at_ts(EXPR_FIRST) {
            p.error("expected expression");
            break;
        }
        expr(p);
        if !p.at(R_PAREN) && !p.expect(COMMA) {
            break;
        }
    }
    p.eat(R_PAREN);
    m.complete(p, ARG_LIST);
}

// test path_expr
// fn foo() {
//     let _ = a;
//     let _ = a::b;
//     let _ = ::a::<b>;
//     let _ = format!();
// }
fn path_expr(p: &mut Parser, r: Restrictions) -> (CompletedMarker, BlockLike) {
    assert!(paths::is_path_start(p) || p.at(L_ANGLE));
    let m = p.start();
    paths::expr_path(p);
    match p.current() {
        L_CURLY if !r.forbid_structs => {
            named_field_list(p);
            (m.complete(p, STRUCT_LIT), BlockLike::Block)
        }
        EXCL => {
            let block_like = items::macro_call_after_excl(p);
            return (m.complete(p, MACRO_CALL), block_like);
        }
        _ => (m.complete(p, PATH_EXPR), BlockLike::NotBlock),
    }
}

// test struct_lit
// fn foo() {
//     S {};
//     S { x, y: 32, };
//     S { x, y: 32, ..Default::default() };
// }
pub(crate) fn named_field_list(p: &mut Parser) {
    assert!(p.at(L_CURLY));
    let m = p.start();
    p.bump();
    while !p.at(EOF) && !p.at(R_CURLY) {
        match p.current() {
            IDENT => {
                let m = p.start();
                name_ref(p);
                if p.eat(COLON) {
                    expr(p);
                }
                m.complete(p, NAMED_FIELD);
            }
            DOTDOT => {
                p.bump();
                expr(p);
            }
            L_CURLY => error_block(p, "expected a field"),
            _ => p.err_and_bump("expected identifier"),
        }
        if !p.at(R_CURLY) {
            p.expect(COMMA);
        }
    }
    p.expect(R_CURLY);
    m.complete(p, NAMED_FIELD_LIST);
}
<|endoftext|>


<commit_before>use std::fmt;
use std::collections::BTreeMap;

use itertools::Itertools;
use image::{GenericImage, Pixel, Rgb, Rgba};
use color_quant::NeuQuant;

use hsl::HSL;
use settings;

#[derive(Debug, Hash, PartialEq, Eq, Default)]
pub struct Vibrancy {
    primary: Option<Rgb<u8>>,
    dark: Option<Rgb<u8>>,
    light: Option<Rgb<u8>>,
    muted: Option<Rgb<u8>>,
    dark_muted: Option<Rgb<u8>>,
    light_muted: Option<Rgb<u8>>,
}

impl Vibrancy {
    pub fn new<P, G>(image: &G) -> Vibrancy
        where P: Sized + Pixel<Subpixel = u8>,
              G: Sized + GenericImage<Pixel = P>
    {
        let mut pixels: Vec<u8> = vec![];
        for (_, _, pixel) in image.pixels() {
            let rgba = pixel.to_rgba();
            if is_boring_pixel(&rgba) {
                continue;
            }

            for subpixel in rgba.channels() {
                pixels.push(*subpixel);
            }
        }

        const QUALITY: i32 = 10; // in [1...30] where 1 is best
        const COLOR_COUNT: usize = 256;

        let quant = NeuQuant::new(QUALITY, COLOR_COUNT, &pixels);

        let pixel_counts = image.pixels()
                                .map(|(_, _, pixel)| quant.index_of(&pixel.to_rgba().channels()))
                                .fold(BTreeMap::new(),
                                      |mut acc, pixel| {
                                          *acc.entry(pixel).or_insert(0) += 1;
                                          acc
                                      });

        let palette: Vec<Rgb<u8>> =
            quant.color_map_rgba()
                 .iter()
                 .chunks_lazy(4)
                 .into_iter()
                 .map(|rgba_iter| {
                         let rgba_slice: Vec<u8> = rgba_iter.cloned().collect();
                         Rgba::from_slice(&rgba_slice).clone().to_rgb()
                     })
                 .unique()
                 .collect();

        // println!("palette: {:?}", palette);
        // println!("pixel_counts: {:?}", pixel_counts);

        generate_varation_colors(&palette, &pixel_counts)
    }

    fn color_already_set(&self, color: &Rgb<u8>) -> bool {
        let color = Some(*color);
        self.primary == color || self.dark == color || self.light == color ||
        self.muted == color || self.dark_muted == color || self.light_muted == color
    }

    fn find_color_variation(&self,
                            palette: &[Rgb<u8>],
                            pixel_counts: &BTreeMap<usize, usize>,
                            luma: &MTM<f64>,
                            saturation: &MTM<f64>)
                            -> Option<Rgb<u8>> {
        let mut max = None;
        let mut max_value = 0_f64;

        let complete_population = pixel_counts.values().fold(0, |acc, c| acc + c);

        for (index, swatch) in palette.iter().enumerate() {
            let s = HSL::from_pixel(swatch).s;
            let l = HSL::from_pixel(swatch).l;

            if s >= saturation.min && s <= saturation.max && l >= luma.min && l <= luma.max &&
               !self.color_already_set(swatch) {
                let population = *pixel_counts.get(&index).unwrap_or(&0) as f64;
                if population == 0_f64 {
                    continue;
                }
                let value = create_comparison_value(s,
                                                    saturation.target,
                                                    l,
                                                    luma.target,
                                                    population,
                                                    complete_population as f64);
                if max.is_none() || value > max_value {
                    max = Some(swatch.clone());
                    max_value = value;
                }
            }
        }

        max
    }

    // fn fill_empty_swatches(self) {
    //     if self.primary.is_none() {
    //         // If we do not have a vibrant color...
    //         if let Some(dark) = self.dark {
    //             // ...but we do have a dark vibrant, generate the value by modifying the luma
    //             let hsl = HSL::from_pixel(&dark).clone()
    //             hsl.l = settings::TARGET_NORMAL_LUMA;
    //         }
    //     }
    // }
}

impl fmt::Display for Vibrancy {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        try!(write!(f, "Vibrancy {{\n"));

        macro_rules! display_color {
            ($formatter:expr, $name:expr, $color:expr) => {
                {
                    try!(write!($formatter, "\t"));
                    try!(write!($formatter, $name));
                    if let Some(c) = $color {
                        let rgb = c.channels();
                        try!(write!($formatter,
                            " Color: #{:02X}{:02X}{:02X}\n",
                            rgb[0], rgb[1], rgb[2]
                        ));
                    } else {
                        try!(write!($formatter, " Color: None\n"));
                    }
                }
            };
        }

        display_color!(f, "Primary Vibrant", self.primary);
        display_color!(f, "Dark Vibrant", self.dark);
        display_color!(f, "Light Vibrant", self.light);
        display_color!(f, "Muted", self.muted);
        display_color!(f, "Dark Muted", self.dark_muted);
        display_color!(f, "Light Muted", self.light_muted);

        write!(f, "}}")
    }
}

fn generate_varation_colors(palette: &[Rgb<u8>],
                            pixel_counts: &BTreeMap<usize, usize>)
                            -> Vibrancy {
    let mut vibrancy = Vibrancy::default();
    vibrancy.primary = vibrancy.find_color_variation(palette,
                                                     pixel_counts,
                                                     &MTM {
            min: settings::MIN_NORMAL_LUMA,
            target: settings::TARGET_NORMAL_LUMA,
            max: settings::MAX_NORMAL_LUMA,
        },
                                                     &MTM {
            min: settings::MIN_VIBRANT_SATURATION,
            target: settings::TARGET_VIBRANT_SATURATION,
            max: 1_f64,
        });

    vibrancy.light = vibrancy.find_color_variation(palette,
                                                   pixel_counts,
                                                   &MTM {
            min: settings::MIN_LIGHT_LUMA,
            target: settings::TARGET_LIGHT_LUMA,
            max: 1_f64,
        },
                                                   &MTM {
            min: settings::MIN_VIBRANT_SATURATION,
            target: settings::TARGET_VIBRANT_SATURATION,
            max: 1_f64,
        });

    vibrancy.dark = vibrancy.find_color_variation(palette,
                                                  pixel_counts,
                                                  &MTM {
            min: 0_f64,
            target: settings::TARGET_DARK_LUMA,
            max: settings::MAX_DARK_LUMA,
        },
                                                  &MTM {
            min: settings::MIN_VIBRANT_SATURATION,
            target: settings::TARGET_VIBRANT_SATURATION,
            max: 1_f64,
        });

    vibrancy.muted = vibrancy.find_color_variation(palette,
                                                   pixel_counts,
                                                   &MTM {
            min: settings::MIN_NORMAL_LUMA,
            target: settings::TARGET_NORMAL_LUMA,
            max: settings::MAX_NORMAL_LUMA,
        },
                                                   &MTM {
            min: 0_f64,
            target: settings::TARGET_MUTED_SATURATION,
            max: settings::MAX_MUTED_SATURATION,
        });

    vibrancy.light_muted = vibrancy.find_color_variation(palette,
                                                         pixel_counts,
                                                         &MTM {
            min: settings::MIN_LIGHT_LUMA,
            target: settings::TARGET_LIGHT_LUMA,
            max: 1_f64,
        },
                                                         &MTM {
            min: 0_f64,
            target: settings::TARGET_MUTED_SATURATION,
            max: settings::MAX_MUTED_SATURATION,
        });

    vibrancy.dark_muted = vibrancy.find_color_variation(palette,
                                                        pixel_counts,
                                                        &MTM {
            min: 0_f64,
            target: settings::TARGET_DARK_LUMA,
            max: settings::MAX_DARK_LUMA,
        },
                                                        &MTM {
            min: 0_f64,
            target: settings::TARGET_MUTED_SATURATION,
            max: settings::MAX_MUTED_SATURATION,
        });

    vibrancy
}

fn is_boring_pixel(pixel: &Rgba<u8>) -> bool {
    let (r, g, b, a) = (pixel[0], pixel[1], pixel[2], pixel[3]);

    // If pixel is mostly opaque and not white
    const MIN_ALPHA: u8 = 125;
    const MAX_COLOR: u8 = 250;

    let interesting = (a >= MIN_ALPHA) && !(r > MAX_COLOR && g > MAX_COLOR && b > MAX_COLOR);

    !interesting
}

fn invert_diff(val: f64, target_val: f64) -> f64 {
    1_f64 - (val - target_val).abs()
}

fn weighted_mean(vals: &[(f64, f64)]) -> f64 {
    let (sum, sum_weight) = vals.iter().fold((0_f64, 0_f64),
                                             |(sum, sum_weight), &(val, weight)| {
                                                 (sum + val * weight, sum_weight + weight)
                                             });

    sum / sum_weight
}

fn create_comparison_value(sat: f64,
                           target_sat: f64,
                           luma: f64,
                           target_uma: f64,
                           population: f64,
                           max_population: f64)
                           -> f64 {
    weighted_mean(&[
        (invert_diff(sat, target_sat),   settings::WEIGHT_SATURATION),
        (invert_diff(luma, target_uma),  settings::WEIGHT_LUMA),
        (population / max_population,    settings::WEIGHT_POPULATION),
    ])
}

/// Minimum, Maximum, Target
#[derive(Debug, Hash)]
struct MTM<T> {
    min: T,
    target: T,
    max: T,
}
<commit_msg>Make Pixel Handling Code Cleaner<commit_after>use std::fmt;
use std::collections::BTreeMap;

use itertools::Itertools;
use image::{GenericImage, Pixel, Rgb, Rgba};
use color_quant::NeuQuant;

use hsl::HSL;
use settings;

#[derive(Debug, Hash, PartialEq, Eq, Default)]
pub struct Vibrancy {
    primary: Option<Rgb<u8>>,
    dark: Option<Rgb<u8>>,
    light: Option<Rgb<u8>>,
    muted: Option<Rgb<u8>>,
    dark_muted: Option<Rgb<u8>>,
    light_muted: Option<Rgb<u8>>,
}

impl Vibrancy {
    pub fn new<P, G>(image: &G) -> Vibrancy
        where P: Sized + Pixel<Subpixel = u8>,
              G: Sized + GenericImage<Pixel = P>
    {
        let pixels: Vec<Rgba<u8>> = image.pixels()
                                .map(|(_, _, pixel)| pixel.to_rgba() )
                                .collect();

        let mut flat_pixels: Vec<u8> = Vec::with_capacity(pixels.len());
        for rgba in &pixels {
            if is_boring_pixel(&rgba) {
                continue;
            }

            for subpixel in rgba.channels() {
                flat_pixels.push(*subpixel);
            }
        }

        const QUALITY: i32 = 10; // in [1...30] where 1 is best
        const COLOR_COUNT: usize = 256;

        let quant = NeuQuant::new(QUALITY, COLOR_COUNT, &flat_pixels);

        let pixel_counts = pixels.iter()
                                .map(|rgba| quant.index_of(&rgba.channels()))
                                .fold(BTreeMap::new(),
                                      |mut acc, pixel| {
                                          *acc.entry(pixel).or_insert(0) += 1;
                                          acc
                                      });

        let palette: Vec<Rgb<u8>> =
            quant.color_map_rgba()
                 .iter()
                 .chunks_lazy(4)
                 .into_iter()
                 .map(|rgba_iter| {
                         let rgba_slice: Vec<u8> = rgba_iter.cloned().collect();
                         Rgba::from_slice(&rgba_slice).clone().to_rgb()
                     })
                 .unique()
                 .collect();

        // println!("palette: {:?}", palette);
        // println!("pixel_counts: {:?}", pixel_counts);

        generate_varation_colors(&palette, &pixel_counts)
    }

    fn color_already_set(&self, color: &Rgb<u8>) -> bool {
        let color = Some(*color);
        self.primary == color || self.dark == color || self.light == color ||
        self.muted == color || self.dark_muted == color || self.light_muted == color
    }

    fn find_color_variation(&self,
                            palette: &[Rgb<u8>],
                            pixel_counts: &BTreeMap<usize, usize>,
                            luma: &MTM<f64>,
                            saturation: &MTM<f64>)
                            -> Option<Rgb<u8>> {
        let mut max = None;
        let mut max_value = 0_f64;

        let complete_population = pixel_counts.values().fold(0, |acc, c| acc + c);

        for (index, swatch) in palette.iter().enumerate() {
            let s = HSL::from_pixel(swatch).s;
            let l = HSL::from_pixel(swatch).l;

            if s >= saturation.min && s <= saturation.max && l >= luma.min && l <= luma.max &&
               !self.color_already_set(swatch) {
                let population = *pixel_counts.get(&index).unwrap_or(&0) as f64;
                if population == 0_f64 {
                    continue;
                }
                let value = create_comparison_value(s,
                                                    saturation.target,
                                                    l,
                                                    luma.target,
                                                    population,
                                                    complete_population as f64);
                if max.is_none() || value > max_value {
                    max = Some(swatch.clone());
                    max_value = value;
                }
            }
        }

        max
    }

    // fn fill_empty_swatches(self) {
    //     if self.primary.is_none() {
    //         // If we do not have a vibrant color...
    //         if let Some(dark) = self.dark {
    //             // ...but we do have a dark vibrant, generate the value by modifying the luma
    //             let hsl = HSL::from_pixel(&dark).clone()
    //             hsl.l = settings::TARGET_NORMAL_LUMA;
    //         }
    //     }
    // }
}

impl fmt::Display for Vibrancy {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        try!(write!(f, "Vibrant Colors {{\n"));

        macro_rules! display_color {
            ($formatter:expr, $name:expr, $color:expr) => {
                {
                    try!(write!($formatter, "\t"));
                    try!(write!($formatter, $name));
                    if let Some(c) = $color {
                        let rgb = c.channels();
                        try!(write!($formatter,
                            " Color: #{:02X}{:02X}{:02X}\n",
                            rgb[0], rgb[1], rgb[2]
                        ));
                    } else {
                        try!(write!($formatter, " Color: None\n"));
                    }
                }
            };
        }

        display_color!(f, "Primary Vibrant", self.primary);
        display_color!(f, "Dark Vibrant", self.dark);
        display_color!(f, "Light Vibrant", self.light);
        display_color!(f, "Muted", self.muted);
        display_color!(f, "Dark Muted", self.dark_muted);
        display_color!(f, "Light Muted", self.light_muted);

        write!(f, "}}")
    }
}

fn generate_varation_colors(palette: &[Rgb<u8>],
                            pixel_counts: &BTreeMap<usize, usize>)
                            -> Vibrancy {
    let mut vibrancy = Vibrancy::default();
    vibrancy.primary = vibrancy.find_color_variation(palette,
                                                     pixel_counts,
                                                     &MTM {
            min: settings::MIN_NORMAL_LUMA,
            target: settings::TARGET_NORMAL_LUMA,
            max: settings::MAX_NORMAL_LUMA,
        },
                                                     &MTM {
            min: settings::MIN_VIBRANT_SATURATION,
            target: settings::TARGET_VIBRANT_SATURATION,
            max: 1_f64,
        });

    vibrancy.light = vibrancy.find_color_variation(palette,
                                                   pixel_counts,
                                                   &MTM {
            min: settings::MIN_LIGHT_LUMA,
            target: settings::TARGET_LIGHT_LUMA,
            max: 1_f64,
        },
                                                   &MTM {
            min: settings::MIN_VIBRANT_SATURATION,
            target: settings::TARGET_VIBRANT_SATURATION,
            max: 1_f64,
        });

    vibrancy.dark = vibrancy.find_color_variation(palette,
                                                  pixel_counts,
                                                  &MTM {
            min: 0_f64,
            target: settings::TARGET_DARK_LUMA,
            max: settings::MAX_DARK_LUMA,
        },
                                                  &MTM {
            min: settings::MIN_VIBRANT_SATURATION,
            target: settings::TARGET_VIBRANT_SATURATION,
            max: 1_f64,
        });

    vibrancy.muted = vibrancy.find_color_variation(palette,
                                                   pixel_counts,
                                                   &MTM {
            min: settings::MIN_NORMAL_LUMA,
            target: settings::TARGET_NORMAL_LUMA,
            max: settings::MAX_NORMAL_LUMA,
        },
                                                   &MTM {
            min: 0_f64,
            target: settings::TARGET_MUTED_SATURATION,
            max: settings::MAX_MUTED_SATURATION,
        });

    vibrancy.light_muted = vibrancy.find_color_variation(palette,
                                                         pixel_counts,
                                                         &MTM {
            min: settings::MIN_LIGHT_LUMA,
            target: settings::TARGET_LIGHT_LUMA,
            max: 1_f64,
        },
                                                         &MTM {
            min: 0_f64,
            target: settings::TARGET_MUTED_SATURATION,
            max: settings::MAX_MUTED_SATURATION,
        });

    vibrancy.dark_muted = vibrancy.find_color_variation(palette,
                                                        pixel_counts,
                                                        &MTM {
            min: 0_f64,
            target: settings::TARGET_DARK_LUMA,
            max: settings::MAX_DARK_LUMA,
        },
                                                        &MTM {
            min: 0_f64,
            target: settings::TARGET_MUTED_SATURATION,
            max: settings::MAX_MUTED_SATURATION,
        });

    vibrancy
}

fn is_boring_pixel(pixel: &Rgba<u8>) -> bool {
    let (r, g, b, a) = (pixel[0], pixel[1], pixel[2], pixel[3]);

    // If pixel is mostly opaque and not white
    const MIN_ALPHA: u8 = 125;
    const MAX_COLOR: u8 = 250;

    let interesting = (a >= MIN_ALPHA) && !(r > MAX_COLOR && g > MAX_COLOR && b > MAX_COLOR);

    !interesting
}

fn invert_diff(val: f64, target_val: f64) -> f64 {
    1_f64 - (val - target_val).abs()
}

fn weighted_mean(vals: &[(f64, f64)]) -> f64 {
    let (sum, sum_weight) = vals.iter().fold((0_f64, 0_f64),
                                             |(sum, sum_weight), &(val, weight)| {
                                                 (sum + val * weight, sum_weight + weight)
                                             });

    sum / sum_weight
}

fn create_comparison_value(sat: f64,
                           target_sat: f64,
                           luma: f64,
                           target_uma: f64,
                           population: f64,
                           max_population: f64)
                           -> f64 {
    weighted_mean(&[
        (invert_diff(sat, target_sat),   settings::WEIGHT_SATURATION),
        (invert_diff(luma, target_uma),  settings::WEIGHT_LUMA),
        (population / max_population,    settings::WEIGHT_POPULATION),
    ])
}

/// Minimum, Maximum, Target
#[derive(Debug, Hash)]
struct MTM<T> {
    min: T,
    target: T,
    max: T,
}
<|endoftext|>


<commit_before>//! Encoding of primitive values.
use crate::value::{DicomDate, DicomDateTime, DicomTime};
use std::io::{Result as IoResult, Write};

/** Encode a single date in accordance to the DICOM Date (DA)
 * value representation.
 */
pub fn encode_date<W>(mut to: W, date: DicomDate) -> IoResult<usize>
where
    W: Write,
{
    // YYYY(MM(DD)?)?
    let len = date.to_encoded().len();
    write!(to, "{}", date.to_encoded())?;
    Ok(len)
}

/** Encode a single time value in accordance to the DICOM Time (TM)
 * value representation.
 */
pub fn encode_time<W>(mut to: W, time: DicomTime) -> IoResult<usize>
where
    W: Write,
{
    // HH(MM(SS(.F{1,6})?)?)?
    let len = time.to_encoded().len();
    write!(to, "{}", time.to_encoded())?;
    Ok(len)
}

/** Encode a single date-time value in accordance to the DICOM DateTime (DT)
 * value representation.
 */
pub fn encode_datetime<W>(mut to: W, dt: DicomDateTime) -> IoResult<usize>
where
    W: Write,
{
    let len = dt.to_string().len();
    write!(to, "{}", dt.to_encoded())?;
    Ok(len)
}

#[cfg(test)]
mod test {
    use super::*;
    use chrono::FixedOffset;
    use std::str::from_utf8;

    #[test]
    fn test_encode_date() {
        let mut data = vec![];
        encode_date(&mut data, DicomDate::from_ym(1985, 12).unwrap()).unwrap();
        assert_eq!(&data, &*b"198512");
    }

    #[test]
    fn test_encode_time() {
        let mut data = vec![];
        encode_time(
            &mut data,
            DicomTime::from_hms_micro(23, 59, 48, 123456).unwrap(),
        )
        .unwrap();
        assert_eq!(&data, &*b"235948.123456");

        let mut data = vec![];
        encode_time(&mut data, DicomTime::from_hms(12, 0, 30).unwrap()).unwrap();
        assert_eq!(&data, &*b"120030");

        let mut data = vec![];
        encode_time(&mut data, DicomTime::from_h(9).unwrap()).unwrap();
        assert_eq!(&data, &*b"09");
    }

    #[test]
    fn test_encode_datetime() {
        let mut data = vec![];
        let offset = FixedOffset::east(0);
        encode_datetime(
            &mut data,
            DicomDateTime::from_date_and_time(
                DicomDate::from_ymd(1985, 12, 31).unwrap(),
                DicomTime::from_hms_micro(23, 59, 48, 123_456).unwrap(),
                offset,
            )
            .unwrap(),
        )
        .unwrap();
        // even zero offset gets encoded into string value
        assert_eq!(from_utf8(&data).unwrap(), "19851231235948.123456+0000");

        let mut data = vec![];
        let offset = FixedOffset::east(3600);
        encode_datetime(
            &mut data,
            DicomDateTime::from_date_and_time(
                DicomDate::from_ymd(2018, 12, 24).unwrap(),
                DicomTime::from_h(4).unwrap(),
                offset,
            )
            .unwrap(),
        )
        .unwrap();
        assert_eq!(from_utf8(&data).unwrap(), "2018122404+0100");
    }
}
<commit_msg>[core] Fix reported length of encoded datetime<commit_after>//! Encoding of primitive values.
use crate::value::{DicomDate, DicomDateTime, DicomTime};
use std::io::{Result as IoResult, Write};

/** Encode a single date in accordance to the DICOM Date (DA)
 * value representation.
 */
pub fn encode_date<W>(mut to: W, date: DicomDate) -> IoResult<usize>
where
    W: Write,
{
    // YYYY(MM(DD)?)?
    let len = date.to_encoded().len();
    write!(to, "{}", date.to_encoded())?;
    Ok(len)
}

/** Encode a single time value in accordance to the DICOM Time (TM)
 * value representation.
 */
pub fn encode_time<W>(mut to: W, time: DicomTime) -> IoResult<usize>
where
    W: Write,
{
    // HH(MM(SS(.F{1,6})?)?)?
    let len = time.to_encoded().len();
    write!(to, "{}", time.to_encoded())?;
    Ok(len)
}

/** Encode a single date-time value in accordance to the DICOM DateTime (DT)
 * value representation.
 */
pub fn encode_datetime<W>(mut to: W, dt: DicomDateTime) -> IoResult<usize>
where
    W: Write,
{
    let value = dt.to_encoded();
    let len = value.len();
    write!(to, "{}", value)?;
    Ok(len)
}

#[cfg(test)]
mod test {
    use super::*;
    use chrono::FixedOffset;
    use std::str::from_utf8;

    #[test]
    fn test_encode_date() {
        let mut data = vec![];
        encode_date(&mut data, DicomDate::from_ym(1985, 12).unwrap()).unwrap();
        assert_eq!(&data, &*b"198512");
    }

    #[test]
    fn test_encode_time() {
        let mut data = vec![];
        encode_time(
            &mut data,
            DicomTime::from_hms_micro(23, 59, 48, 123456).unwrap(),
        )
        .unwrap();
        assert_eq!(&data, &*b"235948.123456");

        let mut data = vec![];
        encode_time(&mut data, DicomTime::from_hms(12, 0, 30).unwrap()).unwrap();
        assert_eq!(&data, &*b"120030");

        let mut data = vec![];
        encode_time(&mut data, DicomTime::from_h(9).unwrap()).unwrap();
        assert_eq!(&data, &*b"09");
    }

    #[test]
    fn test_encode_datetime() {
        let mut data = vec![];
        let offset = FixedOffset::east(0);
        let bytes = encode_datetime(
            &mut data,
            DicomDateTime::from_date_and_time(
                DicomDate::from_ymd(1985, 12, 31).unwrap(),
                DicomTime::from_hms_micro(23, 59, 48, 123_456).unwrap(),
                offset,
            )
            .unwrap(),
        )
        .unwrap();
        // even zero offset gets encoded into string value
        assert_eq!(from_utf8(&data).unwrap(), "19851231235948.123456+0000");
        assert_eq!(bytes, 26);

        let mut data = vec![];
        let offset = FixedOffset::east(3600);
        let bytes = encode_datetime(
            &mut data,
            DicomDateTime::from_date_and_time(
                DicomDate::from_ymd(2018, 12, 24).unwrap(),
                DicomTime::from_h(4).unwrap(),
                offset,
            )
            .unwrap(),
        )
        .unwrap();
        assert_eq!(from_utf8(&data).unwrap(), "2018122404+0100");
        assert_eq!(bytes, 15);
    }
}
<|endoftext|>


<commit_before>#![doc(html_root_url="http://sfackler.github.io/rust-phf/doc")]

use std::hash::{Hasher, Hash, SipHasher};

#[inline]
pub fn displace(f1: u32, f2: u32, d1: u32, d2: u32) -> u32 {
    d2 + f1 * d1 + f2
}

#[inline]
fn split(hash: u64) -> (u32, u32, u32) {
    const BITS: u32 = 21;
    const MASK: u64 = (1 << BITS) - 1;

    ((hash & MASK) as u32,
     ((hash >> BITS) & MASK) as u32,
     ((hash >> (2 * BITS)) & MASK) as u32)
}

/// A trait implemented by types which can be used in PHF data structures
pub trait PhfHash {
    /// Hashes the value of `self`, factoring in a seed
    fn phf_hash(&self, seed: u64) -> (u32, u32, u32);
}

impl<'a> PhfHash for &'a str {
    #[inline]
    fn phf_hash(&self, seed: u64) -> (u32, u32, u32) {
        self.as_bytes().phf_hash(seed)
    }
}

impl<'a> PhfHash for &'a [u8] {
    #[inline]
    fn phf_hash(&self, seed: u64) -> (u32, u32, u32) {
        (*self).phf_hash(seed)
    }
}

impl PhfHash for str {
    #[inline]
    fn phf_hash(&self, seed: u64) -> (u32, u32, u32) {
        self.as_bytes().phf_hash(seed)
    }
}

impl PhfHash for [u8] {
    #[inline]
    fn phf_hash(&self, seed: u64) -> (u32, u32, u32) {
        let mut state = SipHasher::new_with_keys(seed, 0);
        Hasher::write(&mut state, self);
        split(state.finish())
    }
}

macro_rules! sip_impl(
    ($t:ty) => (
        impl PhfHash for $t {
            #[inline]
            fn phf_hash(&self, seed: u64) -> (u32, u32, u32) {
                let mut hasher = SipHasher::new_with_keys(seed, 0);
                self.hash(&mut hasher);
                split(hasher.finish())
            }
        }
    )
);

sip_impl!(u8);
sip_impl!(i8);
sip_impl!(u16);
sip_impl!(i16);
sip_impl!(u32);
sip_impl!(i32);
sip_impl!(u64);
sip_impl!(i64);
sip_impl!(char);
sip_impl!(bool);

macro_rules! array_impl(
    ($t:ty, $n:expr) => (
        impl PhfHash for [$t; $n] {
            #[inline]
            fn phf_hash(&self, seed: u64) -> (u32, u32, u32) {
                let mut hasher = SipHasher::new_with_keys(seed, 0);
                Hasher::write(&mut hasher, self);
                split(hasher.finish())
            }
        }
    )
);

array_impl!(u8, 1);
array_impl!(u8, 2);
array_impl!(u8, 3);
array_impl!(u8, 4);
array_impl!(u8, 5);
array_impl!(u8, 6);
array_impl!(u8, 7);
array_impl!(u8, 8);
array_impl!(u8, 9);
array_impl!(u8, 10);
array_impl!(u8, 11);
array_impl!(u8, 12);
array_impl!(u8, 13);
array_impl!(u8, 14);
array_impl!(u8, 15);
array_impl!(u8, 16);
array_impl!(u8, 17);
array_impl!(u8, 18);
array_impl!(u8, 19);
array_impl!(u8, 20);
array_impl!(u8, 21);
array_impl!(u8, 22);
array_impl!(u8, 23);
array_impl!(u8, 24);
array_impl!(u8, 25);
array_impl!(u8, 26);
array_impl!(u8, 27);
array_impl!(u8, 28);
array_impl!(u8, 29);
array_impl!(u8, 30);
array_impl!(u8, 31);
array_impl!(u8, 32);
<commit_msg>Make PhfHash endianness-independent<commit_after>#![doc(html_root_url="http://sfackler.github.io/rust-phf/doc")]

use std::hash::{Hasher, Hash, SipHasher};

#[inline]
pub fn displace(f1: u32, f2: u32, d1: u32, d2: u32) -> u32 {
    d2 + f1 * d1 + f2
}

#[inline]
fn split(hash: u64) -> (u32, u32, u32) {
    const BITS: u32 = 21;
    const MASK: u64 = (1 << BITS) - 1;

    ((hash & MASK) as u32,
     ((hash >> BITS) & MASK) as u32,
     ((hash >> (2 * BITS)) & MASK) as u32)
}

/// A trait implemented by types which can be used in PHF data structures
pub trait PhfHash {
    /// Hashes the value of `self`, factoring in a seed
    fn phf_hash(&self, seed: u64) -> (u32, u32, u32);
}

impl<'a> PhfHash for &'a str {
    #[inline]
    fn phf_hash(&self, seed: u64) -> (u32, u32, u32) {
        self.as_bytes().phf_hash(seed)
    }
}

impl<'a> PhfHash for &'a [u8] {
    #[inline]
    fn phf_hash(&self, seed: u64) -> (u32, u32, u32) {
        (*self).phf_hash(seed)
    }
}

impl PhfHash for str {
    #[inline]
    fn phf_hash(&self, seed: u64) -> (u32, u32, u32) {
        self.as_bytes().phf_hash(seed)
    }
}

impl PhfHash for [u8] {
    #[inline]
    fn phf_hash(&self, seed: u64) -> (u32, u32, u32) {
        let mut state = SipHasher::new_with_keys(seed, 0);
        Hasher::write(&mut state, self);
        split(state.finish())
    }
}

macro_rules! sip_impl(
    (le $t:ty) => (
        impl PhfHash for $t {
            #[inline]
            fn phf_hash(&self, seed: u64) -> (u32, u32, u32) {
                let mut hasher = SipHasher::new_with_keys(seed, 0);
                self.to_le().hash(&mut hasher);
                split(hasher.finish())
            }
        }
    );
    ($t:ty) => (
        impl PhfHash for $t {
            #[inline]
            fn phf_hash(&self, seed: u64) -> (u32, u32, u32) {
                let mut hasher = SipHasher::new_with_keys(seed, 0);
                self.hash(&mut hasher);
                split(hasher.finish())
            }
        }
    )
);

sip_impl!(u8);
sip_impl!(i8);
sip_impl!(le u16);
sip_impl!(le i16);
sip_impl!(le u32);
sip_impl!(le i32);
sip_impl!(le u64);
sip_impl!(le i64);
sip_impl!(bool);

impl PhfHash for char {
    #[inline]
    fn phf_hash(&self, seed: u64) -> (u32, u32, u32) {
        (*self as u32).phf_hash(seed)
    }
}

macro_rules! array_impl(
    ($t:ty, $n:expr) => (
        impl PhfHash for [$t; $n] {
            #[inline]
            fn phf_hash(&self, seed: u64) -> (u32, u32, u32) {
                let mut hasher = SipHasher::new_with_keys(seed, 0);
                Hasher::write(&mut hasher, self);
                split(hasher.finish())
            }
        }
    )
);

array_impl!(u8, 1);
array_impl!(u8, 2);
array_impl!(u8, 3);
array_impl!(u8, 4);
array_impl!(u8, 5);
array_impl!(u8, 6);
array_impl!(u8, 7);
array_impl!(u8, 8);
array_impl!(u8, 9);
array_impl!(u8, 10);
array_impl!(u8, 11);
array_impl!(u8, 12);
array_impl!(u8, 13);
array_impl!(u8, 14);
array_impl!(u8, 15);
array_impl!(u8, 16);
array_impl!(u8, 17);
array_impl!(u8, 18);
array_impl!(u8, 19);
array_impl!(u8, 20);
array_impl!(u8, 21);
array_impl!(u8, 22);
array_impl!(u8, 23);
array_impl!(u8, 24);
array_impl!(u8, 25);
array_impl!(u8, 26);
array_impl!(u8, 27);
array_impl!(u8, 28);
array_impl!(u8, 29);
array_impl!(u8, 30);
array_impl!(u8, 31);
array_impl!(u8, 32);
<|endoftext|>


<commit_before><commit_msg>added AllocError type,  changed atomic load to use Acquire instead of Relaxed ordering. Added more sanity checks<commit_after><|endoftext|>


<commit_before><commit_msg>Fix 'small' feature when built without i128 support<commit_after><|endoftext|>


<commit_before>endogenous C "Consumption" I "Total investment" AG "Growth-rate-stationary pref. process" H "Total labor supply"
AL "level-stationary pref. process" G_H "Growth rate of hours" A "Preference shock"

@#for ii in Sektors
	ZG_@{ii} "Growth-rate-stationary techn. process @{ii}"
	LAMBDA_@{ii} "Multiplier on production @{ii}"
	H_@{ii} "Labor supply in sector @{ii}"
	K_@{ii} "Capital stock in sector @{ii}"
	I_@{ii}	"Investment goods in sector @{ii}"
	Z_@{ii} "Technology shock in sector @{ii}"
	XI_@{ii} "Multiplier on capital accumulation @{ii}"
	ZL_@{ii} "Level-stationary techn. process @{ii}"
	G_@{ii} "Growth rate of @{ii}"
@#end

LG_C LG_I LG_H

observables LG_C LG_I LG_H

exogenous ELA EAG
@#for ii in Sektors
	EL_@{ii} EG_@{ii}
@#end

parameters gam beta	rhola sigla	agtr rhoga sigga  phik_C_tr phih_C_tr
@#for ii in Sektors
	theta_@{ii} eta_@{ii}	kappa_@{ii}	delta_@{ii}	rhol_@{ii}
	sigl_@{ii} zg_@{ii}_tr	rhog_@{ii}	sigg_@{ii}
@#end

model
	# phik_C = 100*abs(phik_C_tr);
	# phik_I = phik_C;
	# phih_C = 100*abs(phih_C_tr);
	# phih_I = phih_C;
	# ag = 1 + agtr;
	# zg_C = 1 + abs(zg_C_tr);
	# zg_I = 1 + abs(zg_I_tr);

	1/(C-gam*C{-1}/(AG{-1}*ZG_I{-1}^theta_C*ZG_C{-1}^(1-theta_C)))-
		beta*gam*1/((AG*ZG_I^theta_C*ZG_C^(1-theta_C))*C{+1}-gam*C)=LAMBDA_C;

@#for ii in Sektors
	1/A=(1-theta_@{ii})*LAMBDA_@{ii}*@{ii}/H_@{ii}-phih_@{ii}*LAMBDA_@{ii}*(AG{-1}*H_@{ii}/H_@{ii}{-1}-eta_@{ii})*
		AG{-1}/H_@{ii}{-1}*(1-phik_@{ii}/2*(I_@{ii}/K_@{ii}{-1}-kappa_@{ii})^2)*K_@{ii}{-1}^theta_@{ii}*(Z_@{ii}*H_@{ii})^(1-theta_@{ii})+
		beta*phih_@{ii}*LAMBDA_@{ii}{+1}*(AG*H_@{ii}{+1}/H_@{ii}-eta_@{ii})*AG*H_@{ii}{+1}/H_@{ii}*1/H_@{ii}*(1-phik_@{ii}/2*
		(I_@{ii}{+1}/K_@{ii}-kappa_@{ii})^2)*K_@{ii}^theta_@{ii}*(Z_@{ii}{+1}*H_@{ii}{+1})^(1-theta_@{ii});

	XI_@{ii}=LAMBDA_I
		@#if strcmp(ii,'I')
			*(1
		@#end
		+phik_@{ii}*
		@#if strcmp(ii,'C')
			LAMBDA_@{ii}*
		@#end
		(1-phih_@{ii}/2*(AG{-1}*H_@{ii}/H_@{ii}{-1}-eta_@{ii})^2)*
			(I_@{ii}/K_@{ii}{-1}-kappa_@{ii})*K_@{ii}{-1}^(theta_@{ii}-1)*(Z_@{ii}*H_@{ii})^(1-theta_@{ii})
		@#if strcmp(ii,'I')
			)
		@#end
		;

	AG*Z_I*XI_@{ii}=beta*(1-delta_@{ii})*XI_@{ii}{+1}+beta*theta_@{ii}*LAMBDA_@{ii}{+1}*@{ii}{+1}/K_@{ii}+beta*phik_@{ii}*LAMBDA_@{ii}{+1}*
		(1-phih_@{ii}/2*(AG*H_@{ii}{+1}/H_@{ii}-eta_@{ii})^2)*
			(I_@{ii}{+1}/K_@{ii}-kappa_@{ii})*I_@{ii}{+1}/K_@{ii}*K_@{ii}^(theta_@{ii}-1)*(Z_@{ii}{+1}*H_@{ii}{+1})^(1-theta_@{ii});

	@{ii} = (1-phih_@{ii}/2*(AG{-1}*H_@{ii}/H_@{ii}{-1}-eta_@{ii})^2)*(1-phik_@{ii}/2*(I_@{ii}/K_@{ii}{-1}-kappa_@{ii})^2)*K_@{ii}{-1}^theta_@{ii}*(Z_@{ii}*H_@{ii})^(1-theta_@{ii});

	(1-delta_@{ii})*K_@{ii}{-1}+I_@{ii}=AG*ZG_I*K_@{ii};

	log(Z_@{ii})=log(ZL_@{ii})+log(ZG_@{ii});

	log(ZL_@{ii})=rhol_@{ii}*log(ZL_@{ii}{-1})+sigl_@{ii}*EL_@{ii};

	log(ZG_@{ii}/zg_@{ii})=rhog_@{ii}*log(ZG_@{ii}{-1}/zg_@{ii})+sigg_@{ii}*EG_@{ii};
@#end

	I=I_C+I_I;

	H=H_C+H_I;

	log(A)=log(AL)+log(AG);

	log(AL)=rhola*log(AL{-1})+sigla*ELA;

	log(AG/ag)=rhoga*log(AG{-1}/ag)+sigga*EAG;

	G_C=AG{-1}*ZG_I{-1}^theta_C*ZG_C{-1}^(1-theta_C)*C/C{-1};

	G_I=AG{-1}*ZG_I{-1}*I/I{-1};

	G_H=AG{-1}*H/H{-1};

	% measurement equations
	%-----------------------

	LG_C=log(G_C);

	LG_I=log(G_I);

	LG_H=log(G_H);

%	LG_C=log(steady_state(G_C))*(1+log(G_C/steady_state(G_C)));
%
%	LG_I=log(steady_state(G_I))*(1+log(G_I/steady_state(G_I)));
%
%	LG_H=log(steady_state(G_H))*(1+log(G_H/steady_state(G_H)));

<commit_msg>cosmetic change<commit_after>endogenous C "Consumption" I "Total investment" AG "Growth-rate-stationary pref. process" H "Total labor supply"
AL "level-stationary pref. process" G_H "Growth rate of hours" A "Preference shock"

@#for ii in Sektors
	ZG_@{ii} "Growth-rate-stationary techn. process @{ii}"
	LAMBDA_@{ii} "Multiplier on production @{ii}"
	H_@{ii} "Labor supply in sector @{ii}"
	K_@{ii} "Capital stock in sector @{ii}"
	I_@{ii}	"Investment goods in sector @{ii}"
	Z_@{ii} "Technology shock in sector @{ii}"
	XI_@{ii} "Multiplier on capital accumulation @{ii}"
	ZL_@{ii} "Level-stationary techn. process @{ii}"
	G_@{ii} "Growth rate of @{ii}"
@#end

LG_C LG_I LG_H

observables LG_C LG_I LG_H

exogenous ELA EAG
@#for ii in Sektors
	EL_@{ii} EG_@{ii}
@#end

parameters gam beta	rhola sigla	agtr rhoga sigga  phik_C_tr phih_C_tr

@#for ii in Sektors
	theta_@{ii} eta_@{ii}	kappa_@{ii}	delta_@{ii}	rhol_@{ii}
	sigl_@{ii} zg_@{ii}_tr	rhog_@{ii}	sigg_@{ii}
@#end

model
	# phik_C = 100*abs(phik_C_tr);
	# phik_I = phik_C;
	# phih_C = 100*abs(phih_C_tr);
	# phih_I = phih_C;
	# ag = 1 + agtr;
	# zg_C = 1 + abs(zg_C_tr);
	# zg_I = 1 + abs(zg_I_tr);

	1/(C-gam*C{-1}/(AG{-1}*ZG_I{-1}^theta_C*ZG_C{-1}^(1-theta_C)))-
		beta*gam*1/((AG*ZG_I^theta_C*ZG_C^(1-theta_C))*C{+1}-gam*C)=LAMBDA_C;

@#for ii in Sektors
	1/A=(1-theta_@{ii})*LAMBDA_@{ii}*@{ii}/H_@{ii}-phih_@{ii}*LAMBDA_@{ii}*(AG{-1}*H_@{ii}/H_@{ii}{-1}-eta_@{ii})*
		AG{-1}/H_@{ii}{-1}*(1-phik_@{ii}/2*(I_@{ii}/K_@{ii}{-1}-kappa_@{ii})^2)*K_@{ii}{-1}^theta_@{ii}*(Z_@{ii}*H_@{ii})^(1-theta_@{ii})+
		beta*phih_@{ii}*LAMBDA_@{ii}{+1}*(AG*H_@{ii}{+1}/H_@{ii}-eta_@{ii})*AG*H_@{ii}{+1}/H_@{ii}*1/H_@{ii}*(1-phik_@{ii}/2*
		(I_@{ii}{+1}/K_@{ii}-kappa_@{ii})^2)*K_@{ii}^theta_@{ii}*(Z_@{ii}{+1}*H_@{ii}{+1})^(1-theta_@{ii});

	XI_@{ii}=LAMBDA_I
		@#if strcmp(ii,'I')
			*(1
		@#end
		+phik_@{ii}*
		@#if strcmp(ii,'C')
			LAMBDA_@{ii}*
		@#end
		(1-phih_@{ii}/2*(AG{-1}*H_@{ii}/H_@{ii}{-1}-eta_@{ii})^2)*
			(I_@{ii}/K_@{ii}{-1}-kappa_@{ii})*K_@{ii}{-1}^(theta_@{ii}-1)*(Z_@{ii}*H_@{ii})^(1-theta_@{ii})
		@#if strcmp(ii,'I')
			)
		@#end
		;

	AG*Z_I*XI_@{ii}=beta*(1-delta_@{ii})*XI_@{ii}{+1}+beta*theta_@{ii}*LAMBDA_@{ii}{+1}*@{ii}{+1}/K_@{ii}+beta*phik_@{ii}*LAMBDA_@{ii}{+1}*
		(1-phih_@{ii}/2*(AG*H_@{ii}{+1}/H_@{ii}-eta_@{ii})^2)*
			(I_@{ii}{+1}/K_@{ii}-kappa_@{ii})*I_@{ii}{+1}/K_@{ii}*K_@{ii}^(theta_@{ii}-1)*(Z_@{ii}{+1}*H_@{ii}{+1})^(1-theta_@{ii});

	@{ii} = (1-phih_@{ii}/2*(AG{-1}*H_@{ii}/H_@{ii}{-1}-eta_@{ii})^2)*(1-phik_@{ii}/2*(I_@{ii}/K_@{ii}{-1}-kappa_@{ii})^2)*K_@{ii}{-1}^theta_@{ii}*(Z_@{ii}*H_@{ii})^(1-theta_@{ii});

	(1-delta_@{ii})*K_@{ii}{-1}+I_@{ii}=AG*ZG_I*K_@{ii};

	log(Z_@{ii})=log(ZL_@{ii})+log(ZG_@{ii});

	log(ZL_@{ii})=rhol_@{ii}*log(ZL_@{ii}{-1})+sigl_@{ii}*EL_@{ii};

	log(ZG_@{ii}/zg_@{ii})=rhog_@{ii}*log(ZG_@{ii}{-1}/zg_@{ii})+sigg_@{ii}*EG_@{ii};
@#end

	I=I_C+I_I;

	H=H_C+H_I;

	log(A)=log(AL)+log(AG);

	log(AL)=rhola*log(AL{-1})+sigla*ELA;

	log(AG/ag)=rhoga*log(AG{-1}/ag)+sigga*EAG;

	G_C=AG{-1}*ZG_I{-1}^theta_C*ZG_C{-1}^(1-theta_C)*C/C{-1};

	G_I=AG{-1}*ZG_I{-1}*I/I{-1};

	G_H=AG{-1}*H/H{-1};

	% measurement equations
	%-----------------------

	LG_C=log(G_C);

	LG_I=log(G_I);

	LG_H=log(G_H);

%	LG_C=log(steady_state(G_C))*(1+log(G_C/steady_state(G_C)));
%
%	LG_I=log(steady_state(G_I))*(1+log(G_I/steady_state(G_I)));
%
%	LG_H=log(steady_state(G_H))*(1+log(G_H/steady_state(G_H)));

<|endoftext|>


<commit_before>//! `core_arch`

#[macro_use]
mod macros;

#[cfg(any(target_arch = "arm", target_arch = "aarch64", dox))]
mod acle;

mod simd;

#[cfg_attr(
    bootstrap,
    doc(include = "../stdarch/crates/core_arch/src/core_arch_docs.md")
)]
#[cfg_attr(not(bootstrap), doc(include = "core_arch_docs.md"))]
#[stable(feature = "simd_arch", since = "1.27.0")]
pub mod arch {
    /// Platform-specific intrinsics for the `x86` platform.
    ///
    /// See the [module documentation](../index.html) for more details.
    #[cfg(any(target_arch = "x86", dox))]
    #[doc(cfg(target_arch = "x86"))]
    #[stable(feature = "simd_x86", since = "1.27.0")]
    pub mod x86 {
        #[stable(feature = "simd_x86", since = "1.27.0")]
        pub use crate::core_arch::x86::*;
    }

    /// Platform-specific intrinsics for the `x86_64` platform.
    ///
    /// See the [module documentation](../index.html) for more details.
    #[cfg(any(target_arch = "x86_64", dox))]
    #[doc(cfg(target_arch = "x86_64"))]
    #[stable(feature = "simd_x86", since = "1.27.0")]
    pub mod x86_64 {
        #[stable(feature = "simd_x86", since = "1.27.0")]
        pub use crate::core_arch::x86::*;
        #[stable(feature = "simd_x86", since = "1.27.0")]
        pub use crate::core_arch::x86_64::*;
    }

    /// Platform-specific intrinsics for the `arm` platform.
    ///
    /// See the [module documentation](../index.html) for more details.
    #[cfg(any(target_arch = "arm", dox))]
    #[doc(cfg(target_arch = "arm"))]
    #[unstable(feature = "stdsimd", issue = "27731")]
    pub mod arm {
        pub use crate::core_arch::arm::*;
    }

    /// Platform-specific intrinsics for the `aarch64` platform.
    ///
    /// See the [module documentation](../index.html) for more details.
    #[cfg(any(target_arch = "aarch64", dox))]
    #[doc(cfg(target_arch = "aarch64"))]
    #[unstable(feature = "stdsimd", issue = "27731")]
    pub mod aarch64 {
        pub use crate::core_arch::{aarch64::*, arm::*};
    }

    /// Platform-specific intrinsics for the `wasm32` platform.
    ///
    /// See the [module documentation](../index.html) for more details.
    #[cfg(any(target_arch = "wasm32", dox))]
    #[doc(cfg(target_arch = "wasm32"))]
    #[stable(feature = "simd_wasm32", since = "1.33.0")]
    pub mod wasm32 {
        #[stable(feature = "simd_wasm32", since = "1.33.0")]
        pub use crate::core_arch::wasm32::*;
    }

    /// Platform-specific intrinsics for the `mips` platform.
    ///
    /// See the [module documentation](../index.html) for more details.
    #[cfg(any(target_arch = "mips", dox))]
    #[doc(cfg(target_arch = "mips"))]
    #[unstable(feature = "stdsimd", issue = "27731")]
    pub mod mips {
        pub use crate::core_arch::mips::*;
    }

    /// Platform-specific intrinsics for the `mips64` platform.
    ///
    /// See the [module documentation](../index.html) for more details.
    #[cfg(any(target_arch = "mips64", dox))]
    #[doc(cfg(target_arch = "mips64"))]
    #[unstable(feature = "stdsimd", issue = "27731")]
    pub mod mips64 {
        pub use crate::core_arch::mips::*;
    }

    /// Platform-specific intrinsics for the `PowerPC` platform.
    ///
    /// See the [module documentation](../index.html) for more details.
    #[cfg(any(target_arch = "powerpc", dox))]
    #[doc(cfg(target_arch = "powerpc"))]
    #[unstable(feature = "stdsimd", issue = "27731")]
    pub mod powerpc {
        pub use crate::core_arch::powerpc::*;
    }

    /// Platform-specific intrinsics for the `PowerPC64` platform.
    ///
    /// See the [module documentation](../index.html) for more details.
    #[cfg(any(target_arch = "powerpc64", dox))]
    #[doc(cfg(target_arch = "powerpc64"))]
    #[unstable(feature = "stdsimd", issue = "27731")]
    pub mod powerpc64 {
        pub use crate::core_arch::powerpc64::*;
    }

    /// Platform-specific intrinsics for the `NVPTX` platform.
    ///
    /// See the [module documentation](../index.html) for more details.
    #[cfg(any(target_arch = "nvptx", target_arch = "nvptx64", dox))]
    #[doc(cfg(any(target_arch = "nvptx", target_arch = "nvptx64")))]
    #[unstable(feature = "stdsimd", issue = "27731")]
    pub mod nvptx {
        pub use crate::core_arch::nvptx::*;
    }
}

mod simd_llvm;

#[cfg(any(target_arch = "x86", target_arch = "x86_64", dox))]
#[doc(cfg(any(target_arch = "x86", target_arch = "x86_64")))]
mod x86;
#[cfg(any(target_arch = "x86_64", dox))]
#[doc(cfg(target_arch = "x86_64"))]
mod x86_64;

#[cfg(any(target_arch = "aarch64", dox))]
#[doc(cfg(target_arch = "aarch64"))]
mod aarch64;
#[cfg(any(target_arch = "arm", target_arch = "aarch64", dox))]
#[doc(cfg(any(target_arch = "arm", target_arch = "aarch64")))]
mod arm;

#[cfg(any(target_arch = "wasm32", dox))]
#[doc(cfg(target_arch = "wasm32"))]
mod wasm32;

#[cfg(any(target_arch = "mips", target_arch = "mips64", dox))]
#[doc(cfg(any(target_arch = "mips", target_arch = "mips64")))]
mod mips;

#[cfg(any(target_arch = "powerpc", target_arch = "powerpc64", dox))]
#[doc(cfg(any(target_arch = "powerpc", target_arch = "powerpc64")))]
mod powerpc;

#[cfg(any(target_arch = "powerpc64", dox))]
#[doc(cfg(target_arch = "powerpc64"))]
mod powerpc64;

#[cfg(any(target_arch = "nvptx", target_arch = "nvptx64", dox))]
#[doc(cfg(any(target_arch = "nvptx", target_arch = "nvptx64")))]
mod nvptx;
<commit_msg>Apply snap of bootstrap compiler in rust-lang/rust<commit_after>//! `core_arch`

#[macro_use]
mod macros;

#[cfg(any(target_arch = "arm", target_arch = "aarch64", dox))]
mod acle;

mod simd;

#[doc(include = "core_arch_docs.md")]
#[stable(feature = "simd_arch", since = "1.27.0")]
pub mod arch {
    /// Platform-specific intrinsics for the `x86` platform.
    ///
    /// See the [module documentation](../index.html) for more details.
    #[cfg(any(target_arch = "x86", dox))]
    #[doc(cfg(target_arch = "x86"))]
    #[stable(feature = "simd_x86", since = "1.27.0")]
    pub mod x86 {
        #[stable(feature = "simd_x86", since = "1.27.0")]
        pub use crate::core_arch::x86::*;
    }

    /// Platform-specific intrinsics for the `x86_64` platform.
    ///
    /// See the [module documentation](../index.html) for more details.
    #[cfg(any(target_arch = "x86_64", dox))]
    #[doc(cfg(target_arch = "x86_64"))]
    #[stable(feature = "simd_x86", since = "1.27.0")]
    pub mod x86_64 {
        #[stable(feature = "simd_x86", since = "1.27.0")]
        pub use crate::core_arch::x86::*;
        #[stable(feature = "simd_x86", since = "1.27.0")]
        pub use crate::core_arch::x86_64::*;
    }

    /// Platform-specific intrinsics for the `arm` platform.
    ///
    /// See the [module documentation](../index.html) for more details.
    #[cfg(any(target_arch = "arm", dox))]
    #[doc(cfg(target_arch = "arm"))]
    #[unstable(feature = "stdsimd", issue = "27731")]
    pub mod arm {
        pub use crate::core_arch::arm::*;
    }

    /// Platform-specific intrinsics for the `aarch64` platform.
    ///
    /// See the [module documentation](../index.html) for more details.
    #[cfg(any(target_arch = "aarch64", dox))]
    #[doc(cfg(target_arch = "aarch64"))]
    #[unstable(feature = "stdsimd", issue = "27731")]
    pub mod aarch64 {
        pub use crate::core_arch::{aarch64::*, arm::*};
    }

    /// Platform-specific intrinsics for the `wasm32` platform.
    ///
    /// See the [module documentation](../index.html) for more details.
    #[cfg(any(target_arch = "wasm32", dox))]
    #[doc(cfg(target_arch = "wasm32"))]
    #[stable(feature = "simd_wasm32", since = "1.33.0")]
    pub mod wasm32 {
        #[stable(feature = "simd_wasm32", since = "1.33.0")]
        pub use crate::core_arch::wasm32::*;
    }

    /// Platform-specific intrinsics for the `mips` platform.
    ///
    /// See the [module documentation](../index.html) for more details.
    #[cfg(any(target_arch = "mips", dox))]
    #[doc(cfg(target_arch = "mips"))]
    #[unstable(feature = "stdsimd", issue = "27731")]
    pub mod mips {
        pub use crate::core_arch::mips::*;
    }

    /// Platform-specific intrinsics for the `mips64` platform.
    ///
    /// See the [module documentation](../index.html) for more details.
    #[cfg(any(target_arch = "mips64", dox))]
    #[doc(cfg(target_arch = "mips64"))]
    #[unstable(feature = "stdsimd", issue = "27731")]
    pub mod mips64 {
        pub use crate::core_arch::mips::*;
    }

    /// Platform-specific intrinsics for the `PowerPC` platform.
    ///
    /// See the [module documentation](../index.html) for more details.
    #[cfg(any(target_arch = "powerpc", dox))]
    #[doc(cfg(target_arch = "powerpc"))]
    #[unstable(feature = "stdsimd", issue = "27731")]
    pub mod powerpc {
        pub use crate::core_arch::powerpc::*;
    }

    /// Platform-specific intrinsics for the `PowerPC64` platform.
    ///
    /// See the [module documentation](../index.html) for more details.
    #[cfg(any(target_arch = "powerpc64", dox))]
    #[doc(cfg(target_arch = "powerpc64"))]
    #[unstable(feature = "stdsimd", issue = "27731")]
    pub mod powerpc64 {
        pub use crate::core_arch::powerpc64::*;
    }

    /// Platform-specific intrinsics for the `NVPTX` platform.
    ///
    /// See the [module documentation](../index.html) for more details.
    #[cfg(any(target_arch = "nvptx", target_arch = "nvptx64", dox))]
    #[doc(cfg(any(target_arch = "nvptx", target_arch = "nvptx64")))]
    #[unstable(feature = "stdsimd", issue = "27731")]
    pub mod nvptx {
        pub use crate::core_arch::nvptx::*;
    }
}

mod simd_llvm;

#[cfg(any(target_arch = "x86", target_arch = "x86_64", dox))]
#[doc(cfg(any(target_arch = "x86", target_arch = "x86_64")))]
mod x86;
#[cfg(any(target_arch = "x86_64", dox))]
#[doc(cfg(target_arch = "x86_64"))]
mod x86_64;

#[cfg(any(target_arch = "aarch64", dox))]
#[doc(cfg(target_arch = "aarch64"))]
mod aarch64;
#[cfg(any(target_arch = "arm", target_arch = "aarch64", dox))]
#[doc(cfg(any(target_arch = "arm", target_arch = "aarch64")))]
mod arm;

#[cfg(any(target_arch = "wasm32", dox))]
#[doc(cfg(target_arch = "wasm32"))]
mod wasm32;

#[cfg(any(target_arch = "mips", target_arch = "mips64", dox))]
#[doc(cfg(any(target_arch = "mips", target_arch = "mips64")))]
mod mips;

#[cfg(any(target_arch = "powerpc", target_arch = "powerpc64", dox))]
#[doc(cfg(any(target_arch = "powerpc", target_arch = "powerpc64")))]
mod powerpc;

#[cfg(any(target_arch = "powerpc64", dox))]
#[doc(cfg(target_arch = "powerpc64"))]
mod powerpc64;

#[cfg(any(target_arch = "nvptx", target_arch = "nvptx64", dox))]
#[doc(cfg(any(target_arch = "nvptx", target_arch = "nvptx64")))]
mod nvptx;
<|endoftext|>