<commit_before>extern crate cairo;
extern crate gio;
extern crate gtk;

use std::cell::RefCell;
use std::env::args;

use std::mem;
use std::rc::Rc;
use std::sync::mpsc;
use std::thread;
use std::time::Duration;

use cairo::prelude::*;
use cairo::{Context, Format, ImageSurface};
use gio::prelude::*;
use gtk::prelude::*;
use gtk::{ApplicationWindow, DrawingArea};

// make moving clones into closures more convenient
macro_rules! clone {
    (@param _) => ( _ );
    (@param $x:ident) => ( $x );
    ($($n:ident),+ => move || $body:expr) => (
        {
            $( let $n = $n.clone(); )+
            move || $body
        }
    );
    ($($n:ident),+ => move |$($p:tt),+| $body:expr) => (
        {
            $( let $n = $n.clone(); )+
            move |$(clone!(@param $p),)+| $body
        }
    );
}

// This example runs four worker threads rendering parts of the image
// independently at different paces in a sort of double buffered way.
//
// +---+---+
// | 0 | 1 |
// +---+---+
// | 2 | 3 |
// +---+---+
//
// Each worker thread waits for a buffer (Box<[u8]>) to render into, wraps
// it into ImageSurface, sleeps for a while, does the drawing, then sends the
// underlying buffer back and waits for the next one.
//
// The GUI thread holds an ImageSurface per image part at all times, these
// surfaces are painted on a DrawingArea in its 'draw' signal handler. This
// thread periodically checks if any worker has sent a freshly rendered buffer.
// Upon receipt it's wrapped in ImageSurface and swapped with the previously
// held surface, whose buffer is sent to the worker thread again. Then the
// appropriate part of the DrawingArea is invalidated prompting a redraw.
//
// The two buffers per thread are allocated and initialized once and sent back
// and forth repeatedly.

fn build_ui(application: &gtk::Application) {
    let window = ApplicationWindow::new(application);
    let area = DrawingArea::new();
    window.add(&area);

    window.connect_delete_event(|win, _| {
        win.destroy();
        Inhibit(false)
    });

    let format = Format::Rgb24;
    let width = 200;
    let height = 200;
    area.set_size_request(width * 2, height * 2);

    let (initial_buf, stride) = draw_initial(format, width, height);
    let (ready_tx, ready_rx) = mpsc::channel();

    let mut images = Vec::new();
    let mut origins = Vec::new();
    let mut workers = Vec::new();

    for thread_num in 0..4 {
        let (tx, rx) = mpsc::channel();
        // allocate two buffers and copy the initial pattern into them
        let buf0 = initial_buf.clone();
        let buf1 = initial_buf.clone();
        // wrap the first one in a surface and set it up to be sent to the
        // worker when the surface is destroyed
        images.push(ImageSurface::create_for_data(buf0, clone!(tx => move |b| { let _ = tx.send(b); }),
            format, width, height, stride).expect("Can't create surface"));
        // send the second one immediately
        let _ = tx.send(buf1);
        origins.push(match thread_num {
            0 => (0, 0),
            1 => (width, 0),
            2 => (0, height),
            _ => (width, height),
        });
        workers.push(tx);

        let x = (width - origins[thread_num].0) as f64;
        let y = (height - origins[thread_num].1) as f64;
        let delay = Duration::from_millis((100 << thread_num) - 5);

        // spawn the worker thread
        thread::spawn(clone!(ready_tx => move || {
            let mut n = 0;
            for buf in rx.iter() {
                n = (n + 1) % 0x10000;
                // create the surface and send the buffer back when it's destroyed
                let image = ImageSurface::create_for_data(buf,
                    clone!(ready_tx => move |b| { let _ = ready_tx.send((thread_num, b)); }),
                    format, width, height, stride).expect("Can't create surface");
                let cr = Context::new(&image);
                // draw an arc with a weirdly calculated radius
                draw_slow(&cr, delay, x, y, 1.2_f64.powi(((n as i32) << thread_num) % 32));
                image.flush();
            }
        }));
    }

    // our signal and timeout handler closures have to be 'static,
    // so they can't just borrow these
    let cell = Rc::new(RefCell::new((images, origins, workers)));

    area.connect_draw(clone!(cell => move |_, cr| {
        let (ref images, ref origins, _) = *cell.borrow();
        for (image, origin) in images.iter().zip(origins.iter()) {
            draw_image_if_dirty(&cr, image, *origin, (width, height));
            // if we don't reset the source, the context may hold on to
            // the surface indefinitely, the buffer will be stuck there
            // and the worker thread will starve
            cr.set_source_rgb(0., 0., 0.);
        }
        Inhibit(false)
    }));

    gtk::timeout_add(100, move || {
        while let Ok((thread_num, buf)) = ready_rx.try_recv() {
            let &mut (ref mut images, ref origins, ref workers) = &mut *cell.borrow_mut();
            let tx = workers[thread_num].clone();
            let mut image = ImageSurface::create_for_data(buf, move |b| { let _ = tx.send(b); },
                format, width, height, stride).expect("Can't create surface");
            mem::swap(&mut images[thread_num], &mut image);
            area.queue_draw_area(origins[thread_num].0, origins[thread_num].1, width, height);
        }
        Continue(true)
    });

    window.show_all();
}

fn main() {
    let application = gtk::Application::new("com.github.cairo_threads",
                                            gio::ApplicationFlags::empty())
                                       .expect("Initialization failed...");

    application.connect_startup(|app| {
        build_ui(app);
    });
    application.connect_activate(|_| {});

    application.run(&args().collect::<Vec<_>>());
}

fn draw_initial(format: Format, width: i32, height: i32) -> (Box<[u8]>, i32) {
    let mut image = ImageSurface::create(format, width, height).expect("Can't create surface");
    {
        let cr = Context::new(&image);
        cr.set_source_rgb(0., 1., 0.);
        cr.paint();
        // Destroying the context releases its reference to `image`.
    }
    // We have a unique reference to `image` again.
    let buf = image.get_data().expect("Couldn't get data from image").to_vec();
    (buf.into_boxed_slice(), image.get_stride())
}

fn draw_slow(cr: &Context, delay: Duration, x: f64, y: f64, radius: f64) {
    thread::sleep(delay);
    cr.set_source_rgb(0., 0., 0.);
    cr.paint();
    cr.set_source_rgb(1., 1., 1.);
    cr.arc(x, y, radius, 0.0, 3.1416 * 2.);
    cr.stroke();
}

fn draw_image_if_dirty(cr: &Context, image: &ImageSurface, origin: (i32, i32),
        dimensions: (i32, i32)) {
    let x = origin.0 as f64;
    let y = origin.1 as f64;
    let w = dimensions.0 as f64;
    let h = dimensions.1 as f64;
    let (clip_x1, clip_y1, clip_x2, clip_y2) = cr.clip_extents();
    if clip_x1 >= x + w || clip_y1 >= y + h || clip_x2 <= x || clip_y2 <= y {
        return;
    }
    cr.set_source_surface(image, x, y);
    cr.paint();
}
<commit_msg>Fix compilation of cairo-threads example<commit_after>extern crate cairo;
extern crate gio;
extern crate gtk;

use std::cell::RefCell;
use std::env::args;

use std::mem;
use std::rc::Rc;
use std::sync::mpsc;
use std::thread;
use std::time::Duration;

use cairo::prelude::*;
use cairo::{Context, Format, ImageSurface};
use gio::prelude::*;
use gtk::prelude::*;
use gtk::{ApplicationWindow, DrawingArea};

// make moving clones into closures more convenient
macro_rules! clone {
    (@param _) => ( _ );
    (@param $x:ident) => ( $x );
    ($($n:ident),+ => move || $body:expr) => (
        {
            $( let $n = $n.clone(); )+
            move || $body
        }
    );
    ($($n:ident),+ => move |$($p:tt),+| $body:expr) => (
        {
            $( let $n = $n.clone(); )+
            move |$(clone!(@param $p),)+| $body
        }
    );
}

// This example runs four worker threads rendering parts of the image
// independently at different paces in a sort of double buffered way.
//
// +---+---+
// | 0 | 1 |
// +---+---+
// | 2 | 3 |
// +---+---+
//
// Each worker thread waits for a buffer (Box<[u8]>) to render into, wraps
// it into ImageSurface, sleeps for a while, does the drawing, then sends the
// underlying buffer back and waits for the next one.
//
// The GUI thread holds an ImageSurface per image part at all times, these
// surfaces are painted on a DrawingArea in its 'draw' signal handler. This
// thread periodically checks if any worker has sent a freshly rendered buffer.
// Upon receipt it's wrapped in ImageSurface and swapped with the previously
// held surface, whose buffer is sent to the worker thread again. Then the
// appropriate part of the DrawingArea is invalidated prompting a redraw.
//
// The two buffers per thread are allocated and initialized once and sent back
// and forth repeatedly.

fn build_ui(application: &gtk::Application) {
    let window = ApplicationWindow::new(application);
    let area = DrawingArea::new();
    window.add(&area);

    window.connect_delete_event(|win, _| {
        win.destroy();
        Inhibit(false)
    });

    let format = Format::Rgb24;
    let width = 200;
    let height = 200;
    area.set_size_request(width * 2, height * 2);

    let initial_image = draw_initial(format, width, height);
    let (ready_tx, ready_rx) = mpsc::channel();

    let mut images = Vec::new();
    let mut origins = Vec::new();
    let mut workers = Vec::new();

    for thread_num in 0..4 {
        let (tx, rx) = mpsc::channel();
        // copy the initial image in two images for the workers
        let image0 = duplicate_image(&initial_image);
        let image1 = duplicate_image(&initial_image);
        // store the first one in our vec
        images.push(image0);
        // send the second one immediately
        let _ = tx.send(image1);
        origins.push(match thread_num {
            0 => (0, 0),
            1 => (width, 0),
            2 => (0, height),
            _ => (width, height),
        });
        workers.push(tx);

        let x = (width - origins[thread_num].0) as f64;
        let y = (height - origins[thread_num].1) as f64;
        let delay = Duration::from_millis((100 << thread_num) - 5);

        // spawn the worker thread
        thread::spawn(clone!(ready_tx => move || {
            let mut n = 0;
            for image in rx.iter() {
                n = (n + 1) % 0x10000;
                let cr = Context::new(&image);
                // draw an arc with a weirdly calculated radius
                draw_slow(&cr, delay, x, y, 1.2_f64.powi(((n as i32) << thread_num) % 32));
                image.flush();
                let _ = ready_tx.send((thread_num, image));
            }
        }));
    }

    // our signal and timeout handler closures have to be 'static,
    // so they can't just borrow these
    let cell = Rc::new(RefCell::new((images, origins, workers)));

    area.connect_draw(clone!(cell => move |_, cr| {
        let (ref images, ref origins, _) = *cell.borrow();
        for (image, origin) in images.iter().zip(origins.iter()) {
            draw_image_if_dirty(&cr, image, *origin, (width, height));
            // if we don't reset the source, the context may hold on to
            // the surface indefinitely, the buffer will be stuck there
            // and the worker thread will starve
            cr.set_source_rgb(0., 0., 0.);
        }
        Inhibit(false)
    }));

    gtk::timeout_add(100, move || {
        while let Ok((thread_num, mut image)) = ready_rx.try_recv() {
            let &mut (ref mut images, ref origins, ref workers) = &mut *cell.borrow_mut();
            let tx = workers[thread_num].clone();
            mem::swap(&mut images[thread_num], &mut image);
            let _ = tx.send(image);
            area.queue_draw_area(origins[thread_num].0, origins[thread_num].1, width, height);
        }
        Continue(true)
    });

    window.show_all();
}

fn main() {
    let application = gtk::Application::new("com.github.cairo_threads",
                                            gio::ApplicationFlags::empty())
                                       .expect("Initialization failed...");

    application.connect_startup(|app| {
        build_ui(app);
    });
    application.connect_activate(|_| {});

    application.run(&args().collect::<Vec<_>>());
}

fn draw_initial(format: Format, width: i32, height: i32) -> ImageSurface {
    let image = ImageSurface::create(format, width, height).expect("Can't create surface");
    {
        let cr = Context::new(&image);
        cr.set_source_rgb(0., 1., 0.);
        cr.paint();
        // Destroying the context releases its reference to `image`.
    }
    // We have a unique reference to `image` again and return it
    image
}

fn draw_slow(cr: &Context, delay: Duration, x: f64, y: f64, radius: f64) {
    thread::sleep(delay);
    cr.set_source_rgb(0., 0., 0.);
    cr.paint();
    cr.set_source_rgb(1., 1., 1.);
    cr.arc(x, y, radius, 0.0, 3.1416 * 2.);
    cr.stroke();
}

fn draw_image_if_dirty(cr: &Context, image: &ImageSurface, origin: (i32, i32),
        dimensions: (i32, i32)) {
    let x = origin.0 as f64;
    let y = origin.1 as f64;
    let w = dimensions.0 as f64;
    let h = dimensions.1 as f64;
    let (clip_x1, clip_y1, clip_x2, clip_y2) = cr.clip_extents();
    if clip_x1 >= x + w || clip_y1 >= y + h || clip_x2 <= x || clip_y2 <= y {
        return;
    }
    cr.set_source_surface(image, x, y);
    cr.paint();
}

fn duplicate_image(image: &ImageSurface) -> ImageSurface {
    let image_dup = ImageSurface::create(image.get_format(), image.get_width(), image.get_height()).expect("Can't create surface");
    {
        let cr = Context::new(&image_dup);
        cr.set_source_surface(image, 0.0, 0.0);
        cr.paint();
    }

    image_dup
}
<|endoftext|>


<commit_before>extern crate rgmk;

use std::fs::File;
use std::io::prelude::*;
use std::io::{BufReader, BufWriter};

fn main() {
    let original = {
        let mut args = std::env::args().skip(1);
        let path = args.next().expect("Expected path as argument");
        let mut file = File::open(&path).unwrap();
        let mut vec = Vec::new();
        file.read_to_end(&mut vec).unwrap();
        vec
    };
    println!("Loaded file");
    let root = rgmk::read_chunk(&mut BufReader::new(&original[..])).unwrap();
    let mut new: Vec<u8> = Vec::with_capacity(original.len());
    unsafe {
        new.set_len(original.len());
    }
    rgmk::write_chunk(&mut BufWriter::new(&mut new[..]), &root).unwrap();
    println!("Written chunk");
    assert_eq!(original, new);
    println!("Compared");
}
<commit_msg>Remove "profiling" prints from identity_test<commit_after>extern crate rgmk;

use std::fs::File;
use std::io::prelude::*;
use std::io::{BufReader, BufWriter};

fn main() {
    let original = {
        let mut args = std::env::args().skip(1);
        let path = args.next().expect("Expected path as argument");
        let mut file = File::open(&path).unwrap();
        let mut vec = Vec::new();
        file.read_to_end(&mut vec).unwrap();
        vec
    };
    let root = rgmk::read_chunk(&mut BufReader::new(&original[..])).unwrap();
    let mut new: Vec<u8> = Vec::with_capacity(original.len());
    unsafe {
        new.set_len(original.len());
    }
    rgmk::write_chunk(&mut BufWriter::new(&mut new[..]), &root).unwrap();
    assert_eq!(original, new);
}
<|endoftext|>


<commit_before>extern crate forth;

use forth::{Error, Forth, Value};

#[test]
fn no_input_no_stack() {
    assert_eq!(Vec::<Value>::new(), Forth::new().stack());
}

#[test]
#[ignore]
fn numbers_just_get_pushed_onto_the_stack() {
    let mut f = Forth::new();
    assert!(f.eval("1 2 3 4 5").is_ok());
    assert_eq!(vec![1, 2, 3, 4, 5], f.stack());
}

#[test]
#[ignore]
fn non_word_characters_are_separators() {
    let mut f = Forth::new();
    assert!(f.eval("1\u{0000}2\u{0001}3\n4\r5 6\t7").is_ok());
    assert_eq!(vec![1, 2, 3, 4, 5, 6, 7], f.stack());
}

#[test]
#[ignore]
fn can_add_two_numbers() {
    let mut f = Forth::new();
    assert!(f.eval("1 2 +").is_ok());
    assert_eq!(vec![3], f.stack());
}

#[test]
#[ignore]
fn addition_error() {
    let mut f = Forth::new();
    assert_eq!(Err(Error::StackUnderflow), f.eval("1 +"));
    assert_eq!(Err(Error::StackUnderflow), f.eval("+"));
}

#[test]
#[ignore]
fn can_subtract_two_numbers() {
    let mut f = Forth::new();
    assert!(f.eval("3 4 -").is_ok());
    assert_eq!(vec![-1], f.stack());
}

#[test]
#[ignore]
fn subtraction_error() {
    let mut f = Forth::new();
    assert_eq!(Err(Error::StackUnderflow), f.eval("1 -"));
    assert_eq!(Err(Error::StackUnderflow), f.eval("-"));
}

#[test]
#[ignore]
fn can_multiply_two_numbers() {
    let mut f = Forth::new();
    assert!(f.eval("2 4 *").is_ok());
    assert_eq!(vec![8], f.stack());
}

#[test]
#[ignore]
fn multiplication_error() {
    let mut f = Forth::new();
    assert_eq!(Err(Error::StackUnderflow), f.eval("1 *"));
    assert_eq!(Err(Error::StackUnderflow), f.eval("*"));
}

#[test]
#[ignore]
fn can_divide_two_numbers() {
    let mut f = Forth::new();
    assert!(f.eval("12 3 /").is_ok());
    assert_eq!(vec![4], f.stack());
}

#[test]
#[ignore]
fn performs_integer_division() {
    let mut f = Forth::new();
    assert!(f.eval("8 3 /").is_ok());
    assert_eq!(vec![2], f.stack());
}

#[test]
#[ignore]
fn division_error() {
    let mut f = Forth::new();
    assert_eq!(Err(Error::StackUnderflow), f.eval("1 /"));
    assert_eq!(Err(Error::StackUnderflow), f.eval("/"));
}

#[test]
#[ignore]
fn errors_if_dividing_by_zero() {
    let mut f = Forth::new();
    assert_eq!(Err(Error::DivisionByZero), f.eval("4 0 /"));
}

#[test]
#[ignore]
fn addition_and_subtraction() {
    let mut f = Forth::new();
    assert!(f.eval("1 2 + 4 -").is_ok());
    assert_eq!(vec![-1], f.stack());
}

#[test]
#[ignore]
fn multiplication_and_division() {
    let mut f = Forth::new();
    assert!(f.eval("2 4 * 3 /").is_ok());
    assert_eq!(vec![2], f.stack());
}

#[test]
#[ignore]
fn dup() {
    let mut f = Forth::new();
    assert!(f.eval("1 DUP").is_ok());
    assert_eq!(vec![1, 1], f.stack());
}

#[test]
#[ignore]
fn dup_case_insensitive() {
    let mut f = Forth::new();
    assert!(f.eval("1 2 Dup").is_ok());
    assert_eq!(vec![1, 2, 2], f.stack());
}

#[test]
#[ignore]
fn dup_error() {
    let mut f = Forth::new();
    assert_eq!(Err(Error::StackUnderflow), f.eval("dup"));
}

#[test]
#[ignore]
fn drop() {
    let mut f = Forth::new();
    assert!(f.eval("1 drop").is_ok());
    assert_eq!(Vec::<Value>::new(), f.stack());
}

#[test]
#[ignore]
fn drop_with_two() {
    let mut f = Forth::new();
    assert!(f.eval("1 2 drop").is_ok());
    assert_eq!(vec![1], f.stack());
}

#[test]
#[ignore]
fn drop_error() {
    let mut f = Forth::new();
    assert_eq!(Err(Error::StackUnderflow), f.eval("drop"));
}

#[test]
#[ignore]
fn swap() {
    let mut f = Forth::new();
    assert!(f.eval("1 2 swap").is_ok());
    assert_eq!(vec![2, 1], f.stack());
}

#[test]
#[ignore]
fn swap_with_three() {
    let mut f = Forth::new();
    assert!(f.eval("1 2 3 swap").is_ok());
    assert_eq!(vec![1, 3, 2], f.stack());
}

#[test]
#[ignore]
fn swap_error() {
    let mut f = Forth::new();
    assert_eq!(Err(Error::StackUnderflow), f.eval("1 swap"));
    assert_eq!(Err(Error::StackUnderflow), f.eval("swap"));
}

#[test]
#[ignore]
fn over() {
    let mut f = Forth::new();
    assert!(f.eval("1 2 over").is_ok());
    assert_eq!(vec![1, 2, 1], f.stack());
}

#[test]
#[ignore]
fn over_with_three() {
    let mut f = Forth::new();
    assert!(f.eval("1 2 3 over").is_ok());
    assert_eq!(vec![1, 2, 3, 2], f.stack());
}

#[test]
#[ignore]
fn over_error() {
    let mut f = Forth::new();
    assert_eq!(Err(Error::StackUnderflow), f.eval("1 over"));
    assert_eq!(Err(Error::StackUnderflow), f.eval("over"));
}

// User-defined words

#[test]
#[ignore]
fn can_consist_of_built_in_words() {
    let mut f = Forth::new();
    assert!(f.eval(": dup-twice dup dup ;").is_ok());
    assert!(f.eval("1 dup-twice").is_ok());
    assert_eq!(vec![1, 1, 1], f.stack());
}

#[test]
#[ignore]
fn definitions_are_case_insensitive() {
    let mut f = Forth::new();
    assert!(f.eval(": CoUnT 1 2 3 ;").is_ok());
    assert!(f.eval("count COUNT").is_ok());
    assert_eq!(vec![1, 2, 3, 1, 2, 3], f.stack());
}

#[test]
#[ignore]
fn redefining_an_existing_word() {
    let mut f = Forth::new();
    assert!(f.eval(": foo dup ;").is_ok());
    assert!(f.eval(": foo dup dup ;").is_ok());
    assert!(f.eval("1 foo").is_ok());
    assert_eq!(vec![1, 1, 1], f.stack());
}

#[test]
#[ignore]
fn redefining_an_existing_built_in_word() {
    let mut f = Forth::new();
    assert!(f.eval(": swap dup ;").is_ok());
    assert!(f.eval("1 swap").is_ok());
    assert_eq!(vec![1, 1], f.stack());
}

#[test]
#[ignore]
fn defining_words_with_odd_characters() {
    let mut f = Forth::new();
    assert!(f.eval(": € 220371 ; €").is_ok());
    assert_eq!(vec![220371], f.stack());
}

#[test]
#[ignore]
fn defining_a_number() {
    let mut f = Forth::new();
    assert_eq!(Err(Error::InvalidWord), f.eval(": 1 2 ;"));
}

#[test]
#[ignore]
fn malformed_word_definition() {
    let mut f = Forth::new();
    assert_eq!(Err(Error::InvalidWord), f.eval(":"));
    assert_eq!(Err(Error::InvalidWord), f.eval(": foo"));
    assert_eq!(Err(Error::InvalidWord), f.eval(": foo 1"));
}

#[test]
#[ignore]
fn calling_non_existing_word() {
    let mut f = Forth::new();
    assert_eq!(Err(Error::UnknownWord), f.eval("1 foo"));
}
<commit_msg>forth: Have individual test for executing in the right order<commit_after>extern crate forth;

use forth::{Error, Forth, Value};

#[test]
fn no_input_no_stack() {
    assert_eq!(Vec::<Value>::new(), Forth::new().stack());
}

#[test]
#[ignore]
fn numbers_just_get_pushed_onto_the_stack() {
    let mut f = Forth::new();
    assert!(f.eval("1 2 3 4 5").is_ok());
    assert_eq!(vec![1, 2, 3, 4, 5], f.stack());
}

#[test]
#[ignore]
fn non_word_characters_are_separators() {
    let mut f = Forth::new();
    assert!(f.eval("1\u{0000}2\u{0001}3\n4\r5 6\t7").is_ok());
    assert_eq!(vec![1, 2, 3, 4, 5, 6, 7], f.stack());
}

#[test]
#[ignore]
fn can_add_two_numbers() {
    let mut f = Forth::new();
    assert!(f.eval("1 2 +").is_ok());
    assert_eq!(vec![3], f.stack());
}

#[test]
#[ignore]
fn addition_error() {
    let mut f = Forth::new();
    assert_eq!(Err(Error::StackUnderflow), f.eval("1 +"));
    assert_eq!(Err(Error::StackUnderflow), f.eval("+"));
}

#[test]
#[ignore]
fn can_subtract_two_numbers() {
    let mut f = Forth::new();
    assert!(f.eval("3 4 -").is_ok());
    assert_eq!(vec![-1], f.stack());
}

#[test]
#[ignore]
fn subtraction_error() {
    let mut f = Forth::new();
    assert_eq!(Err(Error::StackUnderflow), f.eval("1 -"));
    assert_eq!(Err(Error::StackUnderflow), f.eval("-"));
}

#[test]
#[ignore]
fn can_multiply_two_numbers() {
    let mut f = Forth::new();
    assert!(f.eval("2 4 *").is_ok());
    assert_eq!(vec![8], f.stack());
}

#[test]
#[ignore]
fn multiplication_error() {
    let mut f = Forth::new();
    assert_eq!(Err(Error::StackUnderflow), f.eval("1 *"));
    assert_eq!(Err(Error::StackUnderflow), f.eval("*"));
}

#[test]
#[ignore]
fn can_divide_two_numbers() {
    let mut f = Forth::new();
    assert!(f.eval("12 3 /").is_ok());
    assert_eq!(vec![4], f.stack());
}

#[test]
#[ignore]
fn performs_integer_division() {
    let mut f = Forth::new();
    assert!(f.eval("8 3 /").is_ok());
    assert_eq!(vec![2], f.stack());
}

#[test]
#[ignore]
fn division_error() {
    let mut f = Forth::new();
    assert_eq!(Err(Error::StackUnderflow), f.eval("1 /"));
    assert_eq!(Err(Error::StackUnderflow), f.eval("/"));
}

#[test]
#[ignore]
fn errors_if_dividing_by_zero() {
    let mut f = Forth::new();
    assert_eq!(Err(Error::DivisionByZero), f.eval("4 0 /"));
}

#[test]
#[ignore]
fn addition_and_subtraction() {
    let mut f = Forth::new();
    assert!(f.eval("1 2 + 4 -").is_ok());
    assert_eq!(vec![-1], f.stack());
}

#[test]
#[ignore]
fn multiplication_and_division() {
    let mut f = Forth::new();
    assert!(f.eval("2 4 * 3 /").is_ok());
    assert_eq!(vec![2], f.stack());
}

#[test]
#[ignore]
fn dup() {
    let mut f = Forth::new();
    assert!(f.eval("1 DUP").is_ok());
    assert_eq!(vec![1, 1], f.stack());
}

#[test]
#[ignore]
fn dup_case_insensitive() {
    let mut f = Forth::new();
    assert!(f.eval("1 2 Dup").is_ok());
    assert_eq!(vec![1, 2, 2], f.stack());
}

#[test]
#[ignore]
fn dup_error() {
    let mut f = Forth::new();
    assert_eq!(Err(Error::StackUnderflow), f.eval("dup"));
}

#[test]
#[ignore]
fn drop() {
    let mut f = Forth::new();
    assert!(f.eval("1 drop").is_ok());
    assert_eq!(Vec::<Value>::new(), f.stack());
}

#[test]
#[ignore]
fn drop_with_two() {
    let mut f = Forth::new();
    assert!(f.eval("1 2 drop").is_ok());
    assert_eq!(vec![1], f.stack());
}

#[test]
#[ignore]
fn drop_error() {
    let mut f = Forth::new();
    assert_eq!(Err(Error::StackUnderflow), f.eval("drop"));
}

#[test]
#[ignore]
fn swap() {
    let mut f = Forth::new();
    assert!(f.eval("1 2 swap").is_ok());
    assert_eq!(vec![2, 1], f.stack());
}

#[test]
#[ignore]
fn swap_with_three() {
    let mut f = Forth::new();
    assert!(f.eval("1 2 3 swap").is_ok());
    assert_eq!(vec![1, 3, 2], f.stack());
}

#[test]
#[ignore]
fn swap_error() {
    let mut f = Forth::new();
    assert_eq!(Err(Error::StackUnderflow), f.eval("1 swap"));
    assert_eq!(Err(Error::StackUnderflow), f.eval("swap"));
}

#[test]
#[ignore]
fn over() {
    let mut f = Forth::new();
    assert!(f.eval("1 2 over").is_ok());
    assert_eq!(vec![1, 2, 1], f.stack());
}

#[test]
#[ignore]
fn over_with_three() {
    let mut f = Forth::new();
    assert!(f.eval("1 2 3 over").is_ok());
    assert_eq!(vec![1, 2, 3, 2], f.stack());
}

#[test]
#[ignore]
fn over_error() {
    let mut f = Forth::new();
    assert_eq!(Err(Error::StackUnderflow), f.eval("1 over"));
    assert_eq!(Err(Error::StackUnderflow), f.eval("over"));
}

// User-defined words

#[test]
#[ignore]
fn can_consist_of_built_in_words() {
    let mut f = Forth::new();
    assert!(f.eval(": dup-twice dup dup ;").is_ok());
    assert!(f.eval("1 dup-twice").is_ok());
    assert_eq!(vec![1, 1, 1], f.stack());
}

#[test]
#[ignore]
fn execute_in_the_right_order() {
    let mut f = Forth::new();
    assert!(f.eval(": countup 1 2 3 ;").is_ok());
    assert!(f.eval("countup").is_ok());
    assert_eq!(vec![1, 2, 3], f.stack());
}

#[test]
#[ignore]
fn definitions_are_case_insensitive() {
    let mut f = Forth::new();
    assert!(f.eval(": CoUnT 1 2 3 ;").is_ok());
    assert!(f.eval("count COUNT").is_ok());
    assert_eq!(vec![1, 2, 3, 1, 2, 3], f.stack());
}

#[test]
#[ignore]
fn redefining_an_existing_word() {
    let mut f = Forth::new();
    assert!(f.eval(": foo dup ;").is_ok());
    assert!(f.eval(": foo dup dup ;").is_ok());
    assert!(f.eval("1 foo").is_ok());
    assert_eq!(vec![1, 1, 1], f.stack());
}

#[test]
#[ignore]
fn redefining_an_existing_built_in_word() {
    let mut f = Forth::new();
    assert!(f.eval(": swap dup ;").is_ok());
    assert!(f.eval("1 swap").is_ok());
    assert_eq!(vec![1, 1], f.stack());
}

#[test]
#[ignore]
fn defining_words_with_odd_characters() {
    let mut f = Forth::new();
    assert!(f.eval(": € 220371 ; €").is_ok());
    assert_eq!(vec![220371], f.stack());
}

#[test]
#[ignore]
fn defining_a_number() {
    let mut f = Forth::new();
    assert_eq!(Err(Error::InvalidWord), f.eval(": 1 2 ;"));
}

#[test]
#[ignore]
fn malformed_word_definition() {
    let mut f = Forth::new();
    assert_eq!(Err(Error::InvalidWord), f.eval(":"));
    assert_eq!(Err(Error::InvalidWord), f.eval(": foo"));
    assert_eq!(Err(Error::InvalidWord), f.eval(": foo 1"));
}

#[test]
#[ignore]
fn calling_non_existing_word() {
    let mut f = Forth::new();
    assert_eq!(Err(Error::UnknownWord), f.eval("1 foo"));
}
<|endoftext|>


<commit_before>// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Implementation of the install aspects of the compiler.
//!
//! This module is responsible for installing the standard library,
//! compiler, and documentation.

use std::env;
use std::fs;
use std::path::{Path, PathBuf, Component};
use std::process::Command;

use dist::{self, pkgname, sanitize_sh, tmpdir};

use builder::{Builder, RunConfig, ShouldRun, Step};
use cache::Interned;

pub fn install_docs(builder: &Builder, stage: u32, host: Interned<String>) {
    install_sh(builder, "docs", "rust-docs", stage, Some(host));
}

pub fn install_std(builder: &Builder, stage: u32) {
    for target in &builder.build.targets {
        install_sh(builder, "std", "rust-std", stage, Some(*target));
    }
}

pub fn install_cargo(builder: &Builder, stage: u32, host: Interned<String>) {
    install_sh(builder, "cargo", "cargo", stage, Some(host));
}

pub fn install_rls(builder: &Builder, stage: u32, host: Interned<String>) {
    install_sh(builder, "rls", "rls", stage, Some(host));
}

pub fn install_analysis(builder: &Builder, stage: u32, host: Interned<String>) {
    install_sh(builder, "analysis", "rust-analysis", stage, Some(host));
}

pub fn install_src(builder: &Builder, stage: u32) {
    install_sh(builder, "src", "rust-src", stage, None);
}
pub fn install_rustc(builder: &Builder, stage: u32, host: Interned<String>) {
    install_sh(builder, "rustc", "rustc", stage, Some(host));
}

fn install_sh(
    builder: &Builder,
    package: &str,
    name: &str,
    stage: u32,
    host: Option<Interned<String>>
) {
    let build = builder.build;
    println!("Install {} stage{} ({:?})", package, stage, host);

    let prefix_default = PathBuf::from("/usr/local");
    let sysconfdir_default = PathBuf::from("/etc");
    let docdir_default = PathBuf::from("share/doc/rust");
    let bindir_default = PathBuf::from("bin");
    let libdir_default = PathBuf::from("lib");
    let mandir_default = PathBuf::from("share/man");
    let prefix = build.config.prefix.as_ref().unwrap_or(&prefix_default);
    let sysconfdir = build.config.sysconfdir.as_ref().unwrap_or(&sysconfdir_default);
    let docdir = build.config.docdir.as_ref().unwrap_or(&docdir_default);
    let bindir = build.config.bindir.as_ref().unwrap_or(&bindir_default);
    let libdir = build.config.libdir.as_ref().unwrap_or(&libdir_default);
    let mandir = build.config.mandir.as_ref().unwrap_or(&mandir_default);

    let sysconfdir = prefix.join(sysconfdir);
    let docdir = prefix.join(docdir);
    let bindir = prefix.join(bindir);
    let libdir = prefix.join(libdir);
    let mandir = prefix.join(mandir);

    let destdir = env::var_os("DESTDIR").map(PathBuf::from);

    let prefix = add_destdir(&prefix, &destdir);
    let sysconfdir = add_destdir(&sysconfdir, &destdir);
    let docdir = add_destdir(&docdir, &destdir);
    let bindir = add_destdir(&bindir, &destdir);
    let libdir = add_destdir(&libdir, &destdir);
    let mandir = add_destdir(&mandir, &destdir);

    let empty_dir = build.out.join("tmp/empty_dir");

    t!(fs::create_dir_all(&empty_dir));
    let package_name = if let Some(host) = host {
        format!("{}-{}", pkgname(build, name), host)
    } else {
        pkgname(build, name)
    };

    let mut cmd = Command::new("sh");
    cmd.current_dir(&empty_dir)
        .arg(sanitize_sh(&tmpdir(build).join(&package_name).join("install.sh")))
        .arg(format!("--prefix={}", sanitize_sh(&prefix)))
        .arg(format!("--sysconfdir={}", sanitize_sh(&sysconfdir)))
        .arg(format!("--docdir={}", sanitize_sh(&docdir)))
        .arg(format!("--bindir={}", sanitize_sh(&bindir)))
        .arg(format!("--libdir={}", sanitize_sh(&libdir)))
        .arg(format!("--mandir={}", sanitize_sh(&mandir)))
        .arg("--disable-ldconfig");
    build.run(&mut cmd);
    t!(fs::remove_dir_all(&empty_dir));
}

fn add_destdir(path: &Path, destdir: &Option<PathBuf>) -> PathBuf {
    let mut ret = match *destdir {
        Some(ref dest) => dest.clone(),
        None => return path.to_path_buf(),
    };
    for part in path.components() {
        match part {
            Component::Normal(s) => ret.push(s),
            _ => {}
        }
    }
    ret
}

macro_rules! install {
    (($sel:ident, $builder:ident, $_config:ident),
       $($name:ident,
       $path:expr,
       $default_cond:expr,
       only_hosts: $only_hosts:expr,
       $run_item:block $(, $c:ident)*;)+) => {
        $(
            #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
        pub struct $name {
            pub stage: u32,
            pub target: Interned<String>,
            pub host: Interned<String>,
        }

        impl Step for $name {
            type Output = ();
            const DEFAULT: bool = true;
            const ONLY_BUILD_TARGETS: bool = true;
            const ONLY_HOSTS: bool = $only_hosts;
            $(const $c: bool = true;)*

            fn should_run(run: ShouldRun) -> ShouldRun {
                let $_config = &run.builder.config;
                run.path($path).default_condition($default_cond)
            }

            fn make_run(run: RunConfig) {
                run.builder.ensure($name {
                    stage: run.builder.top_stage,
                    target: run.target,
                    host: run.host,
                });
            }

            fn run($sel, $builder: &Builder) {
                $run_item
            }
        })+
    }
}

install!((self, builder, _config),
    Docs, "src/doc", _config.docs, only_hosts: false, {
        builder.ensure(dist::Docs { stage: self.stage, host: self.target });
        install_docs(builder, self.stage, self.target);
    };
    Std, "src/libstd", true, only_hosts: true, {
        builder.ensure(dist::Std {
            compiler: builder.compiler(self.stage, self.host),
            target: self.target
        });
        install_std(builder, self.stage);
    };
    Cargo, "cargo", _config.extended, only_hosts: true, {
        builder.ensure(dist::Cargo { stage: self.stage, target: self.target });
        install_cargo(builder, self.stage, self.target);
    };
    Rls, "rls", _config.extended, only_hosts: true, {
        builder.ensure(dist::Rls { stage: self.stage, target: self.target });
        install_rls(builder, self.stage, self.target);
    };
    Analysis, "analysis", _config.extended, only_hosts: false, {
        builder.ensure(dist::Analysis {
            compiler: builder.compiler(self.stage, self.host),
            target: self.target
        });
        install_analysis(builder, self.stage, self.target);
    };
    Src, "src", _config.extended, only_hosts: true, {
        builder.ensure(dist::Src);
        install_src(builder, self.stage);
    }, ONLY_BUILD;
    Rustc, "src/librustc", _config.extended, only_hosts: true, {
        builder.ensure(dist::Rustc {
            compiler: builder.compiler(self.stage, self.target),
        });
        install_rustc(builder, self.stage, self.target);
    };
);
<commit_msg>Include rustc in the default `./x.py install`<commit_after>// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Implementation of the install aspects of the compiler.
//!
//! This module is responsible for installing the standard library,
//! compiler, and documentation.

use std::env;
use std::fs;
use std::path::{Path, PathBuf, Component};
use std::process::Command;

use dist::{self, pkgname, sanitize_sh, tmpdir};

use builder::{Builder, RunConfig, ShouldRun, Step};
use cache::Interned;

pub fn install_docs(builder: &Builder, stage: u32, host: Interned<String>) {
    install_sh(builder, "docs", "rust-docs", stage, Some(host));
}

pub fn install_std(builder: &Builder, stage: u32) {
    for target in &builder.build.targets {
        install_sh(builder, "std", "rust-std", stage, Some(*target));
    }
}

pub fn install_cargo(builder: &Builder, stage: u32, host: Interned<String>) {
    install_sh(builder, "cargo", "cargo", stage, Some(host));
}

pub fn install_rls(builder: &Builder, stage: u32, host: Interned<String>) {
    install_sh(builder, "rls", "rls", stage, Some(host));
}

pub fn install_analysis(builder: &Builder, stage: u32, host: Interned<String>) {
    install_sh(builder, "analysis", "rust-analysis", stage, Some(host));
}

pub fn install_src(builder: &Builder, stage: u32) {
    install_sh(builder, "src", "rust-src", stage, None);
}
pub fn install_rustc(builder: &Builder, stage: u32, host: Interned<String>) {
    install_sh(builder, "rustc", "rustc", stage, Some(host));
}

fn install_sh(
    builder: &Builder,
    package: &str,
    name: &str,
    stage: u32,
    host: Option<Interned<String>>
) {
    let build = builder.build;
    println!("Install {} stage{} ({:?})", package, stage, host);

    let prefix_default = PathBuf::from("/usr/local");
    let sysconfdir_default = PathBuf::from("/etc");
    let docdir_default = PathBuf::from("share/doc/rust");
    let bindir_default = PathBuf::from("bin");
    let libdir_default = PathBuf::from("lib");
    let mandir_default = PathBuf::from("share/man");
    let prefix = build.config.prefix.as_ref().unwrap_or(&prefix_default);
    let sysconfdir = build.config.sysconfdir.as_ref().unwrap_or(&sysconfdir_default);
    let docdir = build.config.docdir.as_ref().unwrap_or(&docdir_default);
    let bindir = build.config.bindir.as_ref().unwrap_or(&bindir_default);
    let libdir = build.config.libdir.as_ref().unwrap_or(&libdir_default);
    let mandir = build.config.mandir.as_ref().unwrap_or(&mandir_default);

    let sysconfdir = prefix.join(sysconfdir);
    let docdir = prefix.join(docdir);
    let bindir = prefix.join(bindir);
    let libdir = prefix.join(libdir);
    let mandir = prefix.join(mandir);

    let destdir = env::var_os("DESTDIR").map(PathBuf::from);

    let prefix = add_destdir(&prefix, &destdir);
    let sysconfdir = add_destdir(&sysconfdir, &destdir);
    let docdir = add_destdir(&docdir, &destdir);
    let bindir = add_destdir(&bindir, &destdir);
    let libdir = add_destdir(&libdir, &destdir);
    let mandir = add_destdir(&mandir, &destdir);

    let empty_dir = build.out.join("tmp/empty_dir");

    t!(fs::create_dir_all(&empty_dir));
    let package_name = if let Some(host) = host {
        format!("{}-{}", pkgname(build, name), host)
    } else {
        pkgname(build, name)
    };

    let mut cmd = Command::new("sh");
    cmd.current_dir(&empty_dir)
        .arg(sanitize_sh(&tmpdir(build).join(&package_name).join("install.sh")))
        .arg(format!("--prefix={}", sanitize_sh(&prefix)))
        .arg(format!("--sysconfdir={}", sanitize_sh(&sysconfdir)))
        .arg(format!("--docdir={}", sanitize_sh(&docdir)))
        .arg(format!("--bindir={}", sanitize_sh(&bindir)))
        .arg(format!("--libdir={}", sanitize_sh(&libdir)))
        .arg(format!("--mandir={}", sanitize_sh(&mandir)))
        .arg("--disable-ldconfig");
    build.run(&mut cmd);
    t!(fs::remove_dir_all(&empty_dir));
}

fn add_destdir(path: &Path, destdir: &Option<PathBuf>) -> PathBuf {
    let mut ret = match *destdir {
        Some(ref dest) => dest.clone(),
        None => return path.to_path_buf(),
    };
    for part in path.components() {
        match part {
            Component::Normal(s) => ret.push(s),
            _ => {}
        }
    }
    ret
}

macro_rules! install {
    (($sel:ident, $builder:ident, $_config:ident),
       $($name:ident,
       $path:expr,
       $default_cond:expr,
       only_hosts: $only_hosts:expr,
       $run_item:block $(, $c:ident)*;)+) => {
        $(
            #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
        pub struct $name {
            pub stage: u32,
            pub target: Interned<String>,
            pub host: Interned<String>,
        }

        impl Step for $name {
            type Output = ();
            const DEFAULT: bool = true;
            const ONLY_BUILD_TARGETS: bool = true;
            const ONLY_HOSTS: bool = $only_hosts;
            $(const $c: bool = true;)*

            fn should_run(run: ShouldRun) -> ShouldRun {
                let $_config = &run.builder.config;
                run.path($path).default_condition($default_cond)
            }

            fn make_run(run: RunConfig) {
                run.builder.ensure($name {
                    stage: run.builder.top_stage,
                    target: run.target,
                    host: run.host,
                });
            }

            fn run($sel, $builder: &Builder) {
                $run_item
            }
        })+
    }
}

install!((self, builder, _config),
    Docs, "src/doc", _config.docs, only_hosts: false, {
        builder.ensure(dist::Docs { stage: self.stage, host: self.target });
        install_docs(builder, self.stage, self.target);
    };
    Std, "src/libstd", true, only_hosts: true, {
        builder.ensure(dist::Std {
            compiler: builder.compiler(self.stage, self.host),
            target: self.target
        });
        install_std(builder, self.stage);
    };
    Cargo, "cargo", _config.extended, only_hosts: true, {
        builder.ensure(dist::Cargo { stage: self.stage, target: self.target });
        install_cargo(builder, self.stage, self.target);
    };
    Rls, "rls", _config.extended, only_hosts: true, {
        builder.ensure(dist::Rls { stage: self.stage, target: self.target });
        install_rls(builder, self.stage, self.target);
    };
    Analysis, "analysis", _config.extended, only_hosts: false, {
        builder.ensure(dist::Analysis {
            compiler: builder.compiler(self.stage, self.host),
            target: self.target
        });
        install_analysis(builder, self.stage, self.target);
    };
    Src, "src", _config.extended, only_hosts: true, {
        builder.ensure(dist::Src);
        install_src(builder, self.stage);
    }, ONLY_BUILD;
    Rustc, "src/librustc", true, only_hosts: true, {
        builder.ensure(dist::Rustc {
            compiler: builder.compiler(self.stage, self.target),
        });
        install_rustc(builder, self.stage, self.target);
    };
);
<|endoftext|>


<commit_before>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#[repr(C)]
enum CEnum {
    Hello = 30,
    World = 60
}

fn test1(c: CEnum) -> i32 {
  let c2 = CEnum::Hello;
  match (c, c2) {
    (CEnum::Hello, CEnum::Hello) => 42,
    (CEnum::World, CEnum::Hello) => 0,
    _ => 1
  }
}

#[repr(packed)]
#[derive(PartialEq, Debug)]
struct Pakd {
    a: u64,
    b: u32,
    c: u16,
    d: u8,
    e: ()
}

impl Drop for Pakd {
    fn drop(&mut self) {}
}

fn test2() -> Pakd {
    Pakd { a: 42, b: 42, c: 42, d: 42, e: () }
}

#[derive(PartialEq, Debug)]
struct TupleLike(u64, u32);

fn test3() -> TupleLike {
    TupleLike(42, 42)
}

fn test4(x: fn(u64, u32) -> TupleLike) -> (TupleLike, TupleLike) {
    let y = TupleLike;
    (x(42, 84), y(42, 84))
}

fn test5(x: fn(u32) -> Option<u32>) -> (Option<u32>, Option<u32>) {
    let y = Some;
    (x(42), y(42))
}

fn main() {
  assert_eq!(test1(CEnum::Hello), 42);
  assert_eq!(test1(CEnum::World), 0);
  assert_eq!(test2(), Pakd { a: 42, b: 42, c: 42, d: 42, e: () });
  assert_eq!(test3(), TupleLike(42, 42));
  let t4 = test4(TupleLike);
  assert_eq!(t4.0, t4.1);
  let t5 = test5(Some);
  assert_eq!(t5.0, t5.1);
}
<commit_msg>Rollup merge of #39682 - solson:fix-unaligned-read, r=eddyb<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::fmt;

#[repr(C)]
enum CEnum {
    Hello = 30,
    World = 60
}

fn test1(c: CEnum) -> i32 {
    let c2 = CEnum::Hello;
    match (c, c2) {
        (CEnum::Hello, CEnum::Hello) => 42,
        (CEnum::World, CEnum::Hello) => 0,
        _ => 1
    }
}

#[repr(packed)]
struct Pakd {
    a: u64,
    b: u32,
    c: u16,
    d: u8,
    e: ()
}

// It is unsafe to use #[derive(Debug)] on a packed struct because the code generated by the derive
// macro takes references to the fields instead of accessing them directly.
impl fmt::Debug for Pakd {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        // It's important that we load the fields into locals by-value here. This will do safe
        // unaligned loads into the locals, then pass references to the properly-aligned locals to
        // the formatting code.
        let Pakd { a, b, c, d, e } = *self;
        f.debug_struct("Pakd")
            .field("a", &a)
            .field("b", &b)
            .field("c", &c)
            .field("d", &d)
            .field("e", &e)
            .finish()
    }
}

// It is unsafe to use #[derive(PartialEq)] on a packed struct because the code generated by the
// derive macro takes references to the fields instead of accessing them directly.
impl PartialEq for Pakd {
    fn eq(&self, other: &Pakd) -> bool {
        self.a == other.a &&
            self.b == other.b &&
            self.c == other.c &&
            self.d == other.d &&
            self.e == other.e
    }
}

impl Drop for Pakd {
    fn drop(&mut self) {}
}

fn test2() -> Pakd {
    Pakd { a: 42, b: 42, c: 42, d: 42, e: () }
}

#[derive(PartialEq, Debug)]
struct TupleLike(u64, u32);

fn test3() -> TupleLike {
    TupleLike(42, 42)
}

fn test4(x: fn(u64, u32) -> TupleLike) -> (TupleLike, TupleLike) {
    let y = TupleLike;
    (x(42, 84), y(42, 84))
}

fn test5(x: fn(u32) -> Option<u32>) -> (Option<u32>, Option<u32>) {
    let y = Some;
    (x(42), y(42))
}

fn main() {
    assert_eq!(test1(CEnum::Hello), 42);
    assert_eq!(test1(CEnum::World), 0);
    assert_eq!(test2(), Pakd { a: 42, b: 42, c: 42, d: 42, e: () });
    assert_eq!(test3(), TupleLike(42, 42));
    let t4 = test4(TupleLike);
    assert_eq!(t4.0, t4.1);
    let t5 = test5(Some);
    assert_eq!(t5.0, t5.1);
}
<|endoftext|>


<commit_before>/// A type for which the layout is determined by its C++ definition.
///
/// This trait serves the following two related purposes.
///
///

///
/// ## Safely unifying occurrences of the same extern type
///
/// `ExternType` makes it possible for CXX to safely share a consistent Rust
/// type across multiple #\[cxx::bridge\] invocations that refer to a common
/// extern C++ type.
///
/// In the following snippet, two #\[cxx::bridge\] invocations in different
/// files (possibly different crates) both contain function signatures involving
/// the same C++ type `example::Demo`. If both were written just containing
/// `type Demo;`, then both macro expansions would produce their own separate
/// Rust type called `Demo` and thus the compiler wouldn't allow us to take the
/// `Demo` returned by `file1::ffi::create_demo` and pass it as the `Demo`
/// argument accepted by `file2::ffi::take_ref_demo`. Instead, one of the two
/// `Demo`s has been defined as an extern type alias of the other, making them
/// the same type in Rust. The CXX code generator will use an automatically
/// generated `ExternType` impl emitted in file1 to statically verify that in
/// file2 `crate::file1::ffi::Demo` really does refer to the C++ type
/// `example::Demo` as expected in file2.
///
/// ```no_run
/// // file1.rs
/// # mod file1 {
/// #[cxx::bridge(namespace = example)]
/// pub mod ffi {
///     extern "C" {
///         type Demo;
///
///         fn create_demo() -> UniquePtr<Demo>;
///     }
/// }
/// # }
///
/// // file2.rs
/// #[cxx::bridge(namespace = example)]
/// pub mod ffi {
///     extern "C" {
///         type Demo = crate::file1::ffi::Demo;
///
///         fn take_ref_demo(demo: &Demo);
///     }
/// }
/// #
/// # fn main() {}
/// ```
///
///

///
/// ## Integrating with bindgen-generated types
///
/// Handwritten `ExternType` impls make it possible to plug in a data structure
/// emitted by bindgen as the definition of a C++ type emitted by CXX.
///
/// By writing the unsafe `ExternType` impl, the programmer asserts that the C++
/// namespace and type name given in the type id refers to a C++ type that is
/// equivalent to Rust type that is the `Self` type of the impl.
///
/// ```no_run
/// # const _: &str = stringify! {
/// mod folly_sys;  // the bindgen-generated bindings
/// # };
/// # mod folly_sys {
/// #     #[repr(transparent)]
/// #     pub struct StringPiece([usize; 2]);
/// # }
///
/// use cxx::{type_id, ExternType};
///
/// unsafe impl ExternType for folly_sys::StringPiece {
///     type Id = type_id!("folly::StringPiece");
///     type Kind = cxx::kind::Opaque;
/// }
///
/// #[cxx::bridge(namespace = folly)]
/// pub mod ffi {
///     extern "C" {
///         include!("rust_cxx_bindings.h");
///
///         type StringPiece = crate::folly_sys::StringPiece;
///
///         fn print_string_piece(s: &StringPiece);
///     }
/// }
///
/// // Now if we construct a StringPiece or obtain one through one
/// // of the bindgen-generated signatures, we are able to pass it
/// // along to ffi::print_string_piece.
/// #
/// # fn main() {}
/// ```
///
/// ## Opaque and Trivial types
///
/// Some C++ types are safe to hold and pass around in Rust, by value.
/// Those C++ types must have a trivial move constructor, and must
/// have no destructor.
///
/// If you believe your C++ type is indeed trivial, you can specify
/// ```
/// # struct TypeName;
/// # unsafe impl cxx::ExternType for TypeName {
/// type Id = cxx::type_id!("name::space::of::TypeName");
/// type Kind = cxx::kind::Trivial;
/// # }
/// ```
/// which will enable you to pass it into C++ functions by value,
/// return it by value from such functions, and include it in
/// `struct`s that you have declared to `cxx::bridge`. Your promises
/// about the triviality of the C++ type will be checked using
/// `static_assert`s in the generated C++.
///
/// Opaque types can't be passed by value, but can still be held
/// in `UniquePtr`.
pub unsafe trait ExternType {
    /// A type-level representation of the type's C++ namespace and type name.
    ///
    /// This will always be defined using `type_id!` in the following form:
    ///
    /// ```
    /// # struct TypeName;
    /// # unsafe impl cxx::ExternType for TypeName {
    /// type Id = cxx::type_id!("name::space::of::TypeName");
    /// type Kind = cxx::kind::Opaque;
    /// # }
    /// ```
    type Id;

    /// Either `cxx::kind::Opaque` or `cxx::kind::Trivial`. If in doubt, use
    /// `cxx::kind::Opaque`.
    type Kind;
}

pub mod kind {
    /// An opaque type which can't be passed or held by value within Rust.
    /// For example, a C++ type with a destructor, or a non-trivial move
    /// constructor. Rust's strict move semantics mean that we can't own
    /// these by value in Rust, but they can still be owned by a
    /// `UniquePtr`...
    pub struct Opaque;

    /// A type with trivial move constructors and no destructor, which
    /// can therefore be owned and moved around in Rust code directly.
    pub struct Trivial;
}

#[doc(hidden)]
pub fn verify_extern_type<T: ExternType<Id = Id>, Id>() {}

#[doc(hidden)]
pub fn verify_extern_kind<T: ExternType<Kind = Kind>, Kind>() {}
<commit_msg>Add documentation of cxx::kind module<commit_after>/// A type for which the layout is determined by its C++ definition.
///
/// This trait serves the following two related purposes.
///
///

///
/// ## Safely unifying occurrences of the same extern type
///
/// `ExternType` makes it possible for CXX to safely share a consistent Rust
/// type across multiple #\[cxx::bridge\] invocations that refer to a common
/// extern C++ type.
///
/// In the following snippet, two #\[cxx::bridge\] invocations in different
/// files (possibly different crates) both contain function signatures involving
/// the same C++ type `example::Demo`. If both were written just containing
/// `type Demo;`, then both macro expansions would produce their own separate
/// Rust type called `Demo` and thus the compiler wouldn't allow us to take the
/// `Demo` returned by `file1::ffi::create_demo` and pass it as the `Demo`
/// argument accepted by `file2::ffi::take_ref_demo`. Instead, one of the two
/// `Demo`s has been defined as an extern type alias of the other, making them
/// the same type in Rust. The CXX code generator will use an automatically
/// generated `ExternType` impl emitted in file1 to statically verify that in
/// file2 `crate::file1::ffi::Demo` really does refer to the C++ type
/// `example::Demo` as expected in file2.
///
/// ```no_run
/// // file1.rs
/// # mod file1 {
/// #[cxx::bridge(namespace = example)]
/// pub mod ffi {
///     extern "C" {
///         type Demo;
///
///         fn create_demo() -> UniquePtr<Demo>;
///     }
/// }
/// # }
///
/// // file2.rs
/// #[cxx::bridge(namespace = example)]
/// pub mod ffi {
///     extern "C" {
///         type Demo = crate::file1::ffi::Demo;
///
///         fn take_ref_demo(demo: &Demo);
///     }
/// }
/// #
/// # fn main() {}
/// ```
///
///

///
/// ## Integrating with bindgen-generated types
///
/// Handwritten `ExternType` impls make it possible to plug in a data structure
/// emitted by bindgen as the definition of a C++ type emitted by CXX.
///
/// By writing the unsafe `ExternType` impl, the programmer asserts that the C++
/// namespace and type name given in the type id refers to a C++ type that is
/// equivalent to Rust type that is the `Self` type of the impl.
///
/// ```no_run
/// # const _: &str = stringify! {
/// mod folly_sys;  // the bindgen-generated bindings
/// # };
/// # mod folly_sys {
/// #     #[repr(transparent)]
/// #     pub struct StringPiece([usize; 2]);
/// # }
///
/// use cxx::{type_id, ExternType};
///
/// unsafe impl ExternType for folly_sys::StringPiece {
///     type Id = type_id!("folly::StringPiece");
///     type Kind = cxx::kind::Opaque;
/// }
///
/// #[cxx::bridge(namespace = folly)]
/// pub mod ffi {
///     extern "C" {
///         include!("rust_cxx_bindings.h");
///
///         type StringPiece = crate::folly_sys::StringPiece;
///
///         fn print_string_piece(s: &StringPiece);
///     }
/// }
///
/// // Now if we construct a StringPiece or obtain one through one
/// // of the bindgen-generated signatures, we are able to pass it
/// // along to ffi::print_string_piece.
/// #
/// # fn main() {}
/// ```
///
///

///
/// ## Opaque and Trivial types
///
/// Some C++ types are safe to hold and pass around in Rust, by value.
/// Those C++ types must have a trivial move constructor, and must
/// have no destructor.
///
/// If you believe your C++ type is indeed trivial, you can specify
/// ```
/// # struct TypeName;
/// # unsafe impl cxx::ExternType for TypeName {
/// type Id = cxx::type_id!("name::space::of::TypeName");
/// type Kind = cxx::kind::Trivial;
/// # }
/// ```
/// which will enable you to pass it into C++ functions by value,
/// return it by value from such functions, and include it in
/// `struct`s that you have declared to `cxx::bridge`. Your promises
/// about the triviality of the C++ type will be checked using
/// `static_assert`s in the generated C++.
///
/// Opaque types can't be passed by value, but can still be held
/// in `UniquePtr`.
pub unsafe trait ExternType {
    /// A type-level representation of the type's C++ namespace and type name.
    ///
    /// This will always be defined using `type_id!` in the following form:
    ///
    /// ```
    /// # struct TypeName;
    /// # unsafe impl cxx::ExternType for TypeName {
    /// type Id = cxx::type_id!("name::space::of::TypeName");
    /// type Kind = cxx::kind::Opaque;
    /// # }
    /// ```
    type Id;

    /// Either `cxx::kind::Opaque` or `cxx::kind::Trivial`. If in doubt, use
    /// `cxx::kind::Opaque`.
    type Kind;
}

/// Marker types identifying Rust's knowledge about an extern C++ type.
///
/// These markers are used in the `Kind` associated type in impls of the
/// [`ExternType`] trait. Refer to the discussion of [Opaque and Trivial
/// types][trait] for an overview of their purpose.
///
/// [trait]: ExternType#opaque-and-trivial-types
pub mod kind {
    /// An opaque type which can't be passed or held by value within Rust.
    /// For example, a C++ type with a destructor, or a non-trivial move
    /// constructor. Rust's strict move semantics mean that we can't own
    /// these by value in Rust, but they can still be owned by a
    /// `UniquePtr`...
    pub struct Opaque;

    /// A type with trivial move constructors and no destructor, which
    /// can therefore be owned and moved around in Rust code directly.
    pub struct Trivial;
}

#[doc(hidden)]
pub fn verify_extern_type<T: ExternType<Id = Id>, Id>() {}

#[doc(hidden)]
pub fn verify_extern_kind<T: ExternType<Kind = Kind>, Kind>() {}
<|endoftext|>


<commit_before>use std::process::Command;
use std::env;

fn main() {
    if env::var("GIT_HASH").is_err() {
        let output = Command::new("git")
            .args(&["rev-parse", "HEAD"])
            .output()
            .unwrap();
        let git_hash = String::from_utf8(output.stdout).unwrap();
        println!("cargo:rustc-env=GIT_HASH={}", git_hash);
    }
    // This is the closest thing to making sure we rebuild this every time a new commit is made
    println!("cargo:rerun-if-changed=../.git/COMMIT_EDITMSG");
}
<commit_msg>chore(repl): Don't rerun the build script if COMMIT_EDITMSG does not exist<commit_after>use std::path::Path;
use std::process::Command;
use std::env;

fn main() {
    if env::var("GIT_HASH").is_err() {
        let output = Command::new("git")
            .args(&["rev-parse", "HEAD"])
            .output()
            .unwrap();
        let git_hash = String::from_utf8(output.stdout).unwrap();
        println!("cargo:rustc-env=GIT_HASH={}", git_hash);
    }

    let edit_msg = Path::new("../.git/COMMIT_EDITMSG");
    if edit_msg.exists() {
        // This is the closest thing to making sure we rebuild this every time a new commit is made
        println!("cargo:rerun-if-changed={}", edit_msg.display());
    }
}
<|endoftext|>


<commit_before>// A port of selecta's scoring algorithm.
// selecta (c) 2014 John Hawthorn
// Licensed under the MIT license

use std::cmp::Ordering;
use super::eq;
use super::mat::Mat;
use super::bonus::compute_bonus;
use super::consts::*;

/// A score derived from comparing needle and haystack strings, with optional
/// match position information.
#[derive(Debug)]
pub struct Score {
    /// The computed score value
    pub value: f64,

    /// Optional vector of match positions
    pub positions: Option<Vec<usize>>
}

impl Score {
    /// Creates a new Score from the provided needle and haystack
    ///
    /// # Examples
    ///
    /// ```
    /// use rff::fuzzy::Score;
    /// let score = Score::new("abc", "abc");
    /// assert_eq!(score.value, std::f64::INFINITY);
    /// ```
    pub fn new(needle: &str, haystack: &str) -> Score {
        let len_n = needle.chars().count();
        let len_h = haystack.chars().count();

        if len_n == 0 {
            return Score { value: SCORE_MIN, positions: None };
        }

        if len_n == len_h {
            return Score { value: SCORE_MAX, positions: None };
        }

        let (m, _) = generate_score_matrices(needle, haystack, len_n, len_h);

        let score = m.get(len_n - 1, len_h - 1).unwrap_or(SCORE_MIN);
        Score { value: score, positions: None }
    }

    /// Creates a new Score from the provided needle and haystack, calculating
    /// match positions.
    ///
    /// # Examples
    ///
    /// ```
    /// use rff::fuzzy::Score;
    /// let score = Score::with_positions("abc", "abc");
    /// assert_eq!(score.value, std::f64::INFINITY);
    /// assert_eq!(score.positions, Some(vec![0, 1, 2]));
    /// ```
    pub fn with_positions(needle: &str, haystack: &str) -> Score {
        let len_n = needle.chars().count();
        let len_h = haystack.chars().count();

        if len_n == 0 {
            return Score { value: SCORE_MIN, positions: None };
        }

        if len_n == len_h {
            return Score {
                value: SCORE_MAX,
                positions: Some((0..len_n).collect())
            };
        }

        let (m, d) = generate_score_matrices(needle, haystack, len_n, len_h);

        let score = m.get(len_n - 1, len_h - 1).unwrap_or(SCORE_MIN);
        let positions = derive_match_positions(m, d, len_n, len_h);

        Score { value: score, positions: Some(positions)}
    }
}

impl PartialOrd for Score {
    #[inline]
    fn partial_cmp(&self, other: &Score) -> Option<Ordering> {
        self.value.partial_cmp(&other.value)
    }
}

impl PartialEq for Score {
    #[inline]
    fn eq(&self, other: &Score) -> bool {
        self.value == other.value
    }
}

#[inline]
fn generate_score_matrices(needle: &str, haystack: &str, len_n: usize, len_h: usize) -> (Mat, Mat) {
    let bonus = compute_bonus(haystack);

    let mut d = Mat::new(len_n, len_h);
    let mut m = Mat::new(len_n, len_h);

    for (i, n) in needle.char_indices() {
        let mut prev_score = SCORE_MIN;
        let gap_score = if i == len_n - 1 { SCORE_GAP_TRAILING } else { SCORE_GAP_INNER };

        for (j, h) in haystack.char_indices() {
            if eq(n, h) {
                let mut score = SCORE_MIN;

                let bonus_score = bonus[j];

                if i == 0 {
                    score = ((j as f64) * SCORE_GAP_LEADING) + bonus_score;
                } else if j > 0 {
                    let m = m.get(i - 1, j - 1).unwrap();
                    let d = d.get(i - 1, j - 1).unwrap();

                    score = (m + bonus_score).max(d + SCORE_MATCH_CONSECUTIVE);
                }

                prev_score = score.max(prev_score + gap_score);

                d.set(i, j, score);
                m.set(i, j, prev_score);
            } else {
                d.set(i, j, SCORE_MIN);
                m.set(i, j, prev_score + gap_score);
                prev_score += gap_score;
            }
        }
    }

    (m, d)
}

/// Given the length of the input strings, and generated scoring matrices,
/// generates a len_n vector of optimal match positions for each haystack char.
#[inline]
fn derive_match_positions(m: Mat, d: Mat, len_n: usize, len_h: usize) -> Vec<usize> {
    let mut positions = vec![0 as usize; len_n];
    let mut match_required = false;

    let mut j = len_h - 1;

    for i in (0..len_n).rev() {
        while j > (0 as usize) {
            let last = if i > 0 && j > 0 { d.get(i - 1, j - 1).unwrap() } else { 0.0 };

            let d = d.get(i, j).unwrap();
            let m = m.get(i, j).unwrap();

            if d != SCORE_MIN && (match_required || d == m) {
                if i > 0 && j > 0 && m == last + SCORE_MATCH_CONSECUTIVE {
                    match_required = true;
                }

                positions[i] = j;

                break;
            }

            j -= 1
        }
    }

    positions
}

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

    fn score(needle: &str, haystack: &str) -> Score {
        Score::new(needle, haystack)
    }

    #[test]
    fn test_eq() {
        let a = Score { value: 1.0, positions: None };
        let b = Score { value: 1.0, positions: None };
        assert_eq!(a, b);
    }

    #[test]
    fn test_cmp() {
        let a = Score { value: 2.0, positions: None };
        let b = Score { value: 1.0, positions: None };
        assert!(a > b);
        assert!(b < a);

        let b = Score { value: 2.0, positions: None };
        assert!(a == b);
    }

    #[test]
    fn relative_scores() {
        // App/Models/Order is better than App/MOdels/zRder
        assert!(score("amor", "app/models/order") > score("amor", "app/models/zrder"));

        // App/MOdels/foo is better than App/M/fOo
        assert!(score("amo", "app/m/foo") < score("amo", "app/models/foo"));

        // GEMFIle.Lock < GEMFILe
        assert!(score("gemfil", "Gemfile.lock") < score("gemfil", "Gemfile"));

        // GEMFIle.Lock < GEMFILe
        assert!(score("gemfil", "Gemfile.lock") < score("gemfil", "Gemfile"));

        // Prefer shorter scorees
        assert!(score("abce", "abcdef") > score("abce", "abc de"));

        // Prefer shorter candidates
        assert!(score("test", "tests") > score("test", "testing"));

        // Scores first letter highly
        assert!(score("test", "testing") > score("test", "/testing"));

        // Prefer shorter scorees
        assert!(score("abc", "    a b c ") > score("abc", " a  b  c "));
        assert!(score("abc", " a b c    ") > score("abc", " a  b  c "));
    }

    #[test]
    fn positions() {
        macro_rules! test_positions {
            ($needle:expr, $haystack:expr, $result:expr) => {
                let score = Score::with_positions($needle, $haystack);
                assert_eq!(score.positions, Some($result));
            }
        }

        test_positions!("amo", "app/models/foo", vec![0, 4, 5]);
        test_positions!("amor", "app/models/order", vec![0, 4, 11, 12]);
        test_positions!("as", "tags", vec![1, 3]);
        test_positions!("abc", "a/a/b/c/c", vec![2, 4, 6]);
        test_positions!("foo", "foo", vec![0, 1, 2]);
        test_positions!("drivers", "/path/to/drivers/file.txt", vec![9, 10, 11, 12, 13, 14, 15]);
    }
}
<commit_msg>Actually don't use char_indicies<commit_after>// A port of selecta's scoring algorithm.
// selecta (c) 2014 John Hawthorn
// Licensed under the MIT license

use std::cmp::Ordering;
use super::eq;
use super::mat::Mat;
use super::bonus::compute_bonus;
use super::consts::*;

/// A score derived from comparing needle and haystack strings, with optional
/// match position information.
#[derive(Debug)]
pub struct Score {
    /// The computed score value
    pub value: f64,

    /// Optional vector of match positions
    pub positions: Option<Vec<usize>>
}

impl Score {
    /// Creates a new Score from the provided needle and haystack
    ///
    /// # Examples
    ///
    /// ```
    /// use rff::fuzzy::Score;
    /// let score = Score::new("abc", "abc");
    /// assert_eq!(score.value, std::f64::INFINITY);
    /// ```
    pub fn new(needle: &str, haystack: &str) -> Score {
        let len_n = needle.chars().count();
        let len_h = haystack.chars().count();

        if len_n == 0 {
            return Score { value: SCORE_MIN, positions: None };
        }

        if len_n == len_h {
            return Score { value: SCORE_MAX, positions: None };
        }

        let (m, _) = generate_score_matrices(needle, haystack, len_n, len_h);

        let score = m.get(len_n - 1, len_h - 1).unwrap_or(SCORE_MIN);
        Score { value: score, positions: None }
    }

    /// Creates a new Score from the provided needle and haystack, calculating
    /// match positions.
    ///
    /// # Examples
    ///
    /// ```
    /// use rff::fuzzy::Score;
    /// let score = Score::with_positions("abc", "abc");
    /// assert_eq!(score.value, std::f64::INFINITY);
    /// assert_eq!(score.positions, Some(vec![0, 1, 2]));
    /// ```
    pub fn with_positions(needle: &str, haystack: &str) -> Score {
        let len_n = needle.chars().count();
        let len_h = haystack.chars().count();

        if len_n == 0 {
            return Score { value: SCORE_MIN, positions: None };
        }

        if len_n == len_h {
            return Score {
                value: SCORE_MAX,
                positions: Some((0..len_n).collect())
            };
        }

        let (m, d) = generate_score_matrices(needle, haystack, len_n, len_h);

        let score = m.get(len_n - 1, len_h - 1).unwrap_or(SCORE_MIN);
        let positions = derive_match_positions(m, d, len_n, len_h);

        Score { value: score, positions: Some(positions)}
    }
}

impl PartialOrd for Score {
    #[inline]
    fn partial_cmp(&self, other: &Score) -> Option<Ordering> {
        self.value.partial_cmp(&other.value)
    }
}

impl PartialEq for Score {
    #[inline]
    fn eq(&self, other: &Score) -> bool {
        self.value == other.value
    }
}

#[inline]
fn generate_score_matrices(needle: &str, haystack: &str, len_n: usize, len_h: usize) -> (Mat, Mat) {
    let bonus = compute_bonus(haystack);

    let mut d = Mat::new(len_n, len_h);
    let mut m = Mat::new(len_n, len_h);

    for (i, n) in needle.chars().enumerate() {
        let mut prev_score = SCORE_MIN;
        let gap_score = if i == len_n - 1 { SCORE_GAP_TRAILING } else { SCORE_GAP_INNER };

        for (j, h) in haystack.chars().enumerate() {
            if eq(n, h) {
                let mut score = SCORE_MIN;

                let bonus_score = bonus[j];

                if i == 0 {
                    score = ((j as f64) * SCORE_GAP_LEADING) + bonus_score;
                } else if j > 0 {
                    let m = m.get(i - 1, j - 1).unwrap();
                    let d = d.get(i - 1, j - 1).unwrap();

                    score = (m + bonus_score).max(d + SCORE_MATCH_CONSECUTIVE);
                }

                prev_score = score.max(prev_score + gap_score);

                d.set(i, j, score);
                m.set(i, j, prev_score);
            } else {
                d.set(i, j, SCORE_MIN);
                m.set(i, j, prev_score + gap_score);
                prev_score += gap_score;
            }
        }
    }

    (m, d)
}

/// Given the length of the input strings, and generated scoring matrices,
/// generates a len_n vector of optimal match positions for each haystack char.
#[inline]
fn derive_match_positions(m: Mat, d: Mat, len_n: usize, len_h: usize) -> Vec<usize> {
    let mut positions = vec![0 as usize; len_n];
    let mut match_required = false;

    let mut j = len_h - 1;

    for i in (0..len_n).rev() {
        while j > (0 as usize) {
            let last = if i > 0 && j > 0 { d.get(i - 1, j - 1).unwrap() } else { 0.0 };

            let d = d.get(i, j).unwrap();
            let m = m.get(i, j).unwrap();

            if d != SCORE_MIN && (match_required || d == m) {
                if i > 0 && j > 0 && m == last + SCORE_MATCH_CONSECUTIVE {
                    match_required = true;
                }

                positions[i] = j;

                break;
            }

            j -= 1
        }
    }

    positions
}

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

    fn score(needle: &str, haystack: &str) -> Score {
        Score::new(needle, haystack)
    }

    #[test]
    fn test_eq() {
        let a = Score { value: 1.0, positions: None };
        let b = Score { value: 1.0, positions: None };
        assert_eq!(a, b);
    }

    #[test]
    fn test_cmp() {
        let a = Score { value: 2.0, positions: None };
        let b = Score { value: 1.0, positions: None };
        assert!(a > b);
        assert!(b < a);

        let b = Score { value: 2.0, positions: None };
        assert!(a == b);
    }

    #[test]
    fn relative_scores() {
        // App/Models/Order is better than App/MOdels/zRder
        assert!(score("amor", "app/models/order") > score("amor", "app/models/zrder"));

        // App/MOdels/foo is better than App/M/fOo
        assert!(score("amo", "app/m/foo") < score("amo", "app/models/foo"));

        // GEMFIle.Lock < GEMFILe
        assert!(score("gemfil", "Gemfile.lock") < score("gemfil", "Gemfile"));

        // GEMFIle.Lock < GEMFILe
        assert!(score("gemfil", "Gemfile.lock") < score("gemfil", "Gemfile"));

        // Prefer shorter scorees
        assert!(score("abce", "abcdef") > score("abce", "abc de"));

        // Prefer shorter candidates
        assert!(score("test", "tests") > score("test", "testing"));

        // Scores first letter highly
        assert!(score("test", "testing") > score("test", "/testing"));

        // Prefer shorter scorees
        assert!(score("abc", "    a b c ") > score("abc", " a  b  c "));
        assert!(score("abc", " a b c    ") > score("abc", " a  b  c "));
    }

    #[test]
    fn score_utf8() {
        assert_eq!(score("ß", "öäßéè").value, -0.02);
    }

    #[test]
    fn positions() {
        macro_rules! test_positions {
            ($needle:expr, $haystack:expr, $result:expr) => {
                let score = Score::with_positions($needle, $haystack);
                assert_eq!(score.positions, Some($result));
            }
        }

        test_positions!("amo", "app/models/foo", vec![0, 4, 5]);
        test_positions!("amor", "app/models/order", vec![0, 4, 11, 12]);
        test_positions!("as", "tags", vec![1, 3]);
        test_positions!("abc", "a/a/b/c/c", vec![2, 4, 6]);
        test_positions!("foo", "foo", vec![0, 1, 2]);
        test_positions!("drivers", "/path/to/drivers/file.txt", vec![9, 10, 11, 12, 13, 14, 15]);
    }
}
<|endoftext|>


<commit_before>use cblas;
use ndarray::{
    Data,
    IntoDimension,
};
use ndarray::prelude::*;
use std::slice;

#[derive(Clone, Debug)]
pub struct ReorthogonalizedGramSchmidt {
    q: Array2<f64>,
    r: Array2<f64>,
    work_vector: Array1<f64>,
    memory_order: cblas::Layout,
    dirty: bool,
}

impl ReorthogonalizedGramSchmidt {
    /// Reserves the memory for a QR decomposition via a classical, reorthogonalized Gram Schmidt
    /// orthogonalization using the dimensions of a sample matrix. This is also known as CGS2 in
    /// the literature. See [Giraud et al.] for a definition.
    ///
    /// The resulting object can be used to orthogonalize matrices of the same dimensions.
    ///
    /// [Giraud et al.]: https://doi.org/10.1007/s00211-005-0615-4
    ///
    /// # Example
    ///
    /// ```
    /// extern crate gram_schmidt;
    /// extern crate ndarray;
    /// extern crate ndarray_rand;
    /// extern crate rand;
    ///
    /// use gram_schmidt::ReorthogonalizedGramSchmidt;
    /// use ndarray::Array2;
    /// use ndarray_rand::RandomExt;
    /// use rand::distributions::Normal;
    ///
    /// # fn main() {
    ///
    /// let matrix = Array2::random((10,10), Normal::new(0.0, 1.0));
    /// let mut cgs2 = ReorthogonalizedGramSchmidt::from_matrix(&matrix);
    ///
    /// # }
    /// ```
    pub fn from_matrix<S>(a: &ArrayBase<S, Ix2>) -> Self
        where S: Data<Elem = f64>
    {
        let (is_fortran, memory_order) = if let Some(_) = a.as_slice() {
            (false, cblas::Layout::RowMajor)
        } else if let Some(_) = a.as_slice_memory_order() {
            (true, cblas::Layout::ColumnMajor)
        } else {
            panic!("Array not contiguous!")
        };

        let array_shape = a.raw_dim().set_f(is_fortran);

        ReorthogonalizedGramSchmidt {
            q: Array2::zeros(array_shape),
            r: Array2::zeros(array_shape),
            work_vector: Array1::zeros(a.dim().0),
            memory_order,
            dirty: false,
        }
    }

    /// Reserves the memory for a QR decomposition via a classical, reorthogonalized Gram Schmidt
    /// orthogonalization using a shape.
    ///
    /// The resulting object can be used to orthogonalize matrices of the same dimensions.
    ///
    /// # Example
    ///
    /// ```
    /// extern crate gram_schmidt;
    ///
    /// use gram_schmidt::ReorthogonalizedGramSchmidt;
    ///
    /// # fn main() {
    /// let fortran_order = false;
    /// let mut cgs2 = ReorthogonalizedGramSchmidt::from_shape((10,10), fortran_order);
    ///
    /// # }
    /// ```
    pub fn from_shape<T>(shape: T, fortran_order: bool) -> Self
        where T: IntoDimension<Dim = Ix2>,
    {
        let dimension = shape.into_dimension();
        let rows = dimension.into_pattern().0;
        let array_shape = dimension.set_f(fortran_order);
        let memory_order = if fortran_order {
            cblas::Layout::ColumnMajor
        } else {
            cblas::Layout::RowMajor
        };

        ReorthogonalizedGramSchmidt {
            q: Array2::zeros(array_shape),
            r: Array2::zeros(array_shape),
            work_vector: Array1::zeros(rows),
            memory_order,
            dirty: false,
        }
    }

    /// Computes a QR decomposition using the classical, reorthogonalized Gram Schmidt
    /// orthonormalization of the matrix `a`.
    ///
    /// The input matrix `a` has to have exactly the same dimension and memory layout as was
    /// previously configured. Panics otherwise.
    ///
    /// ```
    /// extern crate gram_schmidt;
    /// extern crate ndarray;
    /// extern crate ndarray_rand;
    /// extern crate rand;
    ///
    /// use gram_schmidt::ReorthogonalizedGramSchmidt;
    /// use ndarray::Array2;
    /// use ndarray_rand::RandomExt;
    /// use rand::distributions::Normal;
    ///
    /// # fn main() {
    ///
    /// let matrix = Array2::random((10,10), Normal::new(0.0, 1.0));
    /// let mut cgs2 = ReorthogonalizedGramSchmidt::from_matrix(&matrix);
    /// cgs2.compute(&matrix);
    ///
    /// # }
    /// ```
    pub fn compute<S>(&mut self, a: &ArrayBase<S, Ix2>)
        where S: Data<Elem = f64>,
    {
        assert_eq!(a.shape(), self.q.shape());
        // assert_eq!(a.strides(), self.q.strides());

        let (n_rows, n_cols) = self.q.dim();

        let (a_column_inc, a_layout) = if let Some(_) = a.as_slice() {
            (n_cols as i32, cblas::Layout::RowMajor)
        } else if let Some(_) = a.as_slice_memory_order() {
            (1, cblas::Layout::RowMajor)
        } else {
            panic!("Array not contiguous!")
        };

        // If the struct was previously used for a computation, r needs to be cleaned.
        // q is always overwritten, but r is not.
        if self.dirty {
            self.r.fill(0.0);
        }

        for i in 0..n_cols {
            self.q.column_mut(i).assign(&a.column(i));
            let a_column = match a_layout {
                cblas::Layout::RowMajor => &a.as_slice_memory_order().unwrap()[i..],
                cblas::Layout::ColumnMajor => &a.as_slice_memory_order().unwrap()[n_rows * i..],
            };

            if i > 0 {
                let (lda, r_column, r_inc) = match self.memory_order {
                    cblas::Layout::RowMajor => {
                        let r_column = &mut self.r.as_slice_memory_order_mut().unwrap()[i..];
                        (n_cols as i32, r_column, n_cols as i32)
                    },

                    cblas::Layout::ColumnMajor => {
                        let r_column = &mut self.r.as_slice_memory_order_mut().unwrap()[n_rows*i..];
                        (n_rows as i32, r_column, 1)
                    },
                };

                // The unsafe blocks below are because we need several overlapping slices into the
                // q matrix. The mutable `q_column` is the i-th orthogonal vector which is currently
                // being sought. The immutable `q` represents the already found vectors (vectors 0
                // to i-1). Appropriately choosing the offset, lda, and increment makes sure that
                // blas does not access the same memory location.
                //
                // This is only necessary for row major formats. In column major formats there
                // won't be overlaps.
                let len = self.q.len();
                let q_ptr = self.q.as_mut_ptr();
                let q = unsafe {
                    slice::from_raw_parts(q_ptr, len)
                };
                let (q_column, q_inc) = match self.memory_order {
                    cblas::Layout::RowMajor => {
                        let offset = i as isize;
                        let q_column = unsafe {
                            slice::from_raw_parts_mut(q_ptr.offset(offset), len - i)
                        };
                        (q_column, n_cols as i32)
                    },

                    cblas::Layout::ColumnMajor => {
                        let offset = n_rows * i;
                        let q_column = unsafe {
                            slice::from_raw_parts_mut(q_ptr.offset(offset as isize), len - offset)
                        };
                        (q_column, 1)
                    },
                };

                let work_vector = self.work_vector.as_slice_memory_order_mut().unwrap();

                unsafe {
                    cblas::dgemv(
                        self.memory_order, // layout
                        cblas::Transpose::Ordinary, // transa
                        n_rows as i32, // m
                        i as i32, // n
                        1.0, // alpha
                        q, // a
                        lda, // lda
                        a_column, // x
                        a_column_inc, // incx
                        0.0, // beta
                        r_column, //y
                        r_inc // incy
                    );

                    cblas::dgemv(
                        self.memory_order, // layout
                        cblas::Transpose::None, // transa
                        n_rows as i32, // m
                        i as i32, // n
                        -1.0, // alpha
                        q, // a
                        lda, // lda
                        r_column, // y
                        r_inc, // incx
                        1.0, // beta
                        q_column, // y
                        q_inc, // incy
                    );

                    cblas::dgemv(
                        self.memory_order, // layout
                        cblas::Transpose::Ordinary, // transa
                        n_rows as i32, // m
                        i as i32, // n
                        1.0, // alpha
                        q, // a
                        lda, // lda
                        q_column, // x
                        q_inc, // incx
                        0.0, // beta
                        work_vector, //y
                        1 // incy
                    );

                    cblas::dgemv(
                        self.memory_order, // layout
                        cblas::Transpose::None, // transa
                        n_rows as i32, // m
                        i as i32, // n
                        -1.0, // alpha
                        q, // a
                        lda, // lda
                        work_vector, // y
                        1, // incx
                        1.0, // beta
                        q_column, // y
                        q_inc, // incy
                    );

                    cblas::daxpy(
                        n_rows as i32, // n
                        1.0, // alpha
                        work_vector, // x
                        1, // incx
                        r_column, // y
                        r_inc, // incy
                    );

                }
            };

            let norm = {
                let len = self.q.len();
                let q_ptr = self.q.as_mut_ptr();
                unsafe {
                    let (q_column, q_inc) = match self.memory_order {
                        cblas::Layout::RowMajor => {
                            let offset = i as isize;
                            let q_column = slice::from_raw_parts_mut(q_ptr.offset(offset), len - i);
                            (q_column, n_cols as i32)
                        },

                        cblas::Layout::ColumnMajor => {
                            let offset = n_rows * i;
                            let q_column = slice::from_raw_parts_mut(q_ptr.offset(offset as isize), len - offset);
                            (q_column, 1)
                        },
                    };
                    cblas::dnrm2(n_rows as i32, q_column, q_inc)
                }
            };

            let mut v = self.q.column_mut(i);
            v /= norm;
            self.r[(i,i)] = a.column(i).dot(&v);
        }
    }

    /// Return a reference to the matrix q.
    pub fn q(&self) -> &Array2<f64> {
        &self.q
    }

    /// Return a reference to the matrix q.
    pub fn r(&self) -> &Array2<f64> {
        &self.r
    }
}

#[cfg(test)]
mod tests {
    use ndarray::prelude::*;
    use super::*;
    #[test]
    fn unity_is_unity() {
        let a = arr2(&[[1.0, 0.0, 0.0, 0.0],
                       [0.0, 1.0, 0.0, 0.0],
                       [0.0, 0.0, 1.0, 0.0],
                       [0.0, 0.0, 0.0, 1.0]]);

        let mut cgs2 = ReorthogonalizedGramSchmidt::from_matrix(&a);
        cgs2.compute(&a);

        assert_eq!(a, cgs2.q().dot(cgs2.r()));
    }
}
<commit_msg>Fix linking to openblas_src in doc test<commit_after>use cblas;
use ndarray::{
    Data,
    IntoDimension,
};
use ndarray::prelude::*;
use std::slice;

#[derive(Clone, Debug)]
pub struct ReorthogonalizedGramSchmidt {
    q: Array2<f64>,
    r: Array2<f64>,
    work_vector: Array1<f64>,
    memory_order: cblas::Layout,
    dirty: bool,
}

impl ReorthogonalizedGramSchmidt {
    /// Reserves the memory for a QR decomposition via a classical, reorthogonalized Gram Schmidt
    /// orthogonalization using the dimensions of a sample matrix. This is also known as CGS2 in
    /// the literature. See [Giraud et al.] for a definition.
    ///
    /// The resulting object can be used to orthogonalize matrices of the same dimensions.
    ///
    /// [Giraud et al.]: https://doi.org/10.1007/s00211-005-0615-4
    ///
    /// # Example
    ///
    /// ```
    /// extern crate gram_schmidt;
    /// extern crate ndarray;
    /// extern crate ndarray_rand;
    /// extern crate rand;
    ///
    /// use gram_schmidt::ReorthogonalizedGramSchmidt;
    /// use ndarray::Array2;
    /// use ndarray_rand::RandomExt;
    /// use rand::distributions::Normal;
    ///
    /// # fn main() {
    ///
    /// let matrix = Array2::random((10,10), Normal::new(0.0, 1.0));
    /// let mut cgs2 = ReorthogonalizedGramSchmidt::from_matrix(&matrix);
    ///
    /// # }
    /// ```
    pub fn from_matrix<S>(a: &ArrayBase<S, Ix2>) -> Self
        where S: Data<Elem = f64>
    {
        let (is_fortran, memory_order) = if let Some(_) = a.as_slice() {
            (false, cblas::Layout::RowMajor)
        } else if let Some(_) = a.as_slice_memory_order() {
            (true, cblas::Layout::ColumnMajor)
        } else {
            panic!("Array not contiguous!")
        };

        let array_shape = a.raw_dim().set_f(is_fortran);

        ReorthogonalizedGramSchmidt {
            q: Array2::zeros(array_shape),
            r: Array2::zeros(array_shape),
            work_vector: Array1::zeros(a.dim().0),
            memory_order,
            dirty: false,
        }
    }

    /// Reserves the memory for a QR decomposition via a classical, reorthogonalized Gram Schmidt
    /// orthogonalization using a shape.
    ///
    /// The resulting object can be used to orthogonalize matrices of the same dimensions.
    ///
    /// # Example
    ///
    /// ```
    /// extern crate gram_schmidt;
    ///
    /// use gram_schmidt::ReorthogonalizedGramSchmidt;
    ///
    /// # fn main() {
    /// let fortran_order = false;
    /// let mut cgs2 = ReorthogonalizedGramSchmidt::from_shape((10,10), fortran_order);
    ///
    /// # }
    /// ```
    pub fn from_shape<T>(shape: T, fortran_order: bool) -> Self
        where T: IntoDimension<Dim = Ix2>,
    {
        let dimension = shape.into_dimension();
        let rows = dimension.into_pattern().0;
        let array_shape = dimension.set_f(fortran_order);
        let memory_order = if fortran_order {
            cblas::Layout::ColumnMajor
        } else {
            cblas::Layout::RowMajor
        };

        ReorthogonalizedGramSchmidt {
            q: Array2::zeros(array_shape),
            r: Array2::zeros(array_shape),
            work_vector: Array1::zeros(rows),
            memory_order,
            dirty: false,
        }
    }

    /// Computes a QR decomposition using the classical, reorthogonalized Gram Schmidt
    /// orthonormalization of the matrix `a`.
    ///
    /// The input matrix `a` has to have exactly the same dimension and memory layout as was
    /// previously configured. Panics otherwise.
    ///
    /// ```
    /// extern crate gram_schmidt;
    /// extern crate ndarray;
    /// extern crate ndarray_rand;
    /// extern crate openblas_src;
    /// extern crate rand;
    ///
    /// use gram_schmidt::ReorthogonalizedGramSchmidt;
    /// use ndarray::Array2;
    /// use ndarray_rand::RandomExt;
    /// use rand::distributions::Normal;
    ///
    /// # fn main() {
    ///
    /// let matrix = Array2::random((10,10), Normal::new(0.0, 1.0));
    /// let mut cgs2 = ReorthogonalizedGramSchmidt::from_matrix(&matrix);
    /// cgs2.compute(&matrix);
    ///
    /// # }
    /// ```
    pub fn compute<S>(&mut self, a: &ArrayBase<S, Ix2>)
        where S: Data<Elem = f64>,
    {
        assert_eq!(a.shape(), self.q.shape());
        // assert_eq!(a.strides(), self.q.strides());

        let (n_rows, n_cols) = self.q.dim();

        let (a_column_inc, a_layout) = if let Some(_) = a.as_slice() {
            (n_cols as i32, cblas::Layout::RowMajor)
        } else if let Some(_) = a.as_slice_memory_order() {
            (1, cblas::Layout::RowMajor)
        } else {
            panic!("Array not contiguous!")
        };

        // If the struct was previously used for a computation, r needs to be cleaned.
        // q is always overwritten, but r is not.
        if self.dirty {
            self.r.fill(0.0);
        }

        for i in 0..n_cols {
            self.q.column_mut(i).assign(&a.column(i));
            let a_column = match a_layout {
                cblas::Layout::RowMajor => &a.as_slice_memory_order().unwrap()[i..],
                cblas::Layout::ColumnMajor => &a.as_slice_memory_order().unwrap()[n_rows * i..],
            };

            if i > 0 {
                let (lda, r_column, r_inc) = match self.memory_order {
                    cblas::Layout::RowMajor => {
                        let r_column = &mut self.r.as_slice_memory_order_mut().unwrap()[i..];
                        (n_cols as i32, r_column, n_cols as i32)
                    },

                    cblas::Layout::ColumnMajor => {
                        let r_column = &mut self.r.as_slice_memory_order_mut().unwrap()[n_rows*i..];
                        (n_rows as i32, r_column, 1)
                    },
                };

                // The unsafe blocks below are because we need several overlapping slices into the
                // q matrix. The mutable `q_column` is the i-th orthogonal vector which is currently
                // being sought. The immutable `q` represents the already found vectors (vectors 0
                // to i-1). Appropriately choosing the offset, lda, and increment makes sure that
                // blas does not access the same memory location.
                //
                // This is only necessary for row major formats. In column major formats there
                // won't be overlaps.
                let len = self.q.len();
                let q_ptr = self.q.as_mut_ptr();
                let q = unsafe {
                    slice::from_raw_parts(q_ptr, len)
                };
                let (q_column, q_inc) = match self.memory_order {
                    cblas::Layout::RowMajor => {
                        let offset = i as isize;
                        let q_column = unsafe {
                            slice::from_raw_parts_mut(q_ptr.offset(offset), len - i)
                        };
                        (q_column, n_cols as i32)
                    },

                    cblas::Layout::ColumnMajor => {
                        let offset = n_rows * i;
                        let q_column = unsafe {
                            slice::from_raw_parts_mut(q_ptr.offset(offset as isize), len - offset)
                        };
                        (q_column, 1)
                    },
                };

                let work_vector = self.work_vector.as_slice_memory_order_mut().unwrap();

                unsafe {
                    cblas::dgemv(
                        self.memory_order, // layout
                        cblas::Transpose::Ordinary, // transa
                        n_rows as i32, // m
                        i as i32, // n
                        1.0, // alpha
                        q, // a
                        lda, // lda
                        a_column, // x
                        a_column_inc, // incx
                        0.0, // beta
                        r_column, //y
                        r_inc // incy
                    );

                    cblas::dgemv(
                        self.memory_order, // layout
                        cblas::Transpose::None, // transa
                        n_rows as i32, // m
                        i as i32, // n
                        -1.0, // alpha
                        q, // a
                        lda, // lda
                        r_column, // y
                        r_inc, // incx
                        1.0, // beta
                        q_column, // y
                        q_inc, // incy
                    );

                    cblas::dgemv(
                        self.memory_order, // layout
                        cblas::Transpose::Ordinary, // transa
                        n_rows as i32, // m
                        i as i32, // n
                        1.0, // alpha
                        q, // a
                        lda, // lda
                        q_column, // x
                        q_inc, // incx
                        0.0, // beta
                        work_vector, //y
                        1 // incy
                    );

                    cblas::dgemv(
                        self.memory_order, // layout
                        cblas::Transpose::None, // transa
                        n_rows as i32, // m
                        i as i32, // n
                        -1.0, // alpha
                        q, // a
                        lda, // lda
                        work_vector, // y
                        1, // incx
                        1.0, // beta
                        q_column, // y
                        q_inc, // incy
                    );

                    cblas::daxpy(
                        n_rows as i32, // n
                        1.0, // alpha
                        work_vector, // x
                        1, // incx
                        r_column, // y
                        r_inc, // incy
                    );

                }
            };

            let norm = {
                let len = self.q.len();
                let q_ptr = self.q.as_mut_ptr();
                unsafe {
                    let (q_column, q_inc) = match self.memory_order {
                        cblas::Layout::RowMajor => {
                            let offset = i as isize;
                            let q_column = slice::from_raw_parts_mut(q_ptr.offset(offset), len - i);
                            (q_column, n_cols as i32)
                        },

                        cblas::Layout::ColumnMajor => {
                            let offset = n_rows * i;
                            let q_column = slice::from_raw_parts_mut(q_ptr.offset(offset as isize), len - offset);
                            (q_column, 1)
                        },
                    };
                    cblas::dnrm2(n_rows as i32, q_column, q_inc)
                }
            };

            let mut v = self.q.column_mut(i);
            v /= norm;
            self.r[(i,i)] = a.column(i).dot(&v);
        }
    }

    /// Return a reference to the matrix q.
    pub fn q(&self) -> &Array2<f64> {
        &self.q
    }

    /// Return a reference to the matrix q.
    pub fn r(&self) -> &Array2<f64> {
        &self.r
    }
}

#[cfg(test)]
mod tests {
    use ndarray::prelude::*;
    use super::*;
    #[test]
    fn unity_is_unity() {
        let a = arr2(&[[1.0, 0.0, 0.0, 0.0],
                       [0.0, 1.0, 0.0, 0.0],
                       [0.0, 0.0, 1.0, 0.0],
                       [0.0, 0.0, 0.0, 1.0]]);

        let mut cgs2 = ReorthogonalizedGramSchmidt::from_matrix(&a);
        cgs2.compute(&a);

        assert_eq!(a, cgs2.q().dot(cgs2.r()));
    }
}
<|endoftext|>