<commit_before>// -*- coding: utf-8 -*-
// ------------------------------------------------------------------------------------------------
// Copyright © 2019, HST authors.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
// in compliance with the License.  You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software distributed under the
// License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied.  See the License for the specific language governing permissions and
// limitations under the License.
// ------------------------------------------------------------------------------------------------

//! Defines the external choice (`□`) operator.

use std::fmt::Debug;
use std::fmt::Display;
use std::marker::PhantomData;

use smallvec::smallvec;
use smallvec::SmallVec;

use crate::event::EmptyAlphabet;
use crate::primitives::tau;
use crate::primitives::Tau;
use crate::process::Cursor;
use crate::process::Process;

/// Constructs a new _external choice_ process `P □ Q`.  This process behaves either like `P` _or_
/// `Q`, and the environment gets to choose — the process is willing to do either.
pub fn external_choice<P: From<ExternalChoice
>>(p: P, q: P) -> P {
    ExternalChoice(smallvec![p, q]).into()
}

/// Constructs a new _replicated external choice_ process `□ Ps` over a non-empty collection of
/// processes.  The process behaves like one of the processes in the set, but the environment has
/// no control over which one is chosen.
///
/// Panics if `ps` is empty.
pub fn replicated_external_choice<P: From<ExternalChoice
>, I: IntoIterator<Item = P>>(
    ps: I,
) -> P {
    let ps: SmallVec<[P; 2]> = ps.into_iter().collect();
    ExternalChoice(ps).into()
}

#[doc(hidden)]
#[derive(Clone, Eq, Hash, PartialEq)]
pub struct ExternalChoice
(SmallVec<[P; 2]>);

impl
 Display for ExternalChoice
 {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        if self.0.len() == 2 {
            write!(f, "{} □ {}", self.0[0], self.0[1])
        } else {
            f.write_str("□ ")?;
            f.debug_set().entries(&self.0).finish()
        }
    }
}

impl
 Debug for ExternalChoice
 {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        (self as &dyn Display).fmt(f)
    }
}

// Operational semantics for □ Ps
//
//                  P -τ→ P'
//  1)  ────────────────────────────── P ∈ Ps
//       □ Ps -τ→ □ (Ps ∖ {P} ∪ {P'})
//
//         P -a→ P'
//  2)  ───────────── P ∈ Ps, a ≠ τ
//       □ Ps -a→ P'

#[doc(hidden)]
#[derive(Clone, Eq, Hash, PartialEq)]
pub struct ExternalChoiceCursor<E, C> {
    phantom: PhantomData<E>,
    state: ExternalChoiceState,
    /// The cursors for the choice's subprocesses.  For each one, we keep a vector of cursors, with
    /// each element describing the state after an increasingly large number of τ's have been
    /// performed.  (If a subprocess can't perform any τ's, then there will only ever be a single
    /// subcursor in the corresponding entry of the outer vector.)
    ///
    /// After the choice has been resolved by a visible event, we use the Option part to keep track
    /// of which of the possible choices are able to perform the sequence of events that have
    /// occurred since the choice was resolved.  Subprocesses that aren't able to perform the full
    /// sequence are "eliminated", and retroactively couldn't have been a possible resolution to
    /// the original choice.
    subcursors: Vec<Vec<Option<C>>>,
    /// The number of τ events that have been performed before the choice has been resolved.
    tau_count: usize,
}

#[doc(hidden)]
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub enum ExternalChoiceState {
    Unresolved,
    Resolved,
}

struct Subcursors<'a, C>(&'a Vec<Vec<Option<C>>>);
struct SubcursorTaus<'a, C>(&'a Vec<Option<C>>);
struct SubcursorTau<'a, C>(&'a Option<C>);

impl<E, C> Debug for ExternalChoiceCursor<E, C>
where
    C: Debug,
{
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        f.debug_struct("ExternalChoiceCursor")
            .field("state", &self.state)
            .field("tau_count", &self.tau_count)
            .field("subcursors", &Subcursors(&self.subcursors))
            .finish()
    }
}

impl<'a, C> Debug for Subcursors<'a, C>
where
    C: Debug,
{
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        f.debug_list()
            .entries(self.0.iter().map(SubcursorTaus))
            .finish()
    }
}

impl<'a, C> Debug for SubcursorTaus<'a, C>
where
    C: Debug,
{
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        f.debug_map()
            .entries(self.0.iter().map(SubcursorTau).enumerate())
            .finish()
    }
}

impl<'a, C> Debug for SubcursorTau<'a, C>
where
    C: Debug,
{
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        match self.0 {
            None => f.write_str("None"),
            Some(subcursor) => subcursor.fmt(f),
        }
    }
}

impl<E, P> Process<E> for ExternalChoice

where
    E: Display + Eq + From<Tau> + 'static,
    P: Process<E>,
    P::Cursor: Clone,
{
    type Cursor = ExternalChoiceCursor<E, P::Cursor>;

    fn root(&self) -> Self::Cursor {
        ExternalChoiceCursor {
            phantom: PhantomData,
            state: ExternalChoiceState::Unresolved,
            subcursors: self
                .0
                .iter()
                .map(P::root)
                .map(Some)
                .map(|c| vec![c])
                .collect(),
            tau_count: 0,
        }
    }
}

impl<E, C> ExternalChoiceCursor<E, C> {
    /// Deactivates subprocess states based on the number of τ's that they could have performed
    /// so far, compared to the number of τ's that the choice actually have been performed so far.
    ///
    /// More specifically: Each subprocess will have some number of τ's that it could have
    /// performed, up to a maximum of self.tau_count.  (The subprocess might be willing to perform
    /// more, but we're about to resolve the choice before allowing it to.)  It's only possible for
    /// the subprocess to perform `n` τ's if we can find some way for all of the _other_ τ's (i.e.,
    /// `self.tau_count - n` of them) to be performed by the _other_ τ-eligible subprocesses.  If
    /// we can't, then we deactivate that subprocess state.
    fn deactivate_tau_subprocesses(&mut self) {
        // The total number of τ events performed across all subprocesses at this point.  This will
        // always be ≥ self.tau_count.  It will be larger if there were multiple subprocesses that
        // could perform τ's.
        let total_tau_depth: usize = self.subcursors.iter().map(|taus| taus.len() - 1).sum();

        for taus in &mut self.subcursors {
            // If this subprocess couldn't perform _any_ τ's, then it remains active.  (We might be
            // about to deactivate it based on the visible event that resolves that choice, but
            // it's not being deactivated based on τ's.)
            if taus.len() == 1 {
                continue;
            }

            // The number of τ's this subprocess could have performed.
            let this_tau_count = taus.len() - 1;

            // The total number of τ's that other subprocesses could have performed.
            let remaining_tau_depth = total_tau_depth - this_tau_count;

            if remaining_tau_depth < self.tau_count {
                // The _minimum_ number of τ's this subprocess _must_ perform, to ensure that there
                // are enough other subprocess τ's to cover the total.
                let minimum_tau_count = self.tau_count - remaining_tau_depth;
                for subcursor in taus.iter_mut().take(minimum_tau_count) {
                    subcursor.take();
                }
            }
        }
    }

    fn perform_tau_when_unresolved(&mut self, tau: &E)
    where
        C: Clone + Cursor<E>,
    {
        self.tau_count += 1;

        // For any subprocess that has been able to perform however many τ's occurred _before_
        // this one, try to have it perform another!  If it can, stash away a copy of the
        // subcursor describing its state after this τ.
        for taus in &mut self.subcursors {
            // This subprocess already stopped being able to perform τ's.  No point checking it
            // any further!
            if taus.len() != self.tau_count {
                continue;
            }

            // Check whether this subprocess can perform a τ in the current state.
            let before = taus
                .last()
                .expect("Vector should never be empty")
                .as_ref()
                .expect("All subprocesses should be active in unresolved external choice");
            if !before.can_perform(tau) {
                continue;
            }

            // If so, grab the subprocess's new state after this τ.
            let mut after = before.clone();
            after.perform(tau);
            taus.push(Some(after));
        }

        // Deactivate any τ subprocess states that are no longer eligible (because that state has
        // performed too few τ's, and there aren't enough other subprocesses to make up the
        // difference).
        self.deactivate_tau_subprocesses();
    }

    /// Has each subprocess state that's still activated perform an event, if it can.  If it can't,
    /// deactivates that state.  Returns whether there were any subprocesses that could perform the
    /// event.
    fn perform_and_deactivate(&mut self, event: &E) -> bool
    where
        C: Cursor<E>,
    {
        let mut any_performed = false;
        for subcursor in self.subcursors.iter_mut().flatten() {
            match subcursor {
                Some(subcursor) if subcursor.can_perform(event) => {
                    subcursor.perform(event);
                    any_performed = true;
                }
                Some(_) => {
                    subcursor.take();
                }
                _ => {}
            }
        }
        any_performed
    }

    fn perform_visible_when_unresolved(&mut self, event: &E)
    where
        C: Cursor<E>,
    {
        // Perform the visible event to actually resolve the choice.  This might deactivate
        // additional subprocess states, if any of them can't perform this event.
        self.perform_and_deactivate(event);
        self.state = ExternalChoiceState::Resolved;
    }

    fn perform_when_resolved(&mut self, event: &E)
    where
        C: Cursor<E>,
        E: Display,
    {
        if !self.perform_and_deactivate(event) {
            panic!("Resolved external choice cannot perform {}", event);
        }
    }
}

impl<E, C> Cursor<E> for ExternalChoiceCursor<E, C>
where
    E: Display + Eq + From<Tau>,
    C: Clone + Cursor<E>,
{
    type Alphabet = EmptyAlphabet;

    fn initials(&self) -> EmptyAlphabet {
        EmptyAlphabet
    }

    fn events<'a>(&'a self) -> Box<dyn Iterator<Item = E> + 'a> {
        // Regardless of whether the choice has been resolved yet, we're able to perform any
        // event allowed by any of the still-eligible possible subprocesses.
        Box::new(
            self.subcursors
                .iter()
                // One flatten merges the Vecs, the other takes care of the Options.
                .flatten()
                .flatten()
                .flat_map(C::events),
        )
    }

    fn can_perform(&self, event: &E) -> bool {
        self.subcursors
            .iter()
            // One flatten merges the Vecs, the other takes care of the Options.
            .flatten()
            .flatten()
            .any(|subcursor| subcursor.can_perform(event))
    }

    fn perform(&mut self, event: &E) {
        match self.state {
            ExternalChoiceState::Unresolved => {
                if *event == tau() {
                    self.perform_tau_when_unresolved(event);
                } else {
                    self.perform_visible_when_unresolved(event);
                }
            }
            ExternalChoiceState::Resolved => {
                self.perform_when_resolved(event);
            }
        }
    }
}

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

    use maplit::hashset;
    use proptest_attr_macro::proptest;

    use crate::csp::CSP;
    use crate::process::initials;
    use crate::process::maximal_finite_traces;
    use crate::process::MaximalTraces;
    use crate::test_support::NonemptyVec;
    use crate::test_support::TestEvent;

    #[test]
    fn check_empty_external_choice() {
        let process: CSP<TestEvent> = dbg!(replicated_external_choice(vec![]));
        assert_eq!(maximal_finite_traces(process.root()), hashset! {vec![]});
    }

    #[proptest]
    fn check_singleton_external_choice(p: CSP<TestEvent>) {
        let process = dbg!(replicated_external_choice(vec![p.clone()]));
        assert_eq!(initials(&process.root()), initials(&p.root()));
        assert_eq!(
            maximal_finite_traces(process.root()),
            maximal_finite_traces(p.root())
        );
    }

    #[proptest]
    fn check_doubleton_external_choice(p: CSP<TestEvent>, q: CSP<TestEvent>) {
        let process = dbg!(external_choice(p.clone(), q.clone()));
        assert_eq!(
            initials(&process.root()),
            &initials(&p.root()) | &initials(&q.root())
        );
        assert_eq!(
            maximal_finite_traces(process.root()),
            maximal_finite_traces(p.root()) + maximal_finite_traces(q.root())
        );
    }

    #[proptest]
    fn check_replicated_external_choice(ps: NonemptyVec<CSP<TestEvent>>) {
        let process = dbg!(replicated_external_choice(ps.vec.clone()));
        assert_eq!(
            initials(&process.root()),
            ps.vec
                .iter()
                .map(Process::root)
                .map(|cursor| initials(&cursor))
                .fold(hashset! {}, |prev, next| &prev | &next)
        );
        assert_eq!(
            maximal_finite_traces(process.root()),
            ps.vec
                .iter()
                .map(Process::root)
                .map(maximal_finite_traces)
                .sum::<MaximalTraces<_>>()
        );
    }
}
<commit_msg>Add Alphabet impl for ExternalChoice<commit_after>// -*- coding: utf-8 -*-
// ------------------------------------------------------------------------------------------------
// Copyright © 2019, HST authors.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
// in compliance with the License.  You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software distributed under the
// License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied.  See the License for the specific language governing permissions and
// limitations under the License.
// ------------------------------------------------------------------------------------------------

//! Defines the external choice (`□`) operator.

use std::fmt::Debug;
use std::fmt::Display;
use std::marker::PhantomData;

use smallvec::smallvec;
use smallvec::SmallVec;

use crate::event::Alphabet;
use crate::primitives::tau;
use crate::primitives::Tau;
use crate::process::Cursor;
use crate::process::Process;

/// Constructs a new _external choice_ process `P □ Q`.  This process behaves either like `P` _or_
/// `Q`, and the environment gets to choose — the process is willing to do either.
pub fn external_choice<P: From<ExternalChoice
>>(p: P, q: P) -> P {
    ExternalChoice(smallvec![p, q]).into()
}

/// Constructs a new _replicated external choice_ process `□ Ps` over a non-empty collection of
/// processes.  The process behaves like one of the processes in the set, but the environment has
/// no control over which one is chosen.
///
/// Panics if `ps` is empty.
pub fn replicated_external_choice<P: From<ExternalChoice
>, I: IntoIterator<Item = P>>(
    ps: I,
) -> P {
    let ps: SmallVec<[P; 2]> = ps.into_iter().collect();
    ExternalChoice(ps).into()
}

#[doc(hidden)]
#[derive(Clone, Eq, Hash, PartialEq)]
pub struct ExternalChoice
(SmallVec<[P; 2]>);

impl
 Display for ExternalChoice
 {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        if self.0.len() == 2 {
            write!(f, "{} □ {}", self.0[0], self.0[1])
        } else {
            f.write_str("□ ")?;
            f.debug_set().entries(&self.0).finish()
        }
    }
}

impl
 Debug for ExternalChoice
 {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        (self as &dyn Display).fmt(f)
    }
}

// Operational semantics for □ Ps
//
//                  P -τ→ P'
//  1)  ────────────────────────────── P ∈ Ps
//       □ Ps -τ→ □ (Ps ∖ {P} ∪ {P'})
//
//         P -a→ P'
//  2)  ───────────── P ∈ Ps, a ≠ τ
//       □ Ps -a→ P'

#[doc(hidden)]
#[derive(Clone, Eq, Hash, PartialEq)]
pub struct ExternalChoiceCursor<E, C> {
    phantom: PhantomData<E>,
    state: ExternalChoiceState,
    /// The cursors for the choice's subprocesses.  For each one, we keep a vector of cursors, with
    /// each element describing the state after an increasingly large number of τ's have been
    /// performed.  (If a subprocess can't perform any τ's, then there will only ever be a single
    /// subcursor in the corresponding entry of the outer vector.)
    ///
    /// After the choice has been resolved by a visible event, we use the Option part to keep track
    /// of which of the possible choices are able to perform the sequence of events that have
    /// occurred since the choice was resolved.  Subprocesses that aren't able to perform the full
    /// sequence are "eliminated", and retroactively couldn't have been a possible resolution to
    /// the original choice.
    subcursors: Vec<Vec<Option<C>>>,
    /// The number of τ events that have been performed before the choice has been resolved.
    tau_count: usize,
}

#[doc(hidden)]
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub enum ExternalChoiceState {
    Unresolved,
    Resolved,
}

#[doc(hidden)]
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct ExternalChoiceAlphabet(SmallVec<[A; 2]>);

struct Subcursors<'a, C>(&'a Vec<Vec<Option<C>>>);
struct SubcursorTaus<'a, C>(&'a Vec<Option<C>>);
struct SubcursorTau<'a, C>(&'a Option<C>);

impl<E, C> Debug for ExternalChoiceCursor<E, C>
where
    C: Debug,
{
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        f.debug_struct("ExternalChoiceCursor")
            .field("state", &self.state)
            .field("tau_count", &self.tau_count)
            .field("subcursors", &Subcursors(&self.subcursors))
            .finish()
    }
}

impl<'a, C> Debug for Subcursors<'a, C>
where
    C: Debug,
{
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        f.debug_list()
            .entries(self.0.iter().map(SubcursorTaus))
            .finish()
    }
}

impl<'a, C> Debug for SubcursorTaus<'a, C>
where
    C: Debug,
{
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        f.debug_map()
            .entries(self.0.iter().map(SubcursorTau).enumerate())
            .finish()
    }
}

impl<'a, C> Debug for SubcursorTau<'a, C>
where
    C: Debug,
{
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        match self.0 {
            None => f.write_str("None"),
            Some(subcursor) => subcursor.fmt(f),
        }
    }
}

impl<E, P> Process<E> for ExternalChoice

where
    E: Display + Eq + From<Tau> + 'static,
    P: Process<E>,
    P::Cursor: Clone,
{
    type Cursor = ExternalChoiceCursor<E, P::Cursor>;

    fn root(&self) -> Self::Cursor {
        ExternalChoiceCursor {
            phantom: PhantomData,
            state: ExternalChoiceState::Unresolved,
            subcursors: self
                .0
                .iter()
                .map(P::root)
                .map(Some)
                .map(|c| vec![c])
                .collect(),
            tau_count: 0,
        }
    }
}

impl<E, C> ExternalChoiceCursor<E, C> {
    /// Deactivates subprocess states based on the number of τ's that they could have performed
    /// so far, compared to the number of τ's that the choice actually have been performed so far.
    ///
    /// More specifically: Each subprocess will have some number of τ's that it could have
    /// performed, up to a maximum of self.tau_count.  (The subprocess might be willing to perform
    /// more, but we're about to resolve the choice before allowing it to.)  It's only possible for
    /// the subprocess to perform `n` τ's if we can find some way for all of the _other_ τ's (i.e.,
    /// `self.tau_count - n` of them) to be performed by the _other_ τ-eligible subprocesses.  If
    /// we can't, then we deactivate that subprocess state.
    fn deactivate_tau_subprocesses(&mut self) {
        // The total number of τ events performed across all subprocesses at this point.  This will
        // always be ≥ self.tau_count.  It will be larger if there were multiple subprocesses that
        // could perform τ's.
        let total_tau_depth: usize = self.subcursors.iter().map(|taus| taus.len() - 1).sum();

        for taus in &mut self.subcursors {
            // If this subprocess couldn't perform _any_ τ's, then it remains active.  (We might be
            // about to deactivate it based on the visible event that resolves that choice, but
            // it's not being deactivated based on τ's.)
            if taus.len() == 1 {
                continue;
            }

            // The number of τ's this subprocess could have performed.
            let this_tau_count = taus.len() - 1;

            // The total number of τ's that other subprocesses could have performed.
            let remaining_tau_depth = total_tau_depth - this_tau_count;

            if remaining_tau_depth < self.tau_count {
                // The _minimum_ number of τ's this subprocess _must_ perform, to ensure that there
                // are enough other subprocess τ's to cover the total.
                let minimum_tau_count = self.tau_count - remaining_tau_depth;
                for subcursor in taus.iter_mut().take(minimum_tau_count) {
                    subcursor.take();
                }
            }
        }
    }

    fn perform_tau_when_unresolved(&mut self, tau: &E)
    where
        C: Clone + Cursor<E>,
    {
        self.tau_count += 1;

        // For any subprocess that has been able to perform however many τ's occurred _before_
        // this one, try to have it perform another!  If it can, stash away a copy of the
        // subcursor describing its state after this τ.
        for taus in &mut self.subcursors {
            // This subprocess already stopped being able to perform τ's.  No point checking it
            // any further!
            if taus.len() != self.tau_count {
                continue;
            }

            // Check whether this subprocess can perform a τ in the current state.
            let before = taus
                .last()
                .expect("Vector should never be empty")
                .as_ref()
                .expect("All subprocesses should be active in unresolved external choice");
            if !before.can_perform(tau) {
                continue;
            }

            // If so, grab the subprocess's new state after this τ.
            let mut after = before.clone();
            after.perform(tau);
            taus.push(Some(after));
        }

        // Deactivate any τ subprocess states that are no longer eligible (because that state has
        // performed too few τ's, and there aren't enough other subprocesses to make up the
        // difference).
        self.deactivate_tau_subprocesses();
    }

    /// Has each subprocess state that's still activated perform an event, if it can.  If it can't,
    /// deactivates that state.  Returns whether there were any subprocesses that could perform the
    /// event.
    fn perform_and_deactivate(&mut self, event: &E) -> bool
    where
        C: Cursor<E>,
    {
        let mut any_performed = false;
        for subcursor in self.subcursors.iter_mut().flatten() {
            match subcursor {
                Some(subcursor) if subcursor.can_perform(event) => {
                    subcursor.perform(event);
                    any_performed = true;
                }
                Some(_) => {
                    subcursor.take();
                }
                _ => {}
            }
        }
        any_performed
    }

    fn perform_visible_when_unresolved(&mut self, event: &E)
    where
        C: Cursor<E>,
    {
        // Perform the visible event to actually resolve the choice.  This might deactivate
        // additional subprocess states, if any of them can't perform this event.
        self.perform_and_deactivate(event);
        self.state = ExternalChoiceState::Resolved;
    }

    fn perform_when_resolved(&mut self, event: &E)
    where
        C: Cursor<E>,
        E: Display,
    {
        if !self.perform_and_deactivate(event) {
            panic!("Resolved external choice cannot perform {}", event);
        }
    }
}

impl<E, C> Cursor<E> for ExternalChoiceCursor<E, C>
where
    E: Display + Eq + From<Tau>,
    C: Clone + Cursor<E>,
{
    type Alphabet = ExternalChoiceAlphabet<C::Alphabet>;

    fn initials(&self) -> ExternalChoiceAlphabet<C::Alphabet> {
        ExternalChoiceAlphabet(
            self.subcursors
                .iter()
                // One flatten merges the Vecs, the other takes care of the Options.
                .flatten()
                .flatten()
                .map(C::initials)
                .collect(),
        )
    }

    fn events<'a>(&'a self) -> Box<dyn Iterator<Item = E> + 'a> {
        // Regardless of whether the choice has been resolved yet, we're able to perform any
        // event allowed by any of the still-eligible possible subprocesses.
        Box::new(
            self.subcursors
                .iter()
                // One flatten merges the Vecs, the other takes care of the Options.
                .flatten()
                .flatten()
                .flat_map(C::events),
        )
    }

    fn can_perform(&self, event: &E) -> bool {
        self.subcursors
            .iter()
            // One flatten merges the Vecs, the other takes care of the Options.
            .flatten()
            .flatten()
            .any(|subcursor| subcursor.can_perform(event))
    }

    fn perform(&mut self, event: &E) {
        match self.state {
            ExternalChoiceState::Unresolved => {
                if *event == tau() {
                    self.perform_tau_when_unresolved(event);
                } else {
                    self.perform_visible_when_unresolved(event);
                }
            }
            ExternalChoiceState::Resolved => {
                self.perform_when_resolved(event);
            }
        }
    }
}

impl<E, A> Alphabet<E> for ExternalChoiceAlphabet
where
    A: Alphabet<E>,
{
    fn contains(&self, event: &E) -> bool {
        self.0.iter().any(|alphabet| alphabet.contains(event))
    }
}

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

    use maplit::hashset;
    use proptest_attr_macro::proptest;

    use crate::csp::CSP;
    use crate::process::maximal_finite_traces;
    use crate::process::MaximalTraces;
    use crate::test_support::NonemptyVec;
    use crate::test_support::TestEvent;

    #[proptest]
    fn check_empty_external_choice_initials(event: TestEvent) {
        let process: CSP<TestEvent> = dbg!(replicated_external_choice(vec![]));
        let alphabet = dbg!(process.root().initials());
        assert!(!alphabet.contains(&event));
    }

    #[test]
    fn check_empty_external_choice_traces() {
        let process: CSP<TestEvent> = dbg!(replicated_external_choice(vec![]));
        assert_eq!(maximal_finite_traces(process.root()), hashset! {vec![]});
    }

    #[proptest]
    fn check_singleton_external_choice_initials(event: TestEvent, p: CSP<TestEvent>) {
        let process = dbg!(replicated_external_choice(vec![p.clone()]));
        let alphabet = dbg!(process.root().initials());
        assert_eq!(
            alphabet.contains(&event),
            p.root().initials().contains(&event)
        );
    }

    #[proptest]
    fn check_singleton_external_choice_traces(p: CSP<TestEvent>) {
        let process = dbg!(replicated_external_choice(vec![p.clone()]));
        assert_eq!(
            maximal_finite_traces(process.root()),
            maximal_finite_traces(p.root())
        );
    }

    #[proptest]
    fn check_doubleton_external_choice_initials(
        event: TestEvent,
        p: CSP<TestEvent>,
        q: CSP<TestEvent>,
    ) {
        let process = dbg!(external_choice(p.clone(), q.clone()));
        let alphabet = dbg!(process.root().initials());
        assert_eq!(
            alphabet.contains(&event),
            p.root().initials().contains(&event) || q.root().initials().contains(&event)
        );
    }

    #[proptest]
    fn check_doubleton_external_choice_traces(p: CSP<TestEvent>, q: CSP<TestEvent>) {
        let process = dbg!(external_choice(p.clone(), q.clone()));
        assert_eq!(
            maximal_finite_traces(process.root()),
            maximal_finite_traces(p.root()) + maximal_finite_traces(q.root())
        );
    }

    #[proptest]
    fn check_replicated_external_choice_initials(
        event: TestEvent,
        ps: NonemptyVec<CSP<TestEvent>>,
    ) {
        let process = dbg!(replicated_external_choice(ps.vec.clone()));
        let alphabet = dbg!(process.root().initials());
        assert_eq!(
            alphabet.contains(&event),
            ps.vec.iter().any(|p| p.root().initials().contains(&event))
        );
    }

    #[proptest]
    fn check_replicated_external_choice_traces(ps: NonemptyVec<CSP<TestEvent>>) {
        let process = dbg!(replicated_external_choice(ps.vec.clone()));
        assert_eq!(
            maximal_finite_traces(process.root()),
            ps.vec
                .iter()
                .map(Process::root)
                .map(maximal_finite_traces)
                .sum::<MaximalTraces<_>>()
        );
    }
}
<|endoftext|>


<commit_before>use std::borrow::Borrow;
use std::cmp::{max, min};
use std::mem;

use rustbox::keyboard::Key;
use rustbox::{RustBox};

use tui::style;
use tui::termbox;
use tui::widget::{WidgetRet};

// TODO: Make these settings
const SCROLLOFF : i32 = 5;
const HIST_SIZE : usize = 30;

pub struct TextField {
    /// The message that's currently being edited (not yet sent)
    buffer : Vec<char>,

    /// Cursor in currently shown line
    cursor : i32,

    /// Horizontal scroll
    scroll : i32,

    /// Width of the widget
    width : i32,

    /// A history of sent messages/commands. Once added messages are never
    /// modified. A modification attempt should result in a new buffer with a
    /// copy of the vector in history. (old contents of the buffer will be lost)
    history : Vec<Vec<char>>,

    /// Only available when moving in `history` vector.
    /// INVARIANT: When available, it's a valid index in history.
    hist_curs : Option<i32>,
}

impl TextField {
    pub fn new(width : i32) -> TextField {
        TextField {
            buffer: Vec::with_capacity(512),
            cursor: 0,
            scroll: 0,
            width: width,
            history: Vec::with_capacity(HIST_SIZE),
            hist_curs: None,
        }
    }

    pub fn resize(&mut self, width : i32, _ : i32) {
        self.width = width;
        let cursor = self.cursor;
        self.move_cursor(cursor);
    }

    pub fn draw(&self, _ : &RustBox, pos_x : i32, pos_y : i32) {
        // draw text
        let line_borrow : &[char] = {
            if let Some(hist_curs) = self.hist_curs {
                self.history[hist_curs as usize].borrow()
            } else {
                self.buffer.borrow()
            }
        };

        let slice : &[char] =
            &line_borrow[ self.scroll as usize ..
                          min(line_borrow.len(), (self.scroll + self.width) as usize) ];

        termbox::print_chars(pos_x, pos_y, style::USER_MSG.fg, style::USER_MSG.bg, slice);

        // draw cursor
        // TODO: render the char under the cursor
        termbox::print_char(pos_x + self.cursor - self.scroll, pos_y,
                            style::CURSOR.fg, style::CURSOR.bg,
                            *line_borrow.get(self.cursor as usize).unwrap_or(&' '));
    }

    pub fn keypressed(&mut self, key : Key) -> WidgetRet {
        match key {
            Key::Char(ch) => {
                self.modify();
                self.buffer.insert(self.cursor as usize, ch);
                self.inc_cursor();
                WidgetRet::KeyHandled
            },

            Key::Backspace => {
                if self.cursor > 0 {
                    self.modify();
                    self.buffer.remove(self.cursor as usize - 1);
                    self.dec_cursor();
                }
                WidgetRet::KeyHandled
            },

            Key::Ctrl(ch) => {
                if ch == 'a' {
                    self.move_cursor(0);
                    WidgetRet::KeyHandled
                } else if ch == 'e' {
                    let cur = self.line_len();
                    self.move_cursor(cur);
                    WidgetRet::KeyHandled
                } else if ch == 'k' {
                    self.modify();
                    self.buffer.drain(self.cursor as usize ..);
                    WidgetRet::KeyHandled
                } else if ch == 'w' {
                    self.modify();
                    // TODO: First consume whitespace under the cursor
                    let end_range = self.cursor as usize;
                    let mut begin_range = max(0, self.cursor - 1) as usize;
                    while begin_range > 0
                            && !self.buffer[begin_range].is_whitespace() {
                        begin_range -= 1;
                    }
                    self.buffer.drain(begin_range .. end_range);
                    self.move_cursor(begin_range as i32);
                    WidgetRet::KeyHandled
                } else {
                    WidgetRet::KeyIgnored
                }
            },

            Key::Left => {
                self.dec_cursor();
                WidgetRet::KeyHandled
            },

            Key::Right => {
                self.inc_cursor();
                WidgetRet::KeyHandled
            },

            Key::Enter => {
                let ret = mem::replace(&mut self.buffer, Vec::new());
                if self.history.len() == HIST_SIZE {
                    let mut reuse = self.history.remove(0);
                    reuse.clear();
                    reuse.extend_from_slice(&ret);
                    self.history.push(reuse);
                } else {
                    self.history.push(ret.clone());
                }
                self.move_cursor(0);
                if ret.len() == 0 {
                    WidgetRet::KeyHandled
                } else {
                    WidgetRet::Input(ret)
                }
            },

            ////////////////////////////////////////////////////////////////////
            // Scrolling in history

            Key::Up => {
                match self.hist_curs {
                    Some(hist_curs) if hist_curs > 0 => {
                        self.hist_curs = Some(hist_curs - 1);
                        let cur = self.line_len();
                        self.move_cursor(cur);
                    },
                    Some(_) => {},
                    None => {
                        if !self.history.is_empty() {
                            self.hist_curs = Some((self.history.len() as i32) - 1);
                            let cur = self.line_len();
                            self.move_cursor(cur);
                        }
                    }
                }
                WidgetRet::KeyHandled
            },

            Key::Down => {
                match self.hist_curs {
                    Some(hist_curs) => {
                        if (hist_curs as usize) < self.history.len() - 1 {
                            self.hist_curs = Some(hist_curs + 1);
                            let cur = self.line_len();
                            self.move_cursor(cur);
                        } else {
                            self.hist_curs = None;
                            let cur = self.line_len();
                            self.move_cursor(cur);
                        }
                    },
                    None => {}
                }
                WidgetRet::KeyHandled
            },

            ////////////////////////////////////////////////////////////////////

            _ => WidgetRet::KeyIgnored,
        }
    }

    #[inline]
    fn line_len(&self) -> i32 {
        if let Some(hist_curs) = self.hist_curs {
            self.history[hist_curs as usize].len() as i32
        } else {
            self.buffer.len() as i32
        }
    }

    ////////////////////////////////////////////////////////////////////////////
    // We never modify history, so if the user attempts at a modification, we
    // just make the history entry current message by updating the current
    // buffer. (old contents are lost)

    fn modify(&mut self) {
        if let Some(hist_idx) = self.hist_curs {
            self.buffer.clear();
            self.buffer.extend_from_slice(self.history[hist_idx as usize].borrow());
            self.hist_curs = None;
        }
    }

    ////////////////////////////////////////////////////////////////////////////
    // Manipulating cursor

    fn inc_cursor(&mut self) {
        let cur = min(self.line_len(), self.cursor + 1);
        self.move_cursor(cur);
    }

    fn dec_cursor(&mut self) {
        let cur = max(0, self.cursor - 1);
        self.move_cursor(cur);
    }

    // NOTE: This doesn't do bounds checking! Use dec_cursor() and inc_cursor().
    // move_cursor(0) should always be safe.
    fn move_cursor(&mut self, cursor : i32) {
        self.cursor = cursor;

        if self.line_len() + 1 < self.width {
            self.scroll = 0;
        } else {
            let scrolloff = { if self.width < 2 * SCROLLOFF + 1 { 0 } else { SCROLLOFF } };

            let left_end  = self.scroll;
            let right_end = self.scroll + self.width;

            if cursor - scrolloff < left_end {
                self.scroll = max(0, cursor - scrolloff);
            } else if cursor + scrolloff >= right_end {
                self.scroll = min(// +1 because cursor should be visible, i.e.
                                  // right_end > cursor should hold after this
                                  max(0, cursor + 1 + scrolloff - self.width),
                                  // +1 because cursor goes one more character
                                  // after the buffer, to be able to add chars
                                  max(0, self.line_len() + 1 - self.width));
            }
        }
    }
}
<commit_msg>forgot to remove the TODO comment<commit_after>use std::borrow::Borrow;
use std::cmp::{max, min};
use std::mem;

use rustbox::keyboard::Key;
use rustbox::{RustBox};

use tui::style;
use tui::termbox;
use tui::widget::{WidgetRet};

// TODO: Make these settings
const SCROLLOFF : i32 = 5;
const HIST_SIZE : usize = 30;

pub struct TextField {
    /// The message that's currently being edited (not yet sent)
    buffer : Vec<char>,

    /// Cursor in currently shown line
    cursor : i32,

    /// Horizontal scroll
    scroll : i32,

    /// Width of the widget
    width : i32,

    /// A history of sent messages/commands. Once added messages are never
    /// modified. A modification attempt should result in a new buffer with a
    /// copy of the vector in history. (old contents of the buffer will be lost)
    history : Vec<Vec<char>>,

    /// Only available when moving in `history` vector.
    /// INVARIANT: When available, it's a valid index in history.
    hist_curs : Option<i32>,
}

impl TextField {
    pub fn new(width : i32) -> TextField {
        TextField {
            buffer: Vec::with_capacity(512),
            cursor: 0,
            scroll: 0,
            width: width,
            history: Vec::with_capacity(HIST_SIZE),
            hist_curs: None,
        }
    }

    pub fn resize(&mut self, width : i32, _ : i32) {
        self.width = width;
        let cursor = self.cursor;
        self.move_cursor(cursor);
    }

    pub fn draw(&self, _ : &RustBox, pos_x : i32, pos_y : i32) {
        // draw text
        let line_borrow : &[char] = {
            if let Some(hist_curs) = self.hist_curs {
                self.history[hist_curs as usize].borrow()
            } else {
                self.buffer.borrow()
            }
        };

        let slice : &[char] =
            &line_borrow[ self.scroll as usize ..
                          min(line_borrow.len(), (self.scroll + self.width) as usize) ];

        termbox::print_chars(pos_x, pos_y, style::USER_MSG.fg, style::USER_MSG.bg, slice);

        // draw cursor
        termbox::print_char(pos_x + self.cursor - self.scroll, pos_y,
                            style::CURSOR.fg, style::CURSOR.bg,
                            *line_borrow.get(self.cursor as usize).unwrap_or(&' '));
    }

    pub fn keypressed(&mut self, key : Key) -> WidgetRet {
        match key {
            Key::Char(ch) => {
                self.modify();
                self.buffer.insert(self.cursor as usize, ch);
                self.inc_cursor();
                WidgetRet::KeyHandled
            },

            Key::Backspace => {
                if self.cursor > 0 {
                    self.modify();
                    self.buffer.remove(self.cursor as usize - 1);
                    self.dec_cursor();
                }
                WidgetRet::KeyHandled
            },

            Key::Ctrl(ch) => {
                if ch == 'a' {
                    self.move_cursor(0);
                    WidgetRet::KeyHandled
                } else if ch == 'e' {
                    let cur = self.line_len();
                    self.move_cursor(cur);
                    WidgetRet::KeyHandled
                } else if ch == 'k' {
                    self.modify();
                    self.buffer.drain(self.cursor as usize ..);
                    WidgetRet::KeyHandled
                } else if ch == 'w' {
                    self.modify();
                    // TODO: First consume whitespace under the cursor
                    let end_range = self.cursor as usize;
                    let mut begin_range = max(0, self.cursor - 1) as usize;
                    while begin_range > 0
                            && !self.buffer[begin_range].is_whitespace() {
                        begin_range -= 1;
                    }
                    self.buffer.drain(begin_range .. end_range);
                    self.move_cursor(begin_range as i32);
                    WidgetRet::KeyHandled
                } else {
                    WidgetRet::KeyIgnored
                }
            },

            Key::Left => {
                self.dec_cursor();
                WidgetRet::KeyHandled
            },

            Key::Right => {
                self.inc_cursor();
                WidgetRet::KeyHandled
            },

            Key::Enter => {
                let ret = mem::replace(&mut self.buffer, Vec::new());
                if self.history.len() == HIST_SIZE {
                    let mut reuse = self.history.remove(0);
                    reuse.clear();
                    reuse.extend_from_slice(&ret);
                    self.history.push(reuse);
                } else {
                    self.history.push(ret.clone());
                }
                self.move_cursor(0);
                if ret.len() == 0 {
                    WidgetRet::KeyHandled
                } else {
                    WidgetRet::Input(ret)
                }
            },

            ////////////////////////////////////////////////////////////////////
            // Scrolling in history

            Key::Up => {
                match self.hist_curs {
                    Some(hist_curs) if hist_curs > 0 => {
                        self.hist_curs = Some(hist_curs - 1);
                        let cur = self.line_len();
                        self.move_cursor(cur);
                    },
                    Some(_) => {},
                    None => {
                        if !self.history.is_empty() {
                            self.hist_curs = Some((self.history.len() as i32) - 1);
                            let cur = self.line_len();
                            self.move_cursor(cur);
                        }
                    }
                }
                WidgetRet::KeyHandled
            },

            Key::Down => {
                match self.hist_curs {
                    Some(hist_curs) => {
                        if (hist_curs as usize) < self.history.len() - 1 {
                            self.hist_curs = Some(hist_curs + 1);
                            let cur = self.line_len();
                            self.move_cursor(cur);
                        } else {
                            self.hist_curs = None;
                            let cur = self.line_len();
                            self.move_cursor(cur);
                        }
                    },
                    None => {}
                }
                WidgetRet::KeyHandled
            },

            ////////////////////////////////////////////////////////////////////

            _ => WidgetRet::KeyIgnored,
        }
    }

    #[inline]
    fn line_len(&self) -> i32 {
        if let Some(hist_curs) = self.hist_curs {
            self.history[hist_curs as usize].len() as i32
        } else {
            self.buffer.len() as i32
        }
    }

    ////////////////////////////////////////////////////////////////////////////
    // We never modify history, so if the user attempts at a modification, we
    // just make the history entry current message by updating the current
    // buffer. (old contents are lost)

    fn modify(&mut self) {
        if let Some(hist_idx) = self.hist_curs {
            self.buffer.clear();
            self.buffer.extend_from_slice(self.history[hist_idx as usize].borrow());
            self.hist_curs = None;
        }
    }

    ////////////////////////////////////////////////////////////////////////////
    // Manipulating cursor

    fn inc_cursor(&mut self) {
        let cur = min(self.line_len(), self.cursor + 1);
        self.move_cursor(cur);
    }

    fn dec_cursor(&mut self) {
        let cur = max(0, self.cursor - 1);
        self.move_cursor(cur);
    }

    // NOTE: This doesn't do bounds checking! Use dec_cursor() and inc_cursor().
    // move_cursor(0) should always be safe.
    fn move_cursor(&mut self, cursor : i32) {
        self.cursor = cursor;

        if self.line_len() + 1 < self.width {
            self.scroll = 0;
        } else {
            let scrolloff = { if self.width < 2 * SCROLLOFF + 1 { 0 } else { SCROLLOFF } };

            let left_end  = self.scroll;
            let right_end = self.scroll + self.width;

            if cursor - scrolloff < left_end {
                self.scroll = max(0, cursor - scrolloff);
            } else if cursor + scrolloff >= right_end {
                self.scroll = min(// +1 because cursor should be visible, i.e.
                                  // right_end > cursor should hold after this
                                  max(0, cursor + 1 + scrolloff - self.width),
                                  // +1 because cursor goes one more character
                                  // after the buffer, to be able to add chars
                                  max(0, self.line_len() + 1 - self.width));
            }
        }
    }
}
<|endoftext|>


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

use std::env;
use std::path::{Path, PathBuf};
use std::io::prelude::*;
use std::fs::{canonicalize, read_dir, File};

fn write_shaders(glsl_files: Vec<PathBuf>, shader_file_path: &Path) {
    let mut shader_file = File::create(shader_file_path).unwrap();

    write!(shader_file, "/// AUTO GENERATED BY build.rs\n\n").unwrap();
    write!(shader_file, "use std::collections::HashMap;\n").unwrap();
    write!(shader_file, "lazy_static! {{\n").unwrap();
    write!(shader_file, "  pub static ref SHADERS: HashMap<&'static str, &'static str> = {{\n").unwrap();
    write!(shader_file, "    let mut h = HashMap::with_capacity({});\n", glsl_files.len()).unwrap();
    for glsl in glsl_files {
        let shader_name = glsl.file_name().unwrap().to_str().unwrap();
        // strip .glsl
        let shader_name = shader_name.replace(".glsl", "");
        let full_path = canonicalize(&glsl).unwrap();
        let full_name = full_path.as_os_str().to_str().unwrap();
        // if someone is building on a network share, I'm sorry.
        let full_name = full_name.replace("\\\\?\\", "");
        let full_name = full_name.replace("\\", "/");
        write!(shader_file, "    h.insert(\"{}\", include_str!(\"{}\"));\n",
               shader_name, full_name).unwrap();
    }
    write!(shader_file, "    h\n").unwrap();
    write!(shader_file, "  }};\n").unwrap();
    write!(shader_file, "}}\n").unwrap();
}

fn main() {
    let out_dir = env::var("OUT_DIR").unwrap_or("out".to_owned());

    let shaders_file = Path::new(&out_dir).join("shaders.rs");
    let mut glsl_files = vec![];

    println!("cargo:rerun-if-changed=res");
    let res_dir = Path::new("res");
    for entry in read_dir(res_dir).unwrap() {
        let entry = entry.unwrap();
        let path = entry.path();
        if entry.file_name().to_str().unwrap().ends_with(".glsl") {
            glsl_files.push(path.to_owned());
        }
    }

    write_shaders(glsl_files, &shaders_file);
}
<commit_msg>Make sure we track shader changes in build.rs<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use std::env;
use std::path::{Path, PathBuf};
use std::io::prelude::*;
use std::fs::{canonicalize, read_dir, File};

fn write_shaders(glsl_files: Vec<PathBuf>, shader_file_path: &Path) {
    let mut shader_file = File::create(shader_file_path).unwrap();

    write!(shader_file, "/// AUTO GENERATED BY build.rs\n\n").unwrap();
    write!(shader_file, "use std::collections::HashMap;\n").unwrap();
    write!(shader_file, "lazy_static! {{\n").unwrap();
    write!(shader_file, "  pub static ref SHADERS: HashMap<&'static str, &'static str> = {{\n").unwrap();
    write!(shader_file, "    let mut h = HashMap::with_capacity({});\n", glsl_files.len()).unwrap();
    for glsl in glsl_files {
        let shader_name = glsl.file_name().unwrap().to_str().unwrap();
        // strip .glsl
        let shader_name = shader_name.replace(".glsl", "");
        let full_path = canonicalize(&glsl).unwrap();
        let full_name = full_path.as_os_str().to_str().unwrap();
        // if someone is building on a network share, I'm sorry.
        let full_name = full_name.replace("\\\\?\\", "");
        let full_name = full_name.replace("\\", "/");
        write!(shader_file, "    h.insert(\"{}\", include_str!(\"{}\"));\n",
               shader_name, full_name).unwrap();
    }
    write!(shader_file, "    h\n").unwrap();
    write!(shader_file, "  }};\n").unwrap();
    write!(shader_file, "}}\n").unwrap();
}

fn main() {
    let out_dir = env::var("OUT_DIR").unwrap_or("out".to_owned());

    let shaders_file = Path::new(&out_dir).join("shaders.rs");
    let mut glsl_files = vec![];

    println!("cargo:rerun-if-changed=res");
    let res_dir = Path::new("res");
    for entry in read_dir(res_dir).unwrap() {
        let entry = entry.unwrap();
        let path = entry.path();

        if entry.file_name().to_str().unwrap().ends_with(".glsl") {
            println!("cargo:rerun-if-changed={}", path.display());
            glsl_files.push(path.to_owned());
        }
    }

    write_shaders(glsl_files, &shaders_file);
}
<|endoftext|>


<commit_before>/// π <https://oeis.org/A000796>
pub const PI: f64 =
    3.14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214;

/// sqrt(2) <https://oeis.org/A002193>
pub const SQRT_2: f64 =
    1.41421356237309504880168872420969807856967187537694807317667973799073247846210703885038753432764157f64;

/// sqrt(3) <https://oeis.org/A002194>
pub const SQRT_3: f64 = 1.7320508075688772935274463415058723669428052538103806280558069794519330169088000370811461867572485756756261414154f64;

/// sqrt(6) <https://oeis.org/A010464>
pub const SQRT_6: f64 =
    2.44948974278317809819728407470589139196594748065667012843269256725096037745731502653985943310464023f64;

/// sqrt(2/3) <https://oeis.org/A157697>
pub const SQRT_2_BY_3: f64 =
    0.816496580927726032732428024901963797321982493552223376144230855750320125819105008846619811034880078272864f64;

/// sqt(3/2) <https://oeis.org/A115754>
pub const SQRT_3_BY_2: f64 =
    1.22474487139158904909864203735294569598297374032833506421634628362548018872865751326992971655232011f64;

/// 1/3
pub const ONE_BY_3: f64 =
    0.33333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333f64;

/// 2/3
pub const TWO_BY_3: f64 =
    0.66666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666f64;
<commit_msg>Add numeric constants<commit_after>/// π <https://oeis.org/A000796>
pub const PI: f64 =
    3.14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214;

/// sqrt(2) <https://oeis.org/A002193>
pub const SQRT_2: f64 =
    1.41421356237309504880168872420969807856967187537694807317667973799073247846210703885038753432764157f64;

/// sqrt(3) <https://oeis.org/A002194>
pub const SQRT_3: f64 = 1.7320508075688772935274463415058723669428052538103806280558069794519330169088000370811461867572485756756261414154f64;

/// sqrt(6) <https://oeis.org/A010464>
pub const SQRT_6: f64 =
    2.44948974278317809819728407470589139196594748065667012843269256725096037745731502653985943310464023f64;

/// sqrt(2/3) <https://oeis.org/A157697>
pub const SQRT_2_BY_3: f64 =
    0.816496580927726032732428024901963797321982493552223376144230855750320125819105008846619811034880078272864f64;

/// sqt(3/2) <https://oeis.org/A115754>
pub const SQRT_3_BY_2: f64 =
    1.22474487139158904909864203735294569598297374032833506421634628362548018872865751326992971655232011f64;

/// 1/3
pub const ONE_BY_3: f64 =
    0.33333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333f64;

/// 2/3
pub const TWO_BY_3: f64 =
    0.66666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666f64;

/// 1/sqrt(2) = cos(pi/4) <https://oeis.org/A010503>
pub const ONE_BY_SQRT_2: f64 =
    0.707106781186547524400844362104849039284835937688474036588339868995366239231053519425193767163820786367506f64;

// cos(π/8) = cos(22.5°) <https://oeis.org/A144981>
pub const COS_PI_BY_8: f64 =
    0.923879532511286756128183189396788286822416625863642486115097731280535007501102358714839934850344596097963f64;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#[cfg(test)]
mod tests {
    use super::{COS_PI_BY_8, ONE_BY_3, ONE_BY_SQRT_2, PI, SQRT_2, SQRT_2_BY_3, SQRT_3, SQRT_3_BY_2, SQRT_6, TWO_BY_3};

    #[test]
    fn constants_are_correct() {
        assert_eq!(PI, std::f64::consts::PI);
        assert_eq!(SQRT_2, std::f64::consts::SQRT_2);
        assert_eq!(SQRT_3, f64::sqrt(3.0));
        assert_eq!(SQRT_6, f64::sqrt(6.0));
        assert_eq!(SQRT_2_BY_3, f64::sqrt(2.0 / 3.0));
        assert_eq!(SQRT_3_BY_2, f64::sqrt(3.0 / 2.0));
        assert_eq!(ONE_BY_3, 1.0 / 3.0);
        assert_eq!(TWO_BY_3, 2.0 / 3.0);
        assert_eq!(ONE_BY_SQRT_2, std::f64::consts::FRAC_1_SQRT_2);
        assert_eq!(COS_PI_BY_8, f64::cos(std::f64::consts::PI / 8.0));
    }
}
<|endoftext|>


<commit_before>//! Densely numbered entity references as mapping keys.
//!
//! This module defines an `EntityRef` trait that should be implemented by reference types wrapping
//! a small integer index. The `EntityMap` data structure uses the dense index space to implement a
//! map with a vector. There are primary and secondary entity maps:
//!
//! - A *primary* `EntityMap` contains the main definition of an entity, and it can be used to
//!   allocate new entity references with the `push` method. The values stores in a primary map
//!   must implement the `PrimaryEntityData` marker trait.
//! - A *secondary* `EntityMap` contains additional data about entities kept in a primary map. The
//!   values need to implement `Clone + Default` traits so the map can be grown with `ensure`.

use std::vec::Vec;
use std::default::Default;
use std::marker::PhantomData;
use std::ops::{Index, IndexMut};

/// A type wrapping a small integer index should implement `EntityRef` so it can be used as the key
/// of an `EntityMap`.
pub trait EntityRef: Copy + Eq {
    /// Create a new entity reference from a small integer.
    /// This should crash if the requested index is not representable.
    fn new(usize) -> Self;

    /// Get the index that was used to create this entity reference.
    fn index(self) -> usize;

    /// Convert an `EntityRef` to an `Optional<EntityRef>` by using the default value as the null
    /// reference.
    ///
    /// Entity references are often used in compact data structures like linked lists where a
    /// sentinel 'null' value is needed. Normally we would use an `Optional` for that, but
    /// currently that uses twice the memory of a plain `EntityRef`.
    ///
    /// This method is called `wrap()` because it is the inverse of `unwrap()`.
    fn wrap(self) -> Option<Self>
        where Self: Default
    {
        if self == Self::default() {
            None
        } else {
            Some(self)
        }
    }
}

/// A mapping `K -> V` for densely indexed entity references.
#[derive(Debug, Clone)]
pub struct EntityMap<K, V>
    where K: EntityRef
{
    elems: Vec<V>,
    unused: PhantomData<K>,
}

/// Shared `EntityMap` implementation for all value types.
impl<K, V> EntityMap<K, V>
    where K: EntityRef
{
    /// Create a new empty map.
    pub fn new() -> Self {
        EntityMap {
            elems: Vec::new(),
            unused: PhantomData,
        }
    }

    /// Check if `k` is a valid key in the map.
    pub fn is_valid(&self, k: K) -> bool {
        k.index() < self.elems.len()
    }

    /// Is this map completely empty?
    pub fn is_empty(&self) -> bool {
        self.elems.is_empty()
    }

    /// Remove all entries from this map.
    pub fn clear(&mut self) {
        self.elems.clear()
    }

    /// Iterate over all the keys in this map.
    pub fn keys(&self) -> Keys<K> {
        Keys {
            pos: 0,
            len: self.elems.len(),
            unused: PhantomData,
        }
    }
}

/// A marker trait for data stored in primary entity maps.
///
/// A primary entity map can be used to allocate new entity references with the `push` method. It
/// is important that entity references can't be created anywhere else, so the data stored in a
/// primary entity map must be tagged as `PrimaryEntityData` to unlock the `push` method.
pub trait PrimaryEntityData {}

/// Additional methods for primary entry maps only.
///
/// These are identified by the `PrimaryEntityData` marker trait.
impl<K, V> EntityMap<K, V>
    where K: EntityRef,
          V: PrimaryEntityData
{
    /// Get the key that will be assigned to the next pushed value.
    pub fn next_key(&self) -> K {
        K::new(self.elems.len())
    }

    /// Append `v` to the mapping, assigning a new key which is returned.
    pub fn push(&mut self, v: V) -> K {
        let k = self.next_key();
        self.elems.push(v);
        k
    }

    /// Get the total number of entity references created.
    pub fn len(&self) -> usize {
        self.elems.len()
    }
}

/// Additional methods for value types that implement `Clone` and `Default`.
///
/// When the value type implements these additional traits, the `EntityMap` can be resized
/// explicitly with the `ensure` method.
///
/// Use this for secondary maps that are mapping keys created by another primary map.
impl<K, V> EntityMap<K, V>
    where K: EntityRef,
          V: Clone + Default
{
    /// Create a new secondary `EntityMap` that is prepared to hold `n` elements.
    ///
    /// Use this when the length of the primary map is known:
    /// ```
    /// let secondary_map = EntityMap::with_capacity(primary_map.len());
    /// ```
    pub fn with_capacity(n: usize) -> Self {
        let mut map = EntityMap {
            elems: Vec::with_capacity(n),
            unused: PhantomData,
        };
        map.elems.resize(n, V::default());
        map
    }

    /// Resize the map to have `n` entries by adding default entries as needed.
    pub fn resize(&mut self, n: usize) {
        self.elems.resize(n, V::default());
    }

    /// Ensure that `k` is a valid key but adding default entries if necesssary.
    ///
    /// Return a mutable reference to the corresponding entry.
    pub fn ensure(&mut self, k: K) -> &mut V {
        if !self.is_valid(k) {
            self.resize(k.index() + 1)
        }
        &mut self.elems[k.index()]
    }
}

/// Immutable indexing into an `EntityMap`.
/// The indexed value must be in the map, either because it was created by `push`, or the key was
/// passed to `ensure`.
impl<K, V> Index<K> for EntityMap<K, V>
    where K: EntityRef
{
    type Output = V;

    fn index(&self, k: K) -> &V {
        &self.elems[k.index()]
    }
}

/// Mutable indexing into an `EntityMap`.
/// Use `ensure` instead if the key is not known to be valid.
impl<K, V> IndexMut<K> for EntityMap<K, V>
    where K: EntityRef
{
    fn index_mut(&mut self, k: K) -> &mut V {
        &mut self.elems[k.index()]
    }
}

/// Iterate over all keys in order.
pub struct Keys<K>
    where K: EntityRef
{
    pos: usize,
    len: usize,
    unused: PhantomData<K>,
}

impl<K> Iterator for Keys<K>
    where K: EntityRef
{
    type Item = K;

    fn next(&mut self) -> Option<Self::Item> {
        if self.pos < self.len {
            let k = K::new(self.pos);
            self.pos += 1;
            Some(k)
        } else {
            None
        }
    }
}

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

    // EntityRef impl for testing.
    #[derive(Clone, Copy, Debug, PartialEq, Eq)]
    struct E(u32);

    impl EntityRef for E {
        fn new(i: usize) -> Self {
            E(i as u32)
        }
        fn index(self) -> usize {
            self.0 as usize
        }
    }

    impl PrimaryEntityData for isize {}

    #[test]
    fn basic() {
        let r0 = E(0);
        let r1 = E(1);
        let r2 = E(2);
        let mut m = EntityMap::new();

        let v: Vec<E> = m.keys().collect();
        assert_eq!(v, []);

        assert!(!m.is_valid(r0));
        m.ensure(r2);
        m[r2] = 3;
        assert!(m.is_valid(r1));
        m[r1] = 5;

        assert_eq!(m[r1], 5);
        assert_eq!(m[r2], 3);

        let v: Vec<E> = m.keys().collect();
        assert_eq!(v, [r0, r1, r2]);

        let shared = &m;
        assert_eq!(shared[r0], 0);
        assert_eq!(shared[r1], 5);
        assert_eq!(shared[r2], 3);
    }

    #[test]
    fn push() {
        let mut m = EntityMap::new();
        let k1: E = m.push(12);
        let k2 = m.push(33);

        assert_eq!(m[k1], 12);
        assert_eq!(m[k2], 33);
    }
}
<commit_msg>Expose Vec::get() in EntityMap.<commit_after>//! Densely numbered entity references as mapping keys.
//!
//! This module defines an `EntityRef` trait that should be implemented by reference types wrapping
//! a small integer index. The `EntityMap` data structure uses the dense index space to implement a
//! map with a vector. There are primary and secondary entity maps:
//!
//! - A *primary* `EntityMap` contains the main definition of an entity, and it can be used to
//!   allocate new entity references with the `push` method. The values stores in a primary map
//!   must implement the `PrimaryEntityData` marker trait.
//! - A *secondary* `EntityMap` contains additional data about entities kept in a primary map. The
//!   values need to implement `Clone + Default` traits so the map can be grown with `ensure`.

use std::vec::Vec;
use std::default::Default;
use std::marker::PhantomData;
use std::ops::{Index, IndexMut};

/// A type wrapping a small integer index should implement `EntityRef` so it can be used as the key
/// of an `EntityMap`.
pub trait EntityRef: Copy + Eq {
    /// Create a new entity reference from a small integer.
    /// This should crash if the requested index is not representable.
    fn new(usize) -> Self;

    /// Get the index that was used to create this entity reference.
    fn index(self) -> usize;

    /// Convert an `EntityRef` to an `Optional<EntityRef>` by using the default value as the null
    /// reference.
    ///
    /// Entity references are often used in compact data structures like linked lists where a
    /// sentinel 'null' value is needed. Normally we would use an `Optional` for that, but
    /// currently that uses twice the memory of a plain `EntityRef`.
    ///
    /// This method is called `wrap()` because it is the inverse of `unwrap()`.
    fn wrap(self) -> Option<Self>
        where Self: Default
    {
        if self == Self::default() {
            None
        } else {
            Some(self)
        }
    }
}

/// A mapping `K -> V` for densely indexed entity references.
#[derive(Debug, Clone)]
pub struct EntityMap<K, V>
    where K: EntityRef
{
    elems: Vec<V>,
    unused: PhantomData<K>,
}

/// Shared `EntityMap` implementation for all value types.
impl<K, V> EntityMap<K, V>
    where K: EntityRef
{
    /// Create a new empty map.
    pub fn new() -> Self {
        EntityMap {
            elems: Vec::new(),
            unused: PhantomData,
        }
    }

    /// Check if `k` is a valid key in the map.
    pub fn is_valid(&self, k: K) -> bool {
        k.index() < self.elems.len()
    }

    /// Get the element at `k` if it exists.
    pub fn get(&self, k: K) -> Option<&V> {
        self.elems.get(k.index())
    }

    /// Is this map completely empty?
    pub fn is_empty(&self) -> bool {
        self.elems.is_empty()
    }

    /// Remove all entries from this map.
    pub fn clear(&mut self) {
        self.elems.clear()
    }

    /// Iterate over all the keys in this map.
    pub fn keys(&self) -> Keys<K> {
        Keys {
            pos: 0,
            len: self.elems.len(),
            unused: PhantomData,
        }
    }
}

/// A marker trait for data stored in primary entity maps.
///
/// A primary entity map can be used to allocate new entity references with the `push` method. It
/// is important that entity references can't be created anywhere else, so the data stored in a
/// primary entity map must be tagged as `PrimaryEntityData` to unlock the `push` method.
pub trait PrimaryEntityData {}

/// Additional methods for primary entry maps only.
///
/// These are identified by the `PrimaryEntityData` marker trait.
impl<K, V> EntityMap<K, V>
    where K: EntityRef,
          V: PrimaryEntityData
{
    /// Get the key that will be assigned to the next pushed value.
    pub fn next_key(&self) -> K {
        K::new(self.elems.len())
    }

    /// Append `v` to the mapping, assigning a new key which is returned.
    pub fn push(&mut self, v: V) -> K {
        let k = self.next_key();
        self.elems.push(v);
        k
    }

    /// Get the total number of entity references created.
    pub fn len(&self) -> usize {
        self.elems.len()
    }
}

/// Additional methods for value types that implement `Clone` and `Default`.
///
/// When the value type implements these additional traits, the `EntityMap` can be resized
/// explicitly with the `ensure` method.
///
/// Use this for secondary maps that are mapping keys created by another primary map.
impl<K, V> EntityMap<K, V>
    where K: EntityRef,
          V: Clone + Default
{
    /// Create a new secondary `EntityMap` that is prepared to hold `n` elements.
    ///
    /// Use this when the length of the primary map is known:
    /// ```
    /// let secondary_map = EntityMap::with_capacity(primary_map.len());
    /// ```
    pub fn with_capacity(n: usize) -> Self {
        let mut map = EntityMap {
            elems: Vec::with_capacity(n),
            unused: PhantomData,
        };
        map.elems.resize(n, V::default());
        map
    }

    /// Resize the map to have `n` entries by adding default entries as needed.
    pub fn resize(&mut self, n: usize) {
        self.elems.resize(n, V::default());
    }

    /// Ensure that `k` is a valid key but adding default entries if necesssary.
    ///
    /// Return a mutable reference to the corresponding entry.
    pub fn ensure(&mut self, k: K) -> &mut V {
        if !self.is_valid(k) {
            self.resize(k.index() + 1)
        }
        &mut self.elems[k.index()]
    }
}

/// Immutable indexing into an `EntityMap`.
/// The indexed value must be in the map, either because it was created by `push`, or the key was
/// passed to `ensure`.
impl<K, V> Index<K> for EntityMap<K, V>
    where K: EntityRef
{
    type Output = V;

    fn index(&self, k: K) -> &V {
        &self.elems[k.index()]
    }
}

/// Mutable indexing into an `EntityMap`.
/// Use `ensure` instead if the key is not known to be valid.
impl<K, V> IndexMut<K> for EntityMap<K, V>
    where K: EntityRef
{
    fn index_mut(&mut self, k: K) -> &mut V {
        &mut self.elems[k.index()]
    }
}

/// Iterate over all keys in order.
pub struct Keys<K>
    where K: EntityRef
{
    pos: usize,
    len: usize,
    unused: PhantomData<K>,
}

impl<K> Iterator for Keys<K>
    where K: EntityRef
{
    type Item = K;

    fn next(&mut self) -> Option<Self::Item> {
        if self.pos < self.len {
            let k = K::new(self.pos);
            self.pos += 1;
            Some(k)
        } else {
            None
        }
    }
}

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

    // EntityRef impl for testing.
    #[derive(Clone, Copy, Debug, PartialEq, Eq)]
    struct E(u32);

    impl EntityRef for E {
        fn new(i: usize) -> Self {
            E(i as u32)
        }
        fn index(self) -> usize {
            self.0 as usize
        }
    }

    impl PrimaryEntityData for isize {}

    #[test]
    fn basic() {
        let r0 = E(0);
        let r1 = E(1);
        let r2 = E(2);
        let mut m = EntityMap::new();

        let v: Vec<E> = m.keys().collect();
        assert_eq!(v, []);

        assert!(!m.is_valid(r0));
        m.ensure(r2);
        m[r2] = 3;
        assert!(m.is_valid(r1));
        m[r1] = 5;

        assert_eq!(m[r1], 5);
        assert_eq!(m[r2], 3);

        let v: Vec<E> = m.keys().collect();
        assert_eq!(v, [r0, r1, r2]);

        let shared = &m;
        assert_eq!(shared[r0], 0);
        assert_eq!(shared[r1], 5);
        assert_eq!(shared[r2], 3);
    }

    #[test]
    fn push() {
        let mut m = EntityMap::new();
        let k1: E = m.push(12);
        let k2 = m.push(33);

        assert_eq!(m[k1], 12);
        assert_eq!(m[k2], 33);
    }
}
<|endoftext|>


<commit_before>use super::{ExpressionError, Expression, ElementType};
use std::ops::{Add, Sub, Mul, Div};
use std::num::{Zero, One};
use asexp::Sexp;

pub trait NumType: ElementType + Default + Zero + One + Add<Output=Self> +
Sub<Output=Self> + Mul<Output=Self> + Div<Output=Self> {}

impl ElementType for f32 {}
impl NumType for f32 {}
impl ElementType for f64 {}
impl NumType for f64 {}

/// An expression evaluates to a numeric value of type `NumType`.
#[derive(Clone, PartialEq, Eq, Debug)]
pub enum NumExpr<T: NumType> {
    /// A constant value.
    Const(T),

    /// References a variable by position
    Var(usize),

    Add(Box<NumExpr<T>>, Box<NumExpr<T>>),
    Sub(Box<NumExpr<T>>, Box<NumExpr<T>>),
    Mul(Box<NumExpr<T>>, Box<NumExpr<T>>),
    Div(Box<NumExpr<T>>, Box<NumExpr<T>>),

    /// Safe division with x/0 = 0.0
    Divz(Box<NumExpr<T>>, Box<NumExpr<T>>),

    /// Reciprocal (1 / x).
    Recip(Box<NumExpr<T>>),

    /// Reciprocal using safe division
    Recipz(Box<NumExpr<T>>),
}

impl<T: NumType> Expression for NumExpr<T> {
    type Element = T;

    fn evaluate(&self, variables: &[NumExpr<T>]) -> Result<Self::Element, ExpressionError> {
        Ok(match self {
            &NumExpr::Var(n) => {
                let no_vars: &[NumExpr<T>] = &[];
                try!(try!(variables.get(n).ok_or(ExpressionError::InvalidVariable))
                         .evaluate(no_vars))
            }
            &NumExpr::Const(val) => val,
            &NumExpr::Add(ref e1, ref e2) => {
                try!(e1.evaluate(variables)) + try!(e2.evaluate(variables))
            }
            &NumExpr::Sub(ref e1, ref e2) => {
                try!(e1.evaluate(variables)) - try!(e2.evaluate(variables))
            }
            &NumExpr::Mul(ref e1, ref e2) => {
                try!(e1.evaluate(variables)) * try!(e2.evaluate(variables))
            }
            &NumExpr::Div(ref e1, ref e2) => {
                let a = try!(e1.evaluate(variables));
                let div = try!(e2.evaluate(variables));
                if div == T::zero() {
                    return Err(ExpressionError::DivByZero);
                }
                a / div
            }
            &NumExpr::Divz(ref e1, ref e2) => {
                let a = try!(e1.evaluate(variables));
                let div = try!(e2.evaluate(variables));
                if div == T::zero() {
                    div
                } else {
                    a / div
                }
            }
            &NumExpr::Recip(ref e1) => {
                let div = try!(e1.evaluate(variables));
                if div == T::zero() {
                    return Err(ExpressionError::DivByZero);
                } else {
                    T::one() / div
                }
            }
            &NumExpr::Recipz(ref e1) => {
                let div = try!(e1.evaluate(variables));
                if div == T::zero() {
                    div
                } else {
                    T::one() / div
                }
            }
        })
    }
}

impl<'a, T: NumType + Into<Sexp>> Into<Sexp> for &'a NumExpr<T> {
    fn into(self) -> Sexp {
        match self {
            &NumExpr::Const(n) => n.into(),
            &NumExpr::Var(n) => Sexp::from(format!("${}", n)),
            &NumExpr::Add(ref a, ref b) => {
                Sexp::from(("+",
                            Into::<Sexp>::into(a.as_ref()),
                            Into::<Sexp>::into(b.as_ref())))
            }
            &NumExpr::Sub(ref a, ref b) => {
                Sexp::from(("-",
                            Into::<Sexp>::into(a.as_ref()),
                            Into::<Sexp>::into(b.as_ref())))
            }
            &NumExpr::Mul(ref a, ref b) => {
                Sexp::from(("*",
                            Into::<Sexp>::into(a.as_ref()),
                            Into::<Sexp>::into(b.as_ref())))
            }
            &NumExpr::Div(ref a, ref b) => {
                Sexp::from(("/",
                            Into::<Sexp>::into(a.as_ref()),
                            Into::<Sexp>::into(b.as_ref())))
            }
            &NumExpr::Divz(ref a, ref b) => {
                Sexp::from(("divz",
                            Into::<Sexp>::into(a.as_ref()),
                            Into::<Sexp>::into(b.as_ref())))
            }
            &NumExpr::Recip(ref a) => Sexp::from(("recip", Into::<Sexp>::into(a.as_ref()))),
            &NumExpr::Recipz(ref a) => Sexp::from(("recipz", Into::<Sexp>::into(a.as_ref()))),
        }
    }
}

#[cfg(test)]
const NO_VARS: [NumExpr<f32>; 0] = [];

#[test]
fn test_expr_divz() {
    let expr = NumExpr::Divz(box NumExpr::Const(1.0), box NumExpr::Const(0.0));
    assert_eq!(Ok(0.0), expr.evaluate(&NO_VARS));
}

#[test]
fn test_expr_recipz() {
    let expr = NumExpr::Recipz(box NumExpr::Const(0.0));
    assert_eq!(Ok(0.0), expr.evaluate(&NO_VARS));

    let expr = NumExpr::Recipz(box NumExpr::Const(1.0));
    assert_eq!(Ok(1.0), expr.evaluate(&NO_VARS));

    let expr = NumExpr::Recipz(box NumExpr::Const(0.5));
    assert_eq!(Ok(2.0), expr.evaluate(&NO_VARS));
}

#[test]
fn test_expr() {
    let expr =
        NumExpr::Sub(box NumExpr::Const(0.0),
                     box NumExpr::Div(box NumExpr::Mul(box NumExpr::Add(box NumExpr::Const(1.0),
                                                                        box NumExpr::Var(0)),
                                                       box NumExpr::Var(1)),
                                      box NumExpr::Const(2.0)));

    fn fun(a: f32, b: f32) -> f32 {
        0.0 - ((1.0 + a) * b) / 2.0
    }

    fn check(expr: &NumExpr<f32>, a: f32, b: f32) {
        assert_eq!(Ok(fun(a, b)),
                   expr.evaluate(&[NumExpr::Const(a), NumExpr::Const(b)]))
    }

    check(&expr, 123.0, 4444.0);
    check(&expr, 0.0, -12.0);
}
<commit_msg>Implement NumType and ElementType for u32/u64<commit_after>use super::{ExpressionError, Expression, ElementType};
use std::ops::{Add, Sub, Mul, Div};
use std::num::{Zero, One};
use asexp::Sexp;

pub trait NumType: ElementType + Default + Zero + One + Add<Output=Self> +
Sub<Output=Self> + Mul<Output=Self> + Div<Output=Self> {}

impl ElementType for f32 {}
impl NumType for f32 {}
impl ElementType for f64 {}
impl NumType for f64 {}
impl ElementType for u32 {}
impl NumType for u32 {}
impl ElementType for u64 {}
impl NumType for u64 {}

/// An expression evaluates to a numeric value of type `NumType`.
#[derive(Clone, PartialEq, Eq, Debug)]
pub enum NumExpr<T: NumType> {
    /// A constant value.
    Const(T),

    /// References a variable by position
    Var(usize),

    Add(Box<NumExpr<T>>, Box<NumExpr<T>>),
    Sub(Box<NumExpr<T>>, Box<NumExpr<T>>),
    Mul(Box<NumExpr<T>>, Box<NumExpr<T>>),
    Div(Box<NumExpr<T>>, Box<NumExpr<T>>),

    /// Safe division with x/0 = 0.0
    Divz(Box<NumExpr<T>>, Box<NumExpr<T>>),

    /// Reciprocal (1 / x).
    Recip(Box<NumExpr<T>>),

    /// Reciprocal using safe division
    Recipz(Box<NumExpr<T>>),
}

impl<T: NumType> Expression for NumExpr<T> {
    type Element = T;

    fn evaluate(&self, variables: &[NumExpr<T>]) -> Result<Self::Element, ExpressionError> {
        Ok(match self {
            &NumExpr::Var(n) => {
                let no_vars: &[NumExpr<T>] = &[];
                try!(try!(variables.get(n).ok_or(ExpressionError::InvalidVariable))
                         .evaluate(no_vars))
            }
            &NumExpr::Const(val) => val,
            &NumExpr::Add(ref e1, ref e2) => {
                try!(e1.evaluate(variables)) + try!(e2.evaluate(variables))
            }
            &NumExpr::Sub(ref e1, ref e2) => {
                try!(e1.evaluate(variables)) - try!(e2.evaluate(variables))
            }
            &NumExpr::Mul(ref e1, ref e2) => {
                try!(e1.evaluate(variables)) * try!(e2.evaluate(variables))
            }
            &NumExpr::Div(ref e1, ref e2) => {
                let a = try!(e1.evaluate(variables));
                let div = try!(e2.evaluate(variables));
                if div == T::zero() {
                    return Err(ExpressionError::DivByZero);
                }
                a / div
            }
            &NumExpr::Divz(ref e1, ref e2) => {
                let a = try!(e1.evaluate(variables));
                let div = try!(e2.evaluate(variables));
                if div == T::zero() {
                    div
                } else {
                    a / div
                }
            }
            &NumExpr::Recip(ref e1) => {
                let div = try!(e1.evaluate(variables));
                if div == T::zero() {
                    return Err(ExpressionError::DivByZero);
                } else {
                    T::one() / div
                }
            }
            &NumExpr::Recipz(ref e1) => {
                let div = try!(e1.evaluate(variables));
                if div == T::zero() {
                    div
                } else {
                    T::one() / div
                }
            }
        })
    }
}

impl<'a, T: NumType + Into<Sexp>> Into<Sexp> for &'a NumExpr<T> {
    fn into(self) -> Sexp {
        match self {
            &NumExpr::Const(n) => n.into(),
            &NumExpr::Var(n) => Sexp::from(format!("${}", n)),
            &NumExpr::Add(ref a, ref b) => {
                Sexp::from(("+",
                            Into::<Sexp>::into(a.as_ref()),
                            Into::<Sexp>::into(b.as_ref())))
            }
            &NumExpr::Sub(ref a, ref b) => {
                Sexp::from(("-",
                            Into::<Sexp>::into(a.as_ref()),
                            Into::<Sexp>::into(b.as_ref())))
            }
            &NumExpr::Mul(ref a, ref b) => {
                Sexp::from(("*",
                            Into::<Sexp>::into(a.as_ref()),
                            Into::<Sexp>::into(b.as_ref())))
            }
            &NumExpr::Div(ref a, ref b) => {
                Sexp::from(("/",
                            Into::<Sexp>::into(a.as_ref()),
                            Into::<Sexp>::into(b.as_ref())))
            }
            &NumExpr::Divz(ref a, ref b) => {
                Sexp::from(("divz",
                            Into::<Sexp>::into(a.as_ref()),
                            Into::<Sexp>::into(b.as_ref())))
            }
            &NumExpr::Recip(ref a) => Sexp::from(("recip", Into::<Sexp>::into(a.as_ref()))),
            &NumExpr::Recipz(ref a) => Sexp::from(("recipz", Into::<Sexp>::into(a.as_ref()))),
        }
    }
}

#[cfg(test)]
const NO_VARS: [NumExpr<f32>; 0] = [];

#[test]
fn test_expr_divz() {
    let expr = NumExpr::Divz(box NumExpr::Const(1.0), box NumExpr::Const(0.0));
    assert_eq!(Ok(0.0), expr.evaluate(&NO_VARS));
}

#[test]
fn test_expr_recipz() {
    let expr = NumExpr::Recipz(box NumExpr::Const(0.0));
    assert_eq!(Ok(0.0), expr.evaluate(&NO_VARS));

    let expr = NumExpr::Recipz(box NumExpr::Const(1.0));
    assert_eq!(Ok(1.0), expr.evaluate(&NO_VARS));

    let expr = NumExpr::Recipz(box NumExpr::Const(0.5));
    assert_eq!(Ok(2.0), expr.evaluate(&NO_VARS));
}

#[test]
fn test_expr() {
    let expr =
        NumExpr::Sub(box NumExpr::Const(0.0),
                     box NumExpr::Div(box NumExpr::Mul(box NumExpr::Add(box NumExpr::Const(1.0),
                                                                        box NumExpr::Var(0)),
                                                       box NumExpr::Var(1)),
                                      box NumExpr::Const(2.0)));

    fn fun(a: f32, b: f32) -> f32 {
        0.0 - ((1.0 + a) * b) / 2.0
    }

    fn check(expr: &NumExpr<f32>, a: f32, b: f32) {
        assert_eq!(Ok(fun(a, b)),
                   expr.evaluate(&[NumExpr::Const(a), NumExpr::Const(b)]))
    }

    check(&expr, 123.0, 4444.0);
    check(&expr, 0.0, -12.0);
}
<|endoftext|>


<commit_before>//!
//! A module for implementing the Portaudio Error type and
//! implementing the std Error trait.
//!

/// Error codes returned by PortAudio functions.
#[derive(Copy, Clone, PartialEq, PartialOrd, Debug)]
#[repr(C)]
pub enum Error {
    /// No Error
    NoError = 0,
    /// Portaudio not initialized
    NotInitialized = -10000,
    /// Unanticipated error from the host
    UnanticipatedHostError,
    /// Invalid channel count
    InvalidChannelCount,
    /// Invalid sample rate
    InvalidSampleRate,
    /// Invalid Device
    InvalidDevice,
    /// Invalid Flag
    InvalidFlag,
    /// The Sample format is not supported
    SampleFormatNotSupported,
    /// Input device not compatible with output device
    BadIODeviceCombination,
    /// Memory insufficient
    InsufficientMemory,
    /// The buffer is too big
    BufferTooBig,
    /// The buffer is too small
    BufferTooSmall,
    /// Invalid callback
    NullCallback,
    /// Invalid Stream
    BadStreamPtr,
    /// Time out
    TimedOut,
    /// Portaudio internal error
    InternalError,
    /// Device unavailable
    DeviceUnavailable,
    /// Stream info not compatible with the host
    IncompatibleHostApiSpecificStreamInfo,
    /// The stream is stopped
    StreamIsStopped,
    /// The stream is not stopped
    StreamIsNotStopped,
    /// The input stream has overflowed
    InputOverflowed,
    /// The output has underflowed
    OutputUnderflowed,
    /// The host API is not found by Portaudio
    HostApiNotFound,
    /// The host API is invalid
    InvalidHostApi,
    /// Portaudio cannot read from the callback stream
    CanNotReadFromACallbackStream,
    /// Portaudio cannot write to the callback stream
    CanNotWriteToACallbackStream,
    /// Portaudio cannot read from an output only stream
    CanNotReadFromAnOutputOnlyStream,
    /// Portaudio cannot write to an input only stream
    CanNotWriteToAnInputOnlyStream,
    /// The stream is not compatible with the host API
    IncompatibleStreamHostApi,
    /// Invalid buffer
    BadBufferPtr,
}

impl ::std::fmt::Display for Error {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
        write!(f, "{:?}", self)
    }
}

impl ::std::error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::NoError => "No Error",
            Error::NotInitialized => "PortAudio not initialized",
            Error::UnanticipatedHostError => "Unanticipated error from the host",
            Error::InvalidChannelCount => "Invalid number of channels",
            Error::InvalidSampleRate => "Invalid sample rate",
            Error::InvalidDevice => "Invalid device",
            Error::InvalidFlag => "Invalid flag",
            Error::SampleFormatNotSupported => "Sample format is not supported",
            Error::BadIODeviceCombination => "Input device not compatible with output device",
            Error::InsufficientMemory => "Memory insufficient",
            Error::BufferTooBig => "The buffer is too big",
            Error::BufferTooSmall => "The buffer is too small",
            Error::NullCallback => "Invalid callback",
            Error::BadStreamPtr => "Invalid stream",
            Error::TimedOut => "Time out",
            Error::InternalError => "Portaudio internal error",
            Error::DeviceUnavailable => "Device unavailable",
            Error::IncompatibleHostApiSpecificStreamInfo => "Stream info not compatible with the host",
            Error::StreamIsStopped => "The stream is stopped",
            Error::StreamIsNotStopped => "The stream is not stopped",
            Error::InputOverflowed => "The input stream has overflowed",
            Error::OutputUnderflowed => "The output stream has underflowed",
            Error::HostApiNotFound => "The host api is not found by Portaudio",
            Error::InvalidHostApi => "The host API is invalid",
            Error::CanNotReadFromACallbackStream => "Portaudio cannot read from the callback stream",
            Error::CanNotWriteToACallbackStream => "Portaudio cannot write to the callback stream",
            Error::CanNotReadFromAnOutputOnlyStream => "Portaudio cannot read from an output only stream",
            Error::CanNotWriteToAnInputOnlyStream => "Portaudio cannot write to an input only stream",
            Error::IncompatibleStreamHostApi => "The stream is not compatible with the host API",
            Error::BadBufferPtr => "Invalid buffer",
        }
    }
}

impl ::num::FromPrimitive for Error {

    fn from_i64(n: i64) -> Option<Error> {
        match n {
            0       => Some(Error::NoError),
            -10_000 => Some(Error::NotInitialized),
            -9_999  => Some(Error::UnanticipatedHostError),
            -9_998  => Some(Error::InvalidChannelCount),
            -9_997  => Some(Error::InvalidSampleRate),
            -9_996  => Some(Error::InvalidDevice),
            -9_995  => Some(Error::InvalidFlag),
            -9_994  => Some(Error::SampleFormatNotSupported),
            -9_993  => Some(Error::BadIODeviceCombination),
            -9_992  => Some(Error::InsufficientMemory),
            -9_991  => Some(Error::BufferTooBig),
            -9_990  => Some(Error::BufferTooSmall),
            -9_989  => Some(Error::NullCallback),
            -9_988  => Some(Error::BadStreamPtr),
            -9_987  => Some(Error::TimedOut),
            -9_986  => Some(Error::InternalError),
            -9_985  => Some(Error::DeviceUnavailable),
            -9_984  => Some(Error::IncompatibleHostApiSpecificStreamInfo),
            -9_983  => Some(Error::StreamIsStopped),
            -9_982  => Some(Error::StreamIsNotStopped),
            -9_981  => Some(Error::InputOverflowed),
            -9_980  => Some(Error::OutputUnderflowed),
            -9_979  => Some(Error::HostApiNotFound),
            -9_978  => Some(Error::InvalidHostApi),
            -9_977  => Some(Error::CanNotReadFromACallbackStream),
            -9_976  => Some(Error::CanNotWriteToACallbackStream),
            -9_975  => Some(Error::CanNotReadFromAnOutputOnlyStream),
            -9_974  => Some(Error::CanNotWriteToAnInputOnlyStream),
            -9_973  => Some(Error::IncompatibleStreamHostApi),
            -9_972  => Some(Error::BadBufferPtr),
            _       => None,
        }
    }

    fn from_u64(n: u64) -> Option<Error> {
        match n {
            0 => Some(Error::NoError),
            _ => None,
        }
    }

}

<commit_msg>Fix bug where Error wouldn't convert correctly from unsigned ints<commit_after>//!
//! A module for implementing the Portaudio Error type and
//! implementing the std Error trait.
//!

/// Error codes returned by PortAudio functions.
#[derive(Copy, Clone, PartialEq, PartialOrd, Debug)]
#[repr(C)]
pub enum Error {
    /// No Error
    NoError = 0,
    /// Portaudio not initialized
    NotInitialized = -10000,
    /// Unanticipated error from the host
    UnanticipatedHostError,
    /// Invalid channel count
    InvalidChannelCount,
    /// Invalid sample rate
    InvalidSampleRate,
    /// Invalid Device
    InvalidDevice,
    /// Invalid Flag
    InvalidFlag,
    /// The Sample format is not supported
    SampleFormatNotSupported,
    /// Input device not compatible with output device
    BadIODeviceCombination,
    /// Memory insufficient
    InsufficientMemory,
    /// The buffer is too big
    BufferTooBig,
    /// The buffer is too small
    BufferTooSmall,
    /// Invalid callback
    NullCallback,
    /// Invalid Stream
    BadStreamPtr,
    /// Time out
    TimedOut,
    /// Portaudio internal error
    InternalError,
    /// Device unavailable
    DeviceUnavailable,
    /// Stream info not compatible with the host
    IncompatibleHostApiSpecificStreamInfo,
    /// The stream is stopped
    StreamIsStopped,
    /// The stream is not stopped
    StreamIsNotStopped,
    /// The input stream has overflowed
    InputOverflowed,
    /// The output has underflowed
    OutputUnderflowed,
    /// The host API is not found by Portaudio
    HostApiNotFound,
    /// The host API is invalid
    InvalidHostApi,
    /// Portaudio cannot read from the callback stream
    CanNotReadFromACallbackStream,
    /// Portaudio cannot write to the callback stream
    CanNotWriteToACallbackStream,
    /// Portaudio cannot read from an output only stream
    CanNotReadFromAnOutputOnlyStream,
    /// Portaudio cannot write to an input only stream
    CanNotWriteToAnInputOnlyStream,
    /// The stream is not compatible with the host API
    IncompatibleStreamHostApi,
    /// Invalid buffer
    BadBufferPtr,
}

impl ::std::fmt::Display for Error {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
        write!(f, "{:?}", self)
    }
}

impl ::std::error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::NoError => "No Error",
            Error::NotInitialized => "PortAudio not initialized",
            Error::UnanticipatedHostError => "Unanticipated error from the host",
            Error::InvalidChannelCount => "Invalid number of channels",
            Error::InvalidSampleRate => "Invalid sample rate",
            Error::InvalidDevice => "Invalid device",
            Error::InvalidFlag => "Invalid flag",
            Error::SampleFormatNotSupported => "Sample format is not supported",
            Error::BadIODeviceCombination => "Input device not compatible with output device",
            Error::InsufficientMemory => "Memory insufficient",
            Error::BufferTooBig => "The buffer is too big",
            Error::BufferTooSmall => "The buffer is too small",
            Error::NullCallback => "Invalid callback",
            Error::BadStreamPtr => "Invalid stream",
            Error::TimedOut => "Time out",
            Error::InternalError => "Portaudio internal error",
            Error::DeviceUnavailable => "Device unavailable",
            Error::IncompatibleHostApiSpecificStreamInfo => "Stream info not compatible with the host",
            Error::StreamIsStopped => "The stream is stopped",
            Error::StreamIsNotStopped => "The stream is not stopped",
            Error::InputOverflowed => "The input stream has overflowed",
            Error::OutputUnderflowed => "The output stream has underflowed",
            Error::HostApiNotFound => "The host api is not found by Portaudio",
            Error::InvalidHostApi => "The host API is invalid",
            Error::CanNotReadFromACallbackStream => "Portaudio cannot read from the callback stream",
            Error::CanNotWriteToACallbackStream => "Portaudio cannot write to the callback stream",
            Error::CanNotReadFromAnOutputOnlyStream => "Portaudio cannot read from an output only stream",
            Error::CanNotWriteToAnInputOnlyStream => "Portaudio cannot write to an input only stream",
            Error::IncompatibleStreamHostApi => "The stream is not compatible with the host API",
            Error::BadBufferPtr => "Invalid buffer",
        }
    }
}

impl ::num::FromPrimitive for Error {

    fn from_i64(n: i64) -> Option<Error> {
        match n {
            0       => Some(Error::NoError),
            -10_000 => Some(Error::NotInitialized),
            -9_999  => Some(Error::UnanticipatedHostError),
            -9_998  => Some(Error::InvalidChannelCount),
            -9_997  => Some(Error::InvalidSampleRate),
            -9_996  => Some(Error::InvalidDevice),
            -9_995  => Some(Error::InvalidFlag),
            -9_994  => Some(Error::SampleFormatNotSupported),
            -9_993  => Some(Error::BadIODeviceCombination),
            -9_992  => Some(Error::InsufficientMemory),
            -9_991  => Some(Error::BufferTooBig),
            -9_990  => Some(Error::BufferTooSmall),
            -9_989  => Some(Error::NullCallback),
            -9_988  => Some(Error::BadStreamPtr),
            -9_987  => Some(Error::TimedOut),
            -9_986  => Some(Error::InternalError),
            -9_985  => Some(Error::DeviceUnavailable),
            -9_984  => Some(Error::IncompatibleHostApiSpecificStreamInfo),
            -9_983  => Some(Error::StreamIsStopped),
            -9_982  => Some(Error::StreamIsNotStopped),
            -9_981  => Some(Error::InputOverflowed),
            -9_980  => Some(Error::OutputUnderflowed),
            -9_979  => Some(Error::HostApiNotFound),
            -9_978  => Some(Error::InvalidHostApi),
            -9_977  => Some(Error::CanNotReadFromACallbackStream),
            -9_976  => Some(Error::CanNotWriteToACallbackStream),
            -9_975  => Some(Error::CanNotReadFromAnOutputOnlyStream),
            -9_974  => Some(Error::CanNotWriteToAnInputOnlyStream),
            -9_973  => Some(Error::IncompatibleStreamHostApi),
            -9_972  => Some(Error::BadBufferPtr),
            _       => None,
        }
    }

    fn from_u64(n: u64) -> Option<Error> {
        ::num::FromPrimitive::from_i64(n as i64)
    }

}

<|endoftext|>