<commit_before>use utils::address::Address;
use utils::gas::Gas;

use vm::errors::MachineError;
use vm::{Memory, Machine, MachineStatus};

use std::str::FromStr;

use tiny_keccak::Keccak;
use sha2::Sha256;
use ripemd160::Ripemd160;
use secp256k1::{Secp256k1, RecoverableSignature, Message, RecoveryId, Error};
use digest::{Input, FixedOutput};

fn gas_div_ceil(a: Gas, b: Gas) -> Gas {
    if a % b == Gas::zero() {
        a / b
    } else {
        a / b + Gas::from(1u64)
    }
}

pub fn is_precompiled(address: Address) -> bool {
    let ecrec_address = Address::from_str("0x0000000000000000000000000000000000000001").unwrap();
    let sha256_address = Address::from_str("0x0000000000000000000000000000000000000002").unwrap();
    let rip160_address = Address::from_str("0x0000000000000000000000000000000000000003").unwrap();
    let id_address = Address::from_str("0x0000000000000000000000000000000000000004").unwrap();

    address == ecrec_address ||
        address == sha256_address ||
        address == rip160_address ||
        address == id_address
}

impl<M: Memory + Default> Machine<M> {
    #[allow(unused_variables)]
    pub fn step_precompiled(&mut self) -> bool {
        let ecrec_address = Address::from_str("0x0000000000000000000000000000000000000001").unwrap();
        let sha256_address = Address::from_str("0x0000000000000000000000000000000000000002").unwrap();
        let rip160_address = Address::from_str("0x0000000000000000000000000000000000000003").unwrap();
        let id_address = Address::from_str("0x0000000000000000000000000000000000000004").unwrap();

        if self.state.context.address == id_address {
            self.step_precompiled_id();
            return true;
        } else if self.state.context.address == rip160_address {
            self.step_precompiled_rip160();
            return true;
        } else if self.state.context.address == sha256_address {
            self.step_precompiled_sha256();
            return true;
        } else if self.state.context.address == ecrec_address {
            self.step_precompiled_ecrec();
            return true;
        } else {
            return false;
        }
    }

    fn step_precompiled_id(&mut self) {
        let gas = Gas::from(15u64) +
            Gas::from(3u64) * gas_div_ceil(Gas::from(self.state.context.data.len()),
                                           Gas::from(32u64));
        if gas > self.state.context.gas_limit {
            self.state.used_gas = self.state.context.gas_limit;
            self.status = MachineStatus::ExitedErr(MachineError::EmptyGas);
        } else {
            self.state.used_gas = gas;
            self.state.out = self.state.context.data.clone();
            self.status = MachineStatus::ExitedOk;
        }
    }

    fn step_precompiled_rip160(&mut self) {
        let gas = Gas::from(600u64) +
            Gas::from(120u64) * gas_div_ceil(Gas::from(self.state.context.data.len()),
                                             Gas::from(32u64));
        if gas > self.state.context.gas_limit {
            self.state.used_gas = self.state.context.gas_limit;
            self.status = MachineStatus::ExitedErr(MachineError::EmptyGas);
        } else {
            self.state.used_gas = gas;
            let mut ripemd = Ripemd160::default();
            ripemd.digest(&self.state.context.data);
            let fixed = ripemd.fixed_result();
            let mut result: [u8; 32] = [0u8; 32];
            for i in 0..20 {
                result[i + 12] = fixed[i];
            }
            self.state.out = result.as_ref().into();
            self.status = MachineStatus::ExitedOk;
        }
    }

    fn step_precompiled_sha256(&mut self) {
        let gas = Gas::from(60u64) +
            Gas::from(12u64) * gas_div_ceil(Gas::from(self.state.context.data.len()),
                                            Gas::from(32u64));
        if gas > self.state.context.gas_limit {
            self.state.used_gas = self.state.context.gas_limit;
            self.status = MachineStatus::ExitedErr(MachineError::EmptyGas);
        } else {
            self.state.used_gas = gas;
            let mut sha2 = Sha256::default();
            sha2.digest(&self.state.context.data);
            let fixed = sha2.fixed_result();
            let mut result: [u8; 32] = [0u8; 32];
            for i in 0..32 {
                result[i] = fixed[i];
            }
            self.state.out = result.as_ref().into();
            self.status = MachineStatus::ExitedOk;
        }
    }

    fn step_precompiled_ecrec(&mut self) {
        let gas = Gas::from(3000u64);
        if gas > self.state.context.gas_limit {
            self.state.used_gas = self.state.context.gas_limit;
            self.status = MachineStatus::ExitedErr(MachineError::EmptyGas);
        } else {
            self.state.used_gas = gas;
            let mut data = [0u8; 128];
            for i in 0..self.state.context.data.len() {
                data[i] = self.state.context.data[i];
            }
            match kececrec(&data) {
                Ok(mut ret) => {
                    for i in 0..12 {
                        ret[i] = 0u8;
                    }
                    self.state.out = ret.as_ref().into();
                },
                Err(_) => (),
            }
            self.status = MachineStatus::ExitedOk;
        }
    }
}

fn kececrec(data: &[u8]) -> Result<[u8; 32], Error> {
    let ecrec = Secp256k1::new();
    let message = Message::from_slice(&data[0..32])?;
    let recid = RecoveryId::from_i32(data[63] as i32)?;
    let sig = RecoverableSignature::from_compact(&ecrec, &data[64..128], recid)?;
    let recovered = ecrec.recover(&message, &sig)?;
    let key = recovered.serialize_vec(&ecrec, false);
    let mut kec = Keccak::new_keccak256();
    kec.update(&key);
    let mut ret = [0u8; 32];
    kec.finalize(&mut ret);
    Ok(ret)
}
<commit_msg>Problem: index overthrow when context.data.len() > 128<commit_after>use utils::address::Address;
use utils::gas::Gas;

use vm::errors::MachineError;
use vm::{Memory, Machine, MachineStatus};

use std::str::FromStr;
use std::cmp::min;

use tiny_keccak::Keccak;
use sha2::Sha256;
use ripemd160::Ripemd160;
use secp256k1::{Secp256k1, RecoverableSignature, Message, RecoveryId, Error};
use digest::{Input, FixedOutput};

fn gas_div_ceil(a: Gas, b: Gas) -> Gas {
    if a % b == Gas::zero() {
        a / b
    } else {
        a / b + Gas::from(1u64)
    }
}

pub fn is_precompiled(address: Address) -> bool {
    let ecrec_address = Address::from_str("0x0000000000000000000000000000000000000001").unwrap();
    let sha256_address = Address::from_str("0x0000000000000000000000000000000000000002").unwrap();
    let rip160_address = Address::from_str("0x0000000000000000000000000000000000000003").unwrap();
    let id_address = Address::from_str("0x0000000000000000000000000000000000000004").unwrap();

    address == ecrec_address ||
        address == sha256_address ||
        address == rip160_address ||
        address == id_address
}

impl<M: Memory + Default> Machine<M> {
    #[allow(unused_variables)]
    pub fn step_precompiled(&mut self) -> bool {
        let ecrec_address = Address::from_str("0x0000000000000000000000000000000000000001").unwrap();
        let sha256_address = Address::from_str("0x0000000000000000000000000000000000000002").unwrap();
        let rip160_address = Address::from_str("0x0000000000000000000000000000000000000003").unwrap();
        let id_address = Address::from_str("0x0000000000000000000000000000000000000004").unwrap();

        if self.state.context.address == id_address {
            self.step_precompiled_id();
            return true;
        } else if self.state.context.address == rip160_address {
            self.step_precompiled_rip160();
            return true;
        } else if self.state.context.address == sha256_address {
            self.step_precompiled_sha256();
            return true;
        } else if self.state.context.address == ecrec_address {
            self.step_precompiled_ecrec();
            return true;
        } else {
            return false;
        }
    }

    fn step_precompiled_id(&mut self) {
        let gas = Gas::from(15u64) +
            Gas::from(3u64) * gas_div_ceil(Gas::from(self.state.context.data.len()),
                                           Gas::from(32u64));
        if gas > self.state.context.gas_limit {
            self.state.used_gas = self.state.context.gas_limit;
            self.status = MachineStatus::ExitedErr(MachineError::EmptyGas);
        } else {
            self.state.used_gas = gas;
            self.state.out = self.state.context.data.clone();
            self.status = MachineStatus::ExitedOk;
        }
    }

    fn step_precompiled_rip160(&mut self) {
        let gas = Gas::from(600u64) +
            Gas::from(120u64) * gas_div_ceil(Gas::from(self.state.context.data.len()),
                                             Gas::from(32u64));
        if gas > self.state.context.gas_limit {
            self.state.used_gas = self.state.context.gas_limit;
            self.status = MachineStatus::ExitedErr(MachineError::EmptyGas);
        } else {
            self.state.used_gas = gas;
            let mut ripemd = Ripemd160::default();
            ripemd.digest(&self.state.context.data);
            let fixed = ripemd.fixed_result();
            let mut result: [u8; 32] = [0u8; 32];
            for i in 0..20 {
                result[i + 12] = fixed[i];
            }
            self.state.out = result.as_ref().into();
            self.status = MachineStatus::ExitedOk;
        }
    }

    fn step_precompiled_sha256(&mut self) {
        let gas = Gas::from(60u64) +
            Gas::from(12u64) * gas_div_ceil(Gas::from(self.state.context.data.len()),
                                            Gas::from(32u64));
        if gas > self.state.context.gas_limit {
            self.state.used_gas = self.state.context.gas_limit;
            self.status = MachineStatus::ExitedErr(MachineError::EmptyGas);
        } else {
            self.state.used_gas = gas;
            let mut sha2 = Sha256::default();
            sha2.digest(&self.state.context.data);
            let fixed = sha2.fixed_result();
            let mut result: [u8; 32] = [0u8; 32];
            for i in 0..32 {
                result[i] = fixed[i];
            }
            self.state.out = result.as_ref().into();
            self.status = MachineStatus::ExitedOk;
        }
    }

    fn step_precompiled_ecrec(&mut self) {
        let gas = Gas::from(3000u64);
        if gas > self.state.context.gas_limit {
            self.state.used_gas = self.state.context.gas_limit;
            self.status = MachineStatus::ExitedErr(MachineError::EmptyGas);
        } else {
            self.state.used_gas = gas;
            let mut data = [0u8; 128];
            for i in 0..min(self.state.context.data.len(), 128) {
                data[i] = self.state.context.data[i];
            }
            match kececrec(&data) {
                Ok(mut ret) => {
                    for i in 0..12 {
                        ret[i] = 0u8;
                    }
                    self.state.out = ret.as_ref().into();
                },
                Err(_) => (),
            }
            self.status = MachineStatus::ExitedOk;
        }
    }
}

fn kececrec(data: &[u8]) -> Result<[u8; 32], Error> {
    let ecrec = Secp256k1::new();
    let message = Message::from_slice(&data[0..32])?;
    let recid = RecoveryId::from_i32(data[63] as i32)?;
    let sig = RecoverableSignature::from_compact(&ecrec, &data[64..128], recid)?;
    let recovered = ecrec.recover(&message, &sig)?;
    let key = recovered.serialize_vec(&ecrec, false);
    let mut kec = Keccak::new_keccak256();
    kec.update(&key);
    let mut ret = [0u8; 32];
    kec.finalize(&mut ret);
    Ok(ret)
}
<|endoftext|>


<commit_before>//! Telnet contains code specifically to handle network I/O for a telnet connection
//!
use crate::portal::{Message, Rx, Tx};
use anyhow::anyhow;
use futures::prelude::*;
use log::{error, info};
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Arc;
use tokio::net::TcpListener;
use tokio::sync::mpsc;
use tokio_util::codec::{Framed, LinesCodec};
use uuid::Uuid;

/// A player connection
#[derive(Debug)]
pub struct Socket {
    uuid: Uuid,
    id: usize,
    stream: Framed<tokio::net::TcpStream, LinesCodec>,
    rx: Rx,
    main_tx: Tx,
    addr: String,
}

impl Socket {
    /// Returns a new Socket
    ///
    /// # Arguments
    ///
    /// * `stream` - A `TcpStream` from Tokio
    /// * `id` - A unique incrementing connection identifier
    /// * `main_tx` - Transmit channel to communicate with the main task
    ///
    /// # Errors
    ///
    /// * This function will return an error if any send/recv operations fail on any channel or
    /// stream, which would signal a connection error and disconnect the client.
    pub async fn new(
        stream: tokio::net::TcpStream,
        id: usize,
        main_tx: Tx,
    ) -> Result<Self, anyhow::Error> {
        let addr = match stream.peer_addr() {
            Ok(addr) => addr.to_string(),
            Err(_) => "Unknown".to_string(),
        };
        info!("Telnet client connected: ID: {}, remote_addr: {}", id, addr);
        let mut stream = Framed::new(stream, LinesCodec::new());
        let (tx, rx) = mpsc::unbounded_channel();
        stream.send("Welcome to the Ataxia Portal.").await?;
        stream.send("Please enter your username:").await?;
        let username = match stream.next().await {
            Some(Ok(line)) => line,
            Some(Err(_)) | None => {
                return Err(anyhow!("Failed to get username from {}.", addr));
            }
        };
        stream.send(format!("Welcome, {}!", username)).await?;
        main_tx.send(Message::NewConnection(id, tx, username))?;
        Ok(Self {
            uuid: Uuid::new_v4(),
            id,
            stream,
            rx,
            main_tx,
            addr,
        })
    }

    /// Handle a connection
    ///
    /// # Errors
    ///
    /// * This function will return an error and disconnect the client if any send/recv fails.
    #[allow(clippy::mut_mut)]
    pub async fn handle(mut self) -> Result<(), anyhow::Error> {
        loop {
            futures::select! {
                data = self.rx.recv().fuse() => {
                    if let Some(message) = data {
                        match message {
                            Message::Data(_, message) => self.stream.send(message).await?,
                            _ => error!("Oops"),
                        }
                    } else {
                        // The main loop closed our channel to signal system shutdown
                        self.stream.send("The game is shutting down, goodbye!").await?;
                        break;
                    }
                },
                data = self.stream.next().fuse() => {
                    if let Some(message) = data {
                        if let Err(e) = self.main_tx.send(Message::Data(self.id, message?)) {
                            // The main loop channel was closed, most likely this signals a crash
                            self.stream.send("The game has crashed, sorry! Please try again.").await?;
                            error!("Connection error due to game crash? {}", e);
                            break;
                        }
                    } else {
                        // The other end closed the connection. Nothing left to do.
                        break;
                    }
                },
            };
        }
        self.main_tx.send(Message::CloseConnection(self.id))?;
        Ok(())
    }
}

/// Server data structure holding all the server state
#[derive(Debug)]
pub struct Server {
    listener: TcpListener,
    id_counter: Arc<AtomicUsize>,
    main_tx: Tx,
}

impl Server {
    /// Returns a new Server
    ///
    /// # Arguments
    ///
    /// * `address` - A String containing the listen addr:port
    /// * `clients` - A shared binding to the client list
    /// * `id_counter` - A shared binding to a global connection counter
    ///
    /// # Errors
    ///
    /// * Returns `tokio::io::Error` if the server can't bind to the listen port
    ///
    pub async fn new(
        address: &str,
        id_counter: Arc<AtomicUsize>,
        tx: Tx,
    ) -> Result<Self, anyhow::Error> {
        let listener = TcpListener::bind(address).await?;
        info!("Listening for telnet clients on {:?}", address);
        Ok(Self {
            listener,
            id_counter,
            main_tx: tx,
        })
    }
    /// Start the listener loop, which will spawn individual connections into the runtime
    pub async fn run(self) {
        while let connection = self.listener.accept().await {
            match connection {
                Err(e) => error!("Accept failed: {:?}", e),
                Ok(stream) => {
                    let client_id = self.id_counter.fetch_add(1, Ordering::Relaxed);
                    let main_tx = self.main_tx.clone();
                    tokio::spawn(async move {
                        let socket = match Socket::new(stream.0, client_id, main_tx).await {
                            Ok(socket) => socket,
                            Err(e) => {
                                error!("Client disconnected: {}", e);
                                return;
                            }
                        };
                        if let Err(e) = socket.handle().await {
                            error!("Client error: {}", e);
                            return;
                        };
                    });
                }
            }
        }
    }
}
<commit_msg>Switch from a while let to a plain loop, due to the change in the Tokio 1.0 API.<commit_after>//! Telnet contains code specifically to handle network I/O for a telnet connection
//!
use crate::portal::{Message, Rx, Tx};
use anyhow::anyhow;
use futures::prelude::*;
use log::{error, info};
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Arc;
use tokio::net::TcpListener;
use tokio::sync::mpsc;
use tokio_util::codec::{Framed, LinesCodec};
use uuid::Uuid;

/// A player connection
#[derive(Debug)]
pub struct Socket {
    uuid: Uuid,
    id: usize,
    stream: Framed<tokio::net::TcpStream, LinesCodec>,
    rx: Rx,
    main_tx: Tx,
    addr: String,
}

impl Socket {
    /// Returns a new Socket
    ///
    /// # Arguments
    ///
    /// * `stream` - A `TcpStream` from Tokio
    /// * `id` - A unique incrementing connection identifier
    /// * `main_tx` - Transmit channel to communicate with the main task
    ///
    /// # Errors
    ///
    /// * This function will return an error if any send/recv operations fail on any channel or
    /// stream, which would signal a connection error and disconnect the client.
    pub async fn new(
        stream: tokio::net::TcpStream,
        id: usize,
        main_tx: Tx,
    ) -> Result<Self, anyhow::Error> {
        let addr = match stream.peer_addr() {
            Ok(addr) => addr.to_string(),
            Err(_) => "Unknown".to_string(),
        };
        info!("Telnet client connected: ID: {}, remote_addr: {}", id, addr);
        let mut stream = Framed::new(stream, LinesCodec::new());
        let (tx, rx) = mpsc::unbounded_channel();
        stream.send("Welcome to the Ataxia Portal.").await?;
        stream.send("Please enter your username:").await?;
        let username = match stream.next().await {
            Some(Ok(line)) => line,
            Some(Err(_)) | None => {
                return Err(anyhow!("Failed to get username from {}.", addr));
            }
        };
        stream.send(format!("Welcome, {}!", username)).await?;
        main_tx.send(Message::NewConnection(id, tx, username))?;
        Ok(Self {
            uuid: Uuid::new_v4(),
            id,
            stream,
            rx,
            main_tx,
            addr,
        })
    }

    /// Handle a connection
    ///
    /// # Errors
    ///
    /// * This function will return an error and disconnect the client if any send/recv fails.
    #[allow(clippy::mut_mut)]
    pub async fn handle(mut self) -> Result<(), anyhow::Error> {
        loop {
            futures::select! {
                data = self.rx.recv().fuse() => {
                    if let Some(message) = data {
                        match message {
                            Message::Data(_, message) => self.stream.send(message).await?,
                            _ => error!("Oops"),
                        }
                    } else {
                        // The main loop closed our channel to signal system shutdown
                        self.stream.send("The game is shutting down, goodbye!").await?;
                        break;
                    }
                },
                data = self.stream.next().fuse() => {
                    if let Some(message) = data {
                        if let Err(e) = self.main_tx.send(Message::Data(self.id, message?)) {
                            // The main loop channel was closed, most likely this signals a crash
                            self.stream.send("The game has crashed, sorry! Please try again.").await?;
                            error!("Connection error due to game crash? {}", e);
                            break;
                        }
                    } else {
                        // The other end closed the connection. Nothing left to do.
                        break;
                    }
                },
            };
        }
        self.main_tx.send(Message::CloseConnection(self.id))?;
        Ok(())
    }
}

/// Server data structure holding all the server state
#[derive(Debug)]
pub struct Server {
    listener: TcpListener,
    id_counter: Arc<AtomicUsize>,
    main_tx: Tx,
}

impl Server {
    /// Returns a new Server
    ///
    /// # Arguments
    ///
    /// * `address` - A String containing the listen addr:port
    /// * `clients` - A shared binding to the client list
    /// * `id_counter` - A shared binding to a global connection counter
    ///
    /// # Errors
    ///
    /// * Returns `tokio::io::Error` if the server can't bind to the listen port
    ///
    pub async fn new(
        address: &str,
        id_counter: Arc<AtomicUsize>,
        tx: Tx,
    ) -> Result<Self, anyhow::Error> {
        let listener = TcpListener::bind(address).await?;
        info!("Listening for telnet clients on {:?}", address);
        Ok(Self {
            listener,
            id_counter,
            main_tx: tx,
        })
    }
    /// Start the listener loop, which will spawn individual connections into the runtime
    pub async fn run(self) {
        loop {
            let connection = self.listener.accept().await;
            match connection {
                Err(e) => error!("Accept failed: {:?}", e),
                Ok(stream) => {
                    let client_id = self.id_counter.fetch_add(1, Ordering::Relaxed);
                    let main_tx = self.main_tx.clone();
                    tokio::spawn(async move {
                        let socket = match Socket::new(stream.0, client_id, main_tx).await {
                            Ok(socket) => socket,
                            Err(e) => {
                                error!("Client disconnected: {}", e);
                                return;
                            }
                        };
                        if let Err(e) = socket.handle().await {
                            error!("Client error: {}", e);
                            return;
                        };
                    });
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>// min-llvm-version: 10.0.1
// revisions: s390x
// assembly-output: emit-asm
//[s390x] compile-flags: --target s390x-unknown-linux-gnu
//[s390x] needs-llvm-components: systemz

#![feature(no_core, lang_items, rustc_attrs, repr_simd)]
#![crate_type = "rlib"]
#![no_core]
#![allow(asm_sub_register, non_camel_case_types)]

#[rustc_builtin_macro]
macro_rules! asm {
    () => {};
}
#[rustc_builtin_macro]
macro_rules! concat {
    () => {};
}
#[rustc_builtin_macro]
macro_rules! stringify {
    () => {};
}

#[lang = "sized"]
trait Sized {}
#[lang = "copy"]
trait Copy {}

type ptr = *const i32;

impl Copy for i8 {}
impl Copy for u8 {}
impl Copy for i16 {}
impl Copy for i32 {}
impl Copy for i64 {}
impl Copy for f32 {}
impl Copy for f64 {}
impl Copy for ptr {}

extern "C" {
    fn extern_func();
    static extern_static: u8;
}

// Hack to avoid function merging
extern "Rust" {
    fn dont_merge(s: &str);
}

macro_rules! check { ($func:ident, $ty:ty, $class:ident, $mov:literal) => {

    pub unsafe fn $func(x: $ty) -> $ty {
        dont_merge(stringify!(func));

        let y;
        asm!(concat!($mov," {}, {}"), out($class) y, in($class) x);
        y
    }
};}

macro_rules! check_reg { ($func:ident, $ty:ty, $reg:tt, $mov:literal) => {

    pub unsafe fn $func(x: $ty) -> $ty {
        dont_merge(stringify!(func));

        let y;
        asm!(concat!($mov, " ", $reg, ", ", $reg), lateout($reg) y, in($reg) x);
        y
    }
};}

// systemz-LABEL: sym_fn_32:
// systemz: #APP
// systemz: brasl %r14, extern_func@PLT
// systemz: #NO_APP
#[cfg(s390x)]
pub unsafe fn sym_fn_32() {
    asm!("brasl %r14, {}", sym extern_func);
}

// CHECK-LABEL: reg_i32:
// CHECK: #APP
// CHECK: lgr r{{[0-15]+}}, r{{[0-15]+}}
// CHECK: #NO_APP
check!(reg_i32, i32, reg, "lgr");
<commit_msg>Refactor: added #[no_mangle]<commit_after>// min-llvm-version: 10.0.1
// revisions: s390x
// assembly-output: emit-asm
//[s390x] compile-flags: --target s390x-unknown-linux-gnu
//[s390x] needs-llvm-components: systemz

#![feature(no_core, lang_items, rustc_attrs, repr_simd)]
#![crate_type = "rlib"]
#![no_core]
#![allow(asm_sub_register, non_camel_case_types)]

#[rustc_builtin_macro]
macro_rules! asm {
    () => {};
}
#[rustc_builtin_macro]
macro_rules! concat {
    () => {};
}
#[rustc_builtin_macro]
macro_rules! stringify {
    () => {};
}

#[lang = "sized"]
trait Sized {}
#[lang = "copy"]
trait Copy {}

type ptr = *const i32;

impl Copy for i8 {}
impl Copy for u8 {}
impl Copy for i16 {}
impl Copy for i32 {}
impl Copy for i64 {}
impl Copy for f32 {}
impl Copy for f64 {}
impl Copy for ptr {}

extern "C" {
    fn extern_func();
    static extern_static: u8;
}

// Hack to avoid function merging
extern "Rust" {
    fn dont_merge(s: &str);
}

macro_rules! check { ($func:ident, $ty:ty, $class:ident, $mov:literal) => {

    pub unsafe fn $func(x: $ty) -> $ty {
        dont_merge(stringify!(func));

        let y;
        asm!(concat!($mov," {}, {}"), out($class) y, in($class) x);
        y
    }
};}

macro_rules! check_reg { ($func:ident, $ty:ty, $reg:tt, $mov:literal) => {

    pub unsafe fn $func(x: $ty) -> $ty {
        dont_merge(stringify!(func));

        let y;
        asm!(concat!($mov, " ", $reg, ", ", $reg), lateout($reg) y, in($reg) x);
        y
    }
};}

// systemz-LABEL: sym_fn_32:
// systemz: #APP
// systemz: brasl %r14, extern_func@PLT
// systemz: #NO_APP
#[cfg(s390x)]
#[no_mangle]
pub unsafe fn sym_fn_32() {
    asm!("brasl %r14, {}", sym extern_func);
}

// CHECK-LABEL: reg_i32:
// CHECK: #APP
// CHECK: lgr r{{[0-15]+}}, r{{[0-15]+}}
// CHECK: #NO_APP
#[no_mangle]
check!(reg_i32, i32, reg, "lgr");
<|endoftext|>


<commit_before>use std::collections::hash_set::HashSet;
use std::iter::FromIterator;

use api::server_data::ServerData;
use api::result::*;
use web::data::{APIGeneSummary, TranscriptDetails, FeatureType, GeneShort, InteractionType};

use types::GeneUniquename;

#[derive(Serialize, Deserialize, Eq, PartialEq, Debug, Clone)]
pub enum IntRangeType {
#[serde(rename = "genome_range_contains")]
    GenomeRangeContains,
#[serde(rename = "protein_length")]
    ProteinLength,
#[serde(rename = "tm_domain_count")]
    TMDomainCount,
#[serde(rename = "exon_count")]
    ExonCount,
}

#[derive(Serialize, Deserialize, Eq, PartialEq, Debug, Clone)]
pub enum FloatRangeType {
#[serde(rename = "protein_mol_weight")]
    ProteinMolWeight,
}

#[derive(Serialize, Deserialize, Eq, PartialEq, Debug, Clone)]
pub enum SingleOrMultiAllele {
#[serde(rename = "single")]
    Single,
#[serde(rename = "multi")]
    Multi,
#[serde(rename = "both")]
    Both,
}

#[derive(Serialize, Deserialize, Eq, PartialEq, Debug, Clone)]
pub enum QueryExpressionFilter {
#[serde(rename = "any")]
    Any,
#[serde(rename = "null")]
    Null,
#[serde(rename = "wt-overexpressed")]
    WtOverexpressed,
}

type TermName = String;
type QueryRowsResult = Result<Vec<ResultRow>, String>;
type GeneUniquenameVecResult = Result<Vec<GeneUniquename>, String>;

#[derive(Serialize, Deserialize, Clone, Debug)]
pub enum QueryNode {
#[serde(rename = "or")]
    Or(Vec<QueryNode>),
#[serde(rename = "and")]
    And(Vec<QueryNode>),
#[serde(rename = "not")]
    Not { node_a: Box<QueryNode>, node_b: Box<QueryNode> },
#[serde(rename = "term")]
    Term {
        termid: String,
        name: Option<TermName>,
        single_or_multi_allele: Option<SingleOrMultiAllele>,
        expression: Option<QueryExpressionFilter>,
    },
#[serde(rename = "subset")]
    Subset { subset_name: String },
#[serde(rename = "gene_list")]
    GeneList { genes: Vec<GeneShort> },
#[serde(rename = "int_range")]
    IntRange { range_type: IntRangeType, start: Option<u64>, end: Option<u64> },
#[serde(rename = "float_range")]
    FloatRange { range_type: FloatRangeType, start: Option<f64>, end: Option<f64> },
#[serde(rename = "interactors")]
    Interactors { gene_uniquename: GeneUniquename, interaction_type: String },
}

fn exec_or(server_data: &ServerData, nodes: &Vec<QueryNode>) -> GeneUniquenameVecResult {
    if nodes.len() == 0 {
        return Err("illegal query: OR operator has no nodes".into());
    }

    let mut seen_genes = HashSet::new();
    let mut or_rows = vec![];

    for node in nodes {
        let exec_rows = node.exec(server_data)?;

        for row_gene_uniquename in &exec_rows {
            if !seen_genes.contains(row_gene_uniquename) {
                or_rows.push(row_gene_uniquename.clone());
                seen_genes.insert(row_gene_uniquename.clone());
            }
        }
    }

    Ok(or_rows)
}

fn exec_and(server_data: &ServerData, nodes: &Vec<QueryNode>) -> GeneUniquenameVecResult {
    if nodes.len() == 0 {
        return Err("illegal query: AND operator has no nodes".into());
    }

    let first_node_genes = nodes[0].exec(server_data)?;

    let current_genes = first_node_genes;

    let mut current_gene_set = HashSet::from_iter(current_genes);

    for node in nodes[1..].iter() {
        let node_result_rows = node.exec(server_data)?;
        let node_genes = node_result_rows.into_iter().collect::<HashSet<_>>();

        current_gene_set = current_gene_set.intersection(&node_genes).cloned().collect();
    }

    Ok(current_gene_set.into_iter().collect())
}

fn exec_not(server_data: &ServerData, node_a: &QueryNode, node_b: &QueryNode)
             -> GeneUniquenameVecResult
{
    let node_b_result = node_b.exec(server_data)?;

    let node_b_gene_set: HashSet<GeneUniquename> =
        HashSet::from_iter(node_b_result.into_iter());

    let node_a_result = node_a.exec(server_data)?;

    let mut not_rows = vec![];

    for row_gene_uniquename in &node_a_result {
        if !node_b_gene_set.contains(row_gene_uniquename) {
            not_rows.push(row_gene_uniquename.clone());
        }
    }

    Ok(not_rows)
}

fn exec_termid(server_data: &ServerData, term_id: &str,
               maybe_single_or_multi_allele: &Option<SingleOrMultiAllele>,
               expression: &Option<QueryExpressionFilter>)  -> GeneUniquenameVecResult {
    if let Some(ref single_or_multi_allele) = *maybe_single_or_multi_allele {
        let genes = server_data.genes_of_genotypes(term_id, single_or_multi_allele,
                                                   expression);
        Ok(genes)
    } else {
        Ok(server_data.genes_of_termid(term_id))
    }
}

fn exec_subset(server_data: &ServerData, subset_name: &str)  -> GeneUniquenameVecResult {
    Ok(server_data.genes_of_subset(subset_name))
}

fn exec_gene_list(genes: &Vec<GeneShort>)
                  -> GeneUniquenameVecResult
{
    let mut ret = vec![];

    for gene in genes {
        ret.push(gene.uniquename.clone());
    }

    Ok(ret)
}

fn exec_genome_range_overlaps(server_data: &ServerData,
                              range_start: Option<u64>, range_end: Option<u64>)
                               -> GeneUniquenameVecResult
{
    let gene_uniquenames =
        server_data.filter_genes(&|gene: &APIGeneSummary| {
            if let Some(ref location) = gene.location {
                (range_end.is_none() || location.start_pos as u64 <= range_end.unwrap()) &&
                (range_start.is_none() || location.end_pos as u64 >= range_start.unwrap())
            } else {
                false
            }
        });
    Ok(gene_uniquenames)
}

fn exec_protein_length_range(server_data: &ServerData,
                             range_start: Option<u64>, range_end: Option<u64>)
                              -> GeneUniquenameVecResult
{
    let gene_uniquenames =
        server_data.filter_genes(&|gene: &APIGeneSummary| {
            if gene.transcripts.len() > 0 {
                if let Some(ref protein) = gene.transcripts[0].protein {
                    (range_start.is_none() || protein.sequence.len() as u64 >= range_start.unwrap()) &&
                    (range_end.is_none() || protein.sequence.len() as u64 <= range_end.unwrap())
                } else {
                    false
                }
            } else {
                false
            }
        });
    Ok(gene_uniquenames)
}

fn exec_tm_domain_count_range(server_data: &ServerData,
                              range_start: Option<u64>, range_end: Option<u64>)
                               -> GeneUniquenameVecResult
{
    let gene_uniquenames =
        server_data.filter_genes(&|gene: &APIGeneSummary| {
            (range_start.is_none() || gene.tm_domain_count as u64 >= range_start.unwrap()) &&
            (range_end.is_none() || gene.tm_domain_count as u64 <= range_end.unwrap())
        });
    Ok(gene_uniquenames)
}

fn exec_exon_count_range(server_data: &ServerData,
                         range_start: Option<u64>, range_end: Option<u64>)
                         -> GeneUniquenameVecResult
{
    let gene_uniquenames =
        server_data.filter_genes(&|gene: &APIGeneSummary| {
            (range_start.is_none() || gene.exon_count as u64 >= range_start.unwrap()) &&
            (range_end.is_none() || gene.exon_count as u64 <= range_end.unwrap())
        });
    Ok(gene_uniquenames)
}

fn exec_int_range(server_data: &ServerData, range_type: &IntRangeType,
                  start: Option<u64>, end: Option<u64>) -> GeneUniquenameVecResult {
    match *range_type {
        IntRangeType::GenomeRangeContains => exec_genome_range_overlaps(server_data, start, end),
        IntRangeType::ProteinLength => exec_protein_length_range(server_data, start, end),
        IntRangeType::TMDomainCount => exec_tm_domain_count_range(server_data, start, end),
        IntRangeType::ExonCount => exec_exon_count_range(server_data, start, end),
    }
}

fn exec_mol_weight_range(server_data: &ServerData, range_start: Option<f64>, range_end: Option<f64>)
                         -> GeneUniquenameVecResult
{
    let gene_uniquenames =
        server_data.filter_genes(&|gene: &APIGeneSummary| {
            if gene.transcripts.len() > 0 {
                if let Some(ref protein) = gene.transcripts[0].protein {
                    (range_start.is_none() ||
                        protein.molecular_weight as f64 >= range_start.unwrap()) &&
                    (range_end.is_none() ||
                        protein.molecular_weight as f64 <= range_end.unwrap())
                } else {
                    false
                }
            } else {
                false
            }
        });
    Ok(gene_uniquenames)
}

fn exec_float_range(server_data: &ServerData, range_type: &FloatRangeType,
                    start: Option<f64>, end: Option<f64>) -> GeneUniquenameVecResult {
    match *range_type {
        FloatRangeType::ProteinMolWeight => exec_mol_weight_range(server_data, start, end)
    }
}

fn exec_interactors_of_gene(server_data: &ServerData, gene_uniquename: &GeneUniquename,
                            interaction_type: InteractionType) -> GeneUniquenameVecResult {
    Ok(server_data.interactors_of_genes(gene_uniquename, interaction_type))
}

impl QueryNode {
    pub fn exec(&self, server_data: &ServerData) -> GeneUniquenameVecResult {
        use self::QueryNode::*;
        match *self {
            Or(ref nodes) => exec_or(server_data, nodes),
            And(ref nodes) => exec_and(server_data, nodes),
            Not { ref node_a, ref node_b } => exec_not(server_data, node_a, node_b),
            Term {
                ref termid,
                name: _,
                ref single_or_multi_allele,
                ref expression,
            } => exec_termid(server_data, termid, single_or_multi_allele, expression),
            Subset { ref subset_name } => exec_subset(server_data, subset_name),
            GeneList { ref genes } => exec_gene_list(genes),
            Interactors { ref gene_uniquename, ref interaction_type } => {
                match &interaction_type as &str {
                    "physical" =>
                        exec_interactors_of_gene(server_data, gene_uniquename,
                                                 InteractionType::Physical),
                    "genetic" =>
                        exec_interactors_of_gene(server_data, gene_uniquename,
                                                 InteractionType::Genetic),
                    _ => Err(format!("No such interaction type: {}",
                                    interaction_type))
                }
            },
            IntRange { ref range_type, start, end } =>
                exec_int_range(server_data, range_type, start, end),
            FloatRange { ref range_type, start, end } =>
                exec_float_range(server_data, range_type, start, end),
        }
    }
}

#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct NucleotideDownloadOptions {
    include_introns: bool,
    include_5_prime_utr: bool,
    include_3_prime_utr: bool,
}

#[derive(Serialize, Deserialize, Clone, Debug)]
pub enum SeqType {
#[serde(rename = "protein")]
    Protein,
#[serde(rename = "nucleotide")]
    Nucleotide(NucleotideDownloadOptions),
#[serde(rename = "none")]
    None,
}

#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct QueryOutputOptions {
    pub sequence: SeqType,
    pub field_names: Vec<String>,
}

#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct Query {
    output_options: QueryOutputOptions,
    constraints: QueryNode,
}

impl Query {
    pub fn new(constraints: QueryNode, output_options: QueryOutputOptions) -> Query {
        Query {
            output_options: output_options,
            constraints: constraints
        }
    }

    fn make_nucleotide_sequence(&self, transcript: &TranscriptDetails,
                                options: &NucleotideDownloadOptions) -> String {
        let mut seq = String::from("");

        for part in &transcript.parts {
            if part.feature_type == FeatureType::Exon ||
                options.include_introns && part.feature_type == FeatureType::CdsIntron ||
                options.include_5_prime_utr &&
                (part.feature_type == FeatureType::FivePrimeUtr ||
                 options.include_introns && part.feature_type == FeatureType::FivePrimeUtrIntron) ||
                options.include_3_prime_utr &&
                (part.feature_type == FeatureType::ThreePrimeUtr ||
                 options.include_introns && part.feature_type == FeatureType::ThreePrimeUtrIntron) {
                    seq += &part.residues;
                }
        }

        seq
    }

    fn make_sequence(&self, server_data: &ServerData,
                     gene_uniquename: &str) -> Option<String> {
        let maybe_gene_summary = server_data.get_gene_summary(gene_uniquename);

        if let Some(gene_summary) = maybe_gene_summary {
            let maybe_transcript = gene_summary.transcripts.get(0);
            if let Some(transcript) = maybe_transcript {
                match self.output_options.sequence {
                    SeqType::Protein =>
                        if let Some(ref protein) = transcript.protein {
                            return Some(protein.sequence.clone());
                        }
                    SeqType::Nucleotide(ref options) => {
                        return Some(self.make_nucleotide_sequence(transcript, options))
                    }
                    SeqType::None => (),
                }
            }
        }

        None
    }

    fn make_result_rows(&self, server_data: &ServerData,
                        genes: Vec<String>) -> QueryRowsResult {
        Ok(genes.into_iter()
           .map(|gene_uniquename| {
               let sequence = self.make_sequence(server_data, &gene_uniquename);
               ResultRow {
                   sequence: sequence,
                   gene_uniquename: gene_uniquename,
               }
           }).collect::<Vec<_>>())
    }

    pub fn exec(&self, server_data: &ServerData) -> QueryRowsResult {
        let genes_result = self.constraints.exec(server_data);

        match genes_result {
            Ok(genes) => self.make_result_rows(server_data, genes),
            Err(err) => Err(err)
        }
    }
}
<commit_msg>Add chr. name to GenomeRangeContains query type<commit_after>use std::collections::hash_set::HashSet;
use std::iter::FromIterator;

use api::server_data::ServerData;
use api::result::*;
use web::data::{APIGeneSummary, TranscriptDetails, FeatureType, GeneShort, InteractionType};

use types::GeneUniquename;

#[derive(Serialize, Deserialize, Eq, PartialEq, Debug, Clone)]
pub enum IntRangeType {
#[serde(rename = "protein_length")]
    ProteinLength,
#[serde(rename = "tm_domain_count")]
    TMDomainCount,
#[serde(rename = "exon_count")]
    ExonCount,
}

#[derive(Serialize, Deserialize, Eq, PartialEq, Debug, Clone)]
pub enum FloatRangeType {
#[serde(rename = "protein_mol_weight")]
    ProteinMolWeight,
}

#[derive(Serialize, Deserialize, Eq, PartialEq, Debug, Clone)]
pub enum SingleOrMultiAllele {
#[serde(rename = "single")]
    Single,
#[serde(rename = "multi")]
    Multi,
#[serde(rename = "both")]
    Both,
}

#[derive(Serialize, Deserialize, Eq, PartialEq, Debug, Clone)]
pub enum QueryExpressionFilter {
#[serde(rename = "any")]
    Any,
#[serde(rename = "null")]
    Null,
#[serde(rename = "wt-overexpressed")]
    WtOverexpressed,
}

type TermName = String;
type QueryRowsResult = Result<Vec<ResultRow>, String>;
type GeneUniquenameVecResult = Result<Vec<GeneUniquename>, String>;

#[derive(Serialize, Deserialize, Clone, Debug)]
pub enum QueryNode {
#[serde(rename = "or")]
    Or(Vec<QueryNode>),
#[serde(rename = "and")]
    And(Vec<QueryNode>),
#[serde(rename = "not")]
    Not { node_a: Box<QueryNode>, node_b: Box<QueryNode> },
#[serde(rename = "term")]
    Term {
        termid: String,
        name: Option<TermName>,
        single_or_multi_allele: Option<SingleOrMultiAllele>,
        expression: Option<QueryExpressionFilter>,
    },
#[serde(rename = "subset")]
    Subset { subset_name: String },
#[serde(rename = "gene_list")]
    GeneList { genes: Vec<GeneShort> },
#[serde(rename = "int_range")]
    IntRange { range_type: IntRangeType, start: Option<u64>, end: Option<u64> },
#[serde(rename = "float_range")]
    FloatRange { range_type: FloatRangeType, start: Option<f64>, end: Option<f64> },
#[serde(rename = "genome_range_contains")]
    GenomeRangeContains { start: Option<u64>, end: Option<u64>, chromosome_name: String, },
#[serde(rename = "interactors")]
    Interactors { gene_uniquename: GeneUniquename, interaction_type: String },
}

fn exec_or(server_data: &ServerData, nodes: &Vec<QueryNode>) -> GeneUniquenameVecResult {
    if nodes.len() == 0 {
        return Err("illegal query: OR operator has no nodes".into());
    }

    let mut seen_genes = HashSet::new();
    let mut or_rows = vec![];

    for node in nodes {
        let exec_rows = node.exec(server_data)?;

        for row_gene_uniquename in &exec_rows {
            if !seen_genes.contains(row_gene_uniquename) {
                or_rows.push(row_gene_uniquename.clone());
                seen_genes.insert(row_gene_uniquename.clone());
            }
        }
    }

    Ok(or_rows)
}

fn exec_and(server_data: &ServerData, nodes: &Vec<QueryNode>) -> GeneUniquenameVecResult {
    if nodes.len() == 0 {
        return Err("illegal query: AND operator has no nodes".into());
    }

    let first_node_genes = nodes[0].exec(server_data)?;

    let current_genes = first_node_genes;

    let mut current_gene_set = HashSet::from_iter(current_genes);

    for node in nodes[1..].iter() {
        let node_result_rows = node.exec(server_data)?;
        let node_genes = node_result_rows.into_iter().collect::<HashSet<_>>();

        current_gene_set = current_gene_set.intersection(&node_genes).cloned().collect();
    }

    Ok(current_gene_set.into_iter().collect())
}

fn exec_not(server_data: &ServerData, node_a: &QueryNode, node_b: &QueryNode)
             -> GeneUniquenameVecResult
{
    let node_b_result = node_b.exec(server_data)?;

    let node_b_gene_set: HashSet<GeneUniquename> =
        HashSet::from_iter(node_b_result.into_iter());

    let node_a_result = node_a.exec(server_data)?;

    let mut not_rows = vec![];

    for row_gene_uniquename in &node_a_result {
        if !node_b_gene_set.contains(row_gene_uniquename) {
            not_rows.push(row_gene_uniquename.clone());
        }
    }

    Ok(not_rows)
}

fn exec_termid(server_data: &ServerData, term_id: &str,
               maybe_single_or_multi_allele: &Option<SingleOrMultiAllele>,
               expression: &Option<QueryExpressionFilter>)  -> GeneUniquenameVecResult {
    if let Some(ref single_or_multi_allele) = *maybe_single_or_multi_allele {
        let genes = server_data.genes_of_genotypes(term_id, single_or_multi_allele,
                                                   expression);
        Ok(genes)
    } else {
        Ok(server_data.genes_of_termid(term_id))
    }
}

fn exec_subset(server_data: &ServerData, subset_name: &str)  -> GeneUniquenameVecResult {
    Ok(server_data.genes_of_subset(subset_name))
}

fn exec_gene_list(genes: &Vec<GeneShort>)
                  -> GeneUniquenameVecResult
{
    let mut ret = vec![];

    for gene in genes {
        ret.push(gene.uniquename.clone());
    }

    Ok(ret)
}

fn exec_genome_range_overlaps(server_data: &ServerData, start: Option<u64>, end: Option<u64>,
                              chromosome_name: &str) -> GeneUniquenameVecResult {
    let gene_uniquenames =
        server_data.filter_genes(&|gene: &APIGeneSummary| {
            if let Some(ref location) = gene.location {
                (end.is_none() || location.start_pos as u64 <= end.unwrap()) &&
                    (start.is_none() || location.end_pos as u64 >= start.unwrap()) &&
                    location.chromosome.name == chromosome_name
            } else {
                false
            }
        });
    Ok(gene_uniquenames)
}

fn exec_protein_length_range(server_data: &ServerData,
                             range_start: Option<u64>, range_end: Option<u64>)
                              -> GeneUniquenameVecResult
{
    let gene_uniquenames =
        server_data.filter_genes(&|gene: &APIGeneSummary| {
            if gene.transcripts.len() > 0 {
                if let Some(ref protein) = gene.transcripts[0].protein {
                    (range_start.is_none() || protein.sequence.len() as u64 >= range_start.unwrap()) &&
                    (range_end.is_none() || protein.sequence.len() as u64 <= range_end.unwrap())
                } else {
                    false
                }
            } else {
                false
            }
        });
    Ok(gene_uniquenames)
}

fn exec_tm_domain_count_range(server_data: &ServerData,
                              range_start: Option<u64>, range_end: Option<u64>)
                               -> GeneUniquenameVecResult
{
    let gene_uniquenames =
        server_data.filter_genes(&|gene: &APIGeneSummary| {
            (range_start.is_none() || gene.tm_domain_count as u64 >= range_start.unwrap()) &&
            (range_end.is_none() || gene.tm_domain_count as u64 <= range_end.unwrap())
        });
    Ok(gene_uniquenames)
}

fn exec_exon_count_range(server_data: &ServerData,
                         range_start: Option<u64>, range_end: Option<u64>)
                         -> GeneUniquenameVecResult
{
    let gene_uniquenames =
        server_data.filter_genes(&|gene: &APIGeneSummary| {
            (range_start.is_none() || gene.exon_count as u64 >= range_start.unwrap()) &&
            (range_end.is_none() || gene.exon_count as u64 <= range_end.unwrap())
        });
    Ok(gene_uniquenames)
}

fn exec_int_range(server_data: &ServerData, range_type: &IntRangeType,
                  start: Option<u64>, end: Option<u64>) -> GeneUniquenameVecResult {
    match *range_type {
        IntRangeType::ProteinLength => exec_protein_length_range(server_data, start, end),
        IntRangeType::TMDomainCount => exec_tm_domain_count_range(server_data, start, end),
        IntRangeType::ExonCount => exec_exon_count_range(server_data, start, end),
    }
}

fn exec_mol_weight_range(server_data: &ServerData, range_start: Option<f64>, range_end: Option<f64>)
                         -> GeneUniquenameVecResult
{
    let gene_uniquenames =
        server_data.filter_genes(&|gene: &APIGeneSummary| {
            if gene.transcripts.len() > 0 {
                if let Some(ref protein) = gene.transcripts[0].protein {
                    (range_start.is_none() ||
                        protein.molecular_weight as f64 >= range_start.unwrap()) &&
                    (range_end.is_none() ||
                        protein.molecular_weight as f64 <= range_end.unwrap())
                } else {
                    false
                }
            } else {
                false
            }
        });
    Ok(gene_uniquenames)
}

fn exec_float_range(server_data: &ServerData, range_type: &FloatRangeType,
                    start: Option<f64>, end: Option<f64>) -> GeneUniquenameVecResult {
    match *range_type {
        FloatRangeType::ProteinMolWeight => exec_mol_weight_range(server_data, start, end)
    }
}

fn exec_interactors_of_gene(server_data: &ServerData, gene_uniquename: &GeneUniquename,
                            interaction_type: InteractionType) -> GeneUniquenameVecResult {
    Ok(server_data.interactors_of_genes(gene_uniquename, interaction_type))
}

impl QueryNode {
    pub fn exec(&self, server_data: &ServerData) -> GeneUniquenameVecResult {
        use self::QueryNode::*;
        match *self {
            Or(ref nodes) => exec_or(server_data, nodes),
            And(ref nodes) => exec_and(server_data, nodes),
            Not { ref node_a, ref node_b } => exec_not(server_data, node_a, node_b),
            Term {
                ref termid,
                name: _,
                ref single_or_multi_allele,
                ref expression,
            } => exec_termid(server_data, termid, single_or_multi_allele, expression),
            Subset { ref subset_name } => exec_subset(server_data, subset_name),
            GeneList { ref genes } => exec_gene_list(genes),
            GenomeRangeContains { start, end, ref chromosome_name } =>
                exec_genome_range_overlaps(server_data, start, end, chromosome_name),
            Interactors { ref gene_uniquename, ref interaction_type } => {
                match &interaction_type as &str {
                    "physical" =>
                        exec_interactors_of_gene(server_data, gene_uniquename,
                                                 InteractionType::Physical),
                    "genetic" =>
                        exec_interactors_of_gene(server_data, gene_uniquename,
                                                 InteractionType::Genetic),
                    _ => Err(format!("No such interaction type: {}",
                                    interaction_type))
                }
            },
            IntRange { ref range_type, start, end } =>
                exec_int_range(server_data, range_type, start, end),
            FloatRange { ref range_type, start, end } =>
                exec_float_range(server_data, range_type, start, end),
        }
    }
}

#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct NucleotideDownloadOptions {
    include_introns: bool,
    include_5_prime_utr: bool,
    include_3_prime_utr: bool,
}

#[derive(Serialize, Deserialize, Clone, Debug)]
pub enum SeqType {
#[serde(rename = "protein")]
    Protein,
#[serde(rename = "nucleotide")]
    Nucleotide(NucleotideDownloadOptions),
#[serde(rename = "none")]
    None,
}

#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct QueryOutputOptions {
    pub sequence: SeqType,
    pub field_names: Vec<String>,
}

#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct Query {
    output_options: QueryOutputOptions,
    constraints: QueryNode,
}

impl Query {
    pub fn new(constraints: QueryNode, output_options: QueryOutputOptions) -> Query {
        Query {
            output_options: output_options,
            constraints: constraints
        }
    }

    fn make_nucleotide_sequence(&self, transcript: &TranscriptDetails,
                                options: &NucleotideDownloadOptions) -> String {
        let mut seq = String::from("");

        for part in &transcript.parts {
            if part.feature_type == FeatureType::Exon ||
                options.include_introns && part.feature_type == FeatureType::CdsIntron ||
                options.include_5_prime_utr &&
                (part.feature_type == FeatureType::FivePrimeUtr ||
                 options.include_introns && part.feature_type == FeatureType::FivePrimeUtrIntron) ||
                options.include_3_prime_utr &&
                (part.feature_type == FeatureType::ThreePrimeUtr ||
                 options.include_introns && part.feature_type == FeatureType::ThreePrimeUtrIntron) {
                    seq += &part.residues;
                }
        }

        seq
    }

    fn make_sequence(&self, server_data: &ServerData,
                     gene_uniquename: &str) -> Option<String> {
        let maybe_gene_summary = server_data.get_gene_summary(gene_uniquename);

        if let Some(gene_summary) = maybe_gene_summary {
            let maybe_transcript = gene_summary.transcripts.get(0);
            if let Some(transcript) = maybe_transcript {
                match self.output_options.sequence {
                    SeqType::Protein =>
                        if let Some(ref protein) = transcript.protein {
                            return Some(protein.sequence.clone());
                        }
                    SeqType::Nucleotide(ref options) => {
                        return Some(self.make_nucleotide_sequence(transcript, options))
                    }
                    SeqType::None => (),
                }
            }
        }

        None
    }

    fn make_result_rows(&self, server_data: &ServerData,
                        genes: Vec<String>) -> QueryRowsResult {
        Ok(genes.into_iter()
           .map(|gene_uniquename| {
               let sequence = self.make_sequence(server_data, &gene_uniquename);
               ResultRow {
                   sequence: sequence,
                   gene_uniquename: gene_uniquename,
               }
           }).collect::<Vec<_>>())
    }

    pub fn exec(&self, server_data: &ServerData) -> QueryRowsResult {
        let genes_result = self.constraints.exec(server_data);

        match genes_result {
            Ok(genes) => self.make_result_rows(server_data, genes),
            Err(err) => Err(err)
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>Fix definitions of FIONBIO/FIONCLEX/FIOCLEX constants on s390x-musl.<commit_after><|endoftext|>


<commit_before>//! De-/serialization helpers for other ruma crates

use serde::de::{Deserialize, IntoDeserializer};

pub mod can_be_empty;
mod canonical_json;
mod cow;
pub mod duration;
pub mod empty;
pub mod json_string;
pub mod single_element_seq;
pub mod test;
pub mod time;
pub mod urlencoded;

pub use can_be_empty::{is_empty, CanBeEmpty};
pub use canonical_json::{
    to_canonical_value, to_string as to_canonical_json_string, try_from_json_map,
    value::{CanonicalJsonValue, Object as CanonicalJsonObject},
    Error as CanonicalJsonError,
};
pub use cow::deserialize_cow_str;
pub use empty::vec_as_map_of_empty;

/// Check whether a value is equal to its default value.
pub fn is_default<T: Default + PartialEq>(val: &T) -> bool {
    val == &T::default()
}

/// Simply returns `true`.
///
/// Useful for `#[serde(default = ...)]`.
pub fn default_true() -> bool {
    true
}

/// Simplfy dereferences the given bool.
///
/// Useful for `#[serde(skip_serializing_if = ...)]`
#[allow(clippy::trivially_copy_pass_by_ref)]
pub fn is_true(b: &bool) -> bool {
    *b
}

/// Serde deserialization decorator to map empty Strings to None,
/// and forward non-empty Strings to the Deserialize implementation for T.
/// Useful for the typical
/// "A room with an X event with an absent, null, or empty Y field
/// should be treated the same as a room with no such event."
/// formulation in the spec.
///
/// To be used like this:
/// `#[serde(deserialize_with = "empty_string_as_none")]`
/// Relevant serde issue: https://github.com/serde-rs/serde/issues/1425
pub fn empty_string_as_none<'de, D, T>(de: D) -> Result<Option<T>, D::Error>
where
    D: serde::Deserializer<'de>,
    T: serde::Deserialize<'de>,
{
    let opt = Option::<String>::deserialize(de)?;
    match opt.as_deref() {
        None | Some("") => Ok(None),
        // If T = String, like in m.room.name, the second deserialize is actually superfluous.
        // TODO: optimize that somehow?
        Some(s) => T::deserialize(s.into_deserializer()).map(Some),
    }
}
<commit_msg>Add function to deserialize numbers and strings as an integer<commit_after>//! De-/serialization helpers for other ruma crates

use js_int::Int;
use serde::{
    de::{Error, IntoDeserializer},
    Deserialize,
};
use std::convert::{TryFrom, TryInto};

pub mod can_be_empty;
mod canonical_json;
mod cow;
pub mod duration;
pub mod empty;
pub mod json_string;
pub mod single_element_seq;
pub mod test;
pub mod time;
pub mod urlencoded;

pub use can_be_empty::{is_empty, CanBeEmpty};
pub use canonical_json::{
    to_canonical_value, to_string as to_canonical_json_string, try_from_json_map,
    value::{CanonicalJsonValue, Object as CanonicalJsonObject},
    Error as CanonicalJsonError,
};
pub use cow::deserialize_cow_str;
pub use empty::vec_as_map_of_empty;

/// Check whether a value is equal to its default value.
pub fn is_default<T: Default + PartialEq>(val: &T) -> bool {
    val == &T::default()
}

/// Simply returns `true`.
///
/// Useful for `#[serde(default = ...)]`.
pub fn default_true() -> bool {
    true
}

/// Simplfy dereferences the given bool.
///
/// Useful for `#[serde(skip_serializing_if = ...)]`
#[allow(clippy::trivially_copy_pass_by_ref)]
pub fn is_true(b: &bool) -> bool {
    *b
}

/// Serde deserialization decorator to map empty Strings to None,
/// and forward non-empty Strings to the Deserialize implementation for T.
/// Useful for the typical
/// "A room with an X event with an absent, null, or empty Y field
/// should be treated the same as a room with no such event."
/// formulation in the spec.
///
/// To be used like this:
/// `#[serde(deserialize_with = "empty_string_as_none")]`
/// Relevant serde issue: https://github.com/serde-rs/serde/issues/1425
pub fn empty_string_as_none<'de, D, T>(de: D) -> Result<Option<T>, D::Error>
where
    D: serde::Deserializer<'de>,
    T: serde::Deserialize<'de>,
{
    let opt = Option::<String>::deserialize(de)?;
    match opt.as_deref() {
        None | Some("") => Ok(None),
        // If T = String, like in m.room.name, the second deserialize is actually superfluous.
        // TODO: optimize that somehow?
        Some(s) => T::deserialize(s.into_deserializer()).map(Some),
    }
}

// Helper type for deserialize_int_or_string_to_int
#[derive(Deserialize)]
#[serde(untagged)]
enum IntOrString<'a> {
    Num(Int),
    Str(&'a str),
}

impl TryFrom<IntOrString<'_>> for Int {
    type Error = js_int::ParseIntError;

    fn try_from(input: IntOrString) -> Result<Self, Self::Error> {
        match input {
            IntOrString::Num(n) => Ok(n),
            IntOrString::Str(string) => string.parse(),
        }
    }
}

/// Take either an integer number or a string and deserialize to an integer number.
///
/// To be used like this:
/// `#[serde(deserialize_with = "int_or_string_to_int")]`
pub fn int_or_string_to_int<'de, D>(de: D) -> Result<Int, D::Error>
where
    D: serde::Deserializer<'de>,
{
    IntOrString::deserialize(de)?.try_into().map_err(D::Error::custom)
}
<|endoftext|>


<commit_before>use std::ops::{Mul, Add};

use rand::{Rand, Rng, Closed01};
use num::{Float, Zero};

use rblas::{Gemm, Matrix};
use rblas::attribute::Transpose;

use ndarray::{ArrayBase, DataOwned, DataMut};
use ndarray::blas::{BlasArrayViewMut, AsBlas};

use helpers::random01;

pub trait ShapeAsTuple<T> {
    fn shape_as_tuple(&self) -> T;
}

pub type FloatT = f32;

impl<T> ShapeAsTuple<(usize, usize)> for ArrayBase<Vec<T>, (usize, usize)> {
    #[inline]
    fn shape_as_tuple(&self) -> (usize, usize) {
        (self.shape()[0], self.shape()[1])
    }
}

// TODO Dimension type alias
// TODO OwnedArray

// TODO call this OrthoNMFBlas
pub struct OrthogonalNMFBlas {
    pub hidden: ArrayBase<Vec<FloatT>, (usize, usize)>,
    pub weights: ArrayBase<Vec<FloatT>, (usize, usize)>,

    // these hold temporary results during an iteration.
    // kept in struct to prevent unnecessary memory allocations.
    pub weights_dividend: ArrayBase<Vec<FloatT>, (usize, usize)>,
    pub weights_divisor: ArrayBase<Vec<FloatT>, (usize, usize)>,
    pub weights_divisor_reconstruction: ArrayBase<Vec<FloatT>, (usize, usize)>,

    pub hidden_dividend: ArrayBase<Vec<FloatT>, (usize, usize)>,
    pub hidden_divisor: ArrayBase<Vec<FloatT>, (usize, usize)>,
    pub hidden_divisor_partial: ArrayBase<Vec<FloatT>, (usize, usize)>,
}

impl OrthogonalNMFBlas
    // where FloatT: 'a + Float + Mul + Zero + Clone + Gemm,
          // ArrayBase<Vec<FloatT>, (usize, usize)>: 'a + AsBlas<FloatT, ArrayBase<Vec<FloatT>, (usize, usize)>, (usize, usize)> + DataOwned<Elem=FloatT> + DataMut<Elem=FloatT>,
          // BlasArrayViewMut<'a, FloatT, (usize, usize)>: Matrix<FloatT>,
          // Closed01<FloatT>: Rand
{
    // TODO type alias for that ArrayBase stuff

    pub fn init_random01<R: Rng>(nhidden: usize, nobserved: usize, nsamples: usize, rng: &mut R) -> OrthogonalNMFBlas {
        let mut hidden = ArrayBase::zeros((nhidden, nobserved));
        for x in hidden.iter_mut() {
            *x = random01(rng);
        }

        let mut weights = ArrayBase::zeros((nsamples, nhidden));
        for x in weights.iter_mut() {
            *x = random01(rng);
        }

        Self::init(hidden, weights)
    }

    // TODO initialize with values from last time step t-1 instead of choosing randomly
    pub fn init(hidden: ArrayBase<Vec<FloatT>, (usize, usize)>, weights: ArrayBase<Vec<FloatT>, (usize, usize)>) -> OrthogonalNMFBlas {
        let weights_shape = weights.shape_as_tuple();
        let hidden_shape = hidden.shape_as_tuple();

        let nhidden = hidden_shape.0;
        let nobserved = hidden_shape.1;
        let nsamples = weights_shape.0;

        let samples_shape = (nsamples, nobserved);

        OrthogonalNMFBlas {
            hidden: hidden,
            weights: weights,
            weights_dividend: ArrayBase::zeros(weights_shape),
            weights_divisor: ArrayBase::zeros(weights_shape),
            weights_divisor_reconstruction: ArrayBase::zeros(samples_shape),
            hidden_dividend: ArrayBase::zeros(hidden_shape),
            hidden_divisor: ArrayBase::zeros(hidden_shape),
            hidden_divisor_partial: ArrayBase::zeros((nhidden, nhidden)),
        }
    }

    /// returns the number of observed variables
    #[inline]
    pub fn nobserved(&self) -> usize {
        self.hidden.shape()[1]
    }

    /// returns the number of hidden variables
    #[inline]
    pub fn nhidden(&self) -> usize {
        self.hidden.shape()[0]
    }

    /// returns the number of data points
    #[inline]
    pub fn nsamples(&self) -> usize {
        self.weights.shape()[0]
    }

    pub fn samples_shape(&self) -> (usize, usize) {
        (self.nsamples(), self.nobserved())
    }

    /// `samples * hidden.transpose()`
    #[inline]
    pub fn iterate_weights_dividend(&mut self, samples: &mut ArrayBase<Vec<FloatT>, (usize, usize)>) {
        Gemm::gemm(
            &1.,
            Transpose::NoTrans, &samples.blas(),
            Transpose::Trans, &self.hidden.blas(),
            &0.,
            &mut self.weights_dividend.blas());

    }

    /// `weights * hidden * hidden.transpose()`
    #[inline]
    pub fn iterate_weights_divisor(&mut self) {
        Gemm::gemm(
            &1.,
            Transpose::NoTrans, &self.weights.blas(),
            Transpose::NoTrans, &self.hidden.blas(),
            &0.,
            &mut self.weights_divisor_reconstruction.blas());
        Gemm::gemm(
            &1.,
            Transpose::NoTrans, &self.weights_divisor_reconstruction.blas(),
            Transpose::Trans, &self.hidden.blas(),
            &0.,
            &mut self.weights_divisor.blas());
    }

    /// `weights.transpose() * samples`
    #[inline]
    pub fn iterate_hidden_dividend(&mut self, samples: &mut ArrayBase<Vec<FloatT>, (usize, usize)>) {
        Gemm::gemm(
            &1.,
            Transpose::Trans, &self.weights.blas(),
            Transpose::NoTrans, &samples.blas(),
            &0.,
            &mut self.hidden_dividend.blas());
    }

    /// gamma is a symetric matrix with diagonal elements equal to zero
    /// and other elements = alpha
    pub fn alpha_to_gamma(alpha: FloatT, nhidden: usize) -> ArrayBase<Vec<FloatT>, (usize, usize)> {
        let mut gamma = ArrayBase::<Vec<FloatT>, (usize, usize)>::from_elem((nhidden, nhidden), alpha);
        for x in gamma.diag_mut().iter_mut() {
            *x = 0.
        }
        gamma
    }

    /// `weights.transpose() * weights * hidden + alpha * gamma * hidden`
    #[inline]
    pub fn iterate_hidden_divisor(&mut self, samples: &mut ArrayBase<Vec<FloatT>, (usize, usize)>, gamma: &mut ArrayBase<Vec<FloatT>, (usize, usize)>) {
        // we must make a copy here because we need two mutable
        // references to weights at the same time for .blas()
        // weights_copy.clone_from(&weights);
        // TODO is there away to prevent this
        // maybe use clone_from here
        let mut weights_copy = self.weights.clone();
        Gemm::gemm(
            &1.,
            Transpose::Trans, &self.weights.blas(),
            Transpose::NoTrans, &weights_copy.blas(),
            &0.,
            &mut self.hidden_divisor_partial.blas());
        Gemm::gemm(
            &1.,
            Transpose::NoTrans, &gamma.blas(),
            Transpose::NoTrans, &self.hidden.blas(),
            &0.,
            &mut self.hidden_divisor.blas());
        Gemm::gemm(
            &1.,
            Transpose::NoTrans, &self.hidden_divisor_partial.blas(),
            Transpose::NoTrans, &self.hidden.blas(),
            // add to previous contents of self.hidden_divisor
            &1.,
            &mut self.hidden_divisor.blas());
    }

    // TODO better name
    // per element division
    /// `result(i,j) <- result(i,j) * dividend(i,j) / divisor(i,j)`
    #[inline]
    pub fn update(
        dividend: &ArrayBase<Vec<FloatT>, (usize, usize)>,
        divisor: &ArrayBase<Vec<FloatT>, (usize, usize)>,
        result: &mut ArrayBase<Vec<FloatT>, (usize, usize)>,
    ) {
        let shape = result.shape_as_tuple();
        assert_eq!(shape, dividend.shape_as_tuple());
        assert_eq!(shape, divisor.shape_as_tuple());

        for row in 0..shape.0 {
            for col in 0..shape.1 {
                let index = (row, col);
                let mut div = unsafe { divisor.uget(index).clone() };
                // if we have any zero in any of the matrizes
                // self.weights or self.hidden then
                // divisor will be zero.
                // we can't divide by zero
                if FloatT::zero() == div {
                    div = FloatT::min_positive_value();
                }
                unsafe {
                    *result.uget_mut(index) *= dividend.uget(index) / div;
                }
                // TODO maybe also zero adjust the final weight
            }
        }
    }

    // TODO consider calling this something like iteration_step
    // TODO how many iterations ?
    // TODO compare this to the seoung solution
    /// it gets better and better with each iteration.
    /// one observed per column.
    /// one sample per row.
    pub fn iterate(&mut self, alpha: FloatT, samples: &mut ArrayBase<Vec<FloatT>, (usize, usize)>) {
        assert_eq!(samples.shape_as_tuple(), self.samples_shape());

        // TODO benchmark these individually
        // TODO add little descriptions like
        // X <- X^T
        // TODO also add them to docstrings
        // TODO maybe pass in all data explicitely
        self.iterate_weights_dividend(samples);
        self.iterate_weights_divisor();
        self.iterate_hidden_dividend(samples);
        let mut gamma = OrthogonalNMFBlas::alpha_to_gamma(
            alpha, self.nhidden());
        self.iterate_hidden_divisor(samples, &mut gamma);

        OrthogonalNMFBlas::update(
            &self.weights_dividend,
            &self.weights_divisor,
            &mut self.weights);
        OrthogonalNMFBlas::update(
            &self.hidden_dividend,
            &self.hidden_divisor,
            &mut self.hidden);
    }
}
<commit_msg>ortho nmf blas: perf improv: dont recompute gamma on every iter<commit_after>use std::ops::{Mul, Add};

use rand::{Rand, Rng, Closed01};
use num::{Float, Zero};

use rblas::{Gemm, Matrix};
use rblas::attribute::Transpose;

use ndarray::{ArrayBase, DataOwned, DataMut};
use ndarray::blas::{BlasArrayViewMut, AsBlas};

use helpers::random01;

pub trait ShapeAsTuple<T> {
    fn shape_as_tuple(&self) -> T;
}

pub type FloatT = f32;

impl<T> ShapeAsTuple<(usize, usize)> for ArrayBase<Vec<T>, (usize, usize)> {
    #[inline]
    fn shape_as_tuple(&self) -> (usize, usize) {
        (self.shape()[0], self.shape()[1])
    }
}

// TODO Dimension type alias
// TODO OwnedArray

// TODO call this OrthoNMFBlas
pub struct OrthogonalNMFBlas {
    pub hidden: ArrayBase<Vec<FloatT>, (usize, usize)>,
    pub weights: ArrayBase<Vec<FloatT>, (usize, usize)>,

    // these hold temporary results during an iteration.
    // kept in struct to prevent unnecessary memory allocations.
    pub weights_dividend: ArrayBase<Vec<FloatT>, (usize, usize)>,
    pub weights_divisor: ArrayBase<Vec<FloatT>, (usize, usize)>,
    pub weights_divisor_reconstruction: ArrayBase<Vec<FloatT>, (usize, usize)>,

    pub hidden_dividend: ArrayBase<Vec<FloatT>, (usize, usize)>,
    pub hidden_divisor: ArrayBase<Vec<FloatT>, (usize, usize)>,
    pub hidden_divisor_partial: ArrayBase<Vec<FloatT>, (usize, usize)>,

    pub gamma: ArrayBase<Vec<FloatT>, (usize, usize)>,
}

impl OrthogonalNMFBlas
    // where FloatT: 'a + Float + Mul + Zero + Clone + Gemm,
          // ArrayBase<Vec<FloatT>, (usize, usize)>: 'a + AsBlas<FloatT, ArrayBase<Vec<FloatT>, (usize, usize)>, (usize, usize)> + DataOwned<Elem=FloatT> + DataMut<Elem=FloatT>,
          // BlasArrayViewMut<'a, FloatT, (usize, usize)>: Matrix<FloatT>,
          // Closed01<FloatT>: Rand
{
    // TODO type alias for that ArrayBase stuff

    pub fn init_random01<R: Rng>(nhidden: usize, nobserved: usize, nsamples: usize, rng: &mut R) -> OrthogonalNMFBlas {
        let mut hidden = ArrayBase::zeros((nhidden, nobserved));
        for x in hidden.iter_mut() {
            *x = random01(rng);
        }

        let mut weights = ArrayBase::zeros((nsamples, nhidden));
        for x in weights.iter_mut() {
            *x = random01(rng);
        }

        Self::init(hidden, weights)
    }

    // TODO initialize with values from last time step t-1 instead of choosing randomly
    pub fn init(hidden: ArrayBase<Vec<FloatT>, (usize, usize)>, weights: ArrayBase<Vec<FloatT>, (usize, usize)>) -> OrthogonalNMFBlas {
        let weights_shape = weights.shape_as_tuple();
        let hidden_shape = hidden.shape_as_tuple();

        let nhidden = hidden_shape.0;
        let nobserved = hidden_shape.1;
        let nsamples = weights_shape.0;

        let samples_shape = (nsamples, nobserved);

        OrthogonalNMFBlas {
            hidden: hidden,
            weights: weights,
            weights_dividend: ArrayBase::zeros(weights_shape),
            weights_divisor: ArrayBase::zeros(weights_shape),
            weights_divisor_reconstruction: ArrayBase::zeros(samples_shape),
            hidden_dividend: ArrayBase::zeros(hidden_shape),
            hidden_divisor: ArrayBase::zeros(hidden_shape),
            hidden_divisor_partial: ArrayBase::zeros((nhidden, nhidden)),
            gamma: OrthogonalNMFBlas::gamma(nhidden),
        }
    }

    /// returns the number of observed variables
    #[inline]
    pub fn nobserved(&self) -> usize {
        self.hidden.shape()[1]
    }

    /// returns the number of hidden variables
    #[inline]
    pub fn nhidden(&self) -> usize {
        self.hidden.shape()[0]
    }

    /// returns the number of data points
    #[inline]
    pub fn nsamples(&self) -> usize {
        self.weights.shape()[0]
    }

    pub fn samples_shape(&self) -> (usize, usize) {
        (self.nsamples(), self.nobserved())
    }

    /// `samples * hidden.transpose()`
    #[inline]
    pub fn iterate_weights_dividend(&mut self, samples: &mut ArrayBase<Vec<FloatT>, (usize, usize)>) {
        Gemm::gemm(
            &1.,
            Transpose::NoTrans, &samples.blas(),
            Transpose::Trans, &self.hidden.blas(),
            &0.,
            &mut self.weights_dividend.blas());

    }

    /// `weights * hidden * hidden.transpose()`
    #[inline]
    pub fn iterate_weights_divisor(&mut self) {
        Gemm::gemm(
            &1.,
            Transpose::NoTrans, &self.weights.blas(),
            Transpose::NoTrans, &self.hidden.blas(),
            &0.,
            &mut self.weights_divisor_reconstruction.blas());
        Gemm::gemm(
            &1.,
            Transpose::NoTrans, &self.weights_divisor_reconstruction.blas(),
            Transpose::Trans, &self.hidden.blas(),
            &0.,
            &mut self.weights_divisor.blas());
    }

    /// `weights.transpose() * samples`
    #[inline]
    pub fn iterate_hidden_dividend(&mut self, samples: &mut ArrayBase<Vec<FloatT>, (usize, usize)>) {
        Gemm::gemm(
            &1.,
            Transpose::Trans, &self.weights.blas(),
            Transpose::NoTrans, &samples.blas(),
            &0.,
            &mut self.hidden_dividend.blas());
    }

    /// gamma is a symetric matrix with diagonal elements equal to zero
    /// and other elements equal to 1
    pub fn gamma(size: usize) -> ArrayBase<Vec<FloatT>, (usize, usize)> {
        let mut gamma = ArrayBase::<Vec<FloatT>, (usize, usize)>::from_elem((size, size), 1.);
        for x in gamma.diag_mut().iter_mut() {
            *x = 0.
        }
        gamma
    }

    /// `weights.transpose() * weights * hidden + alpha * gamma * hidden`
    #[inline]
    pub fn iterate_hidden_divisor(&mut self, samples: &mut ArrayBase<Vec<FloatT>, (usize, usize)>, alpha: FloatT) {
        // we must make a copy here because we need two mutable
        // references to weights at the same time for .blas()
        // weights_copy.clone_from(&weights);
        // TODO is there away to prevent this
        // maybe use clone_from here
        let mut weights_copy = self.weights.clone();
        Gemm::gemm(
            &1.,
            Transpose::Trans, &self.weights.blas(),
            Transpose::NoTrans, &weights_copy.blas(),
            &0.,
            &mut self.hidden_divisor_partial.blas());
        Gemm::gemm(
            &alpha,
            Transpose::NoTrans, &self.gamma.blas(),
            Transpose::NoTrans, &self.hidden.blas(),
            &0.,
            &mut self.hidden_divisor.blas());
        Gemm::gemm(
            &1.,
            Transpose::NoTrans, &self.hidden_divisor_partial.blas(),
            Transpose::NoTrans, &self.hidden.blas(),
            // add to previous contents of self.hidden_divisor
            &1.,
            &mut self.hidden_divisor.blas());
    }

    // TODO better name
    // per element division
    /// `result(i,j) <- result(i,j) * dividend(i,j) / divisor(i,j)`
    #[inline]
    pub fn update(
        dividend: &ArrayBase<Vec<FloatT>, (usize, usize)>,
        divisor: &ArrayBase<Vec<FloatT>, (usize, usize)>,
        result: &mut ArrayBase<Vec<FloatT>, (usize, usize)>,
    ) {
        let shape = result.shape_as_tuple();
        assert_eq!(shape, dividend.shape_as_tuple());
        assert_eq!(shape, divisor.shape_as_tuple());

        for row in 0..shape.0 {
            for col in 0..shape.1 {
                let index = (row, col);
                let mut div = unsafe { divisor.uget(index).clone() };
                // if we have any zero in any of the matrizes
                // self.weights or self.hidden then
                // divisor will be zero.
                // we can't divide by zero
                if FloatT::zero() == div {
                    div = FloatT::min_positive_value();
                }
                unsafe {
                    *result.uget_mut(index) *= dividend.uget(index) / div;
                }
                // TODO maybe also zero adjust the final weight
            }
        }
    }

    // TODO consider calling this something like iteration_step
    // TODO how many iterations ?
    // TODO compare this to the seoung solution
    /// it gets better and better with each iteration.
    /// one observed per column.
    /// one sample per row.
    pub fn iterate(&mut self, alpha: FloatT, samples: &mut ArrayBase<Vec<FloatT>, (usize, usize)>) {
        assert_eq!(samples.shape_as_tuple(), self.samples_shape());

        // TODO benchmark these individually
        // TODO add little descriptions like
        // X <- X^T
        // TODO also add them to docstrings
        // TODO maybe pass in all data explicitely
        self.iterate_weights_dividend(samples);
        self.iterate_weights_divisor();
        self.iterate_hidden_dividend(samples);
        self.iterate_hidden_divisor(samples, alpha);

        OrthogonalNMFBlas::update(
            &self.weights_dividend,
            &self.weights_divisor,
            &mut self.weights);
        OrthogonalNMFBlas::update(
            &self.hidden_dividend,
            &self.hidden_divisor,
            &mut self.hidden);
    }
}
<|endoftext|>