<commit_before>//! Implements the "trellis" convolutional error correcting code specified by P25.

use std;

use bits;

/// Half-rate convolutional ("trellis") code state machine.
pub type DibitFSM = TrellisFSM<DibitStates>;

/// 3/4-rate convolutional ("trellis") code state machine.
pub type TribitFSM = TrellisFSM<TribitStates>;

pub trait States {
    /// Symbol type to use for states and input.
    type Symbol;

    /// Number of rows/columns in the state machine.
    fn size() -> usize;

    /// Get the "constallation point" on the transition from the current state to the next
    /// state.
    fn pair_idx(cur: usize, next: usize) -> usize;

    /// Convert the given symbol to a state.
    fn state(input: Self::Symbol) -> usize;
    /// Convert the given state to a symbol.
    fn symbol(state: usize) -> Self::Symbol;

    /// Get the "flushing" symbol fed in at the end of a stream.
    fn finisher() -> Self::Symbol;

    /// Get the dibit pair on the transition from the current state to the next state.
    fn pair(state: usize, next: usize) -> (bits::Dibit, bits::Dibit) {
        const PAIRS: [(u8, u8); 16] = [
            (0b00, 0b10),
            (0b10, 0b10),
            (0b01, 0b11),
            (0b11, 0b11),
            (0b11, 0b10),
            (0b01, 0b10),
            (0b10, 0b11),
            (0b00, 0b11),
            (0b11, 0b01),
            (0b01, 0b01),
            (0b10, 0b00),
            (0b00, 0b00),
            (0b00, 0b01),
            (0b10, 0b01),
            (0b01, 0b00),
            (0b11, 0b00),
        ];

        let (hi, lo) = PAIRS[Self::pair_idx(state, next)];
        (bits::Dibit::new(hi), bits::Dibit::new(lo))
    }
}

/// Half-rate state machine (dibit input).
pub struct DibitStates;

impl States for DibitStates {
    type Symbol = bits::Dibit;

    fn size() -> usize { 4 }

    fn pair_idx(cur: usize, next: usize) -> usize {
        const STATES: [[usize; 4]; 4] = [
            [0, 15, 12, 3],
            [4, 11, 8, 7],
            [13, 2, 1, 14],
            [9, 6, 5, 10],
        ];

        STATES[cur][next]
    }

    fn state(input: bits::Dibit) -> usize { input.bits() as usize }
    fn finisher() -> Self::Symbol { bits::Dibit::new(0b00) }
    fn symbol(state: usize) -> Self::Symbol { bits::Dibit::new(state as u8) }
}

/// 3/4-rate state machine (tribit input).
pub struct TribitStates;

impl States for TribitStates {
    type Symbol = bits::Tribit;

    fn size() -> usize { 8 }

    fn pair_idx(cur: usize, next: usize) -> usize {
        const STATES: [[usize; 8]; 8] = [
            [0,  8, 4, 12, 2, 10, 6, 14],
            [4, 12, 2, 10, 6, 14, 0,  8],
            [1,  9, 5, 13, 3, 11, 7, 15],
            [5, 13, 3, 11, 7, 15, 1,  9],
            [3, 11, 7, 15, 1,  9, 5, 13],
            [7, 15, 1,  9, 5, 13, 3, 11],
            [2, 10, 6, 14, 0,  8, 4, 12],
            [6, 14, 0,  8, 4, 12, 2, 10],
        ];

        STATES[cur][next]
    }

    fn state(input: bits::Tribit) -> usize { input.bits() as usize }
    fn finisher() -> Self::Symbol { bits::Tribit::new(0b000) }
    fn symbol(state: usize) -> Self::Symbol { bits::Tribit::new(state as u8) }
}

/// Convolutional code finite state machine with the given transition table. Each fed-in
/// symbol is used as the next state.
pub struct TrellisFSM<S: States> {
    states: std::marker::PhantomData<S>,
    /// Current state.
    state: usize,
}

impl<S: States> TrellisFSM<S> {
    /// Construct a new `TrellisFSM` at the initial state.
    pub fn new() -> TrellisFSM<S> {
        TrellisFSM {
            states: std::marker::PhantomData,
            state: 0,
        }
    }

    /// Apply the given symbol to the state machine and return the dibit pair on the
    /// transition.
    pub fn feed(&mut self, input: S::Symbol) -> (bits::Dibit, bits::Dibit) {
        let next = S::state(input);
        let pair = S::pair(self.state, next);

        self.state = next;

        pair
    }

    /// Flush the state machine with the finishing symbol and return the final transition.
    pub fn finish(&mut self) -> (bits::Dibit, bits::Dibit) {
        self.feed(S::finisher())
    }
}

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

    #[test]
    fn test_dibit_code() {
        let mut fsm = DibitFSM::new();
        assert_eq!(fsm.feed(Dibit::new(0b00)), (Dibit::new(0b00), Dibit::new(0b10)));
        assert_eq!(fsm.feed(Dibit::new(0b00)), (Dibit::new(0b00), Dibit::new(0b10)));
        assert_eq!(fsm.feed(Dibit::new(0b01)), (Dibit::new(0b11), Dibit::new(0b00)));
        assert_eq!(fsm.feed(Dibit::new(0b01)), (Dibit::new(0b00), Dibit::new(0b00)));
        assert_eq!(fsm.feed(Dibit::new(0b10)), (Dibit::new(0b11), Dibit::new(0b01)));
        assert_eq!(fsm.feed(Dibit::new(0b10)), (Dibit::new(0b10), Dibit::new(0b10)));
        assert_eq!(fsm.feed(Dibit::new(0b11)), (Dibit::new(0b01), Dibit::new(0b00)));
        assert_eq!(fsm.feed(Dibit::new(0b11)), (Dibit::new(0b10), Dibit::new(0b00)));
    }

    #[test]
    fn test_tribit_code() {
        let mut fsm = TribitFSM::new();
        assert_eq!(fsm.feed(Tribit::new(0b000)), (Dibit::new(0b00), Dibit::new(0b10)));
        assert_eq!(fsm.feed(Tribit::new(0b000)), (Dibit::new(0b00), Dibit::new(0b10)));
        assert_eq!(fsm.feed(Tribit::new(0b001)), (Dibit::new(0b11), Dibit::new(0b01)));
        assert_eq!(fsm.feed(Tribit::new(0b010)), (Dibit::new(0b01), Dibit::new(0b11)));
        assert_eq!(fsm.feed(Tribit::new(0b100)), (Dibit::new(0b11), Dibit::new(0b11)));
        assert_eq!(fsm.feed(Tribit::new(0b101)), (Dibit::new(0b01), Dibit::new(0b01)));
        assert_eq!(fsm.feed(Tribit::new(0b110)), (Dibit::new(0b11), Dibit::new(0b11)));
        assert_eq!(fsm.feed(Tribit::new(0b111)), (Dibit::new(0b00), Dibit::new(0b01)));
        assert_eq!(fsm.feed(Tribit::new(0b000)), (Dibit::new(0b10), Dibit::new(0b11)));
        assert_eq!(fsm.feed(Tribit::new(0b111)), (Dibit::new(0b01), Dibit::new(0b00)));
    }
}
<commit_msg>Add Viterbi decoder for trellis code<commit_after>//! Implements encoding and decoding of the "trellis" convolutional error correcting code
//! specified by P25. Encoding is done with a state machine and decoding is done with the
//! Viterbi algorithm, adapted from \[1].
//!
//! \[1]: "Coding Theory and Cryptography: The Essentials", 2nd ed, Hankerson, Hoffman, et
//! al, 2000

use std;
use std::ops::{Deref, DerefMut};

use bits::{self, Dibit};
use util::CollectSlice;

use self::Decision::*;

/// Half-rate convolutional ("trellis") code state machine.
pub type DibitFSM = TrellisFSM<DibitStates>;

/// 3/4-rate convolutional ("trellis") code state machine.
pub type TribitFSM = TrellisFSM<TribitStates>;

/// Half-rate convolution ("trellis") code decoder.
pub type DibitDecoder<T> = ViterbiDecoder<DibitStates, DibitHistory, T>;

/// 3/4-rate convolution ("trellis") code decoder.
pub type TribitDecoder<T> = ViterbiDecoder<TribitStates, TribitHistory, T>;

pub trait States {
    /// Symbol type to use for states and input.
    type Symbol;

    /// Number of rows/columns in the state machine.
    fn size() -> usize;

    /// Get the "constallation point" on the transition from the current state to the next
    /// state.
    fn pair_idx(cur: usize, next: usize) -> usize;

    /// Convert the given symbol to a state.
    fn state(input: Self::Symbol) -> usize;
    /// Convert the given state to a symbol.
    fn symbol(state: usize) -> Self::Symbol;

    /// Get the "flushing" symbol fed in at the end of a stream.
    fn finisher() -> Self::Symbol;

    /// Get the dibit pair on the transition from the current state to the next state.
    fn pair(state: usize, next: usize) -> (bits::Dibit, bits::Dibit) {
        const PAIRS: [(u8, u8); 16] = [
            (0b00, 0b10),
            (0b10, 0b10),
            (0b01, 0b11),
            (0b11, 0b11),
            (0b11, 0b10),
            (0b01, 0b10),
            (0b10, 0b11),
            (0b00, 0b11),
            (0b11, 0b01),
            (0b01, 0b01),
            (0b10, 0b00),
            (0b00, 0b00),
            (0b00, 0b01),
            (0b10, 0b01),
            (0b01, 0b00),
            (0b11, 0b00),
        ];

        let (hi, lo) = PAIRS[Self::pair_idx(state, next)];
        (bits::Dibit::new(hi), bits::Dibit::new(lo))
    }
}

/// Half-rate state machine (dibit input).
pub struct DibitStates;

impl States for DibitStates {
    type Symbol = bits::Dibit;

    fn size() -> usize { 4 }

    fn pair_idx(cur: usize, next: usize) -> usize {
        const STATES: [[usize; 4]; 4] = [
            [0, 15, 12, 3],
            [4, 11, 8, 7],
            [13, 2, 1, 14],
            [9, 6, 5, 10],
        ];

        STATES[cur][next]
    }

    fn state(input: bits::Dibit) -> usize { input.bits() as usize }
    fn finisher() -> Self::Symbol { bits::Dibit::new(0b00) }
    fn symbol(state: usize) -> Self::Symbol { bits::Dibit::new(state as u8) }
}

/// 3/4-rate state machine (tribit input).
pub struct TribitStates;

impl States for TribitStates {
    type Symbol = bits::Tribit;

    fn size() -> usize { 8 }

    fn pair_idx(cur: usize, next: usize) -> usize {
        const STATES: [[usize; 8]; 8] = [
            [0,  8, 4, 12, 2, 10, 6, 14],
            [4, 12, 2, 10, 6, 14, 0,  8],
            [1,  9, 5, 13, 3, 11, 7, 15],
            [5, 13, 3, 11, 7, 15, 1,  9],
            [3, 11, 7, 15, 1,  9, 5, 13],
            [7, 15, 1,  9, 5, 13, 3, 11],
            [2, 10, 6, 14, 0,  8, 4, 12],
            [6, 14, 0,  8, 4, 12, 2, 10],
        ];

        STATES[cur][next]
    }

    fn state(input: bits::Tribit) -> usize { input.bits() as usize }
    fn finisher() -> Self::Symbol { bits::Tribit::new(0b000) }
    fn symbol(state: usize) -> Self::Symbol { bits::Tribit::new(state as u8) }
}

/// Convolutional code finite state machine with the given transition table. Each fed-in
/// symbol is used as the next state.
pub struct TrellisFSM<S: States> {
    states: std::marker::PhantomData<S>,
    /// Current state.
    state: usize,
}

impl<S: States> TrellisFSM<S> {
    /// Construct a new `TrellisFSM` at the initial state.
    pub fn new() -> TrellisFSM<S> {
        TrellisFSM {
            states: std::marker::PhantomData,
            state: 0,
        }
    }

    /// Apply the given symbol to the state machine and return the dibit pair on the
    /// transition.
    pub fn feed(&mut self, input: S::Symbol) -> (bits::Dibit, bits::Dibit) {
        let next = S::state(input);
        let pair = S::pair(self.state, next);

        self.state = next;

        pair
    }

    /// Flush the state machine with the finishing symbol and return the final transition.
    pub fn finish(&mut self) -> (bits::Dibit, bits::Dibit) {
        self.feed(S::finisher())
    }
}

macro_rules! history_type {
    ($name: ident, $history: expr) => {
        #[derive(Copy, Clone, Default)]
        struct $name([Option<usize>; $history]);

        impl Deref for $name {
            type Target = [Option<usize>];
            fn deref<'a>(&'a self) -> &'a Self::Target { &self.0[..] }
        }

        impl DerefMut for $name {
            fn deref_mut<'a>(&'a mut self) -> &'a mut Self::Target { &mut self.0[..] }
        }

        impl WalkHistory for $name {
            fn history() -> usize { $history }
        }
    };
}

history_type!(DibitHistory, 4);
history_type!(TribitHistory, 4);

pub trait WalkHistory: Copy + Clone + Default +
    Deref<Target = [Option<usize>]> + DerefMut
{
    /// The length of each walk associated with each state. This also determines the delay
    /// before the first decoded symbol is yielded.
    fn history() -> usize;
}

/// Decodes a received convolutional code dibit stream to a nearby codeword using the
/// truncated Viterbi algorithm.
pub struct ViterbiDecoder<S, H, T> where
    S: States, H: WalkHistory, T: Iterator<Item = bits::Dibit>
{
    states: std::marker::PhantomData<S>,
    /// Source of dibits.
    src: T,
    /// Walks associated with each state, for the current and previous tick.
    cur: Vec<Walk<H>>,
    prev: Vec<Walk<H>>,
    /// Remaining symbols to yield.
    remain: usize,
}

impl<S, H, T> ViterbiDecoder<S, H, T> where
    S: States, H: WalkHistory, T: Iterator<Item = bits::Dibit>
{
    /// Construct a new `ViterbiDecoder` over the given dibit source.
    pub fn new(src: T) -> ViterbiDecoder<S, H, T> {
        ViterbiDecoder {
            states: std::marker::PhantomData,
            src: src,
            cur: Self::new_walks(),
            prev: Self::new_walks(),
            remain: 0,
        }.prime()
    }

    fn new_walks() -> Vec<Walk<H>> { (0..S::size()).map(Walk::new).collect() }

    fn prime(mut self) -> Self {
        for _ in 0..H::history() - 1 {
            self.step();
        }

        self
    }

    fn switch_walk(&mut self) {
        std::mem::swap(&mut self.cur, &mut self.prev);
    }

    fn step(&mut self) -> bool {
        let input = Edge::new(match (self.src.next(), self.src.next()) {
            (Some(hi), Some(lo)) => (hi, lo),
            (Some(_), None) | (None, Some(_)) => panic!("dibits ended on boundary"),
            (None, None) => return false,
        });

        self.remain += 1;
        self.switch_walk();

        for s in 0..S::size() {
            let (walk, _) = self.search(s, input);
            self.cur[s].append(walk);
        }

        true
    }

    fn search(&self, state: usize, input: Edge) -> (Walk<H>, bool) {
        self.prev.iter()
            .enumerate()
            .map(|(i, w)| (Edge::new(S::pair(i, state)), w))
            .fold((Walk::default(), false), |(walk, amb), (e, w)| {
                match w.distance().checked_add(input.distance(e)) {
                    Some(sum) if sum < walk.distance() => (walk.replace(&w, sum), false),
                    Some(sum) if sum == walk.distance() => (walk.combine(&w, sum), true),
                    _ => (walk, amb),
                }
            })
    }

    fn decode(&self) -> Decision {
        self.cur.iter().fold(Ambiguous(std::usize::MAX), |s, w| {
            match s {
                Ambiguous(min) | Definite(min, _) if w.distance() < min =>
                    Definite(w.distance(), w[self.remain]),
                Definite(min, state) if w.distance() == min && w[self.remain] != state =>
                    Ambiguous(w.distance()),
                _ => s,
            }
        })
    }
}

impl<S, H, T> Iterator for ViterbiDecoder<S, H, T> where
    S: States, H: WalkHistory, T: Iterator<Item = bits::Dibit>
{
    type Item = Result<S::Symbol, ()>;

    fn next(&mut self) -> Option<Self::Item> {
        if !self.step() && self.remain == 0 {
            return None;
        }

        self.remain -= 1;

        Some(match self.decode() {
            Ambiguous(_) | Definite(_, None) => Err(()),
            Definite(_, Some(state)) => Ok(S::symbol(state)),
        })
    }
}

/// Decoding decision.
enum Decision {
    Definite(usize, Option<usize>),
    Ambiguous(usize),
}

#[derive(Copy, Clone, Debug)]
struct Walk<H: WalkHistory>{
    history: H,
    distance: usize,
}

impl<H: WalkHistory> Walk<H> {
    pub fn new(state: usize) -> Walk<H> {
        Walk {
            history: H::default(),
            distance: if state == 0 {
                0
            } else {
                std::usize::MAX
            },
       }.init(state)
    }

    fn init(mut self, state: usize) -> Self {
        self.history[0] = Some(state);
        self
    }

    pub fn distance(&self) -> usize { self.distance }

    pub fn append(&mut self, other: Self) {
        self.distance = other.distance;

        for i in 1..self.len() {
            self[i] = other[i - 1];
        }
    }

    pub fn combine(mut self, other: &Self, distance: usize) -> Self {
        self.distance = distance;

        for (dest, src) in self.iter_mut().zip(other.iter()) {
            if src != dest {
                *dest = None;
            }
        }

        self
    }

    pub fn replace(mut self, other: &Self, distance: usize) -> Self {
        self.distance = distance;
        other.iter().cloned().collect_slice_checked(&mut self[..]);

        self
    }
}

impl<H: WalkHistory> Deref for Walk<H> {
    type Target = [Option<usize>];
    fn deref<'a>(&'a self) -> &'a Self::Target { &self.history }
}

impl<H: WalkHistory> DerefMut for Walk<H> {
    fn deref_mut<'a>(&'a mut self) -> &'a mut Self::Target { &mut self.history }
}

impl<H: WalkHistory> Default for Walk<H> {
    fn default() -> Self { Walk::new(std::usize::MAX) }
}

#[derive(Copy, Clone)]
struct Edge(u8);

impl Edge {
    pub fn new((hi, lo): (bits::Dibit, bits::Dibit)) -> Edge {
        Edge(hi.bits() << 2 | lo.bits())
    }

    pub fn distance(&self, other: Edge) -> usize {
        (self.0 ^ other.0).count_ones() as usize
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use super::{Edge};
    use bits::*;

    #[test]
    fn test_dibit_code() {
        let mut fsm = DibitFSM::new();
        assert_eq!(fsm.feed(Dibit::new(0b00)), (Dibit::new(0b00), Dibit::new(0b10)));
        assert_eq!(fsm.feed(Dibit::new(0b00)), (Dibit::new(0b00), Dibit::new(0b10)));
        assert_eq!(fsm.feed(Dibit::new(0b01)), (Dibit::new(0b11), Dibit::new(0b00)));
        assert_eq!(fsm.feed(Dibit::new(0b01)), (Dibit::new(0b00), Dibit::new(0b00)));
        assert_eq!(fsm.feed(Dibit::new(0b10)), (Dibit::new(0b11), Dibit::new(0b01)));
        assert_eq!(fsm.feed(Dibit::new(0b10)), (Dibit::new(0b10), Dibit::new(0b10)));
        assert_eq!(fsm.feed(Dibit::new(0b11)), (Dibit::new(0b01), Dibit::new(0b00)));
        assert_eq!(fsm.feed(Dibit::new(0b11)), (Dibit::new(0b10), Dibit::new(0b00)));
    }

    #[test]
    fn test_tribit_code() {
        let mut fsm = TribitFSM::new();
        assert_eq!(fsm.feed(Tribit::new(0b000)), (Dibit::new(0b00), Dibit::new(0b10)));
        assert_eq!(fsm.feed(Tribit::new(0b000)), (Dibit::new(0b00), Dibit::new(0b10)));
        assert_eq!(fsm.feed(Tribit::new(0b001)), (Dibit::new(0b11), Dibit::new(0b01)));
        assert_eq!(fsm.feed(Tribit::new(0b010)), (Dibit::new(0b01), Dibit::new(0b11)));
        assert_eq!(fsm.feed(Tribit::new(0b100)), (Dibit::new(0b11), Dibit::new(0b11)));
        assert_eq!(fsm.feed(Tribit::new(0b101)), (Dibit::new(0b01), Dibit::new(0b01)));
        assert_eq!(fsm.feed(Tribit::new(0b110)), (Dibit::new(0b11), Dibit::new(0b11)));
        assert_eq!(fsm.feed(Tribit::new(0b111)), (Dibit::new(0b00), Dibit::new(0b01)));
        assert_eq!(fsm.feed(Tribit::new(0b000)), (Dibit::new(0b10), Dibit::new(0b11)));
        assert_eq!(fsm.feed(Tribit::new(0b111)), (Dibit::new(0b01), Dibit::new(0b00)));
    }

    #[test]
    fn test_edge() {
        assert_eq!(Edge::new((
            Dibit::new(0b11), Dibit::new(0b01)
        )).distance(Edge::new((
            Dibit::new(0b11), Dibit::new(0b01)
        ))), 0);

        assert_eq!(Edge::new((
            Dibit::new(0b11), Dibit::new(0b01)
        )).distance(Edge::new((
            Dibit::new(0b00), Dibit::new(0b10)
        ))), 4);
    }

    #[test]
    fn test_dibit_decoder() {
        let bits = [1, 2, 2, 2, 2, 1, 3, 3, 0, 2];
        let stream = bits.iter().map(|&bits| Dibit::new(bits));

        let mut dibits = vec![];
        let mut fsm = DibitFSM::new();

        for dibit in stream {
            let (hi, lo) = fsm.feed(dibit);
            dibits.push(hi);
            dibits.push(lo);
        }

        dibits[2] = Dibit::new(0b10);
        dibits[4] = Dibit::new(0b10);

        let mut dec = DibitDecoder::new(dibits.iter().cloned());

        assert_eq!(dec.next().unwrap().unwrap().bits(), 1);
        assert_eq!(dec.next().unwrap().unwrap().bits(), 2);
        assert_eq!(dec.next().unwrap().unwrap().bits(), 2);
        assert_eq!(dec.next().unwrap().unwrap().bits(), 2);
        assert_eq!(dec.next().unwrap().unwrap().bits(), 2);
        assert_eq!(dec.next().unwrap().unwrap().bits(), 1);
        assert_eq!(dec.next().unwrap().unwrap().bits(), 3);
        assert_eq!(dec.next().unwrap().unwrap().bits(), 3);
        assert_eq!(dec.next().unwrap().unwrap().bits(), 0);
        assert_eq!(dec.next().unwrap().unwrap().bits(), 2);
    }

    #[test]
    fn test_tribit_decoder() {
        let bits = [
            1, 2, 3, 4, 5, 6, 7, 0,
            1, 2, 3, 4, 5, 6, 7, 0,
        ];
        let stream = bits.iter().map(|&bits| Tribit::new(bits));

        let mut dibits = vec![];
        let mut fsm = TribitFSM::new();

        for tribit in stream {
            let (hi, lo) = fsm.feed(tribit);
            dibits.push(hi);
            dibits.push(lo);
        }

        dibits[6] = Dibit::new(0b10);
        dibits[4] = Dibit::new(0b10);
        dibits[14] = Dibit::new(0b10);

        let mut dec = TribitDecoder::new(dibits.iter().cloned());

        assert_eq!(dec.next().unwrap().unwrap().bits(), 1);
        assert_eq!(dec.next().unwrap().unwrap().bits(), 2);
        assert_eq!(dec.next().unwrap().unwrap().bits(), 3);
        assert_eq!(dec.next().unwrap().unwrap().bits(), 4);
        assert_eq!(dec.next().unwrap().unwrap().bits(), 5);
        assert_eq!(dec.next().unwrap().unwrap().bits(), 6);
        assert_eq!(dec.next().unwrap().unwrap().bits(), 7);
        assert_eq!(dec.next().unwrap().unwrap().bits(), 0);
        assert_eq!(dec.next().unwrap().unwrap().bits(), 1);
        assert_eq!(dec.next().unwrap().unwrap().bits(), 2);
        assert_eq!(dec.next().unwrap().unwrap().bits(), 3);
        assert_eq!(dec.next().unwrap().unwrap().bits(), 4);
        assert_eq!(dec.next().unwrap().unwrap().bits(), 5);
        assert_eq!(dec.next().unwrap().unwrap().bits(), 6);
        assert_eq!(dec.next().unwrap().unwrap().bits(), 7);
        assert_eq!(dec.next().unwrap().unwrap().bits(), 0);
    }
}
<|endoftext|>


<commit_before>// Implements http://rosettacode.org/wiki/LZW_compression

extern crate collections;

use collections::hashmap::HashMap;
use std::vec;
use std::str;

fn compress(original_str: &str) -> ~[int] {
   let original = original_str.as_bytes();
   let mut dict_size = 256;
   let mut dictionary = HashMap::new();

   for i in range(0, dict_size) {
      dictionary.insert(~[i as u8], i);
   }

   let mut result = ~[];
   let mut w:~[u8] = ~[];
   for &c in original.iter() {
      let mut wc = w.clone();
      wc.push(c);

      match dictionary.find(&wc) {
         Some(_) => w = wc,
         None => {
            result.push(*dictionary.get(&w));
            dictionary.insert(wc, dict_size);
            dict_size += 1;
            w = ~[c];
         }
      }
   }

   if w.len() > 0 {
      result.push(*dictionary.get(&w));
   }

   result
}

fn decompress(compressed: &[int]) -> ~str {
   let mut dict_size = 256;
   let mut dictionary = HashMap::new();

   for i in range(0, dict_size) {
      dictionary.insert(i, ~[i as u8]);
   }

   let mut w = ~[compressed[0] as u8];
   let compressed = compressed.slice(1, compressed.len());
   let mut result = w.clone();
   for &k in compressed.iter() {
      let entry =
         match dictionary.find(&k) {
            Some(v) => v.clone(),
            None if k == dict_size => vec::append_one(w.clone(), w[0]),
            None => fail!("Invalid compressed string")
         };

      result = vec::append(result, entry);
      dictionary.insert(dict_size, vec::append_one(w, entry[0]));
      dict_size += 1;
      w = entry;
   }

   str::from_utf8_owned(result).unwrap()
}

fn main() {
   let original = "TOBEORNOTTOBEORTOBEORNOT";

   let compressed = compress(original);
   println!("{:?}", compressed);

   let decompressed = decompress(compressed);
   println!("{:s}", decompressed);

   // Check if the decompressed string corresponds to the original string
   assert!(original == decompressed);
}
<commit_msg>LZW fix for #26<commit_after>// Implements http://rosettacode.org/wiki/LZW_compression

extern crate collections;

use collections::hashmap::HashMap;
use std::slice;
use std::str;

fn compress(original_str: &str) -> ~[int] {
   let original = original_str.as_bytes();
   let mut dict_size = 256;
   let mut dictionary = HashMap::new();

   for i in range(0, dict_size) {
      dictionary.insert(~[i as u8], i);
   }

   let mut result = ~[];
   let mut w:~[u8] = ~[];
   for &c in original.iter() {
      let mut wc = w.clone();
      wc.push(c);

      match dictionary.find(&wc) {
         Some(_) => w = wc,
         None => {
            result.push(*dictionary.get(&w));
            dictionary.insert(wc, dict_size);
            dict_size += 1;
            w = ~[c];
         }
      }
   }

   if w.len() > 0 {
      result.push(*dictionary.get(&w));
   }

   result
}

fn decompress(compressed: &[int]) -> ~str {
   let mut dict_size = 256;
   let mut dictionary = HashMap::new();

   for i in range(0, dict_size) {
      dictionary.insert(i, ~[i as u8]);
   }

   let mut w = ~[compressed[0] as u8];
   let compressed = compressed.slice(1, compressed.len());
   let mut result = w.clone();
   for &k in compressed.iter() {
      let entry =
         match dictionary.find(&k) {
            Some(v) => v.clone(),
            None if k == dict_size => slice::append_one(w.clone(), w[0]),
            None => fail!("Invalid compressed string")
         };

      result = slice::append(result, entry);
      dictionary.insert(dict_size, slice::append_one(w, entry[0]));
      dict_size += 1;
      w = entry;
   }

   str::from_utf8_owned(result).unwrap()
}

fn main() {
   let original = "TOBEORNOTTOBEORTOBEORNOT";

   let compressed = compress(original);
   println!("{:?}", compressed);

   let decompressed = decompress(compressed);
   println!("{:s}", decompressed);

   // Check if the decompressed string corresponds to the original string
   assert!(original == decompressed);
}
<|endoftext|>


<commit_before>#![allow(non_upper_case_globals)]

const cobalt_yml: &'static [u8] = b"name: cobalt blog
source: \".\"
dest: \"build\"
ignore:
  - ./.git/*
  - ./build/*
";

const default_liquid: &'static [u8] = b"<!DOCTYPE html>

        <meta charset=\"utf-8\">

        {% if is_post %}
          <title>{{ title }}</title>
        {% else %}
       	  <title>Cobalt.rs Blog</title>
        {% endif %}

      {% if is_post %}
        {% include '_layouts/post.liquid' %}
      {% else %}
        {{ content }}
      {% endif %}

";

const post_liquid: &'static [u8] = b"

{{ title }}

    {{content}}

";

const post_1_md: &'static [u8] = b"extends: default.liquid

title: First Post
date: 14 January 2016 21:00:30 -0500
---

# This is our first Post!

Welcome to the first post ever on cobalt.rs!
";

const index_liquid: &'static [u8] = b"extends: default.liquid
---

Blog!

    {% for post in posts %}

{{post.title}}

{{ post.title }}

    {% endfor %}

";

use std::path::Path;
use std::fs::{DirBuilder, OpenOptions};
use std::io::Write;
use error::Result;

pub fn create_new_project<P: AsRef<Path>>(dest: P) -> Result<()> {
    let dest = dest.as_ref();

    try!(create_folder(&dest));

    try!(create_file(&dest.join(".coblat.yml"), cobalt_yml));
    try!(create_file(&dest.join("index.liquid"), index_liquid));

    try!(create_folder(&dest.join("_layouts")));
    try!(create_file(&dest.join("_layouts/default.liquid"), default_liquid));
    try!(create_file(&dest.join("_layouts/post.liquid"), post_liquid));

    try!(create_folder(&dest.join("_posts")));
    try!(create_file(&dest.join("_posts/post-1.md"), post_1_md));

    Ok(())
}

fn create_folder<P: AsRef<Path>>(path: P) -> Result<()> {
    trace!("Creating folder {:?}", &path.as_ref());

    try!(DirBuilder::new()
                    .recursive(true)
                    .create(path));

    Ok(())
}

fn create_file<P: AsRef<Path>>(name: P, content: &[u8]) -> Result<()> {
    trace!("Creating file {:?}", &name.as_ref());

    let mut file = try!(OpenOptions::new()
                     .write(true)
                     .create(true)
                     .open(name));

    try!(file.write_all(content));

    Ok(())
}
<commit_msg>removed unused meta<commit_after>#![allow(non_upper_case_globals)]

const cobalt_yml: &'static [u8] = b"name: cobalt blog
source: \".\"
dest: \"build\"
ignore:
  - ./.git/*
  - ./build/*
";

const default_liquid: &'static [u8] = b"<!DOCTYPE html>

        {% if is_post %}
          <title>{{ title }}</title>
        {% else %}
       	  <title>Cobalt.rs Blog</title>
        {% endif %}

      {% if is_post %}
        {% include '_layouts/post.liquid' %}
      {% else %}
        {{ content }}
      {% endif %}

";

const post_liquid: &'static [u8] = b"

{{ title }}

    {{content}}

";

const post_1_md: &'static [u8] = b"extends: default.liquid

title: First Post
date: 14 January 2016 21:00:30 -0500
---

# This is our first Post!

Welcome to the first post ever on cobalt.rs!
";

const index_liquid: &'static [u8] = b"extends: default.liquid
---

Blog!

    {% for post in posts %}

{{post.title}}

{{ post.title }}

    {% endfor %}

";

use std::path::Path;
use std::fs::{DirBuilder, OpenOptions};
use std::io::Write;
use error::Result;

pub fn create_new_project<P: AsRef<Path>>(dest: P) -> Result<()> {
    let dest = dest.as_ref();

    try!(create_folder(&dest));

    try!(create_file(&dest.join(".coblat.yml"), cobalt_yml));
    try!(create_file(&dest.join("index.liquid"), index_liquid));

    try!(create_folder(&dest.join("_layouts")));
    try!(create_file(&dest.join("_layouts/default.liquid"), default_liquid));
    try!(create_file(&dest.join("_layouts/post.liquid"), post_liquid));

    try!(create_folder(&dest.join("_posts")));
    try!(create_file(&dest.join("_posts/post-1.md"), post_1_md));

    Ok(())
}

fn create_folder<P: AsRef<Path>>(path: P) -> Result<()> {
    trace!("Creating folder {:?}", &path.as_ref());

    try!(DirBuilder::new()
                    .recursive(true)
                    .create(path));

    Ok(())
}

fn create_file<P: AsRef<Path>>(name: P, content: &[u8]) -> Result<()> {
    trace!("Creating file {:?}", &name.as_ref());

    let mut file = try!(OpenOptions::new()
                     .write(true)
                     .create(true)
                     .open(name));

    try!(file.write_all(content));

    Ok(())
}
<|endoftext|>


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

use anyhow::Result;
use log::debug;

use crate::{
    analysis::dis,
    aspace::AddressSpace,
    module::{Module, Permissions},
    VA,
};
use lancelot_flirt::*;

/// make a best guess as to the reference target, found at `ref_offset` from
/// `va`.
fn get_ref(module: &Module, decoder: &zydis::Decoder, va: VA, ref_offset: u64) -> Option<VA> {
    for i in (1..=4u64).rev() {
        let candidate_insn_va = va + ref_offset - i;
        let mut insn_buf = [0u8; 16];

        if module.address_space.read_into(candidate_insn_va, &mut insn_buf).is_ok() {
            if let Ok(Some(insn)) = decoder.decode(&insn_buf) {
                let explicit_operands = insn
                    .operands
                    .iter()
                    .filter(|op| matches!(op.visibility, zydis::OperandVisibility::EXPLICIT));
                for (j, op) in explicit_operands.take(2).enumerate() {
                    match op.ty {
                        zydis::OperandType::MEMORY => {
                            if (op.mem.base == zydis::Register::NONE || op.mem.base == zydis::Register::RIP)
                                && op.mem.index == zydis::Register::NONE
                                && op.mem.scale == 0
                                && op.mem.disp.has_displacement
                                && insn.raw.disp_offset == i as u8
                            {
                                if let Ok(target) = insn.calc_absolute_address(candidate_insn_va, op) {
                                    if module.probe_va(target, Permissions::RX) {
                                        return Some(target);
                                    }
                                }
                            }
                            continue;
                        }
                        zydis::OperandType::IMMEDIATE => {
                            if insn.raw.imm[j].offset == i as u8 {
                                if let Ok(target) = insn.calc_absolute_address(candidate_insn_va, op) {
                                    if module.probe_va(target, Permissions::RX) {
                                        return Some(target);
                                    }
                                }
                            }
                            continue;
                        }
                        zydis::OperandType::POINTER => continue,
                        zydis::OperandType::REGISTER => continue,
                        zydis::OperandType::UNUSED => continue,
                    }
                }
            }
        }
    }

    None
}

pub fn match_flirt(module: &Module, sigs: &FlirtSignatureSet, va: VA) -> Result<Vec<FlirtSignature>> {
    fn match_flirt_inner(
        module: &Module,
        sigs: &FlirtSignatureSet,
        decoder: &zydis::Decoder,
        va: VA,
        cache: &mut BTreeMap<VA, Vec<FlirtSignature>>,
    ) -> Result<Vec<FlirtSignature>> {
        let sec = module
            .sections
            .iter()
            .find(|sec| sec.virtual_range.start <= va && va < sec.virtual_range.end)
            .unwrap();

        let size = sec.virtual_range.end - va;
        let buf = module.address_space.read_bytes(va, size as usize)?;

        debug!("flirt: matching: {:#x}", va);

        Ok(sigs
            .r#match(&buf)
            .iter()
            .filter(|sig| {
                let mut does_match_references = true;

                debug!("flirt: {:#x}: candidate: {:?}", va, sig);

                'names: for name in sig.names.iter() {
                    if let Symbol::Reference(Name {
                        offset,
                        name: wanted_name,
                    }) = name
                    {
                        // i dont know what this means.
                        assert!(*offset >= 0, "negative offset");

                        if let Some(target) = get_ref(module, &decoder, va, *offset as u64) {
                            if wanted_name == "." {
                                // special case: name "." matches anything
                                // not exactly sure, might instead match special data `ctype`.
                                // see: https://github.com/williballenthin/lancelot/issues/112#issuecomment-802379966

                                // TODO: get_ref only returns executable references.
                                continue;
                            }

                            // can't use entry API because of mutable cache used to create cache entry.
                            #[allow(clippy::map_entry)]
                            if !cache.contains_key(&target) {
                                let target_sigs = match_flirt_inner(module, sigs, decoder, target, cache)
                                    .unwrap_or_else(|_| Default::default());
                                cache.insert(target, target_sigs);
                            }

                            let target_sigs = cache.get(&target).unwrap();

                            let mut does_name_match = false;
                            'sigs: for target_sig in target_sigs.iter() {
                                debug!("flirt: {:#x}: found reference: {:?} @ {:#x}", va, target_sig, offset);
                                for name in target_sig.names.iter() {
                                    match name {
                                        Symbol::Reference(_) => continue,
                                        Symbol::Local(Name {
                                            name: target_name,
                                            offset,
                                        }) => {
                                            if *offset == 0 && target_name == wanted_name {
                                                does_name_match = true;
                                                break 'sigs;
                                            }
                                        }
                                        Symbol::Public(Name {
                                            name: target_name,
                                            offset,
                                        }) => {
                                            if *offset == 0 && target_name == wanted_name {
                                                does_name_match = true;
                                                break 'sigs;
                                            }
                                        }
                                    }
                                }
                            }

                            if !does_name_match {
                                does_match_references = false;
                                break 'names;
                            }
                        } else {
                            does_match_references = false;
                            break;
                        }
                    }
                }

                does_match_references
            })
            .cloned()
            .cloned()
            .collect::<Vec<_>>())
    }

    let decoder = dis::get_disassembler(module)?;
    let mut cache = Default::default();
    match_flirt_inner(module, sigs, &decoder, va, &mut cache)
}
<commit_msg>flirt: handle special function "."<commit_after>use std::collections::BTreeMap;

use anyhow::Result;
use log::debug;

use crate::{
    analysis::dis,
    aspace::AddressSpace,
    module::{Module, Permissions},
    VA,
};
use lancelot_flirt::*;

const EMPTY_CONTEXT: zydis::ffi::RegisterContext = zydis::ffi::RegisterContext { values: [0u64; 257] };

/// make a best guess for the reference target, found at `ref_offset` from `va`.
///
/// flirt uses references `(offset, name)` to describe that a function contains
/// a pointer to some known name (usually also matched by flirt).
/// the offset is relative to the start of the function, and may point in the
/// middle of an instruction!
/// (this is probably an artifact of extracting via relocations in lib files.)
///
/// its a problem because we don't know where the instruction,
/// so its hard to inspect operands for pointers.
/// we could either disassemble the entire function and find instruction ranges,
/// or scan backwards looking for potential instructions.
/// we do the latter here, as it works well in practice.
///
/// from the given address `ref_offset`, we disassemble backwards, up to -4
/// bytes. at each location, we inspect the operands. if it could be a pointer,
/// then we use metadata provided by zydis for the offset of the operand data.
/// (this is a great feature of zydis!)
/// the offset of the operand pointer data should match the number of bytes
/// we've disassembled backwards, that is, the pointer is found at the
/// reference address.
///
/// in practice, many references look like `call FOO` which is `E8 ?? ?? ?? ??`
/// and we recover the reference on the first try.
fn guess_reference_target(
    module: &Module,
    decoder: &zydis::Decoder,
    va: VA,
    ref_offset: u64,
    perms: Permissions,
) -> Option<VA> {
    // scan from -1 to -4 bytes backwards from the reference
    for i in (1..=4u64).rev() {
        let candidate_insn_va = va + ref_offset - i;
        let mut insn_buf = [0u8; 16];

        if module.address_space.read_into(candidate_insn_va, &mut insn_buf).is_ok() {
            if let Ok(Some(insn)) = decoder.decode(&insn_buf) {
                let explicit_operands = insn
                    .operands
                    .iter()
                    .filter(|op| matches!(op.visibility, zydis::OperandVisibility::EXPLICIT));

                // we assume the pointer will be found in the first two explicit operands,
                // which works well for x86.
                for (j, op) in explicit_operands.take(2).enumerate() {
                    match op.ty {
                        zydis::OperandType::MEMORY => {
                            if (op.mem.base == zydis::Register::NONE || op.mem.base == zydis::Register::RIP)
                                && op.mem.disp.has_displacement
                                && insn.raw.disp_offset == i as u8
                            {
                                if let Ok(target) = insn.calc_absolute_address_ex(candidate_insn_va, op, &EMPTY_CONTEXT)
                                {
                                    if module.probe_va(target, perms) {
                                        return Some(target);
                                    }
                                }
                            }
                            continue;
                        }
                        zydis::OperandType::IMMEDIATE => {
                            if insn.raw.imm[j].offset == i as u8 {
                                if let Ok(target) = insn.calc_absolute_address(candidate_insn_va, op) {
                                    if module.probe_va(target, perms) {
                                        return Some(target);
                                    }
                                }
                            }
                            continue;
                        }
                        zydis::OperandType::POINTER => continue,
                        zydis::OperandType::REGISTER => continue,
                        zydis::OperandType::UNUSED => continue,
                    }
                }
            }
        }
    }

    None
}

/// match the given flirt signatures at the given address.
/// returns a list of the signatures that match.
pub fn match_flirt(module: &Module, sigs: &FlirtSignatureSet, va: VA) -> Result<Vec<FlirtSignature>> {
    fn match_flirt_inner(
        module: &Module,
        sigs: &FlirtSignatureSet,
        decoder: &zydis::Decoder,
        va: VA,
        cache: &mut BTreeMap<VA, Vec<FlirtSignature>>,
    ) -> Result<Vec<FlirtSignature>> {
        let sec = module
            .sections
            .iter()
            .find(|sec| sec.virtual_range.start <= va && va < sec.virtual_range.end)
            .unwrap();

        let size = sec.virtual_range.end - va;
        let buf = module.address_space.read_bytes(va, size as usize)?;

        debug!("flirt: matching: {:#x}", va);

        Ok(sigs
            .r#match(&buf)
            .iter()
            .filter(|sig| {
                let mut does_match_references = true;

                debug!("flirt: {:#x}: candidate: {:?}", va, sig);

                'names: for name in sig.names.iter() {
                    if let Symbol::Reference(Name {
                        offset,
                        name: wanted_name,
                    }) = name
                    {
                        // i dont know what this means.
                        assert!(*offset >= 0, "negative offset");

                        if wanted_name == "." {
                            // special case: name "." matches any data?
                            // not exactly sure if this should only match special data `ctype`?
                            // see: https://github.com/williballenthin/lancelot/issues/112#issuecomment-802379966
                            if let Some(_) =
                                guess_reference_target(module, &decoder, va, *offset as u64, Permissions::R)
                            {
                                continue;
                            } else {
                                does_match_references = false;
                                break;
                            }
                        }

                        // guess the reference target, then match flirt signatures there,
                        // and see if the wanted name matches a name recovered by flirt.
                        //
                        // we use the cache to record whether a negative match was encountered.
                        // this drastically when we have many nested references (like CALL wrappers).
                        // see: https://github.com/fireeye/capa/issues/448
                        if let Some(target) =
                            guess_reference_target(module, &decoder, va, *offset as u64, Permissions::X)
                        {
                            // this is just:
                            //   target_sigs = cached(match_flirt_inner(...target...))
                            //
                            // can't use entry API because of mutable cache used to create cache entry.
                            #[allow(clippy::map_entry)]
                            if !cache.contains_key(&target) {
                                let target_sigs = match_flirt_inner(module, sigs, decoder, target, cache)
                                    .unwrap_or_else(|_| Default::default());
                                cache.insert(target, target_sigs);
                            }
                            let target_sigs = cache.get(&target).unwrap();

                            let mut does_name_match = false;
                            'sigs: for target_sig in target_sigs.iter() {
                                debug!("flirt: {:#x}: found reference: {:?} @ {:#x}", va, target_sig, offset);
                                for name in target_sig.names.iter() {
                                    match name {
                                        Symbol::Reference(_) => continue,
                                        Symbol::Local(Name {
                                            name: target_name,
                                            offset,
                                        })
                                        | Symbol::Public(Name {
                                            name: target_name,
                                            offset,
                                        }) => {
                                            if *offset == 0 && target_name == wanted_name {
                                                does_name_match = true;
                                                break 'sigs;
                                            }
                                        }
                                    }
                                }
                            }

                            if !does_name_match {
                                does_match_references = false;
                                break 'names;
                            }
                        } else {
                            does_match_references = false;
                            break;
                        }
                    }
                }

                does_match_references
            })
            .cloned()
            .cloned()
            .collect::<Vec<_>>())
    }

    let decoder = dis::get_disassembler(module)?;
    let mut cache = Default::default();
    match_flirt_inner(module, sigs, &decoder, va, &mut cache)
}
<|endoftext|>


<commit_before>//! The functions in this section provide optimized copying to persistent memory
//!
//! The `copy`, `copy_nonoverlapping`, and `write_bytes`, provide the same memory copying as
//! `memmove(3)`, `memcpy(3)`, and `memset(3)`, and ensure that the result has been flushed to persistence before returning.
//!
//! > **Warning:** Using these functions where `is_pmem(1)` returns false may not do anything useful.
//! >              Use the normal libc functions in that case.

use ::std::mem;
use ::std::io;
use ::std::marker::PhantomData;

use ::libc::{c_void, c_int};
use ::libc::size_t;
use ::pmem_sys as ffi;

use pmap::PersistentMap;

/// Persistent memory virtual pointer
///
/// This pointer is safe to store.
#[derive(Copy, Clone)]
pub struct PmemConstVirtualPtr<T: ?Sized> {
    poolid: usize,
    offset: usize,
    _t: PhantomData<T>,
}

impl<T: ?Sized> PmemConstVirtualPtr<T> {
    pub unsafe fn new(poolid: usize, offset: usize) -> Self {
        assert!(poolid != 0, "Poolid 0 is reserved for null pointers");
        PmemConstVirtualPtr { poolid: poolid, offset: offset, _t: PhantomData }
    }

    pub fn null() -> Self { PmemConstVirtualPtr { poolid: 0, offset: 0, _t: PhantomData } }

    pub fn is_null(&self) -> bool { self.poolid == 0 }

    pub unsafe fn as_type<U>(&self) -> PmemConstVirtualPtr<U> {
        PmemConstVirtualPtr { poolid: self.poolid, offset: self.offset, _t: PhantomData }
    }

    pub unsafe fn as_mut(&self) -> PmemMutVirtualPtr<T> {
        PmemMutVirtualPtr { poolid: self.poolid, offset: self.offset, _t: PhantomData }
    }
}

impl<T> PmemConstVirtualPtr<T> {
    pub unsafe fn offset(&self, count: isize) -> Self {
        if self.is_null() {
            PmemConstVirtualPtr::null()
        } else {
            let new_offset = self.offset as isize + mem::size_of::<T>() as isize * count;
            PmemConstVirtualPtr { poolid: self.poolid, offset: new_offset as usize, _t: self._t }
        }
    }

    pub unsafe fn link(&self, pool: &PersistentMap) -> PmemConstPtr<T> {
        let new_virt = PmemConstVirtualPtr { poolid: self.poolid, offset: self.offset, _t: self._t };
        PmemConstPtr { virt: new_virt, pool: pool.as_ptr() }
    }
}

impl<T> ::std::fmt::Pointer for PmemConstVirtualPtr<T> {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        write!(f, "{:#x}:{:#x}",self.poolid, self.offset)
    }
}

impl<T> ::std::fmt::Debug for PmemConstVirtualPtr<T> {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        if self.is_null() {
            write!(f, "PmemVirt *const NULL")
        } else {
            write!(f, "PmemVirt *const {{ pool: {:#x}, offset: {:#x} }}", self.poolid, self.offset)
        }
    }
}

/// Persistent memory virtual mutable pointer
///
/// This pointer is safe to store.
#[derive(Copy, Clone)]
pub struct PmemMutVirtualPtr<T: ?Sized> {
    poolid: usize,
    offset: usize,
    _t: PhantomData<T>,
}

impl<T: ?Sized> PmemMutVirtualPtr<T> {
    pub unsafe fn new(poolid: usize, offset: usize) -> Self {
        assert!(poolid != 0, "Poolid 0 is reserved for null pointers");
        PmemMutVirtualPtr { poolid: poolid, offset: offset, _t: PhantomData }
    }

    pub fn null() -> Self { PmemMutVirtualPtr { poolid: 0, offset: 0, _t: PhantomData } }

    pub fn is_null(&self) -> bool { self.poolid == 0 }

    pub unsafe fn as_type<U>(&self) -> PmemMutVirtualPtr<U> {
        PmemMutVirtualPtr { poolid: self.poolid, offset: self.offset, _t: PhantomData }
    }

    pub unsafe fn as_const(&self) -> PmemConstVirtualPtr<T> {
        PmemConstVirtualPtr { poolid: self.poolid, offset: self.offset, _t: PhantomData }
    }
}

impl<T> ::std::fmt::Pointer for PmemMutVirtualPtr<T> {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        write!(f, "{:#x}:{:#x}",self.poolid, self.offset)
    }
}

impl<T> ::std::fmt::Debug for PmemMutVirtualPtr<T> {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        if self.is_null() {
            write!(f, "PmemVirt *mut NULL")
        } else {
            write!(f, "PmemVirt *mut {{ pool: {:#x}, offset: {:#x} }}", self.poolid, self.offset)
        }
    }
}

impl<T> PmemMutVirtualPtr<T> {
    pub unsafe fn offset(&self, count: isize) -> Self {
        if self.is_null() {
            PmemMutVirtualPtr::null()
        } else {
            let new_offset = self.offset as isize + mem::size_of::<T>() as isize * count;
            PmemMutVirtualPtr { poolid: self.poolid, offset: new_offset as usize, _t: self._t }
        }
    }

    pub unsafe fn link(&self, pool: &mut PersistentMap) -> PmemMutPtr<T> {
        let new_virt = PmemMutVirtualPtr { poolid: self.poolid, offset: self.offset, _t: self._t };
        PmemMutPtr { virt: new_virt, pool: pool.as_mut_ptr() }
    }
}

/// Direct `*const T` pointer to a pmem location
///
/// # Safety
///
/// This pointer is **not** safe to store directly on pmem.
/// You can get a _safe_ virtual pointer using `as_virtual()`.
#[derive(Copy, Clone)]
pub struct PmemConstPtr<T: ?Sized> {
    virt: PmemConstVirtualPtr<T>,
    pool: *const T,
}

impl<T: ?Sized> PmemConstPtr<T> {
    pub fn is_null(&self) -> bool { self.virt.is_null() }

    pub unsafe fn as_mut(&self) -> PmemMutPtr<T> {
        PmemMutPtr { virt: self.virt.as_mut(), pool: self.pool as *mut T }
    }
}

impl<T> PmemConstPtr<T> {
    pub unsafe fn direct(&self) -> *const T {
        if self.is_null() {
            ::std::ptr::null()
        } else {
            self.pool.offset(self.virt.offset as isize) as *const T
        }
    }

    pub fn as_virtual(self) -> PmemConstVirtualPtr<T> {
        self.virt
    }

    pub unsafe fn offset(&self, count: isize) -> Self {
        let new_virt = self.virt.offset(count);
        PmemConstPtr { virt: new_virt, pool: self.pool }
    }

    pub unsafe fn as_type<U>(&self) -> PmemConstPtr<U> {
        let new_virt = self.virt.as_type();
        PmemConstPtr { virt: new_virt, pool: self.pool as *mut U }
    }
}

impl<T> ::std::fmt::Pointer for PmemConstPtr<T> {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        write!(f, "{:p} -> {:p}",self.virt, unsafe { self.direct() })
    }
}

impl<T> ::std::fmt::Debug for PmemConstPtr<T> {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        if self.is_null() {
            write!(f, "Pmem *const NULL")
        } else {
            write!(f, "Pmem *const {{ pool: {:#x}, offset: {:#x} }}", self.virt.poolid, self.virt.offset)
        }
    }
}

/// Direct `*mut T` pointer to a pmem location
///
/// # Safety
///
/// This pointer is **not** safe to store directly on pmem.
/// You can get a _safe_ virtual pointer using `as_virtual()`.
#[derive(Copy, Clone)]
pub struct PmemMutPtr<T: ?Sized> {
    virt: PmemMutVirtualPtr<T>,
    pool: *mut T,
}

impl<T: ?Sized> PmemMutPtr<T> {
    pub fn is_null(&self) -> bool { self.virt.is_null() }

    pub unsafe fn as_const(&self) -> PmemConstPtr<T> {
        PmemConstPtr { virt: self.virt.as_const(), pool: self.pool as *const T }
    }
}

impl<T> PmemMutPtr<T> {
    pub unsafe fn direct(&self) -> *mut T {
        if self.is_null() {
            ::std::ptr::null_mut()
        } else {
            self.pool.offset(self.virt.offset as isize) as *mut T
        }
    }

    pub fn as_virtual(self) -> PmemMutVirtualPtr<T> {
        self.virt
    }

    pub unsafe fn offset(&self, count: isize) -> Self {
        let new_virt = self.virt.offset(count);
        PmemMutPtr { virt: new_virt, pool: self.pool }
    }

    pub unsafe fn as_type<U>(&self) -> PmemMutPtr<U> {
        let new_virt = self.virt.as_type();
        PmemMutPtr { virt: new_virt, pool: self.pool as *mut U }
    }
}

impl<T> ::std::fmt::Pointer for PmemMutPtr<T> {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        write!(f, "{:p} -> {:p}",self.virt, unsafe { self.direct() })
    }
}

impl<T> ::std::fmt::Debug for PmemMutPtr<T> {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        if self.is_null() {
            write!(f, "Pmem *mut NULL")
        } else {
            write!(f, "Pmem *mut {{ pool: {:#x}, offset: {:#x} }}", self.virt.poolid, self.virt.offset)
        }
    }
}

pub fn null<T>() -> PmemConstVirtualPtr<T> {
    PmemConstVirtualPtr::null()
}

pub fn null_mut<T>() -> PmemMutVirtualPtr<T> {
    PmemMutVirtualPtr::null()
}

/// Copies `count * size_of<T>` bytes from `src` to `pmemdest`. The source and destination may overlap.
///
/// `copy` is semantically equivalent to C's `memmove` and is optimized for persitent memory.
///
/// Ensures that the result has been flushed to persistence before returning.
///
/// # Safety
///
/// Care must be taken with the ownership of `src` and `pmemdest`.
/// This method semantically moves the values of `src` into `pmemdest`.
/// However it does not drop the contents of `pmemdest`, or prevent the contents of `src` from being dropped or used.
pub unsafe fn copy<T>(src: *const T, pmemdest: *mut T, count: usize) {
    let len = mem::size_of::<T>() * count;
    ffi::pmem_memmove_persist(pmemdest as *mut c_void, src as *const c_void, len as size_t);
}

/// Copies `count * size_of<T>` bytes from `src` to `pmemdest`. The source and destination may _not_ overlap.
///
/// `copy_nonoverlapping` is semantically equivalent to C's `memcpy` and is optimized for persitent memory.
///
/// Ensures that the result has been flushed to persistence before returning.
///
/// # Safety
///
/// Beyond requiring that the program must be allowed to access both regions of memory,
/// it is _Undefined Behavior_ for source and destination to overlap.
/// Care must also be taken with the ownership of `src` and `pmemdest`.
/// This method semantically moves the values of `src` into `pmemdest`.
/// However it does not drop the contents of `pmemdest`, or prevent the contents of `src` from being dropped or used.
pub unsafe fn copy_nonoverlapping<T>(src: *const T, pmemdest: *mut T, count: usize) {
    let len = mem::size_of::<T>() * count;
    ffi::pmem_memcpy_persist(pmemdest as *mut c_void, src as *const c_void, len as size_t);
}

/// Invokes memset on the specified pointer, setting `count * size_of::<T>()` bytes of memory starting at `pmemdest` to `val`.
///
/// Ensures that the result has been flushed to persistence before returning.
pub unsafe fn write_bytes<T>(pmemdest: *mut T, val: u8, count: usize) {
    let len = mem::size_of::<T>() * count;
    ffi::pmem_memset_persist(pmemdest as *mut c_void, val as c_int, len as size_t);
}

/// Overwrites a memory location with the given value without reading or dropping the old value.
///
/// Ensures that the result has been flushed to persistence before returning.
///
/// # Safety
///
/// This operation is marked unsafe because it accepts a raw pointer.
///
/// It does not drop the contents of dst. This is safe, but it could leak allocations or resources,
/// so care must be taken not to overwrite an object that should be dropped.
///
/// This is appropriate for initializing uninitialized memory, or overwriting memory that has previously been read from.
pub unsafe fn write<T>(pmemdest: *mut T, val: T) { copy_nonoverlapping(&val as *const _, pmemdest, 1) }

pub unsafe fn msync<T>(pmemdest: *const T, count: usize) -> Result<(), io::Error> {
    let len = count * mem::size_of::<T>();
    let r = ffi::pmem_msync(pmemdest as *const c_void, len as size_t);
    if r == -1 {
        Err(io::Error::last_os_error())
    } else {
        Ok(())
    }
}
<commit_msg>fix: xxx<commit_after>//! The functions in this section provide optimized copying to persistent memory
//!
//! The `copy`, `copy_nonoverlapping`, and `write_bytes`, provide the same memory copying as
//! `memmove(3)`, `memcpy(3)`, and `memset(3)`, and ensure that the result has been flushed to persistence before returning.
//!
//! > **Warning:** Using these functions where `is_pmem(1)` returns false may not do anything useful.
//! >              Use the normal libc functions in that case.

use ::std::mem;
use ::std::io;
use ::std::marker::PhantomData;

use ::libc::{c_void, c_int};
use ::libc::size_t;
use ::pmem_sys as ffi;

use pmap::PersistentMap;

/// Persistent memory virtual pointer
///
/// This pointer is safe to store.
#[derive(Copy, Clone)]
pub struct PmemConstVirtualPtr<T: ?Sized> {
    poolid: usize,
    /// Offset in bytes
    offset: usize,
    _t: PhantomData<T>,
}

impl<T: ?Sized> PmemConstVirtualPtr<T> {
    pub unsafe fn new(poolid: usize, offset: usize) -> Self {
        assert!(poolid != 0, "Poolid 0 is reserved for null pointers");
        PmemConstVirtualPtr { poolid: poolid, offset: offset, _t: PhantomData }
    }

    pub fn null() -> Self { PmemConstVirtualPtr { poolid: 0, offset: 0, _t: PhantomData } }

    pub fn is_null(&self) -> bool { self.poolid == 0 }

    pub unsafe fn as_type<U>(&self) -> PmemConstVirtualPtr<U> {
        PmemConstVirtualPtr { poolid: self.poolid, offset: self.offset, _t: PhantomData }
    }

    pub unsafe fn as_mut(&self) -> PmemMutVirtualPtr<T> {
        PmemMutVirtualPtr { poolid: self.poolid, offset: self.offset, _t: PhantomData }
    }
}

impl<T> PmemConstVirtualPtr<T> {
    pub unsafe fn offset(&self, count: isize) -> Self {
        if self.is_null() {
            PmemConstVirtualPtr::null()
        } else {
            let new_offset = self.offset as isize + mem::size_of::<T>() as isize * count;
            PmemConstVirtualPtr { poolid: self.poolid, offset: new_offset as usize, _t: self._t }
        }
    }

    pub unsafe fn link(&self, pool: &PersistentMap) -> PmemConstPtr<T> {
        let new_virt = PmemConstVirtualPtr { poolid: self.poolid, offset: self.offset, _t: self._t };
        PmemConstPtr { virt: new_virt, pool: pool.as_ptr() }
    }
}

impl<T> ::std::fmt::Pointer for PmemConstVirtualPtr<T> {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        write!(f, "{:#x}:{:#x}",self.poolid, self.offset)
    }
}

impl<T> ::std::fmt::Debug for PmemConstVirtualPtr<T> {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        if self.is_null() {
            write!(f, "PmemVirt *const NULL")
        } else {
            write!(f, "PmemVirt *const {{ pool: {:#x}, offset: {:#x} }}", self.poolid, self.offset)
        }
    }
}

/// Persistent memory virtual mutable pointer
///
/// This pointer is safe to store.
#[derive(Copy, Clone)]
pub struct PmemMutVirtualPtr<T: ?Sized> {
    poolid: usize,
    /// Offset in bytes
    offset: usize,
    _t: PhantomData<T>,
}

impl<T: ?Sized> PmemMutVirtualPtr<T> {
    pub unsafe fn new(poolid: usize, offset: usize) -> Self {
        assert!(poolid != 0, "Poolid 0 is reserved for null pointers");
        PmemMutVirtualPtr { poolid: poolid, offset: offset, _t: PhantomData }
    }

    pub fn null() -> Self { PmemMutVirtualPtr { poolid: 0, offset: 0, _t: PhantomData } }

    pub fn is_null(&self) -> bool { self.poolid == 0 }

    pub unsafe fn as_type<U>(&self) -> PmemMutVirtualPtr<U> {
        PmemMutVirtualPtr { poolid: self.poolid, offset: self.offset, _t: PhantomData }
    }

    pub unsafe fn as_const(&self) -> PmemConstVirtualPtr<T> {
        PmemConstVirtualPtr { poolid: self.poolid, offset: self.offset, _t: PhantomData }
    }
}

impl<T> ::std::fmt::Pointer for PmemMutVirtualPtr<T> {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        write!(f, "{:#x}:{:#x}",self.poolid, self.offset)
    }
}

impl<T> ::std::fmt::Debug for PmemMutVirtualPtr<T> {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        if self.is_null() {
            write!(f, "PmemVirt *mut NULL")
        } else {
            write!(f, "PmemVirt *mut {{ pool: {:#x}, offset: {:#x} }}", self.poolid, self.offset)
        }
    }
}

impl<T> PmemMutVirtualPtr<T> {
    pub unsafe fn offset(&self, count: isize) -> Self {
        if self.is_null() {
            PmemMutVirtualPtr::null()
        } else {
            let new_offset = self.offset as isize + mem::size_of::<T>() as isize * count;
            PmemMutVirtualPtr { poolid: self.poolid, offset: new_offset as usize, _t: self._t }
        }
    }

    pub unsafe fn link(&self, pool: &mut PersistentMap) -> PmemMutPtr<T> {
        let new_virt = PmemMutVirtualPtr { poolid: self.poolid, offset: self.offset, _t: self._t };
        PmemMutPtr { virt: new_virt, pool: pool.as_mut_ptr() }
    }
}

/// Direct `*const T` pointer to a pmem location
///
/// # Safety
///
/// This pointer is **not** safe to store directly on pmem.
/// You can get a _safe_ virtual pointer using `as_virtual()`.
#[derive(Copy, Clone)]
pub struct PmemConstPtr<T: ?Sized> {
    virt: PmemConstVirtualPtr<T>,
    pool: *const T,
}

impl<T: ?Sized> PmemConstPtr<T> {
    pub fn is_null(&self) -> bool { self.virt.is_null() }

    pub unsafe fn as_mut(&self) -> PmemMutPtr<T> {
        PmemMutPtr { virt: self.virt.as_mut(), pool: self.pool as *mut T }
    }
}

impl<T> PmemConstPtr<T> {
    pub unsafe fn direct(&self) -> *const T {
        if self.is_null() {
            ::std::ptr::null()
        } else {
            (self.pool as *const u8).offset(self.virt.offset as isize) as *const T
        }
    }

    pub fn as_virtual(self) -> PmemConstVirtualPtr<T> {
        self.virt
    }

    pub unsafe fn offset(&self, count: isize) -> Self {
        let new_virt = self.virt.offset(count);
        PmemConstPtr { virt: new_virt, pool: self.pool }
    }

    pub unsafe fn as_type<U>(&self) -> PmemConstPtr<U> {
        let new_virt = self.virt.as_type();
        PmemConstPtr { virt: new_virt, pool: self.pool as *mut U }
    }
}

impl<T> ::std::fmt::Pointer for PmemConstPtr<T> {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        write!(f, "{:p} -> {:p}",self.virt, unsafe { self.direct() })
    }
}

impl<T> ::std::fmt::Debug for PmemConstPtr<T> {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        if self.is_null() {
            write!(f, "Pmem *const NULL")
        } else {
            write!(f, "Pmem *const {{ pool: {:#x}, offset: {:#x} }}", self.virt.poolid, self.virt.offset)
        }
    }
}

/// Direct `*mut T` pointer to a pmem location
///
/// # Safety
///
/// This pointer is **not** safe to store directly on pmem.
/// You can get a _safe_ virtual pointer using `as_virtual()`.
#[derive(Copy, Clone)]
pub struct PmemMutPtr<T: ?Sized> {
    virt: PmemMutVirtualPtr<T>,
    pool: *mut T,
}

impl<T: ?Sized> PmemMutPtr<T> {
    pub fn is_null(&self) -> bool { self.virt.is_null() }

    pub unsafe fn as_const(&self) -> PmemConstPtr<T> {
        PmemConstPtr { virt: self.virt.as_const(), pool: self.pool as *const T }
    }
}

impl<T> PmemMutPtr<T> {
    pub unsafe fn direct(&self) -> *mut T {
        if self.is_null() {
            ::std::ptr::null_mut()
        } else {
            (self.pool as *mut u8).offset(self.virt.offset as isize) as *mut T
        }
    }

    pub fn as_virtual(self) -> PmemMutVirtualPtr<T> {
        self.virt
    }

    pub unsafe fn offset(&self, count: isize) -> Self {
        let new_virt = self.virt.offset(count);
        PmemMutPtr { virt: new_virt, pool: self.pool }
    }

    pub unsafe fn as_type<U>(&self) -> PmemMutPtr<U> {
        let new_virt = self.virt.as_type();
        PmemMutPtr { virt: new_virt, pool: self.pool as *mut U }
    }
}

impl<T> ::std::fmt::Pointer for PmemMutPtr<T> {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        write!(f, "{:p} -> {:p}",self.virt, unsafe { self.direct() })
    }
}

impl<T> ::std::fmt::Debug for PmemMutPtr<T> {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        if self.is_null() {
            write!(f, "Pmem *mut NULL")
        } else {
            write!(f, "Pmem *mut {{ pool: {:#x}, offset: {:#x} }}", self.virt.poolid, self.virt.offset)
        }
    }
}

pub fn null<T>() -> PmemConstVirtualPtr<T> {
    PmemConstVirtualPtr::null()
}

pub fn null_mut<T>() -> PmemMutVirtualPtr<T> {
    PmemMutVirtualPtr::null()
}

/// Copies `count * size_of<T>` bytes from `src` to `pmemdest`. The source and destination may overlap.
///
/// `copy` is semantically equivalent to C's `memmove` and is optimized for persitent memory.
///
/// Ensures that the result has been flushed to persistence before returning.
///
/// # Safety
///
/// Care must be taken with the ownership of `src` and `pmemdest`.
/// This method semantically moves the values of `src` into `pmemdest`.
/// However it does not drop the contents of `pmemdest`, or prevent the contents of `src` from being dropped or used.
pub unsafe fn copy<T>(src: *const T, pmemdest: *mut T, count: usize) {
    let len = mem::size_of::<T>() * count;
    ffi::pmem_memmove_persist(pmemdest as *mut c_void, src as *const c_void, len as size_t);
}

/// Copies `count * size_of<T>` bytes from `src` to `pmemdest`. The source and destination may _not_ overlap.
///
/// `copy_nonoverlapping` is semantically equivalent to C's `memcpy` and is optimized for persitent memory.
///
/// Ensures that the result has been flushed to persistence before returning.
///
/// # Safety
///
/// Beyond requiring that the program must be allowed to access both regions of memory,
/// it is _Undefined Behavior_ for source and destination to overlap.
/// Care must also be taken with the ownership of `src` and `pmemdest`.
/// This method semantically moves the values of `src` into `pmemdest`.
/// However it does not drop the contents of `pmemdest`, or prevent the contents of `src` from being dropped or used.
pub unsafe fn copy_nonoverlapping<T>(src: *const T, pmemdest: *mut T, count: usize) {
    let len = mem::size_of::<T>() * count;
    ffi::pmem_memcpy_persist(pmemdest as *mut c_void, src as *const c_void, len as size_t);
}

/// Invokes memset on the specified pointer, setting `count * size_of::<T>()` bytes of memory starting at `pmemdest` to `val`.
///
/// Ensures that the result has been flushed to persistence before returning.
pub unsafe fn write_bytes<T>(pmemdest: *mut T, val: u8, count: usize) {
    let len = mem::size_of::<T>() * count;
    ffi::pmem_memset_persist(pmemdest as *mut c_void, val as c_int, len as size_t);
}

/// Overwrites a memory location with the given value without reading or dropping the old value.
///
/// Ensures that the result has been flushed to persistence before returning.
///
/// # Safety
///
/// This operation is marked unsafe because it accepts a raw pointer.
///
/// It does not drop the contents of dst. This is safe, but it could leak allocations or resources,
/// so care must be taken not to overwrite an object that should be dropped.
///
/// This is appropriate for initializing uninitialized memory, or overwriting memory that has previously been read from.
pub unsafe fn write<T>(pmemdest: *mut T, val: T) { copy_nonoverlapping(&val as *const _, pmemdest, 1) }

pub unsafe fn msync<T>(pmemdest: *const T, count: usize) -> Result<(), io::Error> {
    let len = count * mem::size_of::<T>();
    let r = ffi::pmem_msync(pmemdest as *const c_void, len as size_t);
    if r == -1 {
        Err(io::Error::last_os_error())
    } else {
        Ok(())
    }
}
<|endoftext|>


<commit_before>use core::ops::Mul;
use core::num::Wrapping;
use {One, CheckedMul};

/// Binary operator for raising a value to a power.
pub trait Pow<RHS> {
    /// The result after applying the operator.
    type Output;

    /// Returns `self` to the power `rhs`.
    ///
    /// # Examples
    ///
    /// ```
    /// use num_traits::Pow;
    /// assert_eq!(Pow::pow(10u32, 2u32), 100);
    /// ```
    fn pow(self, rhs: RHS) -> Self::Output;
}

macro_rules! pow_impl {
    ($t:ty) => {
        pow_impl!($t, u8);
        pow_impl!($t, usize);

        // FIXME: these should be possible
        // pow_impl!($t, u16);
        // pow_impl!($t, u32);
        // pow_impl!($t, u64);
    };
    ($t:ty, $rhs:ty) => {
        pow_impl!($t, $rhs, usize, pow);
    };
    ($t:ty, $rhs:ty, $desired_rhs:ty, $method:expr) => {
        impl Pow<$rhs> for $t {
            type Output = $t;
            #[inline]
            fn pow(self, rhs: $rhs) -> $t {
                ($method)(self, <$desired_rhs>::from(rhs))
            }
        }

        impl<'a> Pow<&'a $rhs> for $t {
            type Output = $t;
            #[inline]
            fn pow(self, rhs: &'a $rhs) -> $t {
                ($method)(self, <$desired_rhs>::from(*rhs))
            }
        }

        impl<'a> Pow<$rhs> for &'a $t {
            type Output = $t;
            #[inline]
            fn pow(self, rhs: $rhs) -> $t {
                ($method)(*self, <$desired_rhs>::from(rhs))
            }
        }

        impl<'a, 'b> Pow<&'a $rhs> for &'b $t {
            type Output = $t;
            #[inline]
            fn pow(self, rhs: &'a $rhs) -> $t {
                ($method)(*self, <$desired_rhs>::from(*rhs))
            }
        }
    };
}

pow_impl!(u8, u8, u32, u8::pow);
pow_impl!(u8, u16, u32, u8::pow);
pow_impl!(u8, u32, u32, u8::pow);
pow_impl!(u8, usize);
pow_impl!(i8, u8, u32, i8::pow);
pow_impl!(i8, u16, u32, i8::pow);
pow_impl!(i8, u32, u32, i8::pow);
pow_impl!(i8, usize);
pow_impl!(u16, u8, u32, u16::pow);
pow_impl!(u16, u16, u32, u16::pow);
pow_impl!(u16, u32, u32, u16::pow);
pow_impl!(u16, usize);
pow_impl!(i16, u8, u32, i16::pow);
pow_impl!(i16, u16, u32, i16::pow);
pow_impl!(i16, u32, u32, i16::pow);
pow_impl!(i16, usize);
pow_impl!(u32, u8, u32, u32::pow);
pow_impl!(u32, u16, u32, u32::pow);
pow_impl!(u32, u32, u32, u32::pow);
pow_impl!(u32, usize);
pow_impl!(i32, u8, u32, i32::pow);
pow_impl!(i32, u16, u32, i32::pow);
pow_impl!(i32, u32, u32, i32::pow);
pow_impl!(i32, usize);
pow_impl!(u64, u8, u32, u64::pow);
pow_impl!(u64, u16, u32, u64::pow);
pow_impl!(u64, u32, u32, u64::pow);
pow_impl!(u64, usize);
pow_impl!(i64, u8, u32, i64::pow);
pow_impl!(i64, u16, u32, i64::pow);
pow_impl!(i64, u32, u32, i64::pow);
pow_impl!(i64, usize);

#[cfg(feature = "i128")]
pow_impl!(u128, u8, u32, u128::pow);
#[cfg(feature = "i128")]
pow_impl!(u128, u16, u32, u128::pow);
#[cfg(feature = "i128")]
pow_impl!(u128, u32, u32, u128::pow);
#[cfg(feature = "i128")]
pow_impl!(u128, u64, u64, u128::pow);
#[cfg(feature = "i128")]
pow_impl!(u128, usize);

#[cfg(feature = "i128")]
pow_impl!(i128, u8, u32, i128::pow);
#[cfg(feature = "i128")]
pow_impl!(i128, u16, u32, i128::pow);
#[cfg(feature = "i128")]
pow_impl!(i128, u32, u32, i128::pow);
#[cfg(feature = "i128")]
pow_impl!(i128, u64, u64, i128::pow);
#[cfg(feature = "i128")]
pow_impl!(i128, usize);

pow_impl!(usize, u8, u32, usize::pow);
pow_impl!(usize, u16, u32, usize::pow);
pow_impl!(usize, u32, u32, usize::pow);
pow_impl!(usize, usize);
pow_impl!(isize, u8, u32, isize::pow);
pow_impl!(isize, u16, u32, isize::pow);
pow_impl!(isize, u32, u32, isize::pow);
pow_impl!(isize, usize);
pow_impl!(Wrapping<u8>);
pow_impl!(Wrapping<i8>);
pow_impl!(Wrapping<u16>);
pow_impl!(Wrapping<i16>);
pow_impl!(Wrapping<u32>);
pow_impl!(Wrapping<i32>);
pow_impl!(Wrapping<u64>);
pow_impl!(Wrapping<i64>);
#[cfg(feature = "i128")]
pow_impl!(Wrapping<u128>);
#[cfg(feature = "i128")]
pow_impl!(Wrapping<i128>);
pow_impl!(Wrapping<usize>);
pow_impl!(Wrapping<isize>);

// FIXME: these should be possible
// pow_impl!(u8, u64);
// pow_impl!(i16, u64);
// pow_impl!(i8, u64);
// pow_impl!(u16, u64);
// pow_impl!(u32, u64);
// pow_impl!(i32, u64);
// pow_impl!(u64, u64);
// pow_impl!(i64, u64);
// pow_impl!(usize, u64);
// pow_impl!(isize, u64);

#[cfg(feature = "std")]
mod float_impls {
    use super::Pow;

    pow_impl!(f32, i8, i32, f32::powi);
    pow_impl!(f32, u8, i32, f32::powi);
    pow_impl!(f32, i16, i32, f32::powi);
    pow_impl!(f32, u16, i32, f32::powi);
    pow_impl!(f32, i32, i32, f32::powi);
    pow_impl!(f64, i8, i32, f64::powi);
    pow_impl!(f64, u8, i32, f64::powi);
    pow_impl!(f64, i16, i32, f64::powi);
    pow_impl!(f64, u16, i32, f64::powi);
    pow_impl!(f64, i32, i32, f64::powi);
    pow_impl!(f32, f32, f32, f32::powf);
    pow_impl!(f64, f32, f64, f64::powf);
    pow_impl!(f64, f64, f64, f64::powf);
}

/// Raises a value to the power of exp, using exponentiation by squaring.
///
/// # Example
///
/// ```rust
/// use num_traits::pow;
///
/// assert_eq!(pow(2i8, 4), 16);
/// assert_eq!(pow(6u8, 3), 216);
/// ```
#[inline]
pub fn pow<T: Clone + One + Mul<T, Output = T>>(mut base: T, mut exp: usize) -> T {
    if exp == 0 { return T::one() }

    while exp & 1 == 0 {
        base = base.clone() * base;
        exp >>= 1;
    }
    if exp == 1 { return base }

    let mut acc = base.clone();
    while exp > 1 {
        exp >>= 1;
        base = base.clone() * base;
        if exp & 1 == 1 {
            acc = acc * base.clone();
        }
    }
    acc
}

/// Raises a value to the power of exp, returning `None` if an overflow occurred.
///
/// Otherwise same as the `pow` function.
///
/// # Example
///
/// ```rust
/// use num_traits::checked_pow;
///
/// assert_eq!(checked_pow(2i8, 4), Some(16));
/// assert_eq!(checked_pow(7i8, 8), None);
/// assert_eq!(checked_pow(7u32, 8), Some(5_764_801));
/// ```
#[inline]
pub fn checked_pow<T: Clone + One + CheckedMul>(mut base: T, mut exp: usize) -> Option<T> {
    if exp == 0 { return Some(T::one()) }

    macro_rules! optry {
        ( $ expr : expr ) => {
            if let Some(val) = $expr { val } else { return None }
        }
    }

    while exp & 1 == 0 {
        base = optry!(base.checked_mul(&base));
        exp >>= 1;
    }
    if exp == 1 { return Some(base) }

    let mut acc = base.clone();
    while exp > 1 {
        exp >>= 1;
        base = optry!(base.checked_mul(&base));
        if exp & 1 == 1 {
            acc = optry!(acc.checked_mul(&base));
        }
    }
    Some(acc)
}
<commit_msg>There's no u64 exponent impl for i128/u128 Pow<commit_after>use core::ops::Mul;
use core::num::Wrapping;
use {One, CheckedMul};

/// Binary operator for raising a value to a power.
pub trait Pow<RHS> {
    /// The result after applying the operator.
    type Output;

    /// Returns `self` to the power `rhs`.
    ///
    /// # Examples
    ///
    /// ```
    /// use num_traits::Pow;
    /// assert_eq!(Pow::pow(10u32, 2u32), 100);
    /// ```
    fn pow(self, rhs: RHS) -> Self::Output;
}

macro_rules! pow_impl {
    ($t:ty) => {
        pow_impl!($t, u8);
        pow_impl!($t, usize);

        // FIXME: these should be possible
        // pow_impl!($t, u16);
        // pow_impl!($t, u32);
        // pow_impl!($t, u64);
    };
    ($t:ty, $rhs:ty) => {
        pow_impl!($t, $rhs, usize, pow);
    };
    ($t:ty, $rhs:ty, $desired_rhs:ty, $method:expr) => {
        impl Pow<$rhs> for $t {
            type Output = $t;
            #[inline]
            fn pow(self, rhs: $rhs) -> $t {
                ($method)(self, <$desired_rhs>::from(rhs))
            }
        }

        impl<'a> Pow<&'a $rhs> for $t {
            type Output = $t;
            #[inline]
            fn pow(self, rhs: &'a $rhs) -> $t {
                ($method)(self, <$desired_rhs>::from(*rhs))
            }
        }

        impl<'a> Pow<$rhs> for &'a $t {
            type Output = $t;
            #[inline]
            fn pow(self, rhs: $rhs) -> $t {
                ($method)(*self, <$desired_rhs>::from(rhs))
            }
        }

        impl<'a, 'b> Pow<&'a $rhs> for &'b $t {
            type Output = $t;
            #[inline]
            fn pow(self, rhs: &'a $rhs) -> $t {
                ($method)(*self, <$desired_rhs>::from(*rhs))
            }
        }
    };
}

pow_impl!(u8, u8, u32, u8::pow);
pow_impl!(u8, u16, u32, u8::pow);
pow_impl!(u8, u32, u32, u8::pow);
pow_impl!(u8, usize);
pow_impl!(i8, u8, u32, i8::pow);
pow_impl!(i8, u16, u32, i8::pow);
pow_impl!(i8, u32, u32, i8::pow);
pow_impl!(i8, usize);
pow_impl!(u16, u8, u32, u16::pow);
pow_impl!(u16, u16, u32, u16::pow);
pow_impl!(u16, u32, u32, u16::pow);
pow_impl!(u16, usize);
pow_impl!(i16, u8, u32, i16::pow);
pow_impl!(i16, u16, u32, i16::pow);
pow_impl!(i16, u32, u32, i16::pow);
pow_impl!(i16, usize);
pow_impl!(u32, u8, u32, u32::pow);
pow_impl!(u32, u16, u32, u32::pow);
pow_impl!(u32, u32, u32, u32::pow);
pow_impl!(u32, usize);
pow_impl!(i32, u8, u32, i32::pow);
pow_impl!(i32, u16, u32, i32::pow);
pow_impl!(i32, u32, u32, i32::pow);
pow_impl!(i32, usize);
pow_impl!(u64, u8, u32, u64::pow);
pow_impl!(u64, u16, u32, u64::pow);
pow_impl!(u64, u32, u32, u64::pow);
pow_impl!(u64, usize);
pow_impl!(i64, u8, u32, i64::pow);
pow_impl!(i64, u16, u32, i64::pow);
pow_impl!(i64, u32, u32, i64::pow);
pow_impl!(i64, usize);

#[cfg(feature = "i128")]
pow_impl!(u128, u8, u32, u128::pow);
#[cfg(feature = "i128")]
pow_impl!(u128, u16, u32, u128::pow);
#[cfg(feature = "i128")]
pow_impl!(u128, u32, u32, u128::pow);
#[cfg(feature = "i128")]
pow_impl!(u128, usize);

#[cfg(feature = "i128")]
pow_impl!(i128, u8, u32, i128::pow);
#[cfg(feature = "i128")]
pow_impl!(i128, u16, u32, i128::pow);
#[cfg(feature = "i128")]
pow_impl!(i128, u32, u32, i128::pow);
#[cfg(feature = "i128")]
pow_impl!(i128, usize);

pow_impl!(usize, u8, u32, usize::pow);
pow_impl!(usize, u16, u32, usize::pow);
pow_impl!(usize, u32, u32, usize::pow);
pow_impl!(usize, usize);
pow_impl!(isize, u8, u32, isize::pow);
pow_impl!(isize, u16, u32, isize::pow);
pow_impl!(isize, u32, u32, isize::pow);
pow_impl!(isize, usize);
pow_impl!(Wrapping<u8>);
pow_impl!(Wrapping<i8>);
pow_impl!(Wrapping<u16>);
pow_impl!(Wrapping<i16>);
pow_impl!(Wrapping<u32>);
pow_impl!(Wrapping<i32>);
pow_impl!(Wrapping<u64>);
pow_impl!(Wrapping<i64>);
#[cfg(feature = "i128")]
pow_impl!(Wrapping<u128>);
#[cfg(feature = "i128")]
pow_impl!(Wrapping<i128>);
pow_impl!(Wrapping<usize>);
pow_impl!(Wrapping<isize>);

// FIXME: these should be possible
// pow_impl!(u8, u64);
// pow_impl!(i16, u64);
// pow_impl!(i8, u64);
// pow_impl!(u16, u64);
// pow_impl!(u32, u64);
// pow_impl!(i32, u64);
// pow_impl!(u64, u64);
// pow_impl!(i64, u64);
// pow_impl!(usize, u64);
// pow_impl!(isize, u64);

#[cfg(feature = "std")]
mod float_impls {
    use super::Pow;

    pow_impl!(f32, i8, i32, f32::powi);
    pow_impl!(f32, u8, i32, f32::powi);
    pow_impl!(f32, i16, i32, f32::powi);
    pow_impl!(f32, u16, i32, f32::powi);
    pow_impl!(f32, i32, i32, f32::powi);
    pow_impl!(f64, i8, i32, f64::powi);
    pow_impl!(f64, u8, i32, f64::powi);
    pow_impl!(f64, i16, i32, f64::powi);
    pow_impl!(f64, u16, i32, f64::powi);
    pow_impl!(f64, i32, i32, f64::powi);
    pow_impl!(f32, f32, f32, f32::powf);
    pow_impl!(f64, f32, f64, f64::powf);
    pow_impl!(f64, f64, f64, f64::powf);
}

/// Raises a value to the power of exp, using exponentiation by squaring.
///
/// # Example
///
/// ```rust
/// use num_traits::pow;
///
/// assert_eq!(pow(2i8, 4), 16);
/// assert_eq!(pow(6u8, 3), 216);
/// ```
#[inline]
pub fn pow<T: Clone + One + Mul<T, Output = T>>(mut base: T, mut exp: usize) -> T {
    if exp == 0 { return T::one() }

    while exp & 1 == 0 {
        base = base.clone() * base;
        exp >>= 1;
    }
    if exp == 1 { return base }

    let mut acc = base.clone();
    while exp > 1 {
        exp >>= 1;
        base = base.clone() * base;
        if exp & 1 == 1 {
            acc = acc * base.clone();
        }
    }
    acc
}

/// Raises a value to the power of exp, returning `None` if an overflow occurred.
///
/// Otherwise same as the `pow` function.
///
/// # Example
///
/// ```rust
/// use num_traits::checked_pow;
///
/// assert_eq!(checked_pow(2i8, 4), Some(16));
/// assert_eq!(checked_pow(7i8, 8), None);
/// assert_eq!(checked_pow(7u32, 8), Some(5_764_801));
/// ```
#[inline]
pub fn checked_pow<T: Clone + One + CheckedMul>(mut base: T, mut exp: usize) -> Option<T> {
    if exp == 0 { return Some(T::one()) }

    macro_rules! optry {
        ( $ expr : expr ) => {
            if let Some(val) = $expr { val } else { return None }
        }
    }

    while exp & 1 == 0 {
        base = optry!(base.checked_mul(&base));
        exp >>= 1;
    }
    if exp == 1 { return Some(base) }

    let mut acc = base.clone();
    while exp > 1 {
        exp >>= 1;
        base = optry!(base.checked_mul(&base));
        if exp & 1 == 1 {
            acc = optry!(acc.checked_mul(&base));
        }
    }
    Some(acc)
}
<|endoftext|>


<commit_before>/*
 * Given a differential function dx(x, t),
 * initial condition x0,
 * and a list of times t,
 * find x(t) at each point in t
 */
pub fn odeint(dx: (&Fn(f64, f64) -> f64), x0: f64, t_vec: Vec<f64>) -> Vec<f64> {
    // Need there to be at least two times for this method to work
    assert!(t_vec.len() >= 2);

    // Collect x values in this vector
    let mut result = Vec::<f64>::new();
    result.push(x0);

    // Need to get step size by taking the difference between
    // two adjacent times
    for i in 0..(t_vec.len() - 1) { // Subtracting 1 from the length isn't a typo
        // This implementation is from Wikipedia
        let ti = t_vec[i];
        let tnext = t_vec[i+1];
        let h = tnext - ti;

        let xi = result.pop().unwrap();

        let k1 = dx(xi, ti);
        let k2 = dx(xi + h/2.0*k1, ti + h/2.0);
        let k3 = dx(xi + h/2.0*k2, ti + h/2.0);
        let k4 = dx(xi + h*k3, ti + h);

        let xnext = xi + h/6.0*(k1 + 2.0*k2 + 2.0*k3 + k4);

        result.push(xi);
        result.push(xnext);
    }
    result
}

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

    // Test differential to give to odeint
    fn velocity_one(x: f64, t: f64) -> f64 {
        1.0 // Velocity of particle is 1
    }

    #[test]
    fn rk4_compiles() {
    }

    #[test]
    fn test_velocity_one() {
        let threshold = 0.000001;

        let t = vec![0.0, 1.0];
        let x0 = 0.0;

        let mut result = odeint(&velocity_one, x0, t);

        assert!((result.pop().unwrap() - 1.0).abs() < threshold);
    }

    #[test]
    fn length_test() {
        let t = vec![0.0, 1.0, 2.0];
        let x0 = 0.0;

        let result = odeint(&velocity_one, x0, t);
        assert_eq!(result.len(), 3);
    }
}
<commit_msg>Tested RK4 for free-fall.<commit_after>/*
 * Given a differential function dx(x, t),
 * initial condition x0,
 * and a list of times t,
 * find x(t) at each point in t
 */
pub fn odeint(dx: (&Fn(f64, f64) -> f64), x0: f64, t_vec: Vec<f64>) -> Vec<f64> {
    // Need there to be at least two times for this method to work
    assert!(t_vec.len() >= 2);

    // Collect x values in this vector
    let mut result = Vec::<f64>::new();
    result.push(x0);

    // Need to get step size by taking the difference between
    // two adjacent times
    for i in 0..(t_vec.len() - 1) { // Subtracting 1 from the length isn't a typo
        // This implementation is from Wikipedia
        let ti = t_vec[i];
        let tnext = t_vec[i+1];
        let h = tnext - ti;

        let xi = result.pop().unwrap();

        let k1 = dx(xi, ti);
        let k2 = dx(xi + h/2.0*k1, ti + h/2.0);
        let k3 = dx(xi + h/2.0*k2, ti + h/2.0);
        let k4 = dx(xi + h*k3, ti + h);

        let xnext = xi + h/6.0*(k1 + 2.0*k2 + 2.0*k3 + k4);

        result.push(xi);
        result.push(xnext);
    }
    result
}

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

    // Test differential to give to odeint
    #[allow(unused_variables)]
    fn velocity_one(x: f64, t: f64) -> f64 {
        1.0 // Velocity of particle is 1
    }

    #[allow(unused_variables)]
    fn free_fall(x: f64, t: f64) -> f64 {
        let g = -9.81;
        g*t
    }

    #[test]
    fn rk4_compiles() {
    }

    #[test]
    fn test_velocity_one() {
        let threshold = 0.000001;

        let t = vec![0.0, 1.0];
        let x0 = 0.0;

        let mut result = odeint(&velocity_one, x0, t);

        assert!((result.pop().unwrap() - 1.0).abs() < threshold);
    }

    #[test]
    fn test_length() {
        let t = vec![0.0, 1.0, 2.0];
        let x0 = 0.0;

        let result = odeint(&velocity_one, x0, t);
        assert_eq!(result.len(), 3);
    }

    #[test]
    fn test_free_fall() {
        let mut times = Vec::<f64>::new();
        let mut i = 0.0;
        while i <= 10.0 {
            times.push(i);
            i += 0.1;
        }

        let x0 = 0.0;
        let mut result = odeint(&free_fall, x0, times);
        let expected_value = -490.5;

        let threshold = 0.00001;
        assert!((result.pop().unwrap() - expected_value).abs() < threshold);
    }
}
<|endoftext|>


<commit_before>//! singular-value decomposition

use ndarray::*;

use super::convert::*;
use super::error::*;
use super::layout::*;
use super::types::*;

pub trait SVD {
    type U;
    type VT;
    type Sigma;
    fn svd(&self, calc_u: bool, calc_vt: bool) -> Result<(Option<Self::U>, Self::Sigma, Option<Self::VT>)>;
}

pub trait SVDInto {
    type U;
    type VT;
    type Sigma;
    fn svd_into(self, calc_u: bool, calc_vt: bool) -> Result<(Option<Self::U>, Self::Sigma, Option<Self::VT>)>;
}

pub trait SVDMut {
    type U;
    type VT;
    type Sigma;
    fn svd_mut(&mut self, calc_u: bool, calc_vt: bool) -> Result<(Option<Self::U>, Self::Sigma, Option<Self::VT>)>;
}

impl<A, S> SVDInto for ArrayBase<S, Ix2>
where
    A: Scalar,
    S: DataMut<Elem = A>,
{
    type U = Array2<A>;
    type VT = Array2<A>;
    type Sigma = Array1<A::Real>;

    fn svd_into(mut self, calc_u: bool, calc_vt: bool) -> Result<(Option<Self::U>, Self::Sigma, Option<Self::VT>)> {
        self.svd_mut(calc_u, calc_vt)
    }
}

impl<A, S> SVD for ArrayBase<S, Ix2>
where
    A: Scalar,
    S: Data<Elem = A>,
{
    type U = Array2<A>;
    type VT = Array2<A>;
    type Sigma = Array1<A::Real>;

    fn svd(&self, calc_u: bool, calc_vt: bool) -> Result<(Option<Self::U>, Self::Sigma, Option<Self::VT>)> {
        let a = self.to_owned();
        a.svd_into(calc_u, calc_vt)
    }
}

impl<A, S> SVDMut for ArrayBase<S, Ix2>
where
    A: Scalar,
    S: DataMut<Elem = A>,
{
    type U = Array2<A>;
    type VT = Array2<A>;
    type Sigma = Array1<A::Real>;

    fn svd_mut(&mut self, calc_u: bool, calc_vt: bool) -> Result<(Option<Self::U>, Self::Sigma, Option<Self::VT>)> {
        let l = self.layout()?;
        let svd_res = A::svd(l, calc_u, calc_vt, self.as_allocated_mut()?)?;
        let (n, m) = l.size();
        let u = svd_res.u.map(|u| into_matrix(l.resized(n, n), u).unwrap());
        let vt = svd_res.vt.map(
            |vt| into_matrix(l.resized(m, m), vt).unwrap(),
        );
        let s = ArrayBase::from_vec(svd_res.s);
        Ok((u, s, vt))
    }
}
<commit_msg>Add doc for SVD<commit_after>//! singular-value decomposition
//!
//! https://en.wikipedia.org/wiki/Singular_value_decomposition

use ndarray::*;

use super::convert::*;
use super::error::*;
use super::layout::*;
use super::types::*;

/// singular-value decomposition of matrix reference
pub trait SVD {
    type U;
    type VT;
    type Sigma;
    fn svd(&self, calc_u: bool, calc_vt: bool) -> Result<(Option<Self::U>, Self::Sigma, Option<Self::VT>)>;
}

/// singular-value decomposition
pub trait SVDInto {
    type U;
    type VT;
    type Sigma;
    fn svd_into(self, calc_u: bool, calc_vt: bool) -> Result<(Option<Self::U>, Self::Sigma, Option<Self::VT>)>;
}

/// singular-value decomposition for mutable reference of matrix
pub trait SVDMut {
    type U;
    type VT;
    type Sigma;
    fn svd_mut(&mut self, calc_u: bool, calc_vt: bool) -> Result<(Option<Self::U>, Self::Sigma, Option<Self::VT>)>;
}

impl<A, S> SVDInto for ArrayBase<S, Ix2>
where
    A: Scalar,
    S: DataMut<Elem = A>,
{
    type U = Array2<A>;
    type VT = Array2<A>;
    type Sigma = Array1<A::Real>;

    fn svd_into(mut self, calc_u: bool, calc_vt: bool) -> Result<(Option<Self::U>, Self::Sigma, Option<Self::VT>)> {
        self.svd_mut(calc_u, calc_vt)
    }
}

impl<A, S> SVD for ArrayBase<S, Ix2>
where
    A: Scalar,
    S: Data<Elem = A>,
{
    type U = Array2<A>;
    type VT = Array2<A>;
    type Sigma = Array1<A::Real>;

    fn svd(&self, calc_u: bool, calc_vt: bool) -> Result<(Option<Self::U>, Self::Sigma, Option<Self::VT>)> {
        let a = self.to_owned();
        a.svd_into(calc_u, calc_vt)
    }
}

impl<A, S> SVDMut for ArrayBase<S, Ix2>
where
    A: Scalar,
    S: DataMut<Elem = A>,
{
    type U = Array2<A>;
    type VT = Array2<A>;
    type Sigma = Array1<A::Real>;

    fn svd_mut(&mut self, calc_u: bool, calc_vt: bool) -> Result<(Option<Self::U>, Self::Sigma, Option<Self::VT>)> {
        let l = self.layout()?;
        let svd_res = A::svd(l, calc_u, calc_vt, self.as_allocated_mut()?)?;
        let (n, m) = l.size();
        let u = svd_res.u.map(|u| into_matrix(l.resized(n, n), u).unwrap());
        let vt = svd_res.vt.map(
            |vt| into_matrix(l.resized(m, m), vt).unwrap(),
        );
        let s = ArrayBase::from_vec(svd_res.s);
        Ok((u, s, vt))
    }
}
<|endoftext|>


<commit_before>pub mod telegram;
<commit_msg>Delete unused file<commit_after><|endoftext|>