<commit_before>// Copyright 2014-2016 bluss and ndarray developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use serde::{self, Serialize, Deserialize};

use std::marker::PhantomData;

use imp_prelude::*;

use super::arraytraits::ARRAY_FORMAT_VERSION;
use super::Iter;
use Dim;
use dimension::DimPrivate;

/// **Requires crate feature `"serde"`**
impl<I> Serialize for Dim<I>
    where I: Serialize,
{
    fn serialize<Se>(&self, serializer: &mut Se) -> Result<(), Se::Error>
        where Se: serde::Serializer
    {
        self.ix().serialize(serializer)
    }
}

/// **Requires crate feature `"serde"`**
impl<I> Deserialize for Dim<I>
    where I: Deserialize,
{
    fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error>
        where D: serde::de::Deserializer
    {
        I::deserialize(deserializer).map(Dim::new)
    }
}

/// **Requires crate feature `"serde"`**
impl<A, D, S> Serialize for ArrayBase<S, D>
    where A: Serialize,
          D: Dimension + Serialize,
          S: Data<Elem = A>

{
    fn serialize<Se>(&self, serializer: &mut Se) -> Result<(), Se::Error>
        where Se: serde::Serializer
    {
        let mut struct_state = try!(serializer.serialize_struct("Array", 3));
        try!(serializer.serialize_struct_elt(&mut struct_state, "v", ARRAY_FORMAT_VERSION));
        try!(serializer.serialize_struct_elt(&mut struct_state, "dim", self.raw_dimension()));
        try!(serializer.serialize_struct_elt(&mut struct_state, "data", Sequence(self.iter())));
        serializer.serialize_struct_end(struct_state)
    }
}

// private iterator wrapper
struct Sequence<'a, A: 'a, D>(Iter<'a, A, D>);

impl<'a, A, D> Serialize for Sequence<'a, A, D>
    where A: Serialize,
          D: Dimension + Serialize
{
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: serde::Serializer
    {
        let iter = &self.0;
        let mut seq_state = try!(serializer.serialize_seq(Some(iter.len())));
        for elt in iter.clone() {
            try!(serializer.serialize_seq_elt(&mut seq_state, elt));
        }
        serializer.serialize_seq_end(seq_state)
    }
}

struct ArrayVisitor<S, Di> {
    _marker_a: PhantomData<S>,
    _marker_b: PhantomData<Di>,
}

enum ArrayField {
    Version,
    Dim,
    Data,
}

impl<S, Di> ArrayVisitor<S, Di> {
    pub fn new() -> Self {
        ArrayVisitor { _marker_a: PhantomData, _marker_b: PhantomData, }
    }
}

/// **Requires crate feature `"serde"`**
impl<A, Di, S> Deserialize for ArrayBase<S, Di>
    where A: Deserialize,
          Di: Deserialize + Dimension,
          S: DataOwned<Elem = A>
{
    fn deserialize<D>(deserializer: &mut D) -> Result<ArrayBase<S, Di>, D::Error>
        where D: serde::de::Deserializer
    {
        static FIELDS: &'static [&'static str] = &["v", "dim", "data"];

        deserializer.deserialize_struct("Array", FIELDS, ArrayVisitor::new())
    }
}

impl serde::de::Deserialize for ArrayField {
    fn deserialize<D>(deserializer: &mut D) -> Result<ArrayField, D::Error>
        where D: serde::de::Deserializer
    {
        struct ArrayFieldVisitor;

        impl serde::de::Visitor for ArrayFieldVisitor {
            type Value = ArrayField;

            fn visit_str<E>(&mut self, value: &str) -> Result<ArrayField, E>
                where E: serde::de::Error
            {
                match value {
                    "v" => Ok(ArrayField::Version),
                    "data" => Ok(ArrayField::Data),
                    "dim" => Ok(ArrayField::Dim),
                    _ => Err(serde::de::Error::custom("expected v, data, or dim")),
                }
            }
        }

        deserializer.deserialize(ArrayFieldVisitor)
    }
}

impl<A, Di, S> serde::de::Visitor for ArrayVisitor<S,Di>
    where A: Deserialize,
          Di: Deserialize + Dimension,
          S: DataOwned<Elem = A>
{
    type Value = ArrayBase<S, Di>;

    fn visit_seq<V>(&mut self, mut visitor: V) -> Result<ArrayBase<S, Di>, V::Error>
        where V: serde::de::SeqVisitor
    {
        let v: u8 = match try!(visitor.visit()) {
            Some(value) => value,
            None => {
                try!(visitor.end());
                return Err(serde::de::Error::invalid_length(0));
            }
        };

        let dim: Di = match try!(visitor.visit()) {
            Some(value) => value,
            None => {
                try!(visitor.end());
                return Err(serde::de::Error::invalid_length(1));
            }
        };

        let data: Vec<A> = match try!(visitor.visit()) {
            Some(value) => value,
            None => {
                try!(visitor.end());
                return Err(serde::de::Error::invalid_length(2));
            }
        };

        try!(visitor.end());

        if v != ARRAY_FORMAT_VERSION {
            try!(Err(serde::de::Error::custom(format!("unknown array version: {}", v))));
        }

        if let Ok(array) = ArrayBase::from_shape_vec(dim, data) {
            Ok(array)
        } else {
            Err(serde::de::Error::custom("data and dimension must match in size"))
        }
    }

    fn visit_map<V>(&mut self, mut visitor: V) -> Result<ArrayBase<S, Di>, V::Error>
        where V: serde::de::MapVisitor,
    {
        let mut v: Option<u8> = None;
        let mut data: Option<Vec<A>> = None;
        let mut dim: Option<Di> = None;

        while let Some(key) = try!(visitor.visit_key::<ArrayField>()) {
            match key {
                ArrayField::Version => { v = Some(try!(visitor.visit_value())); },
                ArrayField::Data => { data = Some(try!(visitor.visit_value())); },
                ArrayField::Dim => { dim = Some(try!(visitor.visit_value())); },
            }
        }
        try!(visitor.end());

        let v = match v {
            Some(v) => v,
            None => try!(visitor.missing_field("v")),
        };

        if v != ARRAY_FORMAT_VERSION {
            try!(Err(serde::de::Error::custom(format!("unknown array version: {}", v))));
        }

        let data = match data {
            Some(data) => data,
            None => try!(visitor.missing_field("data")),
        };

        let dim = match dim {
            Some(dim) => dim,
            None => try!(visitor.missing_field("dim")),
        };

        if let Ok(array) = ArrayBase::from_shape_vec(dim, data) {
            Ok(array)
        } else {
            Err(serde::de::Error::custom("data and dimension must match in size"))
        }
    }
}
<commit_msg>Remove unnecessary turbofish<commit_after>// Copyright 2014-2016 bluss and ndarray developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use serde::{self, Serialize, Deserialize};

use std::marker::PhantomData;

use imp_prelude::*;

use super::arraytraits::ARRAY_FORMAT_VERSION;
use super::Iter;
use Dim;
use dimension::DimPrivate;

/// **Requires crate feature `"serde"`**
impl<I> Serialize for Dim<I>
    where I: Serialize,
{
    fn serialize<Se>(&self, serializer: &mut Se) -> Result<(), Se::Error>
        where Se: serde::Serializer
    {
        self.ix().serialize(serializer)
    }
}

/// **Requires crate feature `"serde"`**
impl<I> Deserialize for Dim<I>
    where I: Deserialize,
{
    fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error>
        where D: serde::de::Deserializer
    {
        I::deserialize(deserializer).map(Dim::new)
    }
}

/// **Requires crate feature `"serde"`**
impl<A, D, S> Serialize for ArrayBase<S, D>
    where A: Serialize,
          D: Dimension + Serialize,
          S: Data<Elem = A>

{
    fn serialize<Se>(&self, serializer: &mut Se) -> Result<(), Se::Error>
        where Se: serde::Serializer
    {
        let mut struct_state = try!(serializer.serialize_struct("Array", 3));
        try!(serializer.serialize_struct_elt(&mut struct_state, "v", ARRAY_FORMAT_VERSION));
        try!(serializer.serialize_struct_elt(&mut struct_state, "dim", self.raw_dimension()));
        try!(serializer.serialize_struct_elt(&mut struct_state, "data", Sequence(self.iter())));
        serializer.serialize_struct_end(struct_state)
    }
}

// private iterator wrapper
struct Sequence<'a, A: 'a, D>(Iter<'a, A, D>);

impl<'a, A, D> Serialize for Sequence<'a, A, D>
    where A: Serialize,
          D: Dimension + Serialize
{
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: serde::Serializer
    {
        let iter = &self.0;
        let mut seq_state = try!(serializer.serialize_seq(Some(iter.len())));
        for elt in iter.clone() {
            try!(serializer.serialize_seq_elt(&mut seq_state, elt));
        }
        serializer.serialize_seq_end(seq_state)
    }
}

struct ArrayVisitor<S, Di> {
    _marker_a: PhantomData<S>,
    _marker_b: PhantomData<Di>,
}

enum ArrayField {
    Version,
    Dim,
    Data,
}

impl<S, Di> ArrayVisitor<S, Di> {
    pub fn new() -> Self {
        ArrayVisitor { _marker_a: PhantomData, _marker_b: PhantomData, }
    }
}

/// **Requires crate feature `"serde"`**
impl<A, Di, S> Deserialize for ArrayBase<S, Di>
    where A: Deserialize,
          Di: Deserialize + Dimension,
          S: DataOwned<Elem = A>
{
    fn deserialize<D>(deserializer: &mut D) -> Result<ArrayBase<S, Di>, D::Error>
        where D: serde::de::Deserializer
    {
        static FIELDS: &'static [&'static str] = &["v", "dim", "data"];

        deserializer.deserialize_struct("Array", FIELDS, ArrayVisitor::new())
    }
}

impl serde::de::Deserialize for ArrayField {
    fn deserialize<D>(deserializer: &mut D) -> Result<ArrayField, D::Error>
        where D: serde::de::Deserializer
    {
        struct ArrayFieldVisitor;

        impl serde::de::Visitor for ArrayFieldVisitor {
            type Value = ArrayField;

            fn visit_str<E>(&mut self, value: &str) -> Result<ArrayField, E>
                where E: serde::de::Error
            {
                match value {
                    "v" => Ok(ArrayField::Version),
                    "data" => Ok(ArrayField::Data),
                    "dim" => Ok(ArrayField::Dim),
                    _ => Err(serde::de::Error::custom("expected v, data, or dim")),
                }
            }
        }

        deserializer.deserialize(ArrayFieldVisitor)
    }
}

impl<A, Di, S> serde::de::Visitor for ArrayVisitor<S,Di>
    where A: Deserialize,
          Di: Deserialize + Dimension,
          S: DataOwned<Elem = A>
{
    type Value = ArrayBase<S, Di>;

    fn visit_seq<V>(&mut self, mut visitor: V) -> Result<ArrayBase<S, Di>, V::Error>
        where V: serde::de::SeqVisitor
    {
        let v: u8 = match try!(visitor.visit()) {
            Some(value) => value,
            None => {
                try!(visitor.end());
                return Err(serde::de::Error::invalid_length(0));
            }
        };

        let dim: Di = match try!(visitor.visit()) {
            Some(value) => value,
            None => {
                try!(visitor.end());
                return Err(serde::de::Error::invalid_length(1));
            }
        };

        let data: Vec<A> = match try!(visitor.visit()) {
            Some(value) => value,
            None => {
                try!(visitor.end());
                return Err(serde::de::Error::invalid_length(2));
            }
        };

        try!(visitor.end());

        if v != ARRAY_FORMAT_VERSION {
            try!(Err(serde::de::Error::custom(format!("unknown array version: {}", v))));
        }

        if let Ok(array) = ArrayBase::from_shape_vec(dim, data) {
            Ok(array)
        } else {
            Err(serde::de::Error::custom("data and dimension must match in size"))
        }
    }

    fn visit_map<V>(&mut self, mut visitor: V) -> Result<ArrayBase<S, Di>, V::Error>
        where V: serde::de::MapVisitor,
    {
        let mut v: Option<u8> = None;
        let mut data: Option<Vec<A>> = None;
        let mut dim: Option<Di> = None;

        while let Some(key) = try!(visitor.visit_key()) {
            match key {
                ArrayField::Version => { v = Some(try!(visitor.visit_value())); },
                ArrayField::Data => { data = Some(try!(visitor.visit_value())); },
                ArrayField::Dim => { dim = Some(try!(visitor.visit_value())); },
            }
        }
        try!(visitor.end());

        let v = match v {
            Some(v) => v,
            None => try!(visitor.missing_field("v")),
        };

        if v != ARRAY_FORMAT_VERSION {
            try!(Err(serde::de::Error::custom(format!("unknown array version: {}", v))));
        }

        let data = match data {
            Some(data) => data,
            None => try!(visitor.missing_field("data")),
        };

        let dim = match dim {
            Some(dim) => dim,
            None => try!(visitor.missing_field("dim")),
        };

        if let Ok(array) = ArrayBase::from_shape_vec(dim, data) {
            Ok(array)
        } else {
            Err(serde::de::Error::custom("data and dimension must match in size"))
        }
    }
}
<|endoftext|>


<commit_before>// This file is part of libfringe, a low-level green threading library.
// Copyright (c) 2015, edef <edef@edef.eu>
// See the LICENSE file included in this distribution.
use core::mem::{size_of, align_of};
use core::cmp::max;
use core::ptr;

use void::{self, Void};

use super::imp::STACK_ALIGN;

pub unsafe extern "C" fn rust_trampoline<F>(f: *const F) -> !
  where F: FnOnce() -> Void {
  void::unreachable(ptr::read(f)())
}

pub unsafe fn push<T>(spp: &mut *mut usize, value: T) -> *mut T {
  let mut sp = *spp as *mut T;
  sp = offset_mut(sp, -1);
  sp = align_down_mut(sp, max(align_of::<T>(), STACK_ALIGN));
  *sp = value;
  *spp = sp as *mut usize;
  sp
}

pub fn align_down_mut<T>(sp: *mut T, n: usize) -> *mut T {
  let sp = (sp as usize) & !(n - 1);
  sp as *mut T
}

// ptr::offset_mut is positive ints only
pub fn offset_mut<T>(ptr: *mut T, count: isize) -> *mut T {
  (ptr as isize + count * (size_of::<T>() as isize)) as *mut T
}
<commit_msg>don't drop uninitialised memory when pushing to stack<commit_after>// This file is part of libfringe, a low-level green threading library.
// Copyright (c) 2015, edef <edef@edef.eu>
// See the LICENSE file included in this distribution.
use core::mem::{size_of, align_of};
use core::cmp::max;
use core::ptr;

use void::{self, Void};

use super::imp::STACK_ALIGN;

pub unsafe extern "C" fn rust_trampoline<F>(f: *const F) -> !
  where F: FnOnce() -> Void {
  void::unreachable(ptr::read(f)())
}

pub unsafe fn push<T>(spp: &mut *mut usize, value: T) -> *mut T {
  let mut sp = *spp as *mut T;
  sp = offset_mut(sp, -1);
  sp = align_down_mut(sp, max(align_of::<T>(), STACK_ALIGN));
  ptr::write(sp, value); // does not attempt to drop old value
  *spp = sp as *mut usize;
  sp
}

pub fn align_down_mut<T>(sp: *mut T, n: usize) -> *mut T {
  let sp = (sp as usize) & !(n - 1);
  sp as *mut T
}

// ptr::offset_mut is positive ints only
pub fn offset_mut<T>(ptr: *mut T, count: isize) -> *mut T {
  (ptr as isize + count * (size_of::<T>() as isize)) as *mut T
}
<|endoftext|>


<commit_before>use serialize::{Encodable, Encoder, Decodable, Decoder};

use std::hash;

use super::{Array, Dimension, Ix};

impl<'a, A, D: Dimension> Index<D, A> for Array<A, D>
{
    #[inline]
    fn index(&self, index: &D) -> &A {
        self.at(index.clone()).unwrap()
    }
}

impl<'a, A: Clone, D: Dimension> IndexMut<D, A> for Array<A, D>
{
    #[inline]
    fn index_mut(&mut self, index: &D) -> &mut A {
        self.at_mut(index.clone()).unwrap()
    }
}

impl<A: PartialEq, D: Dimension>
PartialEq for Array<A, D>
{
    /// Return `true` if the array shapes and all elements of `self` and
    /// `other` are equal. Return `false` otherwise.
    fn eq(&self, other: &Array<A, D>) -> bool
    {
        self.shape() == other.shape() &&
        self.iter().zip(other.iter()).all(|(a, b)| a == b)
    }
}

impl<A: Eq, D: Dimension>
Eq for Array<A, D> {}

impl<A> FromIterator<A> for Array<A, Ix>
{
    fn from_iter<I: Iterator<A>>(it: I) -> Array<A, Ix>
    {
        Array::from_iter(it)
    }
}

impl<S: hash::Writer, A: hash::Hash<S>, D: Dimension>
hash::Hash<S> for Array<A, D>
{
    fn hash(&self, state: &mut S)
    {
        self.shape().hash(state);
        for elt in self.iter() {
            elt.hash(state)
        }
    }
}

// Use version number so we can add a packed format later.
static ARRAY_FORMAT_VERSION: u8 = 1u8;

impl<A: Encodable<S, E>, D: Dimension + Encodable<S, E>, E, S: Encoder<E>>
    Encodable<S, E> for Array<A, D>
{
    fn encode(&self, s: &mut S) -> Result<(), E>
    {
        s.emit_struct("Array", 0, |e| {
            try!(e.emit_struct_field("v", 0, |e| {
                ARRAY_FORMAT_VERSION.encode(e)
            }))
            // FIXME: Write self.dim as a slice (self.shape)
            // The problem is decoding it.
            try!(e.emit_struct_field("dim", 1,
                                           |e| self.dim.encode(e)))
            try!(e.emit_struct_field("data", 2, |e| {
                let sz = self.dim.size();
                e.emit_seq(sz, |e| {
                    for (i, elt) in self.iter().enumerate() {
                        try!(e.emit_seq_elt(i, |e| {
                            elt.encode(e)
                        }))
                    }
                    Ok(())
                })
            }))
            Ok(())
        })
    }
}

impl<A: Decodable<S, E>, D: Dimension + Decodable<S, E>, E, S: Decoder<E>>
    Decodable<S, E> for Array<A, D>
{
    fn decode(d: &mut S) -> Result<Array<A, D>, E>
    {
        d.read_struct("Array", 0, |d| {
            let version: u8 = try!(d.read_struct_field("v", 0, Decodable::decode));
            if version > ARRAY_FORMAT_VERSION {
                return Err(d.error("unknown array version"))
            }
            let dim: D = try!(d.read_struct_field("dim", 1, |d| {
                Decodable::decode(d)
            }));
            let elements = try!(
                d.read_struct_field("data", 2, |d| {
                    d.read_seq(|d, len| {
                        if len != dim.size() {
                            Err(d.error("data and dimension must match in size"))
                        } else {
                            let mut elements = Vec::with_capacity(len);
                            for i in range(0, len) {
                                elements.push(try!(d.read_seq_elt::<A>(i, Decodable::decode)))
                            }
                            Ok(elements)
                        }
                    })
            }));
            unsafe {
                Ok(Array::from_vec_dim(dim, elements))
            }
        })
    }
}
<commit_msg>Fix type param issue in decode<commit_after>use serialize::{Encodable, Encoder, Decodable, Decoder};

use std::hash;

use super::{Array, Dimension, Ix};

impl<'a, A, D: Dimension> Index<D, A> for Array<A, D>
{
    #[inline]
    fn index(&self, index: &D) -> &A {
        self.at(index.clone()).unwrap()
    }
}

impl<'a, A: Clone, D: Dimension> IndexMut<D, A> for Array<A, D>
{
    #[inline]
    fn index_mut(&mut self, index: &D) -> &mut A {
        self.at_mut(index.clone()).unwrap()
    }
}

impl<A: PartialEq, D: Dimension>
PartialEq for Array<A, D>
{
    /// Return `true` if the array shapes and all elements of `self` and
    /// `other` are equal. Return `false` otherwise.
    fn eq(&self, other: &Array<A, D>) -> bool
    {
        self.shape() == other.shape() &&
        self.iter().zip(other.iter()).all(|(a, b)| a == b)
    }
}

impl<A: Eq, D: Dimension>
Eq for Array<A, D> {}

impl<A> FromIterator<A> for Array<A, Ix>
{
    fn from_iter<I: Iterator<A>>(it: I) -> Array<A, Ix>
    {
        Array::from_iter(it)
    }
}

impl<S: hash::Writer, A: hash::Hash<S>, D: Dimension>
hash::Hash<S> for Array<A, D>
{
    fn hash(&self, state: &mut S)
    {
        self.shape().hash(state);
        for elt in self.iter() {
            elt.hash(state)
        }
    }
}

// Use version number so we can add a packed format later.
static ARRAY_FORMAT_VERSION: u8 = 1u8;

impl<A: Encodable<S, E>, D: Dimension + Encodable<S, E>, E, S: Encoder<E>>
    Encodable<S, E> for Array<A, D>
{
    fn encode(&self, s: &mut S) -> Result<(), E>
    {
        s.emit_struct("Array", 0, |e| {
            try!(e.emit_struct_field("v", 0, |e| {
                ARRAY_FORMAT_VERSION.encode(e)
            }))
            // FIXME: Write self.dim as a slice (self.shape)
            // The problem is decoding it.
            try!(e.emit_struct_field("dim", 1,
                                           |e| self.dim.encode(e)))
            try!(e.emit_struct_field("data", 2, |e| {
                let sz = self.dim.size();
                e.emit_seq(sz, |e| {
                    for (i, elt) in self.iter().enumerate() {
                        try!(e.emit_seq_elt(i, |e| {
                            elt.encode(e)
                        }))
                    }
                    Ok(())
                })
            }))
            Ok(())
        })
    }
}

impl<A: Decodable<S, E>, D: Dimension + Decodable<S, E>, E, S: Decoder<E>>
    Decodable<S, E> for Array<A, D>
{
    fn decode(d: &mut S) -> Result<Array<A, D>, E>
    {
        d.read_struct("Array", 0, |d| {
            let version: u8 = try!(d.read_struct_field("v", 0, Decodable::decode));
            if version > ARRAY_FORMAT_VERSION {
                return Err(d.error("unknown array version"))
            }
            let dim: D = try!(d.read_struct_field("dim", 1, |d| {
                Decodable::decode(d)
            }));
            let elements = try!(
                d.read_struct_field("data", 2, |d| {
                    d.read_seq(|d, len| {
                        if len != dim.size() {
                            Err(d.error("data and dimension must match in size"))
                        } else {
                            let mut elements = Vec::with_capacity(len);
                            for i in range(0, len) {
                                elements.push(try!(d.read_seq_elt::<A, _>(i, Decodable::decode)))
                            }
                            Ok(elements)
                        }
                    })
            }));
            unsafe {
                Ok(Array::from_vec_dim(dim, elements))
            }
        })
    }
}
<|endoftext|>


<commit_before>#[macro_use(crate_version, crate_authors)]
extern crate clap;
extern crate inspirer;

use clap::{App, Arg};

use std::fs::File;
use std::io::{Read, BufReader};

fn main() {

    // Define CLI
    let matches = App::new("aux2bib")
                        .version(crate_version!())
                        .author(crate_authors!(",\n"))
                        .about("gets BibTeX keys from Inspire")
                        .arg(Arg::with_name("INPUT")
                             .help("Sets the input file to use")
                             .index(1))
                        .arg(Arg::with_name("OUTPUT")
                            .help("Sets the output file to use")
                            .index(2))
                        .get_matches();

    // Get input from specified file or stdin
    let mut input_data = String::new();

    match matches.value_of("INPUT") {
        Some(input_file_name) => {
            println!("Reading from file: {}", input_file_name);

            let f = File::open(input_file_name).expect("File not found");
            let mut reader = BufReader::new(f);
            reader.read_to_string(&mut input_data).unwrap();
        },
        None => {
            println!("Reading from stdin");

            let stdin = std::io::stdin();
            let stdin = stdin.lock();

            let mut reader = BufReader::new(stdin);
            reader.read_to_string(&mut input_data).unwrap();
        }
    }

    // Extract BibTeX tags from document
    let keys = inspirer::aux2key(input_data);

    // Retrieve BibTeX entries from inspire.net
    println!("Retrieving entries...");
    let mut bibtex_entries: Vec<String> = Vec::new();
    for key in keys {
        if let Some(bibtex_entry) = inspirer::fetch_bibtex_with_key(key) {
            bibtex_entries.push(bibtex_entry);
        }
    }

    // Write BibTeX entries to file or stdout
    match matches.value_of("OUTPUT") {
        Some(output_file_name) => {
            println!("Writing to file: {}", output_file_name);
        },
        None => {
            println!("Writing to stdout");
        }
    }
}
<commit_msg>aux2bib: Write output<commit_after>#[macro_use(crate_version, crate_authors)]
extern crate clap;
extern crate inspirer;

use clap::{App, Arg};

use std::fs::File;
use std::io::{Read, BufReader};
use std::io::{Write, BufWriter};

fn main() {

    // Define CLI
    let matches = App::new("aux2bib")
                        .version(crate_version!())
                        .author(crate_authors!(",\n"))
                        .about("gets BibTeX keys from Inspire")
                        .arg(Arg::with_name("INPUT")
                             .help("Sets the input file to use")
                             .index(1))
                        .arg(Arg::with_name("OUTPUT")
                            .help("Sets the output file to use")
                            .index(2))
                        .get_matches();

    // Get input from specified file or stdin
    let mut input_data = String::new();

    match matches.value_of("INPUT") {
        Some(input_file_name) => {
            println!("Reading from file: {}", input_file_name);

            let f = File::open(input_file_name).expect("File not found");
            let mut reader = BufReader::new(f);
            reader.read_to_string(&mut input_data).unwrap();
        },
        None => {
            println!("Reading from stdin");

            let stdin = std::io::stdin();
            let stdin = stdin.lock();

            let mut reader = BufReader::new(stdin);
            reader.read_to_string(&mut input_data).unwrap();
        }
    }

    // Extract BibTeX tags from document
    let keys = inspirer::aux2key(input_data);

    // Retrieve BibTeX entries from inspire.net
    println!("Retrieving entries...");
    let mut bibtex_entries: Vec<String> = Vec::new();
    for key in keys {
        if let Some(bibtex_entry) = inspirer::fetch_bibtex_with_key(key) {
            bibtex_entries.push(bibtex_entry);
        }
    }

    // Write BibTeX entries to file or stdout

    let mut stdout = std::io::stdout();
    let mut output_file: std::fs::File;

    let writer: &mut Write = match matches.value_of("OUTPUT") {
        Some(file_name) => {
            println!("Writing to file: {}", file_name);
            output_file = File::create(file_name).unwrap();
            &mut output_file
        },
        None            => {
            println!("Writing to stdout");
            // stdout.lock();
            &mut stdout
        },
    };

    let mut writer = BufWriter::new(writer);

    for bibtex_entry in bibtex_entries {
        writer.write(&bibtex_entry.as_bytes()).unwrap();
    }

    writer.flush().unwrap();
}
<|endoftext|>


<commit_before>extern crate markov;

use std::env::args;
use std::path::Path;
use markov::Chain;

#[cfg(not(test))]
fn main() {
    markov_gen(args().skip(1).collect()).iter().map(|s| println!("{}", s)).count();
}

/// Generates a number of strings using a markov chain on specified inputs. This is designed
/// primarily for command-line usage. The arguments are expected to be paths to files to be fed
/// into the chain. Additionally, the argument `-n #` is supported to specify the number of phrases
/// to be generated. This number must be a positive, non-zero integer.
///
/// Some valid usages of this function:
/// `markov_gen(vec!["test".to_owned()])`
/// `markov_gen(vec!["test".to_owned(), "-n".to_owned(), "3".to_owned()])`
/// `markov_gen(vec!["-n".to_owned(), "3".to_owned(), "test".to_owned()])`
///
/// Some invalid usages of this function:
/// `markov_gen(vec!["-n".to_owned(), "3".to_owned()])`
/// `markov_gen(vec!["test".to_owned(), "-n".to_owned(), "0".to_owned()])`
/// `markov_gen(vec!["test".to_owned(), "-n".to_owned(), "test".to_owned()])`
fn markov_gen(args: Vec<String>) -> Vec<String> {
    let mut chain = Chain::for_strings();
    let mut expecting_num = false;
    let mut count = 1usize;
    for arg in args.iter() {
        if expecting_num {
            match arg.parse() {
                Ok(n) if n > 0 => count = n,
                _ => panic!("Expected positive integer argument to -n, found {}.", &arg)
            }
            expecting_num = false;
        } else if &arg[..] == "-n" {
            expecting_num = true;
        } else {
            chain.feed_file(Path::new(&arg));
        }
    }
    if chain.is_empty() { panic!("No files were fed into the chain.") }
    chain.str_iter_for(count).collect()
}

#[cfg(test)]
mod test {
    use super::markov_gen;
    use std::borrow::ToOwned;

    #[test]
    fn gen_default() {
        assert_eq!(markov_gen(vec!["test".to_owned()]).len(), 1)
    }

    #[test]
    fn gen_number_after() {
        assert_eq!(markov_gen(
            vec!["test".to_owned(), "-n".to_owned(), "3".to_owned()]
        ).len(), 3)
    }

    #[test]
    fn gen_before_number() {
        assert_eq!(markov_gen(
            vec!["-n".to_owned(), "3".to_owned(), "test".to_owned()]
        ).len(), 3)
    }

    #[test]
    #[should_fail(message = "No files were fed into the chain.")]
    fn gen_invalid_no_files() {
        markov_gen(vec!["-n".to_owned(), "3".to_owned()]);
    }

    #[test]
    #[should_fail(message = "Expected positive integer argument to -n, found 0.")]
    fn gen_invalid_n_arg_zero() {
        markov_gen(vec!["test".to_owned(), "-n".to_owned(), "0".to_owned()]);
    }

    #[test]
    #[should_fail(message = "Expected positive integer argument to -n, found test.")]
    fn gen_invalid_n_arg_string() {
        markov_gen(vec!["test".to_owned(), "-n".to_owned(), "test".to_owned()]);
    }
}
<commit_msg>Fixed test compilation.<commit_after>extern crate markov;

use std::env::args;
use std::path::Path;
use markov::Chain;

#[cfg(not(test))]
fn main() {
    markov_gen(args().skip(1).collect()).iter().map(|s| println!("{}", s)).count();
}

/// Generates a number of strings using a markov chain on specified inputs. This is designed
/// primarily for command-line usage. The arguments are expected to be paths to files to be fed
/// into the chain. Additionally, the argument `-n #` is supported to specify the number of phrases
/// to be generated. This number must be a positive, non-zero integer.
///
/// Some valid usages of this function:
/// `markov_gen(vec!["test".to_owned()])`
/// `markov_gen(vec!["test".to_owned(), "-n".to_owned(), "3".to_owned()])`
/// `markov_gen(vec!["-n".to_owned(), "3".to_owned(), "test".to_owned()])`
///
/// Some invalid usages of this function:
/// `markov_gen(vec!["-n".to_owned(), "3".to_owned()])`
/// `markov_gen(vec!["test".to_owned(), "-n".to_owned(), "0".to_owned()])`
/// `markov_gen(vec!["test".to_owned(), "-n".to_owned(), "test".to_owned()])`
fn markov_gen(args: Vec<String>) -> Vec<String> {
    let mut chain = Chain::for_strings();
    let mut expecting_num = false;
    let mut count = 1usize;
    for arg in args.iter() {
        if expecting_num {
            match arg.parse() {
                Ok(n) if n > 0 => count = n,
                _ => panic!("Expected positive integer argument to -n, found {}.", &arg)
            }
            expecting_num = false;
        } else if &arg[..] == "-n" {
            expecting_num = true;
        } else {
            chain.feed_file(Path::new(&arg));
        }
    }
    if chain.is_empty() { panic!("No files were fed into the chain.") }
    chain.str_iter_for(count).collect()
}

#[cfg(test)]
mod test {
    use super::markov_gen;
    use std::borrow::ToOwned;

    #[test]
    fn gen_default() {
        assert_eq!(markov_gen(vec!["test".to_owned()]).len(), 1)
    }

    #[test]
    fn gen_number_after() {
        assert_eq!(markov_gen(
            vec!["test".to_owned(), "-n".to_owned(), "3".to_owned()]
        ).len(), 3)
    }

    #[test]
    fn gen_before_number() {
        assert_eq!(markov_gen(
            vec!["-n".to_owned(), "3".to_owned(), "test".to_owned()]
        ).len(), 3)
    }

    #[test]
    #[should_panic(message = "No files were fed into the chain.")]
    fn gen_invalid_no_files() {
        markov_gen(vec!["-n".to_owned(), "3".to_owned()]);
    }

    #[test]
    #[should_panic(message = "Expected positive integer argument to -n, found 0.")]
    fn gen_invalid_n_arg_zero() {
        markov_gen(vec!["test".to_owned(), "-n".to_owned(), "0".to_owned()]);
    }

    #[test]
    #[should_panic(message = "Expected positive integer argument to -n, found test.")]
    fn gen_invalid_n_arg_string() {
        markov_gen(vec!["test".to_owned(), "-n".to_owned(), "test".to_owned()]);
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate serde_derive;
extern crate docopt;
extern crate chan_signal;
extern crate rand;
extern crate sled;

use std::mem;
use std::thread;
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
use std::sync::Arc;

use chan_signal::Signal;
use docopt::Docopt;
use rand::{Rng, thread_rng};

static mut KEY_BYTES: usize = 2;

const USAGE: &'static str = "
Usage: stress2 [options]

Options:
    --burn-in          Don't halt until we receive a signal.
    --duration=<s>     Seconds to run for [default: 10].
    --get=<threads>    Threads spinning on get operations [default: 1].
    --set=<threads>    Threads spinning on set operations [default: 1].
    --del=<threads>    Threads spinning on del operations [default: 0].
    --cas=<threads>    Threads spinning on cas operations [default: 0].
    --scan=<threads>   Threads spinning on scan operations [default: 0].
    --key-len=<bytes>  Length of keys and values [default: 2].
";

#[derive(Deserialize)]
struct Args {
    flag_burn_in: bool,
    flag_duration: u64,
    flag_get: usize,
    flag_set: usize,
    flag_del: usize,
    flag_cas: usize,
    flag_scan: usize,
    flag_key_len: usize,
}

fn report(shutdown: Arc<AtomicBool>, total: Arc<AtomicUsize>) {
    let mut last = 0;
    while !shutdown.load(Ordering::Relaxed) {
        thread::sleep(std::time::Duration::from_secs(1));
        let total = total.load(Ordering::Acquire);

        println!("did {} ops", total - last);

        last = total;
    }
}

fn byte() -> Vec<u8> {
    let mut v = unsafe { vec![0; KEY_BYTES] };
    thread_rng().fill_bytes(&mut v);
    v
}

fn prepopulate(tree: Arc<sled::Tree>) {
    let max = 256_usize.pow(unsafe { KEY_BYTES as u32 });
    for i in 0..max {
        let bytes: [u8; 8] = unsafe { mem::transmute(i) };
        let k = bytes[8 - unsafe { KEY_BYTES }..8].to_vec();
        let v = vec![];
        tree.set(k, v);
    }
}

fn main() {
    let args: Args = Docopt::new(USAGE)
        .and_then(|d| d.argv(std::env::args().into_iter()).deserialize())
        .unwrap_or_else(|e| e.exit());

    unsafe {
        KEY_BYTES = args.flag_key_len;
    }

    let total = Arc::new(AtomicUsize::new(0));
    let shutdown = Arc::new(AtomicBool::new(false));

    let config = sled::Config::default()
        .io_bufs(2)
        .blink_fanout(15)
        .page_consolidation_threshold(10)
        .cache_fixup_threshold(1)
        .cache_bits(6)
        .cache_capacity(128 * 1024 * 1024)
        .flush_every_ms(None)
        // .io_buf_size(10000)
        .path("stress2.db".to_string())
        .snapshot_after_ops(100000);

    println!("recovering");
    let tree = Arc::new(config.tree());

    macro_rules! cloned {
        ($f:expr) => {{
            let tree = tree.clone();
            let total = total.clone();
            let shutdown = shutdown.clone();
            thread::spawn(|| $f(tree, shutdown, total))
        }};
    }

    println!("before prepopulate");
    prepopulate(tree.clone());
    println!("after prepopulate");

    let mut threads =
        vec![cloned!(|_, shutdown, total| report(shutdown, total))];

    macro_rules! spin_up {
        ($($n:expr, $fn:expr;)*)=> (
            $(
            for _ in 0..$n {
                let tree = tree.clone();
                let shutdown = shutdown.clone();
                let total = total.clone();
                let thread = thread::spawn(move || {
                    while !shutdown.load(Ordering::Relaxed) {
                        total.fetch_add(1, Ordering::Release);
                        $fn(&tree);
                    }
                });
                threads.push(thread);
            }
            )*
        );
    }

    #[rustfmt_skip]
    spin_up![
        args.flag_get, |t: &Arc<sled::Tree>| t.get(&*byte());
        args.flag_set, |t: &Arc<sled::Tree>| t.set(byte(), byte());
        args.flag_del, |t: &Arc<sled::Tree>| t.del(&*byte());
        args.flag_cas, |t: &Arc<sled::Tree>| {
            let _ = t.cas(byte(), Some(byte()), Some(byte()));
        };
        args.flag_scan, |t: &Arc<sled::Tree>| t.scan(&*byte())
            .take(thread_rng().gen_range(1, 3))
            .collect::<Vec<_>>();
    ];

    let now = std::time::Instant::now();

    if args.flag_burn_in {
        let signal = chan_signal::notify(&[Signal::INT, Signal::TERM]);

        println!("burning in");
        signal.recv();
        println!("got shutdown signal, cleaning up...");
    } else {
        thread::sleep(std::time::Duration::from_secs(args.flag_duration));
    }

    shutdown.store(true, Ordering::SeqCst);

    for t in threads.into_iter() {
        let _ = t.join();
    }

    let ops = total.load(Ordering::SeqCst);
    let time = now.elapsed().as_secs() as usize;

    sled::M.print_profile();

    println!(
        "did {} total ops in {} seconds. {} ops/s",
        ops,
        time,
        (ops * 1_000) / (time * 1_000)
    );
}
<commit_msg>use 16mb stacks for stress2 to prevent overflow<commit_after>#[macro_use]
extern crate serde_derive;
extern crate docopt;
extern crate chan_signal;
extern crate rand;
extern crate sled;

use std::mem;
use std::thread;
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
use std::sync::Arc;

use chan_signal::Signal;
use docopt::Docopt;
use rand::{Rng, thread_rng};

static mut KEY_BYTES: usize = 2;

const USAGE: &'static str = "
Usage: stress2 [options]

Options:
    --burn-in          Don't halt until we receive a signal.
    --duration=<s>     Seconds to run for [default: 10].
    --get=<threads>    Threads spinning on get operations [default: 1].
    --set=<threads>    Threads spinning on set operations [default: 1].
    --del=<threads>    Threads spinning on del operations [default: 0].
    --cas=<threads>    Threads spinning on cas operations [default: 0].
    --scan=<threads>   Threads spinning on scan operations [default: 0].
    --key-len=<bytes>  Length of keys and values [default: 2].
";

#[derive(Deserialize)]
struct Args {
    flag_burn_in: bool,
    flag_duration: u64,
    flag_get: usize,
    flag_set: usize,
    flag_del: usize,
    flag_cas: usize,
    flag_scan: usize,
    flag_key_len: usize,
}

fn report(shutdown: Arc<AtomicBool>, total: Arc<AtomicUsize>) {
    let mut last = 0;
    while !shutdown.load(Ordering::Relaxed) {
        thread::sleep(std::time::Duration::from_secs(1));
        let total = total.load(Ordering::Acquire);

        println!("did {} ops", total - last);

        last = total;
    }
}

fn byte() -> Vec<u8> {
    let mut v = unsafe { vec![0; KEY_BYTES] };
    thread_rng().fill_bytes(&mut v);
    v
}

fn prepopulate(tree: Arc<sled::Tree>) {
    let max = 256_usize.pow(unsafe { KEY_BYTES as u32 });
    for i in 0..max {
        let bytes: [u8; 8] = unsafe { mem::transmute(i) };
        let k = bytes[8 - unsafe { KEY_BYTES }..8].to_vec();
        let v = vec![];
        tree.set(k, v);
    }
}

fn main() {
    let args: Args = Docopt::new(USAGE)
        .and_then(|d| d.argv(std::env::args().into_iter()).deserialize())
        .unwrap_or_else(|e| e.exit());

    unsafe {
        KEY_BYTES = args.flag_key_len;
    }

    let total = Arc::new(AtomicUsize::new(0));
    let shutdown = Arc::new(AtomicBool::new(false));

    let config = sled::Config::default()
        .io_bufs(2)
        .blink_fanout(15)
        .page_consolidation_threshold(10)
        .cache_fixup_threshold(1)
        .cache_bits(6)
        .cache_capacity(128 * 1024 * 1024)
        .flush_every_ms(None)
        // .io_buf_size(10000)
        .path("stress2.db".to_string())
        .snapshot_after_ops(100000);

    println!("recovering");
    let tree = Arc::new(config.tree());

    macro_rules! cloned {
        ($f:expr) => {{
            let tree = tree.clone();
            let total = total.clone();
            let shutdown = shutdown.clone();
            thread::spawn(|| $f(tree, shutdown, total))
        }};
    }

    println!("before prepopulate");
    prepopulate(tree.clone());
    println!("after prepopulate");

    let mut threads =
        vec![cloned!(|_, shutdown, total| report(shutdown, total))];

    macro_rules! spin_up {
        ($($n:expr, $fn:expr;)*)=> (
            $(
            for _ in 0..$n {
                let tree = tree.clone();
                let shutdown = shutdown.clone();
                let total = total.clone();
                let thread = thread::Builder::new()
                    .stack_size(2 << 23) // make some bigass 16mb stacks
                    .spawn(move || {
                    while !shutdown.load(Ordering::Relaxed) {
                        total.fetch_add(1, Ordering::Release);
                        $fn(&tree);
                    }
                }).unwrap();
                threads.push(thread);
            }
            )*
        );
    }

    #[rustfmt_skip]
    spin_up![
        args.flag_get, |t: &Arc<sled::Tree>| t.get(&*byte());
        args.flag_set, |t: &Arc<sled::Tree>| t.set(byte(), byte());
        args.flag_del, |t: &Arc<sled::Tree>| t.del(&*byte());
        args.flag_cas, |t: &Arc<sled::Tree>| {
            let _ = t.cas(byte(), Some(byte()), Some(byte()));
        };
        args.flag_scan, |t: &Arc<sled::Tree>| t.scan(&*byte())
            .take(thread_rng().gen_range(1, 3))
            .collect::<Vec<_>>();
    ];

    let now = std::time::Instant::now();

    if args.flag_burn_in {
        let signal = chan_signal::notify(&[Signal::INT, Signal::TERM]);

        println!("burning in");
        signal.recv();
        println!("got shutdown signal, cleaning up...");
    } else {
        thread::sleep(std::time::Duration::from_secs(args.flag_duration));
    }

    shutdown.store(true, Ordering::SeqCst);

    for t in threads.into_iter() {
        let _ = t.join();
    }

    let ops = total.load(Ordering::SeqCst);
    let time = now.elapsed().as_secs() as usize;

    sled::M.print_profile();

    println!(
        "did {} total ops in {} seconds. {} ops/s",
        ops,
        time,
        (ops * 1_000) / (time * 1_000)
    );
}
<|endoftext|>


<commit_before>extern crate futures;
extern crate text_ui;
extern crate tokio;
extern crate tokio_serde_msgpack;
extern crate tokio_uds;
extern crate weaver;

use text_ui::app::App;
use text_ui::backend::Backend;
use text_ui::widget::{shared, Linear, Shared, Text, TextInput};
use text_ui::{Event, Input, Key};

use std::sync::mpsc::Sender;
use std::thread;

use futures::sync::mpsc::{unbounded, UnboundedReceiver, UnboundedSender};

use tokio::prelude::{Future, Sink, Stream};
use tokio_serde_msgpack::{from_io, MsgPackReader, MsgPackWriter};
use tokio_uds::UnixStream;

use weaver::{weaver_socket_path, ClientMessage, ServerMessage};

#[derive(Debug, PartialEq, Clone)]
pub enum WeaverNotification {
    _Heartbeat,
}

pub struct WeaverClient {
    pub notifications: Sender<WeaverNotification>,
    pub commands: UnboundedSender<ClientMessage>,
}

impl WeaverClient {
    pub fn new(notifications: Sender<WeaverNotification>) -> Self {
        let socketpath = weaver_socket_path();
        let socket = UnixStream::connect(socketpath).unwrap();

        let (socket_rx, socket_tx): (
            MsgPackReader<UnixStream, ServerMessage>,
            MsgPackWriter<UnixStream, ClientMessage>,
        ) = from_io(socket);
        let socket_tx = socket_tx.sink_map_err(|e| println!("Send Err: {:#?}", e));

        let (commands, commands_tx): (
            UnboundedSender<ClientMessage>,
            UnboundedReceiver<ClientMessage>,
        ) = unbounded();

        let session = commands_tx
            .forward(socket_tx)
            .map_err(|e| println!("Encode Err: {:#?}", e))
            .and_then(|_| Ok(()));

        thread::spawn(move || {
            tokio::run(session);
        });
        WeaverClient {
            notifications,
            commands,
        }
    }

    pub fn send_cmd(&mut self, cmd: ClientMessage) {
        self.commands.unbounded_send(cmd);
    }
}

struct WeaverTui {
    log: Shared<Text>,
    input: Shared<TextInput>,
    vbox: Shared<Linear>,
    weaver: WeaverClient,
}

impl WeaverTui {
    fn new(weaver: WeaverClient) -> WeaverTui {
        let log = shared(Text::new(vec![]));
        let input = shared(TextInput::new(""));
        let mut mainbox = Linear::vbox();
        mainbox.push(&log);
        mainbox.push(&input);
        let vbox = shared(mainbox);
        WeaverTui {
            log,
            input,
            vbox,
            weaver,
        }
    }

    fn submit_input(&mut self) {
        let text = self.input.write().unwrap().submit();
        let lines = text.lines();
        let mut log = self.log.write().unwrap();
        for line in lines {
            self.weaver.send_cmd(ClientMessage {
                id: 5,
                name: line.to_owned(),
            });
            log.push(line.to_owned());
        }
    }

    fn log_msg(&mut self, msg: &str) {
        let lines: Vec<String> = msg.lines().map(|l| l.to_owned()).collect();
        self.log.write().unwrap().lines.extend(lines);
    }

    fn input(&mut self, key: Key) {
        match key {
            Key::Char('\n') => self.submit_input(),
            k => self.input.write().unwrap().keypress(k),
        }
    }
}

impl App for WeaverTui {
    type UI = Shared<Linear>;
    type MyEvent = WeaverNotification;
    fn widget(&self) -> Self::UI {
        self.vbox.clone()
    }
    fn handle_event(&mut self, event: Event<Self::MyEvent>) -> Result<(), Option<String>> {
        self.log_msg(&format!("{:?}", event));
        match event {
            Event::InputEvent(i) => match i {
                Input::Key(Key::Esc) => Err(None),
                Input::Key(k) => {
                    self.input(k);
                    Ok(())
                }
                _ => Ok(()),
            },
            Event::AppEvent(_) => Ok(()),
        }
    }
}

fn main() {
    let mut be = Backend::new();
    let sender = be.sender.clone();
    let weaver = WeaverClient::new(sender);
    let mut app = WeaverTui::new(weaver);
    app.log_msg("Esc to exit");
    be.run_app(&mut app);
}
<commit_msg>Receive messages from server<commit_after>extern crate futures;
extern crate text_ui;
extern crate tokio;
extern crate tokio_serde_msgpack;
extern crate tokio_uds;
extern crate weaver;

use text_ui::app::App;
use text_ui::backend::Backend;
use text_ui::widget::{shared, Linear, Shared, Text, TextInput};
use text_ui::{Event, Input, Key};

use std::sync::mpsc::SendError as StdSendError;
use std::sync::mpsc::Sender;
use std::sync::{Arc, RwLock};
use std::thread;

use futures::sync::mpsc::SendError as FutureSendError;
use futures::sync::mpsc::{unbounded, UnboundedReceiver, UnboundedSender};

use tokio::prelude::{Future, Sink, Stream};
use tokio_serde_msgpack::{from_io, MsgPackReader, MsgPackWriter};
use tokio_uds::UnixStream;

use weaver::{weaver_socket_path, ClientMessage, ServerMessage};

#[derive(Debug, PartialEq)]
pub enum WeaverNotification {
    _Heartbeat,
    Server(ServerMessage),
}

struct WeaverClientCore {
    pub notifications: Sender<WeaverNotification>,
}

impl WeaverClientCore {
    fn new(notifications: Sender<WeaverNotification>) -> Arc<RwLock<Self>> {
        Arc::new(RwLock::new(WeaverClientCore { notifications }))
    }

    fn _send_notification(
        &self,
        n: WeaverNotification,
    ) -> Result<(), StdSendError<WeaverNotification>> {
        self.notifications.send(n)
    }
}

pub struct WeaverClient {
    pub commands: UnboundedSender<ClientMessage>,
    _core: Arc<RwLock<WeaverClientCore>>,
}

impl WeaverClient {
    pub fn new(notifications: Sender<WeaverNotification>) -> Self {
        let (commands, commands_tx): (
            UnboundedSender<ClientMessage>,
            UnboundedReceiver<ClientMessage>,
        ) = unbounded();

        // XXX Can't share Sender between threads
        let notifications2 = notifications.clone();

        let core = WeaverClientCore::new(notifications);
        let core2 = core.clone();
        let socketpath = weaver_socket_path();
        let socketf = futures::future::result(UnixStream::connect(socketpath));

        let run_client_socket = socketf
            .and_then(|socket| {
                let (socket_rx, socket_tx): (
                    MsgPackReader<UnixStream, ServerMessage>,
                    MsgPackWriter<UnixStream, ClientMessage>,
                ) = from_io(socket);
                let socket_tx = socket_tx.sink_map_err(|e| println!("Send Err: {:#?}", e));
                let socket_rx = socket_rx.map_err(|e| panic!("Decode Error: {:#?}", e));

                let send_commands = commands_tx
                    .forward(socket_tx)
                    .map_err(|e| println!("Encode Err: {:#?}", e))
                    .and_then(|_| Ok(()));

                tokio::spawn(send_commands);

                let recv_msgs = socket_rx
                    .for_each(move |msg| notifications2.send(WeaverNotification::Server(msg)))
                    .and_then(|_| Ok(()))
                    .map_err(|e| panic!("Notification Send Error: {:#?}", e));

                tokio::spawn(recv_msgs);

                Ok(())
            })
            .map_err(|e| panic!("Socket Connect Error: {:#?}", e));

        thread::spawn(move || {
            tokio::run(run_client_socket);
        });
        WeaverClient {
            commands,
            _core: core2,
        }
    }

    pub fn send_cmd(
        &mut self,
        cmd: ClientMessage,
    ) -> Result<(), FutureSendError<weaver::ClientMessage>> {
        self.commands.unbounded_send(cmd)
    }
}

struct WeaverTui {
    log: Shared<Text>,
    input: Shared<TextInput>,
    vbox: Shared<Linear>,
    weaver: WeaverClient,
}

impl WeaverTui {
    fn new(weaver: WeaverClient) -> WeaverTui {
        let log = shared(Text::new(vec![]));
        let input = shared(TextInput::new(""));
        let mut mainbox = Linear::vbox();
        mainbox.push(&log);
        mainbox.push(&input);
        let vbox = shared(mainbox);
        WeaverTui {
            log,
            input,
            vbox,
            weaver,
        }
    }

    fn submit_input(&mut self) {
        let text = self.input.write().unwrap().submit();
        let lines = text.lines();
        let mut log = self.log.write().unwrap();
        for line in lines {
            self.weaver
                .send_cmd(ClientMessage {
                    id: 5,
                    name: line.to_owned(),
                })
                .unwrap();
            log.push(line.to_owned());
        }
    }

    fn log_msg(&mut self, msg: &str) {
        let lines: Vec<String> = msg.lines().map(|l| l.to_owned()).collect();
        self.log.write().unwrap().lines.extend(lines);
    }

    fn input(&mut self, key: Key) {
        match key {
            Key::Char('\n') => self.submit_input(),
            k => self.input.write().unwrap().keypress(k),
        }
    }
}

impl App for WeaverTui {
    type UI = Shared<Linear>;
    type MyEvent = WeaverNotification;
    fn widget(&self) -> Self::UI {
        self.vbox.clone()
    }
    fn handle_event(&mut self, event: Event<Self::MyEvent>) -> Result<(), Option<String>> {
        self.log_msg(&format!("{:?}", event));
        match event {
            Event::InputEvent(i) => match i {
                Input::Key(Key::Esc) => Err(None),
                Input::Key(k) => {
                    self.input(k);
                    Ok(())
                }
                _ => Ok(()),
            },
            Event::AppEvent(_) => Ok(()),
        }
    }
}

fn main() {
    let be = Backend::new();
    let sender = be.sender.clone();
    let weaver = WeaverClient::new(sender);
    let mut app = WeaverTui::new(weaver);
    app.log_msg("Esc to exit");
    be.run_app(&mut app);
}
<|endoftext|>


<commit_before>use std::convert::TryFrom;

use rust_decimal::Decimal;
use derive_collect_docs::CollectDocs;
use lazy_static::lazy_static;
use regex::Regex;
use serde::{de::Deserializer, ser::Serializer, Deserialize, Serialize};
use thiserror::Error;

#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord)]
#[derive(CollectDocs)]
pub enum KeyValue {
    Symbol(String),
    Special { id: String, width: Decimal },
    None,
}

impl From<Option<String>> for KeyValue {
    fn from(x: Option<String>) -> Self {
        x.map(KeyValue::Symbol).unwrap_or(KeyValue::None)
    }
}

impl From<String> for KeyValue {
    fn from(x: String) -> Self {
        KeyValue::Symbol(x)
    }
}

impl ToString for KeyValue {
    fn to_string(&self) -> String {
        serialize(self)
    }
}

impl<'de> Deserialize<'de> for KeyValue {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        let x: &str = Deserialize::deserialize(deserializer)?;
        Ok(deserialize(x))
    }
}

impl Serialize for KeyValue {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        serializer.serialize_str(&serialize(self))
    }
}

pub fn deserialize_special(input: &str) -> Option<KeyValue> {
    lazy_static! {
        static ref RE: Regex =
            Regex::new(r"^\\s\{([^}:]+)(?::(\d+(?:\.\d+)?))?\}$").expect("valid regex");
    }

    // Symbol syntax \s{id:width}, or with optional width defaulting to 1.0, \s{id}
    RE.captures(input).map(|cap| KeyValue::Special {
        id: match cap.get(1).unwrap().as_str() {
            id if id.starts_with('"') && id.ends_with('"') => id.to_owned(),
            id => format!("_{}", id),
        },
        width: cap
            .get(2)
            .and_then(|v| v.as_str().parse::<Decimal>().ok())
            .unwrap_or_else(|| Decimal::try_from(1.0).unwrap()),
    })
}

pub fn deserialize(input: &str) -> KeyValue {
    if let Some(special) = deserialize_special(input) {
        special
    } else if input == r"\u{0}" {
        KeyValue::None
    } else {
        KeyValue::Symbol(decode_unicode_escapes(input))
    }
}

pub fn serialize_special(id: &str, width: &Decimal) -> String {
    let id = if id.starts_with('"') && id.ends_with('"') {
        id
    } else {
        &id[1..]
    };

    if width == &Decimal::try_from(1.0).unwrap() {
        format!("\\s{{{}}}", id)
    } else {
        format!("\\s{{{}:{:.2}}}", id, width)
    }
}

pub fn serialize(input: &KeyValue) -> String {
    match input {
        KeyValue::Special { id, width } => serialize_special(id, width),
        KeyValue::Symbol(input) => decode_unicode_escapes(input)
            .chars()
            .map(|c| {
                let char_category = unic_ucd_category::GeneralCategory::of(c);

                if char_category.is_other()
                    || char_category.is_separator()
                    || char_category.is_mark()
                {
                    c.escape_unicode().to_string()
                } else {
                    c.to_string()
                }
            })
            .collect(),
        _ => String::from(r"\u{0}"),
    }
}

/// Decode unicode escapes like `\u{30A}`
fn decode_unicode_escapes(input: &str) -> String {
    lazy_static! {
        static ref RE: Regex = Regex::new(r"\\u\{([0-9A-Fa-f]{1,6})\}").expect("valid regex");
    }

    let new = RE.replace_all(input, |hex: &regex::Captures| {
        let number = u32::from_str_radix(hex.get(1).unwrap().as_str(), 16).unwrap_or(0xfeff);
        std::char::from_u32(number).unwrap().to_string()
    });

    new.to_string()
}

#[derive(Debug, Error)]
pub enum Error {
    #[error("std failed to parse `{input}` as char: {source}")]
    CharParseError {
        input: String,
        source: std::char::ParseCharError,
    },
    #[error("Error parsing `{input}` as char: {description}")]
    CharFromStrError { input: String, description: String },
}

#[cfg(test)]
#[allow(clippy::unnecessary_operation)]
mod tests {
    use super::{decode_unicode_escapes, deserialize, deserialize_special, serialize, KeyValue};
    use proptest::prelude::*;

    #[test]
    fn test_unicode_escapes() {
        assert_eq!("\u{35}", decode_unicode_escapes(r"\u{35}"));
        assert_eq!("5", decode_unicode_escapes(r"\u{35}"));

        assert_eq!("\u{5}", decode_unicode_escapes(r"\u{5}"));
        assert_eq!("\"", decode_unicode_escapes(r"\u{22}"));
    }

    #[test]
    fn roundtrips() {
        let x = r"0 1 2 3 4 5 6 7 8 9 0 \u{1F} = \
            \u{11} \u{17} \u{5} \u{12} \u{14} \u{19} \u{15} \u{9} \u{F} \u{10} \u{1B} \u{1D} \
            \u{1} \u{13} \u{4} \u{6} \u{7} \u{8} \u{A} \u{B} \u{C} ; ' \u{1C} \
            ` \u{1A} \u{18} \u{3} \u{16} \u{2} \u{E} \u{D} , . /";

        for s in x.split_whitespace() {
            assert_eq!(s.to_lowercase(), serialize(&deserialize(&s)));
        }
    }

    #[test]
    fn roundtrips_special_chars() {
        let x = r"0 1 2 3 4 5 6 7 8 9 0 \u{1F} = \
            \u{11} \u{17} \u{5} \u{12} \u{14} \u{19} \u{15} \u{9} \s{sdsda:1.50} \u{10} \u{1B} \u{1D} \
            \u{1} \u{13} \u{4} \s{hello:1.05} \u{7} \u{8} \u{A} \u{B} \u{C} ; ' \u{1C} \
            ` \s{casdc:1.20} \u{18} \u{3} \u{16} \u{2} \u{E} \s{helvfvflo} , . /";

        for s in x.split_whitespace() {
            assert_eq!(s.to_lowercase(), serialize(&deserialize(&s)));
        }
    }

    #[test]
    fn special_chars() {
        assert_eq!(
            deserialize_special(r"\s{hello:1.00}"),
            Some(KeyValue::Special {
                id: "_hello".to_owned(),
                width: 1.0.into()
            })
        )
    }

    proptest! {
        #[test]
        fn doesnt_crash(s in ".") {
            serialize(&deserialize(&s))
        }

        #[test]
        fn escape_unicode_rountrip(c: char) {
            prop_assume!(c != '\u{0}');
            let esc = c.escape_unicode().to_string();
            assert_eq!(KeyValue::Symbol(c.to_string()), deserialize(&esc));
        }

        #[test]
        fn unescape_unicode_rountrip(c: char) {
            prop_assume!(c != '\u{0}');
            assert_eq!(KeyValue::Symbol(c.to_string()), deserialize(&serialize(&KeyValue::Symbol(c.to_string()))));
        }
    }
}
<commit_msg>Fix tests<commit_after>use std::convert::TryFrom;

use rust_decimal::Decimal;
use derive_collect_docs::CollectDocs;
use lazy_static::lazy_static;
use regex::Regex;
use serde::{de::Deserializer, ser::Serializer, Deserialize, Serialize};
use thiserror::Error;

#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord)]
#[derive(CollectDocs)]
pub enum KeyValue {
    Symbol(String),
    Special { id: String, width: Decimal },
    None,
}

impl From<Option<String>> for KeyValue {
    fn from(x: Option<String>) -> Self {
        x.map(KeyValue::Symbol).unwrap_or(KeyValue::None)
    }
}

impl From<String> for KeyValue {
    fn from(x: String) -> Self {
        KeyValue::Symbol(x)
    }
}

impl ToString for KeyValue {
    fn to_string(&self) -> String {
        serialize(self)
    }
}

impl<'de> Deserialize<'de> for KeyValue {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        let x: &str = Deserialize::deserialize(deserializer)?;
        Ok(deserialize(x))
    }
}

impl Serialize for KeyValue {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        serializer.serialize_str(&serialize(self))
    }
}

pub fn deserialize_special(input: &str) -> Option<KeyValue> {
    lazy_static! {
        static ref RE: Regex =
            Regex::new(r"^\\s\{([^}:]+)(?::(\d+(?:\.\d+)?))?\}$").expect("valid regex");
    }

    // Symbol syntax \s{id:width}, or with optional width defaulting to 1.0, \s{id}
    RE.captures(input).map(|cap| KeyValue::Special {
        id: match cap.get(1).unwrap().as_str() {
            id if id.starts_with('"') && id.ends_with('"') => id.to_owned(),
            id => format!("_{}", id),
        },
        width: cap
            .get(2)
            .and_then(|v| v.as_str().parse::<Decimal>().ok())
            .unwrap_or_else(|| Decimal::try_from(1.0).unwrap()),
    })
}

pub fn deserialize(input: &str) -> KeyValue {
    if let Some(special) = deserialize_special(input) {
        special
    } else if input == r"\u{0}" {
        KeyValue::None
    } else {
        KeyValue::Symbol(decode_unicode_escapes(input))
    }
}

pub fn serialize_special(id: &str, width: &Decimal) -> String {
    let id = if id.starts_with('"') && id.ends_with('"') {
        id
    } else {
        &id[1..]
    };

    if width == &Decimal::try_from(1.0).unwrap() {
        format!("\\s{{{}}}", id)
    } else {
        format!("\\s{{{}:{:.2}}}", id, width)
    }
}

pub fn serialize(input: &KeyValue) -> String {
    match input {
        KeyValue::Special { id, width } => serialize_special(id, width),
        KeyValue::Symbol(input) => decode_unicode_escapes(input)
            .chars()
            .map(|c| {
                let char_category = unic_ucd_category::GeneralCategory::of(c);

                if char_category.is_other()
                    || char_category.is_separator()
                    || char_category.is_mark()
                {
                    c.escape_unicode().to_string()
                } else {
                    c.to_string()
                }
            })
            .collect(),
        _ => String::from(r"\u{0}"),
    }
}

/// Decode unicode escapes like `\u{30A}`
fn decode_unicode_escapes(input: &str) -> String {
    lazy_static! {
        static ref RE: Regex = Regex::new(r"\\u\{([0-9A-Fa-f]{1,6})\}").expect("valid regex");
    }

    let new = RE.replace_all(input, |hex: &regex::Captures| {
        let number = u32::from_str_radix(hex.get(1).unwrap().as_str(), 16).unwrap_or(0xfeff);
        std::char::from_u32(number).unwrap().to_string()
    });

    new.to_string()
}

#[derive(Debug, Error)]
pub enum Error {
    #[error("std failed to parse `{input}` as char: {source}")]
    CharParseError {
        input: String,
        source: std::char::ParseCharError,
    },
    #[error("Error parsing `{input}` as char: {description}")]
    CharFromStrError { input: String, description: String },
}

#[cfg(test)]
#[allow(clippy::unnecessary_operation)]
mod tests {
    use super::{decode_unicode_escapes, deserialize, deserialize_special, serialize, KeyValue};
    use proptest::prelude::*;

    #[test]
    fn test_unicode_escapes() {
        assert_eq!("\u{35}", decode_unicode_escapes(r"\u{35}"));
        assert_eq!("5", decode_unicode_escapes(r"\u{35}"));

        assert_eq!("\u{5}", decode_unicode_escapes(r"\u{5}"));
        assert_eq!("\"", decode_unicode_escapes(r"\u{22}"));
    }

    #[test]
    fn roundtrips() {
        let x = r"0 1 2 3 4 5 6 7 8 9 0 \u{1F} = \
            \u{11} \u{17} \u{5} \u{12} \u{14} \u{19} \u{15} \u{9} \u{F} \u{10} \u{1B} \u{1D} \
            \u{1} \u{13} \u{4} \u{6} \u{7} \u{8} \u{A} \u{B} \u{C} ; ' \u{1C} \
            ` \u{1A} \u{18} \u{3} \u{16} \u{2} \u{E} \u{D} , . /";

        for s in x.split_whitespace() {
            assert_eq!(s.to_lowercase(), serialize(&deserialize(&s)));
        }
    }

    #[test]
    fn roundtrips_special_chars() {
        let x = r"0 1 2 3 4 5 6 7 8 9 0 \u{1F} = \
            \u{11} \u{17} \u{5} \u{12} \u{14} \u{19} \u{15} \u{9} \s{sdsda:1.50} \u{10} \u{1B} \u{1D} \
            \u{1} \u{13} \u{4} \s{hello:1.05} \u{7} \u{8} \u{A} \u{B} \u{C} ; ' \u{1C} \
            ` \s{casdc:1.20} \u{18} \u{3} \u{16} \u{2} \u{E} \s{helvfvflo} , . /";

        for s in x.split_whitespace() {
            assert_eq!(s.to_lowercase(), serialize(&deserialize(&s)));
        }
    }

    #[test]
    fn special_chars() {
        use rust_decimal::{Decimal, prelude::FromPrimitive};
        assert_eq!(
            deserialize_special(r"\s{hello:1.00}"),
            Some(KeyValue::Special {
                id: "_hello".to_owned(),
                width: Decimal::from_f32(1.0).unwrap(),
            })
        )
    }

    proptest! {
        #[test]
        fn doesnt_crash(s in ".") {
            serialize(&deserialize(&s))
        }

        #[test]
        fn escape_unicode_rountrip(c: char) {
            prop_assume!(c != '\u{0}');
            let esc = c.escape_unicode().to_string();
            assert_eq!(KeyValue::Symbol(c.to_string()), deserialize(&esc));
        }

        #[test]
        fn unescape_unicode_rountrip(c: char) {
            prop_assume!(c != '\u{0}');
            assert_eq!(KeyValue::Symbol(c.to_string()), deserialize(&serialize(&KeyValue::Symbol(c.to_string()))));
        }
    }
}
<|endoftext|>


<commit_before>//! [Standard terms](https://en.wikipedia.org/wiki/Lambda_calculus#Standard_terms) and
//! [combinators](https://en.wikipedia.org/wiki/Combinatory_logic#Combinatory_calculi)
//!
//! * [SKI](https://en.wikipedia.org/wiki/SKI_combinator_calculus)
//! * [Iota](https://en.wikipedia.org/wiki/Iota_and_Jot)
//! * [BCKW](https://en.wikipedia.org/wiki/B,_C,_K,_W_system)
//! * the self-application combinator ω
//! * the divergent combinator Ω
//! * [the fixed-point combinators Y and Z](https://en.wikipedia.org/wiki/Fixed-point_combinator)
//! * the reverse application (thrush) combinator R

#![allow(non_snake_case)]

use term::{Term, abs, app};
use term::Term::*;

/// I - the identity combinator.
///
/// I := λx.x = λ 1
///
/// # Example
/// ```
/// use lambda_calculus::combinators::I;
/// use lambda_calculus::*;
///
/// assert_eq!(beta(app(I(), Var(1)), NOR, 0), Var(1));
/// assert_eq!(beta(app(I(), abs(Var(1))), NOR, 0), abs(Var(1)));
/// ```
pub fn I() -> Term { abs(Var(1)) }

/// K - the constant / discarding combinator.
///
/// K := λxy.x = λ λ 2 = TRUE
///
/// # Example
/// ```
/// use lambda_calculus::combinators::K;
/// use lambda_calculus::*;
///
/// assert_eq!(beta(app!(K(), Var(1), Var(2)), NOR, 0), Var(1));
/// assert_eq!(beta(app!(K(), Var(2), Var(1)), NOR, 0), Var(2));
/// ```
pub fn K() -> Term { abs!(2, Var(2)) }

/// S - the substitution combinator.
///
/// S := λxyz.x z (y z) = λ λ λ 3 1 (2 1)
///
/// # Example
/// ```
/// use lambda_calculus::combinators::S;
/// use lambda_calculus::*;
///
/// assert_eq!(
///     beta(app!(S(), Var(1), Var(2), Var(3)), NOR, 0),
///     app!(Var(1), Var(3), app(Var(2), Var(3)))
/// );
/// ```
pub fn S() -> Term {
    abs!(3, app!(Var(3), Var(1), app(Var(2), Var(1))))
}

/// Iota - the universal combinator.
///
/// i := λx.x S K = λ 1 S K
///
/// # Example
/// ```
/// use lambda_calculus::combinators::{i, I, K, S};
/// use lambda_calculus::*;
///
/// assert_eq!(beta(app(i(), i()), NOR, 0), I());
/// assert_eq!(beta(app(i(), app(i(), app(i(), i()))), NOR, 0), K());
/// assert_eq!(beta(app(i(), app(i(), app(i(), app(i(), i())))), NOR, 0), S());
/// ```
pub fn i() -> Term { abs(app!(Var(1), S(), K())) }

/// B - the composition combinator.
///
/// B := λxyz.x (y z) = λ λ λ 3 (2 1)
///
/// # Example
/// ```
/// use lambda_calculus::combinators::B;
/// use lambda_calculus::*;
///
/// assert_eq!(
///     beta(app!(B(), Var(1), Var(2), Var(3)), NOR, 0),
///     app(Var(1), app(Var(2), Var(3)))
/// );
/// ```
pub fn B() -> Term {
    abs!(3, app(Var(3), app(Var(2), Var(1))))
}

/// C - the swapping combinator.
///
/// C := λxyz.x z y = λ λ λ 3 1 2
///
/// # Example
/// ```
/// use lambda_calculus::combinators::C;
/// use lambda_calculus::*;
///
/// assert_eq!(
///     beta(app!(C(), Var(1), Var(2), Var(3)), NOR, 0),
///     app!(Var(1), Var(3), Var(2))
/// );
/// ```
pub fn C() -> Term {
    abs!(3, app!(Var(3), Var(1), Var(2)))
}

/// W - the duplicating combinator.
///
/// W := λxy.x y y = λ λ 2 1 1
///
/// # Example
/// ```
/// use lambda_calculus::combinators::W;
/// use lambda_calculus::*;
///
/// assert_eq!(
///     beta(app!(W(), Var(1), Var(2)), NOR, 0),
///     app!(Var(1), Var(2), Var(2))
/// );
/// ```
pub fn W() -> Term {
    abs!(2, app!(Var(2), Var(1), Var(1)))
}

/// ω - the self-application combinator.
///
/// ω := λx.x x = λ 1 1
///
/// # Example
/// ```
/// use lambda_calculus::combinators::o;
/// use lambda_calculus::*;
///
/// assert_eq!(
///     beta(app(o(), Var(1)), NOR, 0),
///     app(Var(1), Var(1))
/// );
/// ```
pub fn o() -> Term { abs(app(Var(1), Var(1))) }

/// Ω - the divergent combinator.
///
/// Ω := ω ω
///
/// # Example
/// ```
/// use lambda_calculus::combinators::O;
/// use lambda_calculus::*;
///
/// assert_eq!(beta(O(), NOR, 3), O()); // 3 β-reductions do nothing
/// ```
pub fn O() -> Term { app(o(), o()) }

/// Y - the lazy fixed-point combinator.
///
/// It is suitable for `NOR` (normal), `HNO` (hybrid normal), `CBN` (call-by-name) and `HSP`
/// (head spine) reduction `Order`s.
///
/// Y := λf.(λx.f (x x)) (λx.f (x x)) = λ (λ 2 (1 1)) (λ 2 (1 1))
///
/// # Example
/// ```
/// use lambda_calculus::combinators::Y;
/// use lambda_calculus::*;
///
/// fn dummy() -> Term { abs(Var(2)) } // a dummy term that won't easily reduce
///
/// assert_eq!(
///     beta(app(Y(), dummy()), NOR, 0),
///     beta(app(dummy(), app(Y(), dummy())), NOR, 0)
/// );
/// ```
pub fn Y() -> Term {
    abs(app(
        abs(app(Var(2), app(Var(1), Var(1)))),
        abs(app(Var(2), app(Var(1), Var(1))))
    ))
}

/// Z - the strict fixed-point combinator.
///
/// It will work with all the reduction orders suitable for its lazy counterpart (the `Y`
/// combinator). In addition, it will also work with `CBV` (call-by-value) and `HAP` (hybrid
/// applicative) reduction `Order`s, though it is not a drop-in replacement - in order for such
/// expressions to work, they need to be modified so that the evaluation of arguments of conditionals
/// and other terms that need to be lazy is delayed.
///
/// Z := λf.(λx.f (λv.x x v)) (λx.f (λv.x x v)) = λ (λ 2 (λ 2 2 1)) (λ 2 (λ 2 2 1))
///
/// # Example
/// ```
/// use lambda_calculus::combinators::Z;
/// use lambda_calculus::*;
///
/// fn dummy() -> Term { abs(Var(2)) } // a dummy term that won't easily reduce
///
/// assert_eq!(
///     beta(app(Z(), dummy()), CBV, 0),
///     beta(app(dummy(), app(Z(), dummy())), CBV, 0)
/// );
/// ```
pub fn Z() -> Term {
    abs(app(
        abs(app(Var(2), abs(app!(Var(2), Var(2), Var(1))))),
        abs(app(Var(2), abs(app!(Var(2), Var(2), Var(1)))))
    ))
}

/// R - the reverse application (thrush) combinator.
///
/// R := λxf.f x = λ λ 1 2
///
/// # Example
/// ```
/// use lambda_calculus::combinators::R;
/// use lambda_calculus::*;
///
/// assert_eq!(
///     beta(app!(R(), Var(1), Var(2)), NOR, 0),
///     app(Var(2), Var(1))
/// );
/// ```
pub fn R() -> Term {
    abs!(2, app(Var(1), Var(2)))
}

/// Θ - Turing's fixed-point combinator (call-by-value form)
///
/// Θ := (λxy.y (x x y)) (λxy.y (x x y)) = (λ λ 1 (2 2 1)) (λ λ 1 (2 2 1))
///
/// It is suitable for `NOR` (normal), `HNO` (hybrid normal), `CBN` (call-by-name), and `HSP` (head
/// spine) reduction `Order`s.
///
/// # Example
/// ```
/// use lambda_calculus::combinators::T;
/// use lambda_calculus::*;
///
/// fn dummy() -> Term { abs(Var(2)) } // a dummy term that won't easily reduce
///
/// assert_eq!(
///     beta(app(T(), dummy()), NOR, 0),
///     beta(app(dummy(), app(T(), dummy())), NOR, 0)
/// );
/// ```
pub fn T() -> Term {
    app(
        abs!(2, app(Var(1), app!(Var(2), Var(2), Var(1)))),
        abs!(2, app(Var(1), app!(Var(2), Var(2), Var(1))))
    )
}
<commit_msg>fix T combinator docs<commit_after>//! [Standard terms](https://en.wikipedia.org/wiki/Lambda_calculus#Standard_terms) and
//! [combinators](https://en.wikipedia.org/wiki/Combinatory_logic#Combinatory_calculi)
//!
//! * [SKI](https://en.wikipedia.org/wiki/SKI_combinator_calculus)
//! * [Iota](https://en.wikipedia.org/wiki/Iota_and_Jot)
//! * [BCKW](https://en.wikipedia.org/wiki/B,_C,_K,_W_system)
//! * the self-application combinator ω
//! * the divergent combinator Ω
//! * [the fixed-point combinators Y and Z](https://en.wikipedia.org/wiki/Fixed-point_combinator)
//! * the reverse application (thrush) combinator R

#![allow(non_snake_case)]

use term::{Term, abs, app};
use term::Term::*;

/// I - the identity combinator.
///
/// I := λx.x = λ 1
///
/// # Example
/// ```
/// use lambda_calculus::combinators::I;
/// use lambda_calculus::*;
///
/// assert_eq!(beta(app(I(), Var(1)), NOR, 0), Var(1));
/// assert_eq!(beta(app(I(), abs(Var(1))), NOR, 0), abs(Var(1)));
/// ```
pub fn I() -> Term { abs(Var(1)) }

/// K - the constant / discarding combinator.
///
/// K := λxy.x = λ λ 2 = TRUE
///
/// # Example
/// ```
/// use lambda_calculus::combinators::K;
/// use lambda_calculus::*;
///
/// assert_eq!(beta(app!(K(), Var(1), Var(2)), NOR, 0), Var(1));
/// assert_eq!(beta(app!(K(), Var(2), Var(1)), NOR, 0), Var(2));
/// ```
pub fn K() -> Term { abs!(2, Var(2)) }

/// S - the substitution combinator.
///
/// S := λxyz.x z (y z) = λ λ λ 3 1 (2 1)
///
/// # Example
/// ```
/// use lambda_calculus::combinators::S;
/// use lambda_calculus::*;
///
/// assert_eq!(
///     beta(app!(S(), Var(1), Var(2), Var(3)), NOR, 0),
///     app!(Var(1), Var(3), app(Var(2), Var(3)))
/// );
/// ```
pub fn S() -> Term {
    abs!(3, app!(Var(3), Var(1), app(Var(2), Var(1))))
}

/// Iota - the universal combinator.
///
/// i := λx.x S K = λ 1 S K
///
/// # Example
/// ```
/// use lambda_calculus::combinators::{i, I, K, S};
/// use lambda_calculus::*;
///
/// assert_eq!(beta(app(i(), i()), NOR, 0), I());
/// assert_eq!(beta(app(i(), app(i(), app(i(), i()))), NOR, 0), K());
/// assert_eq!(beta(app(i(), app(i(), app(i(), app(i(), i())))), NOR, 0), S());
/// ```
pub fn i() -> Term { abs(app!(Var(1), S(), K())) }

/// B - the composition combinator.
///
/// B := λxyz.x (y z) = λ λ λ 3 (2 1)
///
/// # Example
/// ```
/// use lambda_calculus::combinators::B;
/// use lambda_calculus::*;
///
/// assert_eq!(
///     beta(app!(B(), Var(1), Var(2), Var(3)), NOR, 0),
///     app(Var(1), app(Var(2), Var(3)))
/// );
/// ```
pub fn B() -> Term {
    abs!(3, app(Var(3), app(Var(2), Var(1))))
}

/// C - the swapping combinator.
///
/// C := λxyz.x z y = λ λ λ 3 1 2
///
/// # Example
/// ```
/// use lambda_calculus::combinators::C;
/// use lambda_calculus::*;
///
/// assert_eq!(
///     beta(app!(C(), Var(1), Var(2), Var(3)), NOR, 0),
///     app!(Var(1), Var(3), Var(2))
/// );
/// ```
pub fn C() -> Term {
    abs!(3, app!(Var(3), Var(1), Var(2)))
}

/// W - the duplicating combinator.
///
/// W := λxy.x y y = λ λ 2 1 1
///
/// # Example
/// ```
/// use lambda_calculus::combinators::W;
/// use lambda_calculus::*;
///
/// assert_eq!(
///     beta(app!(W(), Var(1), Var(2)), NOR, 0),
///     app!(Var(1), Var(2), Var(2))
/// );
/// ```
pub fn W() -> Term {
    abs!(2, app!(Var(2), Var(1), Var(1)))
}

/// ω - the self-application combinator.
///
/// ω := λx.x x = λ 1 1
///
/// # Example
/// ```
/// use lambda_calculus::combinators::o;
/// use lambda_calculus::*;
///
/// assert_eq!(
///     beta(app(o(), Var(1)), NOR, 0),
///     app(Var(1), Var(1))
/// );
/// ```
pub fn o() -> Term { abs(app(Var(1), Var(1))) }

/// Ω - the divergent combinator.
///
/// Ω := ω ω
///
/// # Example
/// ```
/// use lambda_calculus::combinators::O;
/// use lambda_calculus::*;
///
/// assert_eq!(beta(O(), NOR, 3), O()); // 3 β-reductions do nothing
/// ```
pub fn O() -> Term { app(o(), o()) }

/// Y - the lazy fixed-point combinator.
///
/// It is suitable for `NOR` (normal), `HNO` (hybrid normal), `CBN` (call-by-name) and `HSP`
/// (head spine) reduction `Order`s.
///
/// Y := λf.(λx.f (x x)) (λx.f (x x)) = λ (λ 2 (1 1)) (λ 2 (1 1))
///
/// # Example
/// ```
/// use lambda_calculus::combinators::Y;
/// use lambda_calculus::*;
///
/// fn dummy() -> Term { abs(Var(2)) } // a dummy term that won't easily reduce
///
/// assert_eq!(
///     beta(app(Y(), dummy()), NOR, 0),
///     beta(app(dummy(), app(Y(), dummy())), NOR, 0)
/// );
/// ```
pub fn Y() -> Term {
    abs(app(
        abs(app(Var(2), app(Var(1), Var(1)))),
        abs(app(Var(2), app(Var(1), Var(1))))
    ))
}

/// Z - the strict fixed-point combinator.
///
/// It will work with all the reduction orders suitable for its lazy counterpart (the `Y`
/// combinator). In addition, it will also work with `CBV` (call-by-value) and `HAP` (hybrid
/// applicative) reduction `Order`s, though it is not a drop-in replacement - in order for such
/// expressions to work, they need to be modified so that the evaluation of arguments of conditionals
/// and other terms that need to be lazy is delayed.
///
/// Z := λf.(λx.f (λv.x x v)) (λx.f (λv.x x v)) = λ (λ 2 (λ 2 2 1)) (λ 2 (λ 2 2 1))
///
/// # Example
/// ```
/// use lambda_calculus::combinators::Z;
/// use lambda_calculus::*;
///
/// fn dummy() -> Term { abs(Var(2)) } // a dummy term that won't easily reduce
///
/// assert_eq!(
///     beta(app(Z(), dummy()), CBV, 0),
///     beta(app(dummy(), app(Z(), dummy())), CBV, 0)
/// );
/// ```
pub fn Z() -> Term {
    abs(app(
        abs(app(Var(2), abs(app!(Var(2), Var(2), Var(1))))),
        abs(app(Var(2), abs(app!(Var(2), Var(2), Var(1)))))
    ))
}

/// R - the reverse application (thrush) combinator.
///
/// R := λxf.f x = λ λ 1 2
///
/// # Example
/// ```
/// use lambda_calculus::combinators::R;
/// use lambda_calculus::*;
///
/// assert_eq!(
///     beta(app!(R(), Var(1), Var(2)), NOR, 0),
///     app(Var(2), Var(1))
/// );
/// ```
pub fn R() -> Term {
    abs!(2, app(Var(1), Var(2)))
}

/// Θ - Turing's fixed-point combinator
///
/// Θ := (λxy.y (x x y)) (λxy.y (x x y)) = (λ λ 1 (2 2 1)) (λ λ 1 (2 2 1))
///
/// It is suitable for `NOR` (normal), `HNO` (hybrid normal), `CBN` (call-by-name), and `HSP` (head
/// spine) reduction `Order`s.
///
/// # Example
/// ```
/// use lambda_calculus::combinators::T;
/// use lambda_calculus::*;
///
/// fn dummy() -> Term { abs(Var(2)) } // a dummy term that won't easily reduce
///
/// assert_eq!(
///     beta(app(T(), dummy()), NOR, 0),
///     beta(app(dummy(), app(T(), dummy())), NOR, 0)
/// );
/// ```
pub fn T() -> Term {
    app(
        abs!(2, app(Var(1), app!(Var(2), Var(2), Var(1)))),
        abs!(2, app(Var(1), app!(Var(2), Var(2), Var(1))))
    )
}
<|endoftext|>


<commit_before>use std::mem;
use std::f64;

use itertools::Itertools;
use ndarray::prelude::*;
use bit_vec::BitVec;
use ordered_float::NotNaN;
use ndarray_rand::RandomExt;
use rand::distributions::Range;

use bio::stats::{Prob, LogProb};

use io::codebook::Codebook;

pub type Readout = BitVec;

pub fn estimate<I: Iterator<Item=(String, Readout)>>(
    codebook: &Codebook,
    readouts: I
) -> (Vec<Prob>, Vec<Prob>) {
    let max_diff = 0.001;
    let shape = (codebook.len(), codebook.N as usize);

    let mut observed_01_errors = Array2::from_elem(shape, 0.0);
    let mut observed_10_errors = Array2::from_elem(shape, 0.0);
    let mut exact_count = Array2::from_elem((codebook.len(), 1), 0.0);

    for (feat, readout) in readouts {
        let feature_id = codebook.get_id(&feat);
        let rec = codebook.record(feature_id);
        if !rec.expressed() {
            continue;
        }
        let encoding = rec.codeword();

        let mut err_count = 0;
        for k in 0..codebook.N as usize {
            match (encoding[k], readout[k]) {
                (true, true) | (false, false) => exact_count[(feature_id, 0)] += 1.0,
                (false, true) => {
                    observed_01_errors[(feature_id, k)] += 1.0;
                    err_count += 1;
                },
                (true, false) => {
                    observed_10_errors[(feature_id, k)] += 1.0;
                    err_count += 1;
                }
            };
        }
        assert!(
            err_count <= 1,
            "unexpected number of errors in readout: {} (<=1 expected)",
            err_count
        );
    }

    debug!("10: {:?}", observed_10_errors);

    // calculate observed (joint) error rates
    let observed_p0 = observed_01_errors / &exact_count;
    let observed_p1 = observed_10_errors / &exact_count;

    // estimate error rates
    let feat_p0 = observed_p0.map(|&o| o / (1.0 + o));
    let feat_p1 = observed_p1.map(|&o| o / (1.0 + o));

    //debug!("p0 {:?}", feat_p0);
    debug!("p1 {:?}", feat_p1);

    let mut p0 = Vec::new();
    let mut p1 = Vec::new();
    for k in 0..codebook.N as usize {
        let p = |feat_p: &Array2<f64>, bit: bool| {
            let mut count = 0.0;
            let p = (0..codebook.len()).filter_map(|feature_id| {
                let encoding = codebook.record(feature_id).codeword();
                if exact_count[(feature_id, 0)] < 10.0 || encoding[k] != bit {
                    None
                } else {
                    count += 1.0;
                    Some(feat_p[(feature_id, k)])
                }
            }).sum::<f64>() / count;
            if count == 0.0 {
                panic!("not enough counts to estimate error rate (at least 1 feature with 50 counts over all cells required)");
            }
            p
        };

        p0.push(Prob(p(&feat_p0, false)));
        p1.push(Prob(p(&feat_p1, true)));
    }

    (p0, p1)
}

// pub fn estimate<I: Iterator<Item=(String, Readout)>>(
//     codebook: &Codebook,
//     readouts: I
// ) -> (Vec<Prob>, Vec<Prob>) {
//     let max_diff = 0.001;
//     let shape = (codebook.len(), codebook.N as usize);
//
//     let mut observed_01_errors = Array2::from_elem(shape, 0.0);
//     let mut observed_10_errors = Array2::from_elem(shape, 0.0);
//     let mut feat_count = Array2::from_elem((codebook.len(), 1), 0.0);
//
//     for (feat, readout) in readouts {
//         let feature_id = codebook.get_id(&feat);
//         let rec = codebook.record(feature_id);
//         if !rec.expressed() {
//             continue;
//         }
//         let encoding = rec.codeword();
//
//         // count features
//         feat_count[(feature_id, 0)] += 1.0;
//
//         let mut err_count = 0;
//         for k in 0..codebook.N as usize {
//             if encoding[k] == false {
//                 // count 01 errors
//                 if readout[k] == true {
//                     observed_01_errors[(feature_id, k)] += 1.0;
//                     err_count += 1;
//                 }
//             } else {
//                 // count 10 errors
//                 if readout[k] == false {
//                     observed_10_errors[(feature_id, k)] += 1.0;
//                     err_count += 1;
//                 }
//             }
//         }
//         assert!(
//             err_count <= 1,
//             "unexpected number of errors in readout: {} (<=1 expected)",
//             err_count
//         );
//     }
//
//     // calculate observed (joint) error rates
//     let observed_p0 = observed_01_errors / &feat_count;
//     let observed_p1 = observed_10_errors / &feat_count;
//     debug!("p0 {:?}", observed_p0);
//     debug!("p1 {:?}", observed_p1);
//
//     // run EM algorithm to estimate error rates
//     let mut prob_no_error = Array2::from_elem(
//         (codebook.len(), codebook.N as usize), LogProb::ln_one()
//     );
//
//
//     let mut p0 = Array1::random(codebook.N as usize, Range::new(0.0, 1.0));
//     let mut p1 = Array1::random(codebook.N as usize, Range::new(0.0, 1.0));
//
//     let mut p0_last = Array1::from_elem(codebook.N as usize, 0.0);
//     let mut p1_last = Array1::from_elem(codebook.N as usize, 0.0);
//     for i in 0..1000 {
//         // E-step: estimate probability to have no errors in rest of readout
//         for feature_id in 0..codebook.len() {
//             let encoding = codebook.record(feature_id).codeword();
//             for k in 0..codebook.N as usize {
//                 let p = LogProb((0..codebook.N as usize).filter_map(|l| {
//                     if l != k {
//                         let p_err = if encoding[l] == false {
//                             p0[k]
//                         } else {
//                             p1[k]
//                         };
//                         Some(*LogProb((p_err as f64).ln()).ln_one_minus_exp())
//                     } else { None }
//                 }).sum());
//                 prob_no_error[(feature_id, k)] = p;
//             }
//         }
//
//         // M-step: find p0 and p1 that maximizes the likelihood
//         mem::swap(&mut p0, &mut p0_last);
//         mem::swap(&mut p1, &mut p1_last);
//         for k in 0..codebook.N as usize {
//             // solve least squares: take mean of all estimates
//             let p = |observed_p: &Array2<f64>, bit: bool| {
//                 let mut count = 0.0;
//                 let p = (0..codebook.len()).filter_map(|feature_id| {
//                     let encoding = codebook.record(feature_id).codeword();
//                     if feat_count[(feature_id, 0)] < 100.0 || encoding[k] != bit {
//                         None
//                     } else {
//                         count += 1.0;
//                         let p = observed_p[(feature_id, k)] * prob_no_error[(feature_id, k)].exp();
//                         if k == 4 {
//                             debug!("p={}, c={}, obs={}, noerr={}", p, feat_count[(feature_id, 0)], observed_p[(feature_id, k)], prob_no_error[(feature_id, k)].exp());
//                         }
//                         Some(p)
//                     }
//                 }).sum::<f64>() / count;
//                 if count == 0.0 {
//                     panic!("not enough counts to estimate error rate (at least 1 feature with 50 counts over all cells required)");
//                 }
//                 p
//             };
//             debug!("----------- p0 ------------");
//             p0[k] = p(&observed_p0, false);
//             //debug!("DEBUG: p0={}", p0[k]);
//             debug!("----------- p1 ------------");
//             p1[k] = p(&observed_p1, true);
//             //debug!("DEBUG: p1={}", p1[k]);
//         }
//
//         // check convergence
//         let abs = |d: &f64| NotNaN::new(d.abs()).unwrap();
//         //debug!("{:?}", p0);
//         let convergence = p0.all_close(&p0_last, max_diff) && p1.all_close(&p1_last, max_diff);
//
//         if convergence && i >= 5 {
//             debug!("convergence reached");
//             debug!("{:?}", p1);
//             break;
//         }
//
//         debug!("EM-algorithm step {} of {}.", i + 1, 100);
//     }
//
//     (
//         p0.iter().map(|p| Prob(*p)).collect_vec(),
//         p1.iter().map(|p| Prob(*p)).collect_vec()
//     )
// }
<commit_msg>Credits<commit_after>use std::mem;
use std::f64;

use itertools::Itertools;
use ndarray::prelude::*;
use bit_vec::BitVec;
use ordered_float::NotNaN;
use ndarray_rand::RandomExt;
use rand::distributions::Range;

use bio::stats::{Prob, LogProb};

use io::codebook::Codebook;

pub type Readout = BitVec;

/// Estimate position-wise error rates as presented by Chen et al. 2015.
pub fn estimate<I: Iterator<Item=(String, Readout)>>(
    codebook: &Codebook,
    readouts: I
) -> (Vec<Prob>, Vec<Prob>) {
    let max_diff = 0.001;
    let shape = (codebook.len(), codebook.N as usize);

    let mut observed_01_errors = Array2::from_elem(shape, 0.0);
    let mut observed_10_errors = Array2::from_elem(shape, 0.0);
    let mut exact_count = Array2::from_elem((codebook.len(), 1), 0.0);

    for (feat, readout) in readouts {
        let feature_id = codebook.get_id(&feat);
        let rec = codebook.record(feature_id);
        if !rec.expressed() {
            continue;
        }
        let encoding = rec.codeword();

        let mut err_count = 0;
        for k in 0..codebook.N as usize {
            match (encoding[k], readout[k]) {
                (true, true) | (false, false) => exact_count[(feature_id, 0)] += 1.0,
                (false, true) => {
                    observed_01_errors[(feature_id, k)] += 1.0;
                    err_count += 1;
                },
                (true, false) => {
                    observed_10_errors[(feature_id, k)] += 1.0;
                    err_count += 1;
                }
            };
        }
        assert!(
            err_count <= 1,
            "unexpected number of errors in readout: {} (<=1 expected)",
            err_count
        );
    }

    debug!("10: {:?}", observed_10_errors);

    // calculate observed (joint) error rates
    let observed_p0 = observed_01_errors / &exact_count;
    let observed_p1 = observed_10_errors / &exact_count;

    // estimate error rates
    let feat_p0 = observed_p0.map(|&o| o / (1.0 + o));
    let feat_p1 = observed_p1.map(|&o| o / (1.0 + o));

    //debug!("p0 {:?}", feat_p0);
    debug!("p1 {:?}", feat_p1);

    let mut p0 = Vec::new();
    let mut p1 = Vec::new();
    for k in 0..codebook.N as usize {
        let p = |feat_p: &Array2<f64>, bit: bool| {
            let mut count = 0.0;
            let p = (0..codebook.len()).filter_map(|feature_id| {
                let encoding = codebook.record(feature_id).codeword();
                if exact_count[(feature_id, 0)] < 10.0 || encoding[k] != bit {
                    None
                } else {
                    count += 1.0;
                    Some(feat_p[(feature_id, k)])
                }
            }).sum::<f64>() / count;
            if count == 0.0 {
                panic!("not enough counts to estimate error rate (at least 1 feature with 50 counts over all cells required)");
            }
            p
        };

        p0.push(Prob(p(&feat_p0, false)));
        p1.push(Prob(p(&feat_p1, true)));
    }

    (p0, p1)
}

// pub fn estimate<I: Iterator<Item=(String, Readout)>>(
//     codebook: &Codebook,
//     readouts: I
// ) -> (Vec<Prob>, Vec<Prob>) {
//     let max_diff = 0.001;
//     let shape = (codebook.len(), codebook.N as usize);
//
//     let mut observed_01_errors = Array2::from_elem(shape, 0.0);
//     let mut observed_10_errors = Array2::from_elem(shape, 0.0);
//     let mut feat_count = Array2::from_elem((codebook.len(), 1), 0.0);
//
//     for (feat, readout) in readouts {
//         let feature_id = codebook.get_id(&feat);
//         let rec = codebook.record(feature_id);
//         if !rec.expressed() {
//             continue;
//         }
//         let encoding = rec.codeword();
//
//         // count features
//         feat_count[(feature_id, 0)] += 1.0;
//
//         let mut err_count = 0;
//         for k in 0..codebook.N as usize {
//             if encoding[k] == false {
//                 // count 01 errors
//                 if readout[k] == true {
//                     observed_01_errors[(feature_id, k)] += 1.0;
//                     err_count += 1;
//                 }
//             } else {
//                 // count 10 errors
//                 if readout[k] == false {
//                     observed_10_errors[(feature_id, k)] += 1.0;
//                     err_count += 1;
//                 }
//             }
//         }
//         assert!(
//             err_count <= 1,
//             "unexpected number of errors in readout: {} (<=1 expected)",
//             err_count
//         );
//     }
//
//     // calculate observed (joint) error rates
//     let observed_p0 = observed_01_errors / &feat_count;
//     let observed_p1 = observed_10_errors / &feat_count;
//     debug!("p0 {:?}", observed_p0);
//     debug!("p1 {:?}", observed_p1);
//
//     // run EM algorithm to estimate error rates
//     let mut prob_no_error = Array2::from_elem(
//         (codebook.len(), codebook.N as usize), LogProb::ln_one()
//     );
//
//
//     let mut p0 = Array1::random(codebook.N as usize, Range::new(0.0, 1.0));
//     let mut p1 = Array1::random(codebook.N as usize, Range::new(0.0, 1.0));
//
//     let mut p0_last = Array1::from_elem(codebook.N as usize, 0.0);
//     let mut p1_last = Array1::from_elem(codebook.N as usize, 0.0);
//     for i in 0..1000 {
//         // E-step: estimate probability to have no errors in rest of readout
//         for feature_id in 0..codebook.len() {
//             let encoding = codebook.record(feature_id).codeword();
//             for k in 0..codebook.N as usize {
//                 let p = LogProb((0..codebook.N as usize).filter_map(|l| {
//                     if l != k {
//                         let p_err = if encoding[l] == false {
//                             p0[k]
//                         } else {
//                             p1[k]
//                         };
//                         Some(*LogProb((p_err as f64).ln()).ln_one_minus_exp())
//                     } else { None }
//                 }).sum());
//                 prob_no_error[(feature_id, k)] = p;
//             }
//         }
//
//         // M-step: find p0 and p1 that maximizes the likelihood
//         mem::swap(&mut p0, &mut p0_last);
//         mem::swap(&mut p1, &mut p1_last);
//         for k in 0..codebook.N as usize {
//             // solve least squares: take mean of all estimates
//             let p = |observed_p: &Array2<f64>, bit: bool| {
//                 let mut count = 0.0;
//                 let p = (0..codebook.len()).filter_map(|feature_id| {
//                     let encoding = codebook.record(feature_id).codeword();
//                     if feat_count[(feature_id, 0)] < 100.0 || encoding[k] != bit {
//                         None
//                     } else {
//                         count += 1.0;
//                         let p = observed_p[(feature_id, k)] * prob_no_error[(feature_id, k)].exp();
//                         if k == 4 {
//                             debug!("p={}, c={}, obs={}, noerr={}", p, feat_count[(feature_id, 0)], observed_p[(feature_id, k)], prob_no_error[(feature_id, k)].exp());
//                         }
//                         Some(p)
//                     }
//                 }).sum::<f64>() / count;
//                 if count == 0.0 {
//                     panic!("not enough counts to estimate error rate (at least 1 feature with 50 counts over all cells required)");
//                 }
//                 p
//             };
//             debug!("----------- p0 ------------");
//             p0[k] = p(&observed_p0, false);
//             //debug!("DEBUG: p0={}", p0[k]);
//             debug!("----------- p1 ------------");
//             p1[k] = p(&observed_p1, true);
//             //debug!("DEBUG: p1={}", p1[k]);
//         }
//
//         // check convergence
//         let abs = |d: &f64| NotNaN::new(d.abs()).unwrap();
//         //debug!("{:?}", p0);
//         let convergence = p0.all_close(&p0_last, max_diff) && p1.all_close(&p1_last, max_diff);
//
//         if convergence && i >= 5 {
//             debug!("convergence reached");
//             debug!("{:?}", p1);
//             break;
//         }
//
//         debug!("EM-algorithm step {} of {}.", i + 1, 100);
//     }
//
//     (
//         p0.iter().map(|p| Prob(*p)).collect_vec(),
//         p1.iter().map(|p| Prob(*p)).collect_vec()
//     )
// }
<|endoftext|>