<commit_before>//! [Church pair](https://en.wikipedia.org/wiki/Church_encoding#Church_pairs)

use term::*;
use term::Term::*;
use term::Error::*;
use booleans::*;

/// Produces a Church-encoded pair; applying it to two other terms puts them inside it.
///
/// PAIR := λxyz.z x y = λ λ λ 1 3 2
///
/// # Example
/// ```
/// # #[macro_use] extern crate lambda_calculus;
/// # fn main() {
/// use lambda_calculus::pair::pair;
/// use lambda_calculus::arithmetic::{zero, one};
///
/// let pair01 = app!(pair(), zero(), one());
///
/// assert_eq!(pair01.fst_ref(), Ok(&zero()));
/// assert_eq!(pair01.snd_ref(), Ok(&one()));
/// # }
/// ```
pub fn pair() -> Term {
    abs(abs(abs(
        app!(Var(1), Var(3), Var(2))
    )))
}

/// Applied to a Church-encoded pair `(a, b)` it yields `a`.
///
/// FIRST := λp.p TRUE = λ 1 TRUE
///
/// # Example
/// ```
/// # #[macro_use] extern crate lambda_calculus;
/// # fn main() {
/// use lambda_calculus::pair::{pair, first};
/// use lambda_calculus::arithmetic::{zero, one};
/// use lambda_calculus::reduction::beta_full;
/// use lambda_calculus::reduction::Order::*;
///
/// let pair_0_1 = app!(pair(), zero(), one());
///
/// assert_eq!(beta_full(first().app(pair_0_1), &Normal), zero());
/// # }
/// ```
pub fn first() -> Term { abs(Var(1).app(tru())) }

/// Applied to a Church-encoded pair `(a, b)` it yields `b`.
///
/// SECOND := λp.p FALSE = λ 1 FALSE
///
/// # Example
/// ```
/// # #[macro_use] extern crate lambda_calculus;
/// # fn main() {
/// use lambda_calculus::pair::{pair, second};
/// use lambda_calculus::arithmetic::{zero, one};
/// use lambda_calculus::reduction::beta_full;
/// use lambda_calculus::reduction::Order::*;
///
/// let pair_0_1 = app!(pair(), zero(), one());
///
/// assert_eq!(beta_full(second().app(pair_0_1), &Normal), one());
/// # }
/// ```
pub fn second() -> Term { abs(Var(1).app(fls())) }

impl Term {
    /// Checks whether `self` is a Church-encoded pair.
    ///
    /// # Example
    /// ```
    /// # #[macro_use] extern crate lambda_calculus;
    /// # fn main() {
    /// use lambda_calculus::pair::pair;
    /// use lambda_calculus::arithmetic::{zero, one};
    ///
    /// let pair01 = app!(pair(), zero(), one());
    ///
    /// assert!(pair01.is_pair());
    /// # }
    /// ```
    pub fn is_pair(&self) -> bool {
        self.fst_ref().is_ok() && self.snd_ref().is_ok()
    }

    /// Splits a Church-encoded pair into a pair of terms, consuming `self`.
    ///
    /// # Example
    /// ```
    /// # #[macro_use] extern crate lambda_calculus;
    /// # fn main() {
    /// use lambda_calculus::pair::pair;
    /// use lambda_calculus::arithmetic::{zero, one};
    ///
    /// let pair01 = app!(pair(), zero(), one());
    ///
    /// assert_eq!(pair01.unpair(), Ok((zero(), one())));
    /// # }
    /// ```
    pub fn unpair(self) -> Result<(Term, Term), Error> {
        if let Abs(_) = self {
            if let Ok((wrapped_a, b)) = self.unabs().and_then(|t| t.unapp()) {
                Ok((try!(wrapped_a.rhs()), b))
            } else {
                Err(NotAPair)
            }
        } else {
            if let Ok((wrapped_a, b)) = self.unapp() {
                Ok((try!(wrapped_a.rhs()), b))
            } else {
                Err(NotAPair)
            }
        }
    }

    /// Splits a Church-encoded pair into a pair of references to its underlying terms.
    ///
    /// # Example
    /// ```
    /// # #[macro_use] extern crate lambda_calculus;
    /// # fn main() {
    /// use lambda_calculus::pair::pair;
    /// use lambda_calculus::arithmetic::{zero, one};
    ///
    /// let pair01 = app!(pair(), zero(), one());
    ///
    /// assert_eq!(pair01.unpair_ref(), Ok((&zero(), &one())));
    /// # }
    /// ```
    pub fn unpair_ref(&self) -> Result<(&Term, &Term), Error> {
        if let Abs(_) = *self {
            if let Ok((wrapped_a, b)) = self.unabs_ref().and_then(|t| t.unapp_ref()) {
                Ok((try!(wrapped_a.rhs_ref()), b))
            } else {
                Err(NotAPair)
            }
        } else {
            if let Ok((wrapped_a, b)) = self.unapp_ref() {
                Ok((try!(wrapped_a.rhs_ref()), b))
            } else {
                Err(NotAPair)
            }
        }
    }

    /// Splits a Church-encoded pair into a pair of mutable references to its underlying terms.
    ///
    /// # Example
    /// ```
    /// # #[macro_use] extern crate lambda_calculus;
    /// # fn main() {
    /// use lambda_calculus::pair::pair;
    /// use lambda_calculus::arithmetic::{zero, one};
    ///
    /// let mut pair01 = app!(pair(), zero(), one());
    ///
    /// assert_eq!(pair01.unpair_ref_mut(), Ok((&mut zero(), &mut one())));
    /// # }
    /// ```
    pub fn unpair_ref_mut(&mut self) -> Result<(&mut Term, &mut Term), Error> {
        if let Abs(_) = *self {
            if let Ok((wrapped_a, b)) = self.unabs_ref_mut().and_then(|t| t.unapp_ref_mut()) {
                Ok((try!(wrapped_a.rhs_ref_mut()), b))
            } else {
                Err(NotAPair)
            }
        } else {
            if let Ok((wrapped_a, b)) = self.unapp_ref_mut() {
                Ok((try!(wrapped_a.rhs_ref_mut()), b))
            } else {
                Err(NotAPair)
            }
        }
    }

    /// Returns the first term from a Church-encoded pair, consuming `self`.
    ///
    /// # Example
    /// ```
    /// # #[macro_use] extern crate lambda_calculus;
    /// # fn main() {
    /// use lambda_calculus::pair::pair;
    /// use lambda_calculus::arithmetic::{zero, one};
    ///
    /// let pair01 = app!(pair(), zero(), one());
    ///
    /// assert_eq!(pair01.fst(), Ok(zero()));
    /// # }
    /// ```
    pub fn fst(self) -> Result<Term, Error> {
        Ok(try!(self.unpair()).0)
    }

    /// Returns a reference to the first term of a Church-encoded pair.
    ///
    /// # Example
    /// ```
    /// # #[macro_use] extern crate lambda_calculus;
    /// # fn main() {
    /// use lambda_calculus::pair::pair;
    /// use lambda_calculus::arithmetic::{zero, one};
    ///
    /// let pair01 = app!(pair(), zero(), one());
    ///
    /// assert_eq!(pair01.fst_ref(), Ok(&zero()));
    /// # }
    /// ```
    pub fn fst_ref(&self) -> Result<&Term, Error> {
        Ok(try!(self.unpair_ref()).0)
    }

    /// Returns a mutable reference to the first term of a Church-encoded pair.
    /// Returns a reference to the first term of a Church-encoded pair.
    ///
    /// # Example
    /// ```
    /// # #[macro_use] extern crate lambda_calculus;
    /// # fn main() {
    /// use lambda_calculus::pair::pair;
    /// use lambda_calculus::arithmetic::{zero, one};
    ///
    /// let mut pair01 = app!(pair(), zero(), one());
    ///
    /// assert_eq!(pair01.fst_ref_mut(), Ok(&mut zero()));
    /// # }
    /// ```
    pub fn fst_ref_mut(&mut self) -> Result<&mut Term, Error> {
        Ok(try!(self.unpair_ref_mut()).0)
    }

    /// Returns the second term from a Church-encoded pair, consuming `self`.
    ///
    /// # Example
    /// ```
    /// # #[macro_use] extern crate lambda_calculus;
    /// # fn main() {
    /// use lambda_calculus::pair::pair;
    /// use lambda_calculus::arithmetic::{zero, one};
    ///
    /// let pair01 = app!(pair(), zero(), one());
    ///
    /// assert_eq!(pair01.snd(), Ok(one()));
    /// # }
    /// ```
    pub fn snd(self) -> Result<Term, Error> {
        Ok(try!(self.unpair()).1)
    }

    /// Returns a reference to the second term of a Church-encoded pair.
    ///
    /// # Example
    /// ```
    /// # #[macro_use] extern crate lambda_calculus;
    /// # fn main() {
    /// use lambda_calculus::pair::pair;
    /// use lambda_calculus::arithmetic::{zero, one};
    ///
    /// let pair01 = app!(pair(), zero(), one());
    ///
    /// assert_eq!(pair01.snd_ref(), Ok(&one()));
    /// # }
    /// ```
    pub fn snd_ref(&self) -> Result<&Term, Error> {
        Ok(try!(self.unpair_ref()).1)
    }

    /// Returns a mutable reference to the second term of a Church-encoded pair.
    ///
    /// # Example
    /// ```
    /// # #[macro_use] extern crate lambda_calculus;
    /// # fn main() {
    /// use lambda_calculus::pair::pair;
    /// use lambda_calculus::arithmetic::{zero, one};
    ///
    /// let mut pair01 = app!(pair(), zero(), one());
    ///
    /// assert_eq!(pair01.snd_ref_mut(), Ok(&mut one()));
    /// # }
    /// ```
    pub fn snd_ref_mut(&mut self) -> Result<&mut Term, Error> {
        Ok(try!(self.unpair_ref_mut()).1)
    }
}

impl From<(Term, Term)> for Term {
    fn from((t1, t2): (Term, Term)) -> Self {
        abs(app!(Var(1), t1, t2))
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use reduction::beta_full;
    use reduction::Order::*;

    #[test]
    fn pair_from_pair() {
        assert_eq!(Term::from((0.into(), 1.into())),
                   beta_full(app!(pair(), 0.into(), 1.into()), &Normal));
    }

    #[test]
    fn pair_operations() {
        let pair_four_three = beta_full(app!(pair(), 4.into(), 3.into()), &Normal);

        assert!(pair_four_three.is_pair());

        assert_eq!(pair_four_three.fst_ref(), Ok(&4.into()));
        assert_eq!(pair_four_three.snd_ref(), Ok(&3.into()));

        let unpaired = pair_four_three.unpair();
        assert_eq!(unpaired, Ok((4.into(), 3.into())));
    }
}

<commit_msg>migrate pairs to new beta<commit_after>//! [Church pair](https://en.wikipedia.org/wiki/Church_encoding#Church_pairs)

use term::*;
use term::Term::*;
use term::Error::*;
use booleans::*;

/// Produces a Church-encoded pair; applying it to two other terms puts them inside it.
///
/// PAIR := λxyz.z x y = λ λ λ 1 3 2
///
/// # Example
/// ```
/// # #[macro_use] extern crate lambda_calculus;
/// # fn main() {
/// use lambda_calculus::pair::pair;
/// use lambda_calculus::arithmetic::{zero, one};
///
/// let pair01 = app!(pair(), zero(), one());
///
/// assert_eq!(pair01.fst_ref(), Ok(&zero()));
/// assert_eq!(pair01.snd_ref(), Ok(&one()));
/// # }
/// ```
pub fn pair() -> Term {
    abs(abs(abs(
        app!(Var(1), Var(3), Var(2))
    )))
}

/// Applied to a Church-encoded pair `(a, b)` it yields `a`.
///
/// FIRST := λp.p TRUE = λ 1 TRUE
///
/// # Example
/// ```
/// # #[macro_use] extern crate lambda_calculus;
/// # fn main() {
/// use lambda_calculus::pair::{pair, first};
/// use lambda_calculus::arithmetic::{zero, one};
/// use lambda_calculus::reduction::beta;
/// use lambda_calculus::reduction::Order::*;
///
/// let pair_0_1 = app!(pair(), zero(), one());
///
/// assert_eq!(beta(first().app(pair_0_1), &Normal, None), zero());
/// # }
/// ```
pub fn first() -> Term { abs(Var(1).app(tru())) }

/// Applied to a Church-encoded pair `(a, b)` it yields `b`.
///
/// SECOND := λp.p FALSE = λ 1 FALSE
///
/// # Example
/// ```
/// # #[macro_use] extern crate lambda_calculus;
/// # fn main() {
/// use lambda_calculus::pair::{pair, second};
/// use lambda_calculus::arithmetic::{zero, one};
/// use lambda_calculus::reduction::beta;
/// use lambda_calculus::reduction::Order::*;
///
/// let pair_0_1 = app!(pair(), zero(), one());
///
/// assert_eq!(beta(second().app(pair_0_1), &Normal, None), one());
/// # }
/// ```
pub fn second() -> Term { abs(Var(1).app(fls())) }

impl Term {
    /// Checks whether `self` is a Church-encoded pair.
    ///
    /// # Example
    /// ```
    /// # #[macro_use] extern crate lambda_calculus;
    /// # fn main() {
    /// use lambda_calculus::pair::pair;
    /// use lambda_calculus::arithmetic::{zero, one};
    ///
    /// let pair01 = app!(pair(), zero(), one());
    ///
    /// assert!(pair01.is_pair());
    /// # }
    /// ```
    pub fn is_pair(&self) -> bool {
        self.fst_ref().is_ok() && self.snd_ref().is_ok()
    }

    /// Splits a Church-encoded pair into a pair of terms, consuming `self`.
    ///
    /// # Example
    /// ```
    /// # #[macro_use] extern crate lambda_calculus;
    /// # fn main() {
    /// use lambda_calculus::pair::pair;
    /// use lambda_calculus::arithmetic::{zero, one};
    ///
    /// let pair01 = app!(pair(), zero(), one());
    ///
    /// assert_eq!(pair01.unpair(), Ok((zero(), one())));
    /// # }
    /// ```
    pub fn unpair(self) -> Result<(Term, Term), Error> {
        if let Abs(_) = self {
            if let Ok((wrapped_a, b)) = self.unabs().and_then(|t| t.unapp()) {
                Ok((try!(wrapped_a.rhs()), b))
            } else {
                Err(NotAPair)
            }
        } else {
            if let Ok((wrapped_a, b)) = self.unapp() {
                Ok((try!(wrapped_a.rhs()), b))
            } else {
                Err(NotAPair)
            }
        }
    }

    /// Splits a Church-encoded pair into a pair of references to its underlying terms.
    ///
    /// # Example
    /// ```
    /// # #[macro_use] extern crate lambda_calculus;
    /// # fn main() {
    /// use lambda_calculus::pair::pair;
    /// use lambda_calculus::arithmetic::{zero, one};
    ///
    /// let pair01 = app!(pair(), zero(), one());
    ///
    /// assert_eq!(pair01.unpair_ref(), Ok((&zero(), &one())));
    /// # }
    /// ```
    pub fn unpair_ref(&self) -> Result<(&Term, &Term), Error> {
        if let Abs(_) = *self {
            if let Ok((wrapped_a, b)) = self.unabs_ref().and_then(|t| t.unapp_ref()) {
                Ok((try!(wrapped_a.rhs_ref()), b))
            } else {
                Err(NotAPair)
            }
        } else {
            if let Ok((wrapped_a, b)) = self.unapp_ref() {
                Ok((try!(wrapped_a.rhs_ref()), b))
            } else {
                Err(NotAPair)
            }
        }
    }

    /// Splits a Church-encoded pair into a pair of mutable references to its underlying terms.
    ///
    /// # Example
    /// ```
    /// # #[macro_use] extern crate lambda_calculus;
    /// # fn main() {
    /// use lambda_calculus::pair::pair;
    /// use lambda_calculus::arithmetic::{zero, one};
    ///
    /// let mut pair01 = app!(pair(), zero(), one());
    ///
    /// assert_eq!(pair01.unpair_ref_mut(), Ok((&mut zero(), &mut one())));
    /// # }
    /// ```
    pub fn unpair_ref_mut(&mut self) -> Result<(&mut Term, &mut Term), Error> {
        if let Abs(_) = *self {
            if let Ok((wrapped_a, b)) = self.unabs_ref_mut().and_then(|t| t.unapp_ref_mut()) {
                Ok((try!(wrapped_a.rhs_ref_mut()), b))
            } else {
                Err(NotAPair)
            }
        } else {
            if let Ok((wrapped_a, b)) = self.unapp_ref_mut() {
                Ok((try!(wrapped_a.rhs_ref_mut()), b))
            } else {
                Err(NotAPair)
            }
        }
    }

    /// Returns the first term from a Church-encoded pair, consuming `self`.
    ///
    /// # Example
    /// ```
    /// # #[macro_use] extern crate lambda_calculus;
    /// # fn main() {
    /// use lambda_calculus::pair::pair;
    /// use lambda_calculus::arithmetic::{zero, one};
    ///
    /// let pair01 = app!(pair(), zero(), one());
    ///
    /// assert_eq!(pair01.fst(), Ok(zero()));
    /// # }
    /// ```
    pub fn fst(self) -> Result<Term, Error> {
        Ok(try!(self.unpair()).0)
    }

    /// Returns a reference to the first term of a Church-encoded pair.
    ///
    /// # Example
    /// ```
    /// # #[macro_use] extern crate lambda_calculus;
    /// # fn main() {
    /// use lambda_calculus::pair::pair;
    /// use lambda_calculus::arithmetic::{zero, one};
    ///
    /// let pair01 = app!(pair(), zero(), one());
    ///
    /// assert_eq!(pair01.fst_ref(), Ok(&zero()));
    /// # }
    /// ```
    pub fn fst_ref(&self) -> Result<&Term, Error> {
        Ok(try!(self.unpair_ref()).0)
    }

    /// Returns a mutable reference to the first term of a Church-encoded pair.
    /// Returns a reference to the first term of a Church-encoded pair.
    ///
    /// # Example
    /// ```
    /// # #[macro_use] extern crate lambda_calculus;
    /// # fn main() {
    /// use lambda_calculus::pair::pair;
    /// use lambda_calculus::arithmetic::{zero, one};
    ///
    /// let mut pair01 = app!(pair(), zero(), one());
    ///
    /// assert_eq!(pair01.fst_ref_mut(), Ok(&mut zero()));
    /// # }
    /// ```
    pub fn fst_ref_mut(&mut self) -> Result<&mut Term, Error> {
        Ok(try!(self.unpair_ref_mut()).0)
    }

    /// Returns the second term from a Church-encoded pair, consuming `self`.
    ///
    /// # Example
    /// ```
    /// # #[macro_use] extern crate lambda_calculus;
    /// # fn main() {
    /// use lambda_calculus::pair::pair;
    /// use lambda_calculus::arithmetic::{zero, one};
    ///
    /// let pair01 = app!(pair(), zero(), one());
    ///
    /// assert_eq!(pair01.snd(), Ok(one()));
    /// # }
    /// ```
    pub fn snd(self) -> Result<Term, Error> {
        Ok(try!(self.unpair()).1)
    }

    /// Returns a reference to the second term of a Church-encoded pair.
    ///
    /// # Example
    /// ```
    /// # #[macro_use] extern crate lambda_calculus;
    /// # fn main() {
    /// use lambda_calculus::pair::pair;
    /// use lambda_calculus::arithmetic::{zero, one};
    ///
    /// let pair01 = app!(pair(), zero(), one());
    ///
    /// assert_eq!(pair01.snd_ref(), Ok(&one()));
    /// # }
    /// ```
    pub fn snd_ref(&self) -> Result<&Term, Error> {
        Ok(try!(self.unpair_ref()).1)
    }

    /// Returns a mutable reference to the second term of a Church-encoded pair.
    ///
    /// # Example
    /// ```
    /// # #[macro_use] extern crate lambda_calculus;
    /// # fn main() {
    /// use lambda_calculus::pair::pair;
    /// use lambda_calculus::arithmetic::{zero, one};
    ///
    /// let mut pair01 = app!(pair(), zero(), one());
    ///
    /// assert_eq!(pair01.snd_ref_mut(), Ok(&mut one()));
    /// # }
    /// ```
    pub fn snd_ref_mut(&mut self) -> Result<&mut Term, Error> {
        Ok(try!(self.unpair_ref_mut()).1)
    }
}

impl From<(Term, Term)> for Term {
    fn from((t1, t2): (Term, Term)) -> Self {
        abs(app!(Var(1), t1, t2))
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use reduction::beta;
    use reduction::Order::*;

    #[test]
    fn pair_from_pair() {
        assert_eq!(Term::from((0.into(), 1.into())),
                   beta(app!(pair(), 0.into(), 1.into()), &Normal, None));
    }

    #[test]
    fn pair_operations() {
        let pair_four_three = beta(app!(pair(), 4.into(), 3.into()), &Normal, None);

        assert!(pair_four_three.is_pair());

        assert_eq!(pair_four_three.fst_ref(), Ok(&4.into()));
        assert_eq!(pair_four_three.snd_ref(), Ok(&3.into()));

        let unpaired = pair_four_three.unpair();
        assert_eq!(unpaired, Ok((4.into(), 3.into())));
    }
}

<|endoftext|>


<commit_before>//! Safe-interface corresponding to out-place transform

use super::aligned_vec::*;
use super::enums::*;
use super::plan::*;
use super::r2r::*;

use num_traits::Zero;

/// Safe-interface corresponding to out-place transform
///
/// FFTW interface modifies an array in `fftw_execute` function
/// which does not takes the array as its arguments.
/// It is not compatible to the programing model of safe Rust.
/// `Pair` interface composes the array and plan to manage
/// mutability in the safe Rust way.
pub struct Pair<A, B> {
    pub field: AlignedVec<A>,
    pub coef: AlignedVec<B>,
    logical_size: usize,
    forward: Plan<A, B>,
    backward: Plan<B, A>,
}

impl<A, B> Pair<A, B> {
    pub fn logical_size(&self) -> usize {
        self.logical_size
    }

    /// Execute forward transformation
    pub fn forward(&mut self) {
        unsafe {
            self.forward.execute();
        }
    }

    /// Execute backward transformation
    pub fn backward(&mut self) {
        unsafe {
            self.backward.execute();
        }
    }
}

impl<R> Pair<R, R>
where
    R: R2RPlanCreate + AlignedAllocable + Zero,
{
    /// Create one-dimensional Real-to-Real transformation pair
    pub fn r2r_1d(n: usize, kind: R2R_KIND, flag: FLAG) -> Self {
        let mut field = AlignedVec::new(n);
        let mut coef = AlignedVec::new(n);
        let forward = Plan::r2r_1d(n, &mut field, &mut coef, forward(kind), flag);
        let backward = Plan::r2r_1d(n, &mut coef, &mut field, backward(kind), flag);
        Pair {
            field: field,
            coef: coef,
            logical_size: logical_size(n, kind),
            forward: forward,
            backward: backward,
        }
    }
}

impl<C> Pair<C, C>
where
    C: C2CPlanCreate + AlignedAllocable + Zero,
{
    /// Create one-dimensional Complex-to-Complex transformation pair
    pub fn c2c_1d(n: usize, sign: SIGN, flag: FLAG) -> Self {
        let mut field = AlignedVec::new(n);
        let mut coef = AlignedVec::new(n);
        let forward = Plan::c2c_1d(n, &mut field, &mut coef, sign, flag);
        let backward = Plan::c2c_1d(n, &mut coef, &mut field, -sign, flag);
        Pair {
            field: field,
            coef: coef,
            logical_size: n,
            forward: forward,
            backward: backward,
        }
    }
}

impl<R, C> Pair<R, C>
where
    (C, R): C2RPlanCreate<Real = R, Complex = C>,
    R: AlignedAllocable + Zero,
    C: AlignedAllocable + Zero,
{
    /// Create one-dimensional Real-to-Complex transformation pair
    pub fn r2c_1d(n: usize, flag: FLAG) -> Self {
        let mut field = AlignedVec::<R>::new(n);
        let mut coef = AlignedVec::<C>::new(n / 2 + 1);
        let forward = Plan::r2c_1d(n, &mut field, &mut coef, flag);
        let backward = Plan::c2r_1d(n, &mut coef, &mut field, flag);
        Pair {
            field: field,
            coef: coef,
            logical_size: n,
            forward: forward,
            backward: backward,
        }
    }
}
<commit_msg>Add ToPair trait and configure structs<commit_after>//! Safe-interface corresponding to out-place transform

use super::aligned_vec::*;
use super::enums::*;
use super::plan::*;
use super::r2r::*;

use ndarray::*;
use num_traits::Zero;
use std::marker::PhantomData;

/// Safe-interface corresponding to out-place transform
///
/// FFTW interface modifies an array in `fftw_execute` function
/// which does not takes the array as its arguments.
/// It is not compatible to the programing model of safe Rust.
/// `Pair` interface composes the array and plan to manage
/// mutability in the safe Rust way.
pub struct Pair<A, B, D> {
    pub field: AlignedVec<A>,
    pub coef: AlignedVec<B>,
    logical_size: usize,
    forward: RawPlan,
    backward: RawPlan,
    phantom: PhantomData<D>,
}

impl<A, B, D: Dimension> Pair<A, B, D> {
    pub fn logical_size(&self) -> usize {
        self.logical_size
    }

    /// Execute forward transformation
    pub fn forward(&mut self) {
        unsafe {
            self.forward.execute();
        }
    }

    /// Execute backward transformation
    pub fn backward(&mut self) {
        unsafe {
            self.backward.execute();
        }
    }
}

pub trait ToPair<A, B> {
    type Dim: Dimension;
    fn to_pair(&self) -> Pair<A, B, Self::Dim>;
}

#[derive(Debug, Clone, Copy)]
pub struct R2R1D {
    n: usize,
    kind: R2R_KIND,
    flag: FLAG,
}

impl<T: R2R + AlignedAllocable + Zero> ToPair<T, T> for R2R1D {
    type Dim = Ix1;
    fn to_pair(&self) -> Pair<T, T, Ix1> {
        let mut field = AlignedVec::new(self.n);
        let mut coef = AlignedVec::new(self.n);
        let forward = unsafe { T::r2r_1d(self.n, &mut field, &mut coef, forward(self.kind), self.flag) };
        let backward = unsafe {
            T::r2r_1d(
                self.n,
                &mut coef,
                &mut field,
                backward(self.kind),
                self.flag,
            )
        };
        Pair {
            field: field,
            coef: coef,
            logical_size: logical_size(self.n, self.kind),
            forward: forward,
            backward: backward,
            phantom: PhantomData,
        }
    }
}

#[derive(Debug, Clone, Copy)]
pub struct C2C1D {
    n: usize,
    sign: SIGN,
    flag: FLAG,
}

impl<T: C2C + AlignedAllocable + Zero> ToPair<T, T> for C2C1D {
    type Dim = Ix1;
    fn to_pair(&self) -> Pair<T, T, Ix1> {
        let mut field = AlignedVec::new(self.n);
        let mut coef = AlignedVec::new(self.n);
        let forward = unsafe { T::c2c_1d(self.n, &mut field, &mut coef, self.sign, self.flag) };
        let backward = unsafe { T::c2c_1d(self.n, &mut coef, &mut field, -self.sign, self.flag) };
        Pair {
            field: field,
            coef: coef,
            logical_size: self.n,
            forward: forward,
            backward: backward,
            phantom: PhantomData,
        }
    }
}

#[derive(Debug, Clone, Copy)]
pub struct R2C1D {
    n: usize,
    flag: FLAG,
}

impl<R, C> ToPair<R, C> for R2C1D
where
    (C, R): C2R<Real = R, Complex = C>,
    R: AlignedAllocable + Zero,
    C: AlignedAllocable + Zero,
{
    type Dim = Ix1;
    fn to_pair(&self) -> Pair<R, C, Ix1> {
        let mut field = AlignedVec::<R>::new(self.n);
        let mut coef = AlignedVec::<C>::new(self.n / 2 + 1);
        let forward = unsafe { <(C, R) as C2R>::r2c_1d(self.n, &mut field, &mut coef, self.flag) };
        let backward = unsafe { <(C, R) as C2R>::c2r_1d(self.n, &mut coef, &mut field, self.flag) };
        Pair {
            field: field,
            coef: coef,
            logical_size: self.n,
            forward: forward,
            backward: backward,
            phantom: PhantomData,
        }
    }
}
<|endoftext|>


<commit_before>use std::fmt::{self, Display};

/// Path to the current value in the input, like `dependencies.serde.typo1`.
#[derive(Copy, Clone)]
pub enum Path<'a> {
    Root,
    Seq { parent: &'a Path<'a>, index: usize },
    Map { parent: &'a Path<'a>, key: &'a str },
    Some { parent: &'a Path<'a> },
    NewtypeStruct { parent: &'a Path<'a> },
    NewtypeVariant { parent: &'a Path<'a> },
    Alias { parent: &'a Path<'a> },
    Unknown { parent: &'a Path<'a> },
}

impl<'a> Display for Path<'a> {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        struct Parent<'a>(&'a Path<'a>);

        impl<'a> Display for Parent<'a> {
            fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
                match *self.0 {
                    Path::Root => Ok(()),
                    ref path => write!(formatter, "{}.", path),
                }
            }
        }

        match *self {
            Path::Root => formatter.write_str("."),
            Path::Seq { parent, index } => write!(formatter, "{}[{}]", parent, index),
            Path::Map { parent, key } => write!(formatter, "{}{}", Parent(parent), key),
            Path::Some { parent } | Path::NewtypeStruct { parent } | Path::Alias { parent } => {
                write!(formatter, "{}", parent)
            }
            Path::NewtypeVariant { parent } | Path::Unknown { parent } => {
                write!(formatter, "{}?", Parent(parent))
            }
        }
    }
}
<commit_msg>Remove Path variants that were never constructed<commit_after>use std::fmt::{self, Display};

/// Path to the current value in the input, like `dependencies.serde.typo1`.
#[derive(Copy, Clone)]
pub enum Path<'a> {
    Root,
    Seq { parent: &'a Path<'a>, index: usize },
    Map { parent: &'a Path<'a>, key: &'a str },
    Alias { parent: &'a Path<'a> },
    Unknown { parent: &'a Path<'a> },
}

impl<'a> Display for Path<'a> {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        struct Parent<'a>(&'a Path<'a>);

        impl<'a> Display for Parent<'a> {
            fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
                match *self.0 {
                    Path::Root => Ok(()),
                    ref path => write!(formatter, "{}.", path),
                }
            }
        }

        match *self {
            Path::Root => formatter.write_str("."),
            Path::Seq { parent, index } => write!(formatter, "{}[{}]", parent, index),
            Path::Map { parent, key } => write!(formatter, "{}{}", Parent(parent), key),
            Path::Alias { parent } => {
                write!(formatter, "{}", parent)
            }
            Path::Unknown { parent } => {
                write!(formatter, "{}?", Parent(parent))
            }
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2013 The rust-pcre authors.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#[link(name = "pcre", vers = "0.1")];
#[crate_type = "lib"];

use std::libc::{c_int, c_uchar, c_void};
use std::option::{None, Option, Some};
use std::ptr::{is_not_null, null};
use std::vec::{from_elem};
use std::vec::raw::{to_mut_ptr};

pub type options = c_int;

pub static PCRE_CASELESS: options = 0x00000001;
pub static PCRE_MULTILINE: options = 0x00000002;
pub static PCRE_DOTALL: options = 0x00000004;
pub static PCRE_EXTENDED: options = 0x00000008;
pub static PCRE_ANCHORED: options = 0x00000010;
pub static PCRE_DOLLAR_ENDONLY: options = 0x00000020;
pub static PCRE_EXTRA: options = 0x00000040;
pub static PCRE_NOTBOL: options = 0x00000080;
pub static PCRE_NOTEOL: options = 0x00000100;
pub static PCRE_UNGREEDY: options = 0x00000200;
pub static PCRE_NOTEMPTY: options = 0x00000400;
pub static PCRE_UTF8: options = 0x00000800;
pub static PCRE_UTF16: options = 0x00000800;
pub static PCRE_UTF32: options = 0x00000800;
pub static PCRE_NO_AUTO_CAPTURE: options = 0x00001000;
pub static PCRE_NO_UTF8_CHECK: options = 0x00002000;
pub static PCRE_NO_UTF16_CHECK: options = 0x00002000;
pub static PCRE_NO_UTF32_CHECK: options = 0x00002000;
pub static PCRE_AUTO_CALLOUT: options = 0x00004000;
pub static PCRE_PARTIAL_SOFT: options = 0x00008000;
pub static PCRE_PARTIAL: options = 0x00008000;
pub static PCRE_NEVER_UTF: options = 0x00010000;
pub static PCRE_DFA_SHORTEST: options = 0x00010000;
pub static PCRE_DFA_RESTART: options = 0x00020000;
pub static PCRE_FIRSTLINE: options = 0x00040000;
pub static PCRE_DUPNAMES: options = 0x00080000;
pub static PCRE_NEWLINE_CR: options = 0x00100000;
pub static PCRE_NEWLINE_LF: options = 0x00200000;
pub static PCRE_NEWLINE_CRLF: options = 0x00300000;
pub static PCRE_NEWLINE_ANY: options = 0x00400000;
pub static PCRE_NEWLINE_ANYCRLF: options = 0x00500000;
pub static PCRE_BSR_ANYCRLF: options = 0x00800000;
pub static PCRE_BSR_UNICODE: options = 0x01000000;
pub static PCRE_JAVASCRIPT_COMPAT: options = 0x02000000;
pub static PCRE_NO_START_OPTIMIZE: options = 0x04000000;
pub static PCRE_NO_START_OPTIMISE: options = 0x04000000;
pub static PCRE_PARTIAL_HARD: options = 0x08000000;
pub static PCRE_NOTEMPTY_ATSTART: options = 0x10000000;
pub static PCRE_UCP: options = 0x20000000;

mod detail {

    use std::c_str::*;
    use std::libc::*;
    use std::ptr::*;

    pub type fullinfo_field = c_int;
    pub type pcre = c_void;
    pub type pcre_error = c_int;
    pub type pcre_extra = c_void;

    pub static PCRE_ERROR_NOMATCH: pcre_error = -1;
    pub static PCRE_ERROR_NULL: pcre_error = -2;

    pub static PCRE_INFO_CAPTURECOUNT: fullinfo_field = 2;

    mod native {

        use std::libc::*;

        #[link_args = "-lpcre.1"]
        extern {
            static pcre_free: extern "C" fn(ptr: *c_void);

            fn pcre_compile(pattern: *c_char, options: ::options, errptr: *mut *c_char, erroffset: *mut c_int, tableptr: *c_uchar) -> *::detail::pcre;
            fn pcre_exec(code: *::detail::pcre, extra: *::detail::pcre_extra, subject: *c_char, length: c_int, startoffset: c_int, options: ::options, ovector: *mut c_int, ovecsize: c_int) -> ::detail::pcre_error;
            fn pcre_free_study(extra: *::detail::pcre_extra);
            fn pcre_fullinfo(code: *::detail::pcre, extra: *::detail::pcre_extra, what: ::detail::fullinfo_field, where: *mut c_void) -> c_int;
        }

    }

    #[fixed_stack_segment]
    #[inline(never)]
    pub fn pcre_compile(pattern: *c_char, options: ::options, tableptr: *c_uchar) -> *pcre {
        assert!(is_not_null(pattern));
        let mut err: *c_char = null();
        let mut erroffset: c_int = 0;
        let code = unsafe { native::pcre_compile(pattern, options, &mut err, &mut erroffset, tableptr) };

        if is_null(code) {
            // "Otherwise, if  compilation  of  a  pattern fails, pcre_compile() returns
            // NULL, and sets the variable pointed to by errptr to point to a textual
            // error message. This is a static string that is part of the library. You
            // must not try to free it."
            // http://pcre.org/pcre.txt
            unsafe {
                let err_cstring = CString::new(err, false);
                error!("pcre_compile() failed at offset %u: %s", erroffset as uint, err_cstring.as_str().unwrap());
            }
            fail!("pcre_compile");
        }
        assert!(is_not_null(code) && erroffset == 0);

        code
    }

    #[fixed_stack_segment]
    #[inline(never)]
    pub fn pcre_exec(code: *pcre, extra: *pcre_extra, subject: *c_char, length: c_int, startoffset: c_int, options: ::options, ovector: *mut c_int, ovecsize: c_int) -> bool {
        assert!(is_not_null(code));
        assert!(ovecsize >= 0 && ovecsize % 3 == 0);
        let rc = unsafe { native::pcre_exec(code, extra, subject, length, startoffset, options, ovector, ovecsize) };
        if rc == PCRE_ERROR_NOMATCH {
            return false;
        } else if rc < 0 && rc != PCRE_ERROR_NULL {
            fail!("pcre_exec");
        }

        true
    }

    #[fixed_stack_segment]
    #[inline(never)]
    pub fn pcre_free(ptr: *c_void) {
        native::pcre_free(ptr);
    }

    #[fixed_stack_segment]
    #[inline(never)]
    pub fn pcre_free_study(extra: *pcre_extra) {
        unsafe { native::pcre_free_study(extra); }
    }

    #[fixed_stack_segment]
    #[inline(never)]
    pub fn pcre_fullinfo(code: *pcre, extra: *pcre_extra, what: fullinfo_field, where: *mut c_void) {
        assert!(is_not_null(code));
        let rc = unsafe { native::pcre_fullinfo(code, extra, what, where) };
        if rc < 0 && rc != PCRE_ERROR_NULL {
            fail!("pcre_fullinfo");
        }
    }

} // End `mod detail`.

pub struct Pcre {

    priv code: *detail::pcre,

    priv extra: *detail::pcre_extra,

    capture_count: uint

}

pub struct Match<'self> {

    priv subject: &'self str,

    priv ovector: ~[c_int]

}

impl Pcre {
    fn compile(pattern: &str) -> Pcre {
        Pcre::compile_with_options(pattern, 0)
    }

    fn compile_with_options(pattern: &str, options: options) -> Pcre {
        pattern.with_c_str(|pattern_c_str| {
            // Use the default character tables.
            let tableptr: *c_uchar = null();
            let code = detail::pcre_compile(pattern_c_str, options, tableptr);
            assert!(is_not_null(code));

            let extra: *detail::pcre_extra = null();

            let mut capture_count: c_int = 0;
            detail::pcre_fullinfo(code, extra, detail::PCRE_INFO_CAPTURECOUNT, &mut capture_count as *mut c_int as *mut c_void);

            Pcre {
                code: code,
                extra: extra,
                capture_count: capture_count as uint
            }
        })
    }

    fn exec<'a>(&self, subject: &'a str) -> Option<Match<'a>> {
        self.exec_from(subject, 0)
    }

    fn exec_from<'a>(&self, subject: &'a str, startoffset: uint) -> Option<Match<'a>> {
        self.exec_from_with_options(subject, startoffset, 0)
    }

    fn exec_from_with_options<'a>(&self, subject: &'a str, startoffset: uint, options: options) -> Option<Match<'a>> {
        let ovecsize = (self.capture_count + 1) * 3;
        let mut ovector: ~[c_int] = from_elem(ovecsize, 0 as c_int);

        unsafe {
            subject.with_c_str_unchecked(|subject_c_str| -> Option<Match<'a>> {
                if detail::pcre_exec(self.code, self.extra, subject_c_str, subject.len() as c_int, startoffset as c_int, options, to_mut_ptr(ovector), ovecsize as c_int) {
                    Some(Match {
                        subject: subject,
                        // TODO: Is it possible to avoid to_owned()?
                        // Probably need multiple lifetime parameters:
                        // https://mail.mozilla.org/pipermail/rust-dev/2013-September/005829.html
                        ovector: ovector.slice_to((self.capture_count + 1) * 2).to_owned()
                    })
                } else {
                    None
                }
            })
        }
    }
}

impl Drop for Pcre {
    fn drop(&mut self) {
        if is_not_null(self.extra) {
            detail::pcre_free_study(self.extra);
            self.extra = null();
        }
        detail::pcre_free(self.code);
        self.code = null();
    }
}

impl<'self> Match<'self> {

    fn group_start(&self, n: uint) -> uint {
        self.ovector[(n * 2) as uint] as uint
    }

    fn group_end(&self, n: uint) -> uint {
        self.ovector[(n * 2 + 1) as uint] as uint
    }

    fn group_len(&self, n: uint) -> uint {
        let group_offsets = self.ovector.slice_from((n * 2) as uint);
        (group_offsets[1] - group_offsets[0]) as uint
    }

    fn group(&self, n: uint) -> &'self str {
        let group_offsets = self.ovector.slice_from((n * 2) as uint);
        let start = group_offsets[0];
        let end = group_offsets[1];
        self.subject.slice(start as uint, end as uint)
    }

}

#[cfg(test)]
mod tests {

    #[test]
    #[should_fail]
    fn test_compile_nul() {
        // Nul bytes are not allowed in the pattern string.
        ::Pcre::compile("\0abc");
    }

    #[test]
    #[should_fail]
    fn test_compile_bad_pattern() {
        ::Pcre::compile("[");
    }

    #[test]
    fn test_compile_capture_count() {
        let re = ::Pcre::compile("(?:abc)(def)");
        assert_eq!(re.capture_count, 1u);
    }

    #[test]
    fn test_exec_basic() {
        let re = ::Pcre::compile("^...$");
        assert_eq!(re.capture_count, 0u);
        let m = re.exec("abc").unwrap();
        assert_eq!(m.group(0), "abc");
    }

    #[test]
    fn test_exec_no_match() {
        let re = ::Pcre::compile("abc");
        assert!(re.exec("def").is_none());
    }

    #[test]
    fn test_exec_nul_byte() {
        // Nul bytes *are* allowed in subject strings, however.
        let re = ::Pcre::compile("abc\\0def");
        let m = re.exec("abc\0def").unwrap();
        assert_eq!(m.group(0), "abc\0def");
    }

    #[test]
    fn test_exec_from_basic() {
        let re = ::Pcre::compile("abc");
        let subject = "abcabc";
        let m1 = re.exec_from(subject, 1u).unwrap();
        assert_eq!(m1.group_start(0u), 3u);
        assert_eq!(m1.group_end(0u), 6u);
        assert_eq!(m1.group_len(0u), 3u);
        let m2 = re.exec(subject).unwrap();
        assert_eq!(m2.group_start(0u), 0u);
    }
}
<commit_msg>chmod -x<commit_after>// Copyright 2013 The rust-pcre authors.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#[link(name = "pcre", vers = "0.1")];
#[crate_type = "lib"];

use std::libc::{c_int, c_uchar, c_void};
use std::option::{None, Option, Some};
use std::ptr::{is_not_null, null};
use std::vec::{from_elem};
use std::vec::raw::{to_mut_ptr};

pub type options = c_int;

pub static PCRE_CASELESS: options = 0x00000001;
pub static PCRE_MULTILINE: options = 0x00000002;
pub static PCRE_DOTALL: options = 0x00000004;
pub static PCRE_EXTENDED: options = 0x00000008;
pub static PCRE_ANCHORED: options = 0x00000010;
pub static PCRE_DOLLAR_ENDONLY: options = 0x00000020;
pub static PCRE_EXTRA: options = 0x00000040;
pub static PCRE_NOTBOL: options = 0x00000080;
pub static PCRE_NOTEOL: options = 0x00000100;
pub static PCRE_UNGREEDY: options = 0x00000200;
pub static PCRE_NOTEMPTY: options = 0x00000400;
pub static PCRE_UTF8: options = 0x00000800;
pub static PCRE_UTF16: options = 0x00000800;
pub static PCRE_UTF32: options = 0x00000800;
pub static PCRE_NO_AUTO_CAPTURE: options = 0x00001000;
pub static PCRE_NO_UTF8_CHECK: options = 0x00002000;
pub static PCRE_NO_UTF16_CHECK: options = 0x00002000;
pub static PCRE_NO_UTF32_CHECK: options = 0x00002000;
pub static PCRE_AUTO_CALLOUT: options = 0x00004000;
pub static PCRE_PARTIAL_SOFT: options = 0x00008000;
pub static PCRE_PARTIAL: options = 0x00008000;
pub static PCRE_NEVER_UTF: options = 0x00010000;
pub static PCRE_DFA_SHORTEST: options = 0x00010000;
pub static PCRE_DFA_RESTART: options = 0x00020000;
pub static PCRE_FIRSTLINE: options = 0x00040000;
pub static PCRE_DUPNAMES: options = 0x00080000;
pub static PCRE_NEWLINE_CR: options = 0x00100000;
pub static PCRE_NEWLINE_LF: options = 0x00200000;
pub static PCRE_NEWLINE_CRLF: options = 0x00300000;
pub static PCRE_NEWLINE_ANY: options = 0x00400000;
pub static PCRE_NEWLINE_ANYCRLF: options = 0x00500000;
pub static PCRE_BSR_ANYCRLF: options = 0x00800000;
pub static PCRE_BSR_UNICODE: options = 0x01000000;
pub static PCRE_JAVASCRIPT_COMPAT: options = 0x02000000;
pub static PCRE_NO_START_OPTIMIZE: options = 0x04000000;
pub static PCRE_NO_START_OPTIMISE: options = 0x04000000;
pub static PCRE_PARTIAL_HARD: options = 0x08000000;
pub static PCRE_NOTEMPTY_ATSTART: options = 0x10000000;
pub static PCRE_UCP: options = 0x20000000;

mod detail {

    use std::c_str::*;
    use std::libc::*;
    use std::ptr::*;

    pub type fullinfo_field = c_int;
    pub type pcre = c_void;
    pub type pcre_error = c_int;
    pub type pcre_extra = c_void;

    pub static PCRE_ERROR_NOMATCH: pcre_error = -1;
    pub static PCRE_ERROR_NULL: pcre_error = -2;

    pub static PCRE_INFO_CAPTURECOUNT: fullinfo_field = 2;

    mod native {

        use std::libc::*;

        #[link_args = "-lpcre.1"]
        extern {
            static pcre_free: extern "C" fn(ptr: *c_void);

            fn pcre_compile(pattern: *c_char, options: ::options, errptr: *mut *c_char, erroffset: *mut c_int, tableptr: *c_uchar) -> *::detail::pcre;
            fn pcre_exec(code: *::detail::pcre, extra: *::detail::pcre_extra, subject: *c_char, length: c_int, startoffset: c_int, options: ::options, ovector: *mut c_int, ovecsize: c_int) -> ::detail::pcre_error;
            fn pcre_free_study(extra: *::detail::pcre_extra);
            fn pcre_fullinfo(code: *::detail::pcre, extra: *::detail::pcre_extra, what: ::detail::fullinfo_field, where: *mut c_void) -> c_int;
        }

    }

    #[fixed_stack_segment]
    #[inline(never)]
    pub fn pcre_compile(pattern: *c_char, options: ::options, tableptr: *c_uchar) -> *pcre {
        assert!(is_not_null(pattern));
        let mut err: *c_char = null();
        let mut erroffset: c_int = 0;
        let code = unsafe { native::pcre_compile(pattern, options, &mut err, &mut erroffset, tableptr) };

        if is_null(code) {
            // "Otherwise, if  compilation  of  a  pattern fails, pcre_compile() returns
            // NULL, and sets the variable pointed to by errptr to point to a textual
            // error message. This is a static string that is part of the library. You
            // must not try to free it."
            // http://pcre.org/pcre.txt
            unsafe {
                let err_cstring = CString::new(err, false);
                error!("pcre_compile() failed at offset %u: %s", erroffset as uint, err_cstring.as_str().unwrap());
            }
            fail!("pcre_compile");
        }
        assert!(is_not_null(code) && erroffset == 0);

        code
    }

    #[fixed_stack_segment]
    #[inline(never)]
    pub fn pcre_exec(code: *pcre, extra: *pcre_extra, subject: *c_char, length: c_int, startoffset: c_int, options: ::options, ovector: *mut c_int, ovecsize: c_int) -> bool {
        assert!(is_not_null(code));
        assert!(ovecsize >= 0 && ovecsize % 3 == 0);
        let rc = unsafe { native::pcre_exec(code, extra, subject, length, startoffset, options, ovector, ovecsize) };
        if rc == PCRE_ERROR_NOMATCH {
            return false;
        } else if rc < 0 && rc != PCRE_ERROR_NULL {
            fail!("pcre_exec");
        }

        true
    }

    #[fixed_stack_segment]
    #[inline(never)]
    pub fn pcre_free(ptr: *c_void) {
        native::pcre_free(ptr);
    }

    #[fixed_stack_segment]
    #[inline(never)]
    pub fn pcre_free_study(extra: *pcre_extra) {
        unsafe { native::pcre_free_study(extra); }
    }

    #[fixed_stack_segment]
    #[inline(never)]
    pub fn pcre_fullinfo(code: *pcre, extra: *pcre_extra, what: fullinfo_field, where: *mut c_void) {
        assert!(is_not_null(code));
        let rc = unsafe { native::pcre_fullinfo(code, extra, what, where) };
        if rc < 0 && rc != PCRE_ERROR_NULL {
            fail!("pcre_fullinfo");
        }
    }

} // End `mod detail`.

pub struct Pcre {

    priv code: *detail::pcre,

    priv extra: *detail::pcre_extra,

    capture_count: uint

}

pub struct Match<'self> {

    priv subject: &'self str,

    priv ovector: ~[c_int]

}

impl Pcre {
    fn compile(pattern: &str) -> Pcre {
        Pcre::compile_with_options(pattern, 0)
    }

    fn compile_with_options(pattern: &str, options: options) -> Pcre {
        pattern.with_c_str(|pattern_c_str| {
            // Use the default character tables.
            let tableptr: *c_uchar = null();
            let code = detail::pcre_compile(pattern_c_str, options, tableptr);
            assert!(is_not_null(code));

            let extra: *detail::pcre_extra = null();

            let mut capture_count: c_int = 0;
            detail::pcre_fullinfo(code, extra, detail::PCRE_INFO_CAPTURECOUNT, &mut capture_count as *mut c_int as *mut c_void);

            Pcre {
                code: code,
                extra: extra,
                capture_count: capture_count as uint
            }
        })
    }

    fn exec<'a>(&self, subject: &'a str) -> Option<Match<'a>> {
        self.exec_from(subject, 0)
    }

    fn exec_from<'a>(&self, subject: &'a str, startoffset: uint) -> Option<Match<'a>> {
        self.exec_from_with_options(subject, startoffset, 0)
    }

    fn exec_from_with_options<'a>(&self, subject: &'a str, startoffset: uint, options: options) -> Option<Match<'a>> {
        let ovecsize = (self.capture_count + 1) * 3;
        let mut ovector: ~[c_int] = from_elem(ovecsize, 0 as c_int);

        unsafe {
            subject.with_c_str_unchecked(|subject_c_str| -> Option<Match<'a>> {
                if detail::pcre_exec(self.code, self.extra, subject_c_str, subject.len() as c_int, startoffset as c_int, options, to_mut_ptr(ovector), ovecsize as c_int) {
                    Some(Match {
                        subject: subject,
                        // TODO: Is it possible to avoid to_owned()?
                        // Probably need multiple lifetime parameters:
                        // https://mail.mozilla.org/pipermail/rust-dev/2013-September/005829.html
                        ovector: ovector.slice_to((self.capture_count + 1) * 2).to_owned()
                    })
                } else {
                    None
                }
            })
        }
    }
}

impl Drop for Pcre {
    fn drop(&mut self) {
        if is_not_null(self.extra) {
            detail::pcre_free_study(self.extra);
            self.extra = null();
        }
        detail::pcre_free(self.code);
        self.code = null();
    }
}

impl<'self> Match<'self> {

    fn group_start(&self, n: uint) -> uint {
        self.ovector[(n * 2) as uint] as uint
    }

    fn group_end(&self, n: uint) -> uint {
        self.ovector[(n * 2 + 1) as uint] as uint
    }

    fn group_len(&self, n: uint) -> uint {
        let group_offsets = self.ovector.slice_from((n * 2) as uint);
        (group_offsets[1] - group_offsets[0]) as uint
    }

    fn group(&self, n: uint) -> &'self str {
        let group_offsets = self.ovector.slice_from((n * 2) as uint);
        let start = group_offsets[0];
        let end = group_offsets[1];
        self.subject.slice(start as uint, end as uint)
    }

}

#[cfg(test)]
mod tests {

    #[test]
    #[should_fail]
    fn test_compile_nul() {
        // Nul bytes are not allowed in the pattern string.
        ::Pcre::compile("\0abc");
    }

    #[test]
    #[should_fail]
    fn test_compile_bad_pattern() {
        ::Pcre::compile("[");
    }

    #[test]
    fn test_compile_capture_count() {
        let re = ::Pcre::compile("(?:abc)(def)");
        assert_eq!(re.capture_count, 1u);
    }

    #[test]
    fn test_exec_basic() {
        let re = ::Pcre::compile("^...$");
        assert_eq!(re.capture_count, 0u);
        let m = re.exec("abc").unwrap();
        assert_eq!(m.group(0), "abc");
    }

    #[test]
    fn test_exec_no_match() {
        let re = ::Pcre::compile("abc");
        assert!(re.exec("def").is_none());
    }

    #[test]
    fn test_exec_nul_byte() {
        // Nul bytes *are* allowed in subject strings, however.
        let re = ::Pcre::compile("abc\\0def");
        let m = re.exec("abc\0def").unwrap();
        assert_eq!(m.group(0), "abc\0def");
    }

    #[test]
    fn test_exec_from_basic() {
        let re = ::Pcre::compile("abc");
        let subject = "abcabc";
        let m1 = re.exec_from(subject, 1u).unwrap();
        assert_eq!(m1.group_start(0u), 3u);
        assert_eq!(m1.group_end(0u), 6u);
        assert_eq!(m1.group_len(0u), 3u);
        let m2 = re.exec(subject).unwrap();
        assert_eq!(m2.group_start(0u), 0u);
    }
}
<|endoftext|>


<commit_before>use super::{c32, c64};
use super::aligned_vec::AlignedVec;
use super::enums::*;
use super::util::FFTW_MUTEX;
use ffi;

use std::os::raw::c_void;
use std::ptr::null;

pub enum RawPlan {
    _64(ffi::fftw_plan),
    _32(ffi::fftwf_plan),
}

impl RawPlan {
    pub unsafe fn execute(&self) {
        self.null_check();
        match *self {
            RawPlan::_64(p) => ffi::fftw_execute(p),
            RawPlan::_32(p) => ffi::fftwf_execute(p),
        }
    }

    fn null_check(&self) {
        let p = match *self {
            RawPlan::_64(p) => p as *const c_void,
            RawPlan::_32(p) => p as *const c_void,
        };
        if p == null() {
            panic!(
                "Plan is NULL. If you use MKL binding, check here: https://software.intel.com/en-us/mkl-developer-reference-c-using-fftw3-wrappers"
            );
        }
    }
}

impl Drop for RawPlan {
    fn drop(&mut self) {
        self.null_check();
        let _lock = FFTW_MUTEX.lock().expect("Cannot get lock");
        unsafe {
            match *self {
                RawPlan::_64(p) => ffi::fftw_destroy_plan(p),
                RawPlan::_32(p) => ffi::fftwf_destroy_plan(p),
            }
        }
    }
}

pub trait R2R: Sized {
    unsafe fn r2r_1d(n: usize, in_: &mut AlignedVec<Self>, out: &mut AlignedVec<Self>, R2R_KIND, FLAG) -> RawPlan;
    unsafe fn r2r_2d(
        n0: usize,
        n1: usize,
        in_: &mut AlignedVec<Self>,
        out: &mut AlignedVec<Self>,
        R2R_KIND,
        R2R_KIND,
        FLAG,
    ) -> RawPlan;
    unsafe fn r2r_3d(
        n0: usize,
        n1: usize,
        n2: usize,
        in_: &mut AlignedVec<Self>,
        out: &mut AlignedVec<Self>,
        R2R_KIND,
        R2R_KIND,
        R2R_KIND,
        FLAG,
    ) -> RawPlan;
}
pub trait C2C: Sized {
    unsafe fn c2c_1d(n: usize, in_: &mut AlignedVec<Self>, out: &mut AlignedVec<Self>, SIGN, FLAG) -> RawPlan;
    unsafe fn c2c_2d(
        n0: usize,
        n1: usize,
        in_: &mut AlignedVec<Self>,
        out: &mut AlignedVec<Self>,
        SIGN,
        FLAG,
    ) -> RawPlan;
    unsafe fn c2c_3d(
        n0: usize,
        n1: usize,
        n2: usize,
        in_: &mut AlignedVec<Self>,
        out: &mut AlignedVec<Self>,
        SIGN,
        FLAG,
    ) -> RawPlan;
}

pub trait C2R {
    type Real: Sized;
    type Complex: Sized;
    unsafe fn r2c_1d(n: usize, in_: &mut AlignedVec<Self::Real>, out: &mut AlignedVec<Self::Complex>, FLAG) -> RawPlan;
    unsafe fn c2r_1d(n: usize, in_: &mut AlignedVec<Self::Complex>, out: &mut AlignedVec<Self::Real>, FLAG) -> RawPlan;
    unsafe fn r2c_2d(
        n0: usize,
        n1: usize,
        in_: &mut AlignedVec<Self::Real>,
        out: &mut AlignedVec<Self::Complex>,
        FLAG,
    ) -> RawPlan;
    unsafe fn c2r_2d(
        n0: usize,
        n1: usize,
        in_: &mut AlignedVec<Self::Complex>,
        out: &mut AlignedVec<Self::Real>,
        FLAG,
    ) -> RawPlan;
    unsafe fn r2c_3d(
        n0: usize,
        n1: usize,
        n2: usize,
        in_: &mut AlignedVec<Self::Real>,
        out: &mut AlignedVec<Self::Complex>,
        FLAG,
    ) -> RawPlan;
    unsafe fn c2r_3d(
        n0: usize,
        n1: usize,
        n2: usize,
        in_: &mut AlignedVec<Self::Complex>,
        out: &mut AlignedVec<Self::Real>,
        FLAG,
    ) -> RawPlan;
}

macro_rules! impl_plan_create {
    ($bit:ident, $float:ty, $complex:ty,
     $r2r_1d:ident, $r2c_1d:ident, $c2r_1d:ident, $c2c_1d:ident,
     $r2r_2d:ident, $r2c_2d:ident, $c2r_2d:ident, $c2c_2d:ident,
     $r2r_3d:ident, $r2c_3d:ident, $c2r_3d:ident, $c2c_3d:ident) => {

impl R2R for $float {
    unsafe fn r2r_1d(n: usize, in_: &mut AlignedVec<Self>, out: &mut AlignedVec<Self>, kind: R2R_KIND, flag: FLAG) -> RawPlan {
        RawPlan::$bit(ffi::$r2r_1d(n as i32, in_.as_mut_ptr(), out.as_mut_ptr(), kind, flag as u32))
    }
    unsafe fn r2r_2d(n0: usize, n1: usize, in_: &mut AlignedVec<Self>, out: &mut AlignedVec<Self>, k0: R2R_KIND, k1: R2R_KIND, flag: FLAG) -> RawPlan {
        RawPlan::$bit(ffi::$r2r_2d(n0 as i32, n1 as i32, in_.as_mut_ptr(), out.as_mut_ptr(), k0, k1, flag as u32))
    }
    unsafe fn r2r_3d(n0: usize, n1: usize, n2: usize, in_: &mut AlignedVec<Self>, out: &mut AlignedVec<Self>, k0: R2R_KIND, k1: R2R_KIND, k2: R2R_KIND, flag: FLAG) -> RawPlan {
        RawPlan::$bit(ffi::$r2r_3d(n0 as i32, n1 as i32, n2 as i32, in_.as_mut_ptr(), out.as_mut_ptr(), k0, k1, k2, flag as u32))
    }
}

impl C2C for $complex {
    unsafe fn c2c_1d(n: usize, i: &mut AlignedVec<Self>, o: &mut AlignedVec<Self>, s: SIGN, f: FLAG) -> RawPlan {
        RawPlan::$bit(ffi::$c2c_1d(n as i32, i.as_mut_ptr(), o.as_mut_ptr(), s as i32, f as u32))
    }
    unsafe fn c2c_2d(n0: usize, n1: usize, i: &mut AlignedVec<Self>, o: &mut AlignedVec<Self>, s: SIGN, f: FLAG) -> RawPlan {
        RawPlan::$bit(ffi::$c2c_2d(n0 as i32, n1 as i32, i.as_mut_ptr(), o.as_mut_ptr(), s as i32, f as u32))
    }
    unsafe fn c2c_3d(n0: usize, n1: usize, n2: usize, i: &mut AlignedVec<Self>, o: &mut AlignedVec<Self>, s: SIGN, f: FLAG) -> RawPlan {
        RawPlan::$bit(ffi::$c2c_3d(n0 as i32, n1 as i32, n2 as i32, i.as_mut_ptr(), o.as_mut_ptr(), s as i32, f as u32))
    }
}

impl C2R for ($complex, $float) {
    type Real = $float;
    type Complex = $complex;
    unsafe fn r2c_1d(n: usize, i: &mut AlignedVec<Self::Real>, o: &mut AlignedVec<Self::Complex>, f: FLAG) -> RawPlan {
        RawPlan::$bit(ffi::$r2c_1d(n as i32, i.as_mut_ptr(), o.as_mut_ptr(), f as u32))
    }
    unsafe fn c2r_1d(n: usize, i: &mut AlignedVec<Self::Complex>, o: &mut AlignedVec<Self::Real>, f: FLAG) -> RawPlan {
        RawPlan::$bit(ffi::$c2r_1d(n as i32, i.as_mut_ptr(), o.as_mut_ptr(), f as u32))
    }
    unsafe fn r2c_2d(n0: usize, n1: usize, i: &mut AlignedVec<Self::Real>, o: &mut AlignedVec<Self::Complex>, f: FLAG) -> RawPlan {
        RawPlan::$bit(ffi::$r2c_2d(n0 as i32, n1 as i32, i.as_mut_ptr(), o.as_mut_ptr(), f as u32))
    }
    unsafe fn c2r_2d(n0: usize, n1: usize, i: &mut AlignedVec<Self::Complex>, o: &mut AlignedVec<Self::Real>, f: FLAG) -> RawPlan {
        RawPlan::$bit(ffi::$c2r_2d(n0 as i32, n1 as i32, i.as_mut_ptr(), o.as_mut_ptr(), f as u32))
    }
    unsafe fn r2c_3d(n0: usize, n1: usize, n2: usize, i: &mut AlignedVec<Self::Real>, o: &mut AlignedVec<Self::Complex>, f: FLAG) -> RawPlan {
        RawPlan::$bit(ffi::$r2c_3d(n0 as i32, n1 as i32, n2 as i32, i.as_mut_ptr(), o.as_mut_ptr(), f as u32))
    }
    unsafe fn c2r_3d(n0: usize, n1: usize, n2: usize, i: &mut AlignedVec<Self::Complex>, o: &mut AlignedVec<Self::Real>, f: FLAG) -> RawPlan {
        RawPlan::$bit(ffi::$c2r_3d(n0 as i32, n1 as i32, n2 as i32, i.as_mut_ptr(), o.as_mut_ptr(), f as u32))
    }
}

}} // impl_plan_create

impl_plan_create!(
    _64,
    f64,
    c64,
    fftw_plan_r2r_1d,
    fftw_plan_dft_r2c_1d,
    fftw_plan_dft_c2r_1d,
    fftw_plan_dft_1d,
    fftw_plan_r2r_2d,
    fftw_plan_dft_r2c_2d,
    fftw_plan_dft_c2r_2d,
    fftw_plan_dft_2d,
    fftw_plan_r2r_3d,
    fftw_plan_dft_r2c_3d,
    fftw_plan_dft_c2r_3d,
    fftw_plan_dft_3d
);
impl_plan_create!(
    _32,
    f32,
    c32,
    fftwf_plan_r2r_1d,
    fftwf_plan_dft_r2c_1d,
    fftwf_plan_dft_c2r_1d,
    fftwf_plan_dft_1d,
    fftwf_plan_r2r_2d,
    fftwf_plan_dft_r2c_2d,
    fftwf_plan_dft_c2r_2d,
    fftwf_plan_dft_2d,
    fftwf_plan_r2r_3d,
    fftwf_plan_dft_r2c_3d,
    fftwf_plan_dft_c2r_3d,
    fftwf_plan_dft_3d
);
<commit_msg>Add mutex lock for each plan creation<commit_after>use super::{c32, c64};
use super::aligned_vec::AlignedVec;
use super::enums::*;
use super::util::FFTW_MUTEX;
use ffi;

use std::os::raw::c_void;
use std::ptr::null;

pub enum RawPlan {
    _64(ffi::fftw_plan),
    _32(ffi::fftwf_plan),
}

impl RawPlan {
    pub unsafe fn execute(&self) {
        self.null_check();
        match *self {
            RawPlan::_64(p) => ffi::fftw_execute(p),
            RawPlan::_32(p) => ffi::fftwf_execute(p),
        }
    }

    fn null_check(&self) {
        let p = match *self {
            RawPlan::_64(p) => p as *const c_void,
            RawPlan::_32(p) => p as *const c_void,
        };
        if p == null() {
            panic!(
                "Plan is NULL. If you use MKL binding, check here: https://software.intel.com/en-us/mkl-developer-reference-c-using-fftw3-wrappers"
            );
        }
    }
}

impl Drop for RawPlan {
    fn drop(&mut self) {
        self.null_check();
        let _lock = FFTW_MUTEX.lock().expect("Cannot get lock");
        unsafe {
            match *self {
                RawPlan::_64(p) => ffi::fftw_destroy_plan(p),
                RawPlan::_32(p) => ffi::fftwf_destroy_plan(p),
            }
        }
    }
}

pub trait R2R: Sized {
    unsafe fn r2r_1d(n: usize, in_: &mut AlignedVec<Self>, out: &mut AlignedVec<Self>, R2R_KIND, FLAG) -> RawPlan;
    unsafe fn r2r_2d(
        n0: usize,
        n1: usize,
        in_: &mut AlignedVec<Self>,
        out: &mut AlignedVec<Self>,
        R2R_KIND,
        R2R_KIND,
        FLAG,
    ) -> RawPlan;
    unsafe fn r2r_3d(
        n0: usize,
        n1: usize,
        n2: usize,
        in_: &mut AlignedVec<Self>,
        out: &mut AlignedVec<Self>,
        R2R_KIND,
        R2R_KIND,
        R2R_KIND,
        FLAG,
    ) -> RawPlan;
}
pub trait C2C: Sized {
    unsafe fn c2c_1d(n: usize, in_: &mut AlignedVec<Self>, out: &mut AlignedVec<Self>, SIGN, FLAG) -> RawPlan;
    unsafe fn c2c_2d(
        n0: usize,
        n1: usize,
        in_: &mut AlignedVec<Self>,
        out: &mut AlignedVec<Self>,
        SIGN,
        FLAG,
    ) -> RawPlan;
    unsafe fn c2c_3d(
        n0: usize,
        n1: usize,
        n2: usize,
        in_: &mut AlignedVec<Self>,
        out: &mut AlignedVec<Self>,
        SIGN,
        FLAG,
    ) -> RawPlan;
}

pub trait C2R {
    type Real: Sized;
    type Complex: Sized;
    unsafe fn r2c_1d(n: usize, in_: &mut AlignedVec<Self::Real>, out: &mut AlignedVec<Self::Complex>, FLAG) -> RawPlan;
    unsafe fn c2r_1d(n: usize, in_: &mut AlignedVec<Self::Complex>, out: &mut AlignedVec<Self::Real>, FLAG) -> RawPlan;
    unsafe fn r2c_2d(
        n0: usize,
        n1: usize,
        in_: &mut AlignedVec<Self::Real>,
        out: &mut AlignedVec<Self::Complex>,
        FLAG,
    ) -> RawPlan;
    unsafe fn c2r_2d(
        n0: usize,
        n1: usize,
        in_: &mut AlignedVec<Self::Complex>,
        out: &mut AlignedVec<Self::Real>,
        FLAG,
    ) -> RawPlan;
    unsafe fn r2c_3d(
        n0: usize,
        n1: usize,
        n2: usize,
        in_: &mut AlignedVec<Self::Real>,
        out: &mut AlignedVec<Self::Complex>,
        FLAG,
    ) -> RawPlan;
    unsafe fn c2r_3d(
        n0: usize,
        n1: usize,
        n2: usize,
        in_: &mut AlignedVec<Self::Complex>,
        out: &mut AlignedVec<Self::Real>,
        FLAG,
    ) -> RawPlan;
}

macro_rules! impl_plan_create {
    ($bit:ident, $float:ty, $complex:ty,
     $r2r_1d:ident, $r2c_1d:ident, $c2r_1d:ident, $c2c_1d:ident,
     $r2r_2d:ident, $r2c_2d:ident, $c2r_2d:ident, $c2c_2d:ident,
     $r2r_3d:ident, $r2c_3d:ident, $c2r_3d:ident, $c2c_3d:ident) => {

impl R2R for $float {
    unsafe fn r2r_1d(n: usize, in_: &mut AlignedVec<Self>, out: &mut AlignedVec<Self>, kind: R2R_KIND, flag: FLAG) -> RawPlan {
        let _lock = FFTW_MUTEX.lock().expect("Cannot get lock");
        RawPlan::$bit(ffi::$r2r_1d(n as i32, in_.as_mut_ptr(), out.as_mut_ptr(), kind, flag as u32))
    }
    unsafe fn r2r_2d(n0: usize, n1: usize, in_: &mut AlignedVec<Self>, out: &mut AlignedVec<Self>, k0: R2R_KIND, k1: R2R_KIND, flag: FLAG) -> RawPlan {
        let _lock = FFTW_MUTEX.lock().expect("Cannot get lock");
        RawPlan::$bit(ffi::$r2r_2d(n0 as i32, n1 as i32, in_.as_mut_ptr(), out.as_mut_ptr(), k0, k1, flag as u32))
    }
    unsafe fn r2r_3d(n0: usize, n1: usize, n2: usize, in_: &mut AlignedVec<Self>, out: &mut AlignedVec<Self>, k0: R2R_KIND, k1: R2R_KIND, k2: R2R_KIND, flag: FLAG) -> RawPlan {
        let _lock = FFTW_MUTEX.lock().expect("Cannot get lock");
        RawPlan::$bit(ffi::$r2r_3d(n0 as i32, n1 as i32, n2 as i32, in_.as_mut_ptr(), out.as_mut_ptr(), k0, k1, k2, flag as u32))
    }
}

impl C2C for $complex {
    unsafe fn c2c_1d(n: usize, i: &mut AlignedVec<Self>, o: &mut AlignedVec<Self>, s: SIGN, f: FLAG) -> RawPlan {
        let _lock = FFTW_MUTEX.lock().expect("Cannot get lock");
        RawPlan::$bit(ffi::$c2c_1d(n as i32, i.as_mut_ptr(), o.as_mut_ptr(), s as i32, f as u32))
    }
    unsafe fn c2c_2d(n0: usize, n1: usize, i: &mut AlignedVec<Self>, o: &mut AlignedVec<Self>, s: SIGN, f: FLAG) -> RawPlan {
        let _lock = FFTW_MUTEX.lock().expect("Cannot get lock");
        RawPlan::$bit(ffi::$c2c_2d(n0 as i32, n1 as i32, i.as_mut_ptr(), o.as_mut_ptr(), s as i32, f as u32))
    }
    unsafe fn c2c_3d(n0: usize, n1: usize, n2: usize, i: &mut AlignedVec<Self>, o: &mut AlignedVec<Self>, s: SIGN, f: FLAG) -> RawPlan {
        let _lock = FFTW_MUTEX.lock().expect("Cannot get lock");
        RawPlan::$bit(ffi::$c2c_3d(n0 as i32, n1 as i32, n2 as i32, i.as_mut_ptr(), o.as_mut_ptr(), s as i32, f as u32))
    }
}

impl C2R for ($complex, $float) {
    type Real = $float;
    type Complex = $complex;
    unsafe fn r2c_1d(n: usize, i: &mut AlignedVec<Self::Real>, o: &mut AlignedVec<Self::Complex>, f: FLAG) -> RawPlan {
        let _lock = FFTW_MUTEX.lock().expect("Cannot get lock");
        RawPlan::$bit(ffi::$r2c_1d(n as i32, i.as_mut_ptr(), o.as_mut_ptr(), f as u32))
    }
    unsafe fn c2r_1d(n: usize, i: &mut AlignedVec<Self::Complex>, o: &mut AlignedVec<Self::Real>, f: FLAG) -> RawPlan {
        let _lock = FFTW_MUTEX.lock().expect("Cannot get lock");
        RawPlan::$bit(ffi::$c2r_1d(n as i32, i.as_mut_ptr(), o.as_mut_ptr(), f as u32))
    }
    unsafe fn r2c_2d(n0: usize, n1: usize, i: &mut AlignedVec<Self::Real>, o: &mut AlignedVec<Self::Complex>, f: FLAG) -> RawPlan {
        let _lock = FFTW_MUTEX.lock().expect("Cannot get lock");
        RawPlan::$bit(ffi::$r2c_2d(n0 as i32, n1 as i32, i.as_mut_ptr(), o.as_mut_ptr(), f as u32))
    }
    unsafe fn c2r_2d(n0: usize, n1: usize, i: &mut AlignedVec<Self::Complex>, o: &mut AlignedVec<Self::Real>, f: FLAG) -> RawPlan {
        let _lock = FFTW_MUTEX.lock().expect("Cannot get lock");
        RawPlan::$bit(ffi::$c2r_2d(n0 as i32, n1 as i32, i.as_mut_ptr(), o.as_mut_ptr(), f as u32))
    }
    unsafe fn r2c_3d(n0: usize, n1: usize, n2: usize, i: &mut AlignedVec<Self::Real>, o: &mut AlignedVec<Self::Complex>, f: FLAG) -> RawPlan {
        let _lock = FFTW_MUTEX.lock().expect("Cannot get lock");
        RawPlan::$bit(ffi::$r2c_3d(n0 as i32, n1 as i32, n2 as i32, i.as_mut_ptr(), o.as_mut_ptr(), f as u32))
    }
    unsafe fn c2r_3d(n0: usize, n1: usize, n2: usize, i: &mut AlignedVec<Self::Complex>, o: &mut AlignedVec<Self::Real>, f: FLAG) -> RawPlan {
        let _lock = FFTW_MUTEX.lock().expect("Cannot get lock");
        RawPlan::$bit(ffi::$c2r_3d(n0 as i32, n1 as i32, n2 as i32, i.as_mut_ptr(), o.as_mut_ptr(), f as u32))
    }
}

}} // impl_plan_create

impl_plan_create!(
    _64,
    f64,
    c64,
    fftw_plan_r2r_1d,
    fftw_plan_dft_r2c_1d,
    fftw_plan_dft_c2r_1d,
    fftw_plan_dft_1d,
    fftw_plan_r2r_2d,
    fftw_plan_dft_r2c_2d,
    fftw_plan_dft_c2r_2d,
    fftw_plan_dft_2d,
    fftw_plan_r2r_3d,
    fftw_plan_dft_r2c_3d,
    fftw_plan_dft_c2r_3d,
    fftw_plan_dft_3d
);
impl_plan_create!(
    _32,
    f32,
    c32,
    fftwf_plan_r2r_1d,
    fftwf_plan_dft_r2c_1d,
    fftwf_plan_dft_c2r_1d,
    fftwf_plan_dft_1d,
    fftwf_plan_r2r_2d,
    fftwf_plan_dft_r2c_2d,
    fftwf_plan_dft_c2r_2d,
    fftwf_plan_dft_2d,
    fftwf_plan_r2r_3d,
    fftwf_plan_dft_r2c_3d,
    fftwf_plan_dft_c2r_3d,
    fftwf_plan_dft_3d
);
<|endoftext|>


<commit_before>use color::Color;
use scene::Scene;
use camera::Camera;
use ray::Ray;
use intersection::Intersection;
use material::Material;
use math::EPSILON;

use rayon::prelude::*;
use std::ops::Range;

#[derive(Deserialize, Debug, Copy, Clone)]
pub enum SuperSampling {
    Off,
    On(u32),
}

pub struct Renderer<'a> {
    scene: &'a Scene<'a>,
    camera: &'a Camera,
    super_sampling: SuperSampling,
}

unsafe impl<'a> Sync for Renderer<'a> {}
unsafe impl<'a> Send for Renderer<'a> {}

impl<'a> Renderer<'a> {
    pub fn new(
        scene: &'a Scene<'a>,
        camera: &'a Camera,
        super_sampling: SuperSampling,
    ) -> Renderer<'a> {
        Renderer {
            scene: scene,
            camera: camera,
            super_sampling: super_sampling,
        }
    }

    pub fn render(&self, max_depth: u32) -> Vec<u8> {
        let range: Range<usize> = (0 as usize)..(self.camera.height as usize);
        self.render_segment(0, &range, max_depth)
    }

    fn render_segment(
        &self,
        segment_offset: usize,
        segment_range: &Range<usize>,
        max_depth: u32,
    ) -> Vec<u8> {
        let width = self.camera.width as usize;

        segment_range
            .clone()
            .into_par_iter()
            .flat_map(|y| {
                (0..width)
                    .flat_map(move |x| {
                        self.render_point(segment_offset, max_depth, x, y)
                            .into_iter()
                    })
                    .collect::<Vec<u8>>()
                    .into_par_iter()
            })
            .collect::<Vec<u8>>()
    }

    fn render_point(&self, segment_offset: usize, max_depth: u32, x: usize, y: usize) -> Color {
        let samples = match self.super_sampling {
            SuperSampling::Off => 1,
            SuperSampling::On(samples) => samples,
        };

        let mut sample_colors = vec![Color::black(); (samples * samples) as usize];
        let global_y = segment_offset + y;

        for x_sample in 0..samples {
            for y_sample in 0..samples {
                let ray = self.camera.create_ray(
                    x as u32,
                    self.camera.height - global_y as u32,
                    x_sample,
                    y_sample,
                    samples,
                );
                sample_colors[(y_sample * samples + x_sample) as usize] =
                    self.trace(ray, max_depth, true);
            }
        }

        let mut sum_r: f64 = 0.0;
        let mut sum_g: f64 = 0.0;
        let mut sum_b: f64 = 0.0;

        for color in &sample_colors {
            sum_r += color.r_f64();
            sum_g += color.g_f64();
            sum_b += color.b_f64();
        }

        Color::new_f64(
            sum_r / sample_colors.len() as f64,
            sum_g / sample_colors.len() as f64,
            sum_b / sample_colors.len() as f64,
        )
    }

    fn trace(&self, ray: Ray, depth: u32, cull: bool) -> Color {
        if depth == 0 {
            return Color::black();
        }

        let mut result = self.scene.clear_color;
        let possible_hit = self.scene.intersect(ray, cull);

        if let Some(hit) = possible_hit {
            result = self.shade(&hit, ray);

            if hit.shape.material().is_reflective() {
                result = result + self.reflect(&hit, ray, depth);
            }

            if hit.shape.material().is_refractive() {
                result = result + self.refract(&hit, ray, depth);
            }
        }

        result
    }

    fn shade(&self, intersection: &Intersection, original_ray: Ray) -> Color {
        let material: &Material = intersection.shape.material();
        let mut result = material.ambient_color;

        for light in self.scene.lights {
            let mut in_shadow = false;
            let distance_to_light = (intersection.point - light.origin).length();
            let light_direction = (light.origin - intersection.point).normalize();
            let ray = Ray::new(
                (intersection.point + light_direction * EPSILON).as_point(),
                light_direction,
                Some(original_ray.medium_refraction),
            );

            for object in self.scene.objects {
                if let Some(hit) = object.intersect(ray, false) {
                    if hit.t < distance_to_light {
                        in_shadow = true;
                        break;
                    }
                }
            }

            if in_shadow {
                continue;
            }

            let mut dot = light_direction.dot(&intersection.normal);

            // Diffuse
            if dot > 0.0 {
                result = result +
                    (light.color * material.diffuse_color) * dot *
                        light.intensity(distance_to_light);
            }

            dot = original_ray
                .direction
                .dot(&light_direction.reflect(&intersection.normal));

            // Specular
            if dot > 0.0 {
                let spec = dot.powf(material.specular_exponent);

                result = result +
                    (light.color * material.specular_color) * spec *
                        light.intensity(distance_to_light);
            }
        }

        result
    }

    fn reflect(&self, intersection: &Intersection, original_ray: Ray, current_depth: u32) -> Color {
        let new_direction = original_ray
            .direction
            .reflect(&intersection.normal)
            .normalize();

        let new_ray = Ray::new(
            (intersection.point + new_direction * EPSILON).as_point(),
            new_direction,
            Some(original_ray.medium_refraction),
        );

        let reflected_color = self.trace(new_ray, current_depth - 1, false);

        reflected_color *
            intersection
                .shape
                .material()
                .reflection_coefficient
                .unwrap_or(0.0)
    }

    fn refract(&self, intersection: &Intersection, original_ray: Ray, current_depth: u32) -> Color {
        assert!(
            intersection
                .shape
                .material()
                .refraction_coefficient
                .is_some(),
            "Don't call refract for materials that aren't refractive"
        );
        let mut refraction_coefficient = intersection
            .shape
            .material()
            .refraction_coefficient
            .unwrap_or(1.0);

        if intersection.inside {
            // Leaving refractive material
            refraction_coefficient = 1.0;
        }

        let n = original_ray.medium_refraction / refraction_coefficient;
        let normal = match intersection.inside {
            true => -intersection.normal,
            false => intersection.normal,
        };

        let cos_i = normal.dot(&original_ray.direction);
        let c2 = 1.0 - n * (1.0 - cos_i * cos_i);

        if c2 > 0.0 {
            let direction =
                (original_ray.direction * n + normal * (n * cos_i - c2.sqrt())).normalize();

            let new_ray = Ray::new(
                (intersection.point + direction * EPSILON).as_point(),
                direction,
                Some(refraction_coefficient),
            );

            let refraction_color = self.trace(new_ray, current_depth - 1, false);
            let absorbance = intersection.shape.material().ambient_color * 0.15 * -intersection.t;
            let transparency = Color::new_f64(
                absorbance.r_f64().exp(),
                absorbance.g_f64().exp(),
                absorbance.b_f64().exp(),
            );

            return refraction_color * transparency;
        }

        return Color::black();
    }
}
<commit_msg>Remove redundant method in renderer<commit_after>use color::Color;
use scene::Scene;
use camera::Camera;
use ray::Ray;
use intersection::Intersection;
use material::Material;
use math::EPSILON;

use rayon::prelude::*;
use std::ops::Range;

#[derive(Deserialize, Debug, Copy, Clone)]
pub enum SuperSampling {
    Off,
    On(u32),
}

pub struct Renderer<'a> {
    scene: &'a Scene<'a>,
    camera: &'a Camera,
    super_sampling: SuperSampling,
}

unsafe impl<'a> Sync for Renderer<'a> {}
unsafe impl<'a> Send for Renderer<'a> {}

impl<'a> Renderer<'a> {
    pub fn new(
        scene: &'a Scene<'a>,
        camera: &'a Camera,
        super_sampling: SuperSampling,
    ) -> Renderer<'a> {
        Renderer {
            scene: scene,
            camera: camera,
            super_sampling: super_sampling,
        }
    }

    pub fn render(&self, max_depth: u32) -> Vec<u8> {
        let range: Range<usize> = (0 as usize)..(self.camera.height as usize);
        let width = self.camera.width as usize;

        range
            .clone()
            .into_par_iter()
            .flat_map(|y| {
                (0..width)
                    .flat_map(move |x| self.render_point(max_depth, x, y).into_iter())
                    .collect::<Vec<u8>>()
                    .into_par_iter()
            })
            .collect::<Vec<u8>>()
    }

    fn render_point(&self, max_depth: u32, x: usize, y: usize) -> Color {
        let samples = match self.super_sampling {
            SuperSampling::Off => 1,
            SuperSampling::On(samples) => samples,
        };

        // TODO: Get rid of this vec in favour of just accumulating the sums directly?
        let mut sample_colors = vec![Color::black(); (samples * samples) as usize];

        for x_sample in 0..samples {
            for y_sample in 0..samples {
                let ray = self.camera.create_ray(
                    x as u32,
                    self.camera.height - y as u32,
                    x_sample,
                    y_sample,
                    samples,
                );
                sample_colors[(y_sample * samples + x_sample) as usize] =
                    self.trace(ray, max_depth, true);
            }
        }

        let mut sum_r: f64 = 0.0;
        let mut sum_g: f64 = 0.0;
        let mut sum_b: f64 = 0.0;

        for color in &sample_colors {
            sum_r += color.r_f64();
            sum_g += color.g_f64();
            sum_b += color.b_f64();
        }

        Color::new_f64(
            sum_r / sample_colors.len() as f64,
            sum_g / sample_colors.len() as f64,
            sum_b / sample_colors.len() as f64,
        )
    }

    fn trace(&self, ray: Ray, depth: u32, cull: bool) -> Color {
        if depth == 0 {
            return Color::black();
        }

        let mut result = self.scene.clear_color;
        let possible_hit = self.scene.intersect(ray, cull);

        if let Some(hit) = possible_hit {
            result = self.shade(&hit, ray);

            if hit.shape.material().is_reflective() {
                result = result + self.reflect(&hit, ray, depth);
            }

            if hit.shape.material().is_refractive() {
                result = result + self.refract(&hit, ray, depth);
            }
        }

        result
    }

    fn shade(&self, intersection: &Intersection, original_ray: Ray) -> Color {
        let material: &Material = intersection.shape.material();
        let mut result = material.ambient_color;

        for light in self.scene.lights {
            let mut in_shadow = false;
            let distance_to_light = (intersection.point - light.origin).length();
            let light_direction = (light.origin - intersection.point).normalize();
            let ray = Ray::new(
                (intersection.point + light_direction * EPSILON).as_point(),
                light_direction,
                Some(original_ray.medium_refraction),
            );

            for object in self.scene.objects {
                if let Some(hit) = object.intersect(ray, false) {
                    if hit.t < distance_to_light {
                        in_shadow = true;
                        break;
                    }
                }
            }

            if in_shadow {
                continue;
            }

            let mut dot = light_direction.dot(&intersection.normal);

            // Diffuse
            if dot > 0.0 {
                result = result +
                    (light.color * material.diffuse_color) * dot *
                        light.intensity(distance_to_light);
            }

            dot = original_ray
                .direction
                .dot(&light_direction.reflect(&intersection.normal));

            // Specular
            if dot > 0.0 {
                let spec = dot.powf(material.specular_exponent);

                result = result +
                    (light.color * material.specular_color) * spec *
                        light.intensity(distance_to_light);
            }
        }

        result
    }

    fn reflect(&self, intersection: &Intersection, original_ray: Ray, current_depth: u32) -> Color {
        let new_direction = original_ray
            .direction
            .reflect(&intersection.normal)
            .normalize();

        let new_ray = Ray::new(
            (intersection.point + new_direction * EPSILON).as_point(),
            new_direction,
            Some(original_ray.medium_refraction),
        );

        let reflected_color = self.trace(new_ray, current_depth - 1, false);

        reflected_color *
            intersection
                .shape
                .material()
                .reflection_coefficient
                .unwrap_or(0.0)
    }

    fn refract(&self, intersection: &Intersection, original_ray: Ray, current_depth: u32) -> Color {
        assert!(
            intersection.shape.material().is_refractive(),
            "Don't call refract for materials that aren't refractive"
        );
        let mut refraction_coefficient = intersection
            .shape
            .material()
            .refraction_coefficient
            .unwrap_or(1.0);

        if intersection.inside {
            // Leaving refractive material
            refraction_coefficient = 1.0;
        }

        let n = original_ray.medium_refraction / refraction_coefficient;
        let normal = match intersection.inside {
            true => -intersection.normal,
            false => intersection.normal,
        };

        let cos_i = normal.dot(&original_ray.direction);
        let c2 = 1.0 - n * (1.0 - cos_i * cos_i);

        if c2 > 0.0 {
            let direction =
                (original_ray.direction * n + normal * (n * cos_i - c2.sqrt())).normalize();

            let new_ray = Ray::new(
                (intersection.point + direction * EPSILON).as_point(),
                direction,
                Some(refraction_coefficient),
            );

            let refraction_color = self.trace(new_ray, current_depth - 1, false);
            let absorbance = intersection.shape.material().ambient_color * 0.15 * -intersection.t;
            let transparency = Color::new_f64(
                absorbance.r_f64().exp(),
                absorbance.g_f64().exp(),
                absorbance.b_f64().exp(),
            );

            return refraction_color * transparency;
        }

        return Color::black();
    }
}
<|endoftext|>