<commit_before>//! Codegen of the [`PointerCast::Unsize`] operation.
//!
//! [`PointerCast::Unsize`]: `rustc_middle::ty::adjustment::PointerCast::Unsize`

use crate::prelude::*;

// Adapted from https://github.com/rust-lang/rust/blob/2a663555ddf36f6b041445894a8c175cd1bc718c/src/librustc_codegen_ssa/base.rs#L159-L307

/// Retrieve the information we are losing (making dynamic) in an unsizing
/// adjustment.
///
/// The `old_info` argument is a bit funny. It is intended for use
/// in an upcast, where the new vtable for an object will be derived
/// from the old one.
pub(crate) fn unsized_info<'tcx>(
    fx: &mut FunctionCx<'_, '_, 'tcx>,
    source: Ty<'tcx>,
    target: Ty<'tcx>,
    old_info: Option<Value>,
) -> Value {
    let (source, target) =
        fx.tcx.struct_lockstep_tails_erasing_lifetimes(source, target, ParamEnv::reveal_all());
    match (&source.kind(), &target.kind()) {
        (&ty::Array(_, len), &ty::Slice(_)) => fx
            .bcx
            .ins()
            .iconst(fx.pointer_type, len.eval_usize(fx.tcx, ParamEnv::reveal_all()) as i64),
        (&ty::Dynamic(ref data_a, ..), &ty::Dynamic(ref data_b, ..)) => {
            let old_info =
                old_info.expect("unsized_info: missing old info for trait upcasting coercion");
            if data_a.principal_def_id() == data_b.principal_def_id() {
                return old_info;
            }
            // trait upcasting coercion

            // if both of the two `principal`s are `None`, this function would have returned early above.
            // and if one of the two `principal`s is `None`, typechecking would have rejected this case.
            let principal_a = data_a
                .principal()
                .expect("unsized_info: missing principal trait for trait upcasting coercion");
            let principal_b = data_b
                .principal()
                .expect("unsized_info: missing principal trait for trait upcasting coercion");

            let vptr_entry_idx = fx.tcx.vtable_trait_upcasting_coercion_new_vptr_slot((
                principal_a.with_self_ty(fx.tcx, source),
                principal_b.with_self_ty(fx.tcx, source),
            ));

            if let Some(entry_idx) = vptr_entry_idx {
                let entry_idx = u32::try_from(entry_idx).unwrap();
                let entry_offset = entry_idx * fx.pointer_type.bytes();
                let vptr_ptr = Pointer::new(old_info).offset_i64(fx, entry_offset.into()).load(
                    fx,
                    fx.pointer_type,
                    crate::vtable::vtable_memflags(),
                );
                vptr_ptr
            } else {
                old_info
            }
        }
        (_, &ty::Dynamic(ref data, ..)) => crate::vtable::get_vtable(fx, source, data.principal()),
        _ => bug!("unsized_info: invalid unsizing {:?} -> {:?}", source, target),
    }
}

/// Coerce `src` to `dst_ty`.
fn unsize_ptr<'tcx>(
    fx: &mut FunctionCx<'_, '_, 'tcx>,
    src: Value,
    src_layout: TyAndLayout<'tcx>,
    dst_layout: TyAndLayout<'tcx>,
    old_info: Option<Value>,
) -> (Value, Value) {
    match (&src_layout.ty.kind(), &dst_layout.ty.kind()) {
        (&ty::Ref(_, a, _), &ty::Ref(_, b, _))
        | (&ty::Ref(_, a, _), &ty::RawPtr(ty::TypeAndMut { ty: b, .. }))
        | (&ty::RawPtr(ty::TypeAndMut { ty: a, .. }), &ty::RawPtr(ty::TypeAndMut { ty: b, .. })) => {
            (src, unsized_info(fx, a, b, old_info))
        }
        (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) if def_a.is_box() && def_b.is_box() => {
            let (a, b) = (src_layout.ty.boxed_ty(), dst_layout.ty.boxed_ty());
            (src, unsized_info(fx, a, b, old_info))
        }
        (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => {
            assert_eq!(def_a, def_b);

            if src_layout == dst_layout {
                return (src, old_info.unwrap());
            }

            let mut result = None;
            for i in 0..src_layout.fields.count() {
                let src_f = src_layout.field(fx, i);
                assert_eq!(src_layout.fields.offset(i).bytes(), 0);
                assert_eq!(dst_layout.fields.offset(i).bytes(), 0);
                if src_f.is_zst() {
                    continue;
                }
                assert_eq!(src_layout.size, src_f.size);

                let dst_f = dst_layout.field(fx, i);
                assert_ne!(src_f.ty, dst_f.ty);
                assert_eq!(result, None);
                result = Some(unsize_ptr(fx, src, src_f, dst_f, old_info));
            }
            result.unwrap()
        }
        _ => bug!("unsize_ptr: called on bad types"),
    }
}

/// Coerce `src`, which is a reference to a value of type `src_ty`,
/// to a value of type `dst_ty` and store the result in `dst`
pub(crate) fn coerce_unsized_into<'tcx>(
    fx: &mut FunctionCx<'_, '_, 'tcx>,
    src: CValue<'tcx>,
    dst: CPlace<'tcx>,
) {
    let src_ty = src.layout().ty;
    let dst_ty = dst.layout().ty;
    let mut coerce_ptr = || {
        let (base, info) =
            if fx.layout_of(src.layout().ty.builtin_deref(true).unwrap().ty).is_unsized() {
                let (old_base, old_info) = src.load_scalar_pair(fx);
                unsize_ptr(fx, old_base, src.layout(), dst.layout(), Some(old_info))
            } else {
                let base = src.load_scalar(fx);
                unsize_ptr(fx, base, src.layout(), dst.layout(), None)
            };
        dst.write_cvalue(fx, CValue::by_val_pair(base, info, dst.layout()));
    };
    match (&src_ty.kind(), &dst_ty.kind()) {
        (&ty::Ref(..), &ty::Ref(..))
        | (&ty::Ref(..), &ty::RawPtr(..))
        | (&ty::RawPtr(..), &ty::RawPtr(..)) => coerce_ptr(),
        (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => {
            assert_eq!(def_a, def_b);

            for i in 0..def_a.variants[VariantIdx::new(0)].fields.len() {
                let src_f = src.value_field(fx, mir::Field::new(i));
                let dst_f = dst.place_field(fx, mir::Field::new(i));

                if dst_f.layout().is_zst() {
                    continue;
                }

                if src_f.layout().ty == dst_f.layout().ty {
                    dst_f.write_cvalue(fx, src_f);
                } else {
                    coerce_unsized_into(fx, src_f, dst_f);
                }
            }
        }
        _ => bug!("coerce_unsized_into: invalid coercion {:?} -> {:?}", src_ty, dst_ty),
    }
}

// Adapted from https://github.com/rust-lang/rust/blob/2a663555ddf36f6b041445894a8c175cd1bc718c/src/librustc_codegen_ssa/glue.rs

pub(crate) fn size_and_align_of_dst<'tcx>(
    fx: &mut FunctionCx<'_, '_, 'tcx>,
    layout: TyAndLayout<'tcx>,
    info: Value,
) -> (Value, Value) {
    if !layout.is_unsized() {
        let size = fx.bcx.ins().iconst(fx.pointer_type, layout.size.bytes() as i64);
        let align = fx.bcx.ins().iconst(fx.pointer_type, layout.align.abi.bytes() as i64);
        return (size, align);
    }
    match layout.ty.kind() {
        ty::Dynamic(..) => {
            // load size/align from vtable
            (crate::vtable::size_of_obj(fx, info), crate::vtable::min_align_of_obj(fx, info))
        }
        ty::Slice(_) | ty::Str => {
            let unit = layout.field(fx, 0);
            // The info in this case is the length of the str, so the size is that
            // times the unit size.
            (
                fx.bcx.ins().imul_imm(info, unit.size.bytes() as i64),
                fx.bcx.ins().iconst(fx.pointer_type, unit.align.abi.bytes() as i64),
            )
        }
        _ => {
            // First get the size of all statically known fields.
            // Don't use size_of because it also rounds up to alignment, which we
            // want to avoid, as the unsized field's alignment could be smaller.
            assert!(!layout.ty.is_simd());

            let i = layout.fields.count() - 1;
            let sized_size = layout.fields.offset(i).bytes();
            let sized_align = layout.align.abi.bytes();
            let sized_align = fx.bcx.ins().iconst(fx.pointer_type, sized_align as i64);

            // Recurse to get the size of the dynamically sized field (must be
            // the last field).
            let field_layout = layout.field(fx, i);
            let (unsized_size, mut unsized_align) = size_and_align_of_dst(fx, field_layout, info);

            // FIXME (#26403, #27023): We should be adding padding
            // to `sized_size` (to accommodate the `unsized_align`
            // required of the unsized field that follows) before
            // summing it with `sized_size`. (Note that since #26403
            // is unfixed, we do not yet add the necessary padding
            // here. But this is where the add would go.)

            // Return the sum of sizes and max of aligns.
            let size = fx.bcx.ins().iadd_imm(unsized_size, sized_size as i64);

            // Packed types ignore the alignment of their fields.
            if let ty::Adt(def, _) = layout.ty.kind() {
                if def.repr.packed() {
                    unsized_align = sized_align;
                }
            }

            // Choose max of two known alignments (combined value must
            // be aligned according to more restrictive of the two).
            let cmp = fx.bcx.ins().icmp(IntCC::UnsignedGreaterThan, sized_align, unsized_align);
            let align = fx.bcx.ins().select(cmp, sized_align, unsized_align);

            // Issue #27023: must add any necessary padding to `size`
            // (to make it a multiple of `align`) before returning it.
            //
            // Namely, the returned size should be, in C notation:
            //
            //   `size + ((size & (align-1)) ? align : 0)`
            //
            // emulated via the semi-standard fast bit trick:
            //
            //   `(size + (align-1)) & -align`
            let addend = fx.bcx.ins().iadd_imm(align, -1);
            let add = fx.bcx.ins().iadd(size, addend);
            let neg = fx.bcx.ins().ineg(align);
            let size = fx.bcx.ins().band(add, neg);

            (size, align)
        }
    }
}
<commit_msg>Auto merge of #88135 - crlf0710:trait_upcasting_part_3, r=nikomatsakis<commit_after>//! Codegen of the [`PointerCast::Unsize`] operation.
//!
//! [`PointerCast::Unsize`]: `rustc_middle::ty::adjustment::PointerCast::Unsize`

use crate::prelude::*;

// Adapted from https://github.com/rust-lang/rust/blob/2a663555ddf36f6b041445894a8c175cd1bc718c/src/librustc_codegen_ssa/base.rs#L159-L307

/// Retrieve the information we are losing (making dynamic) in an unsizing
/// adjustment.
///
/// The `old_info` argument is a bit funny. It is intended for use
/// in an upcast, where the new vtable for an object will be derived
/// from the old one.
pub(crate) fn unsized_info<'tcx>(
    fx: &mut FunctionCx<'_, '_, 'tcx>,
    source: Ty<'tcx>,
    target: Ty<'tcx>,
    old_info: Option<Value>,
) -> Value {
    let (source, target) =
        fx.tcx.struct_lockstep_tails_erasing_lifetimes(source, target, ParamEnv::reveal_all());
    match (&source.kind(), &target.kind()) {
        (&ty::Array(_, len), &ty::Slice(_)) => fx
            .bcx
            .ins()
            .iconst(fx.pointer_type, len.eval_usize(fx.tcx, ParamEnv::reveal_all()) as i64),
        (&ty::Dynamic(ref data_a, ..), &ty::Dynamic(ref data_b, ..)) => {
            let old_info =
                old_info.expect("unsized_info: missing old info for trait upcasting coercion");
            if data_a.principal_def_id() == data_b.principal_def_id() {
                return old_info;
            }

            // trait upcasting coercion
            let vptr_entry_idx =
                fx.tcx.vtable_trait_upcasting_coercion_new_vptr_slot((source, target));

            if let Some(entry_idx) = vptr_entry_idx {
                let entry_idx = u32::try_from(entry_idx).unwrap();
                let entry_offset = entry_idx * fx.pointer_type.bytes();
                let vptr_ptr = Pointer::new(old_info).offset_i64(fx, entry_offset.into()).load(
                    fx,
                    fx.pointer_type,
                    crate::vtable::vtable_memflags(),
                );
                vptr_ptr
            } else {
                old_info
            }
        }
        (_, &ty::Dynamic(ref data, ..)) => crate::vtable::get_vtable(fx, source, data.principal()),
        _ => bug!("unsized_info: invalid unsizing {:?} -> {:?}", source, target),
    }
}

/// Coerce `src` to `dst_ty`.
fn unsize_ptr<'tcx>(
    fx: &mut FunctionCx<'_, '_, 'tcx>,
    src: Value,
    src_layout: TyAndLayout<'tcx>,
    dst_layout: TyAndLayout<'tcx>,
    old_info: Option<Value>,
) -> (Value, Value) {
    match (&src_layout.ty.kind(), &dst_layout.ty.kind()) {
        (&ty::Ref(_, a, _), &ty::Ref(_, b, _))
        | (&ty::Ref(_, a, _), &ty::RawPtr(ty::TypeAndMut { ty: b, .. }))
        | (&ty::RawPtr(ty::TypeAndMut { ty: a, .. }), &ty::RawPtr(ty::TypeAndMut { ty: b, .. })) => {
            (src, unsized_info(fx, a, b, old_info))
        }
        (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) if def_a.is_box() && def_b.is_box() => {
            let (a, b) = (src_layout.ty.boxed_ty(), dst_layout.ty.boxed_ty());
            (src, unsized_info(fx, a, b, old_info))
        }
        (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => {
            assert_eq!(def_a, def_b);

            if src_layout == dst_layout {
                return (src, old_info.unwrap());
            }

            let mut result = None;
            for i in 0..src_layout.fields.count() {
                let src_f = src_layout.field(fx, i);
                assert_eq!(src_layout.fields.offset(i).bytes(), 0);
                assert_eq!(dst_layout.fields.offset(i).bytes(), 0);
                if src_f.is_zst() {
                    continue;
                }
                assert_eq!(src_layout.size, src_f.size);

                let dst_f = dst_layout.field(fx, i);
                assert_ne!(src_f.ty, dst_f.ty);
                assert_eq!(result, None);
                result = Some(unsize_ptr(fx, src, src_f, dst_f, old_info));
            }
            result.unwrap()
        }
        _ => bug!("unsize_ptr: called on bad types"),
    }
}

/// Coerce `src`, which is a reference to a value of type `src_ty`,
/// to a value of type `dst_ty` and store the result in `dst`
pub(crate) fn coerce_unsized_into<'tcx>(
    fx: &mut FunctionCx<'_, '_, 'tcx>,
    src: CValue<'tcx>,
    dst: CPlace<'tcx>,
) {
    let src_ty = src.layout().ty;
    let dst_ty = dst.layout().ty;
    let mut coerce_ptr = || {
        let (base, info) =
            if fx.layout_of(src.layout().ty.builtin_deref(true).unwrap().ty).is_unsized() {
                let (old_base, old_info) = src.load_scalar_pair(fx);
                unsize_ptr(fx, old_base, src.layout(), dst.layout(), Some(old_info))
            } else {
                let base = src.load_scalar(fx);
                unsize_ptr(fx, base, src.layout(), dst.layout(), None)
            };
        dst.write_cvalue(fx, CValue::by_val_pair(base, info, dst.layout()));
    };
    match (&src_ty.kind(), &dst_ty.kind()) {
        (&ty::Ref(..), &ty::Ref(..))
        | (&ty::Ref(..), &ty::RawPtr(..))
        | (&ty::RawPtr(..), &ty::RawPtr(..)) => coerce_ptr(),
        (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => {
            assert_eq!(def_a, def_b);

            for i in 0..def_a.variants[VariantIdx::new(0)].fields.len() {
                let src_f = src.value_field(fx, mir::Field::new(i));
                let dst_f = dst.place_field(fx, mir::Field::new(i));

                if dst_f.layout().is_zst() {
                    continue;
                }

                if src_f.layout().ty == dst_f.layout().ty {
                    dst_f.write_cvalue(fx, src_f);
                } else {
                    coerce_unsized_into(fx, src_f, dst_f);
                }
            }
        }
        _ => bug!("coerce_unsized_into: invalid coercion {:?} -> {:?}", src_ty, dst_ty),
    }
}

// Adapted from https://github.com/rust-lang/rust/blob/2a663555ddf36f6b041445894a8c175cd1bc718c/src/librustc_codegen_ssa/glue.rs

pub(crate) fn size_and_align_of_dst<'tcx>(
    fx: &mut FunctionCx<'_, '_, 'tcx>,
    layout: TyAndLayout<'tcx>,
    info: Value,
) -> (Value, Value) {
    if !layout.is_unsized() {
        let size = fx.bcx.ins().iconst(fx.pointer_type, layout.size.bytes() as i64);
        let align = fx.bcx.ins().iconst(fx.pointer_type, layout.align.abi.bytes() as i64);
        return (size, align);
    }
    match layout.ty.kind() {
        ty::Dynamic(..) => {
            // load size/align from vtable
            (crate::vtable::size_of_obj(fx, info), crate::vtable::min_align_of_obj(fx, info))
        }
        ty::Slice(_) | ty::Str => {
            let unit = layout.field(fx, 0);
            // The info in this case is the length of the str, so the size is that
            // times the unit size.
            (
                fx.bcx.ins().imul_imm(info, unit.size.bytes() as i64),
                fx.bcx.ins().iconst(fx.pointer_type, unit.align.abi.bytes() as i64),
            )
        }
        _ => {
            // First get the size of all statically known fields.
            // Don't use size_of because it also rounds up to alignment, which we
            // want to avoid, as the unsized field's alignment could be smaller.
            assert!(!layout.ty.is_simd());

            let i = layout.fields.count() - 1;
            let sized_size = layout.fields.offset(i).bytes();
            let sized_align = layout.align.abi.bytes();
            let sized_align = fx.bcx.ins().iconst(fx.pointer_type, sized_align as i64);

            // Recurse to get the size of the dynamically sized field (must be
            // the last field).
            let field_layout = layout.field(fx, i);
            let (unsized_size, mut unsized_align) = size_and_align_of_dst(fx, field_layout, info);

            // FIXME (#26403, #27023): We should be adding padding
            // to `sized_size` (to accommodate the `unsized_align`
            // required of the unsized field that follows) before
            // summing it with `sized_size`. (Note that since #26403
            // is unfixed, we do not yet add the necessary padding
            // here. But this is where the add would go.)

            // Return the sum of sizes and max of aligns.
            let size = fx.bcx.ins().iadd_imm(unsized_size, sized_size as i64);

            // Packed types ignore the alignment of their fields.
            if let ty::Adt(def, _) = layout.ty.kind() {
                if def.repr.packed() {
                    unsized_align = sized_align;
                }
            }

            // Choose max of two known alignments (combined value must
            // be aligned according to more restrictive of the two).
            let cmp = fx.bcx.ins().icmp(IntCC::UnsignedGreaterThan, sized_align, unsized_align);
            let align = fx.bcx.ins().select(cmp, sized_align, unsized_align);

            // Issue #27023: must add any necessary padding to `size`
            // (to make it a multiple of `align`) before returning it.
            //
            // Namely, the returned size should be, in C notation:
            //
            //   `size + ((size & (align-1)) ? align : 0)`
            //
            // emulated via the semi-standard fast bit trick:
            //
            //   `(size + (align-1)) & -align`
            let addend = fx.bcx.ins().iadd_imm(align, -1);
            let add = fx.bcx.ins().iadd(size, addend);
            let neg = fx.bcx.ins().ineg(align);
            let size = fx.bcx.ins().band(add, neg);

            (size, align)
        }
    }
}
<|endoftext|>


<commit_before>extern crate serialize;

use serialize::{Decodable,json};
use std::io::Process;
use std::io::fs::File;
use std::io::process::ProcessOutput;
use std::io::{fs,IoResult,Truncate,UserRWX,Write};
use std::str;

#[deriving(Decodable,Show)]
struct Example {
    id: ~str,
    title: ~str,
}

fn read(file: &Path) -> IoResult<~str> {
    let mut file = try!(File::open(file));

    Ok(try!(file.read_to_str()))
}

fn write(file: &Path, contents: &str) -> IoResult<()> {
    let mut file = try!(File::open_mode(file, Truncate, Write));

    Ok(try!(file.write_str(contents)))
}

fn update(example: &Example) -> bool {
    print!("{}... ", example.id);

    let src_dir = Path::new(format!("src/{}", example.id));
    let out_dir = Path::new(format!("output/examples/{}", example.id));

    let sources: Vec<Path> = match fs::readdir(&src_dir) {
        Err(_) => {
            println!("couldn't read {}", src_dir.display());
            return false
        } Ok(contents) => contents.move_iter().filter(|path| match path.extension_str() {
            None => false,
            Some(extension) => extension == "rs",
        }).collect(),
    };

    let mut template = match read(&src_dir.join("input.md")) {
        Err(_) => {
            println!("couldn't read input.md");
            return false
        } Ok(contents) => format!("\\# {}\n\n{}", example.title, contents),
    };

    // insert source code in markdown
    for source in sources.iter() {
        let filename = source.filename_str().unwrap();
        let code = match read(source) {
            Err(_) => {
                println!("couldn't read {}", filename);
                return false;
            }, Ok(contents) => format!("``` rust\n// {}\n{}```", filename, contents),
        };

        template = template.replace(format!("\\{{}\\}", filename), code);
    }

    // insert program output in markdown
    for source in sources.iter() {
        let filename = source.filename_str().unwrap();
        let token = format!("\\{{}\\}", source.with_extension("out").filename_str().unwrap());

        if template.contains(token) {
            match compile_run(source) {
                Err(action) => {
                    println!("couldn't {} {}", action, filename);
                    return false;
                }, Ok(output) => {
                    let output = format!("```\n$ rustc {} && ./{}\n{}```",
                                         filename,
                                         filename.split('.').nth(0).unwrap(),
                                         output);

                    template = template.replace(token, output);
                }
            }
        }
    }

    if !out_dir.exists() {
        fs::mkdir(&out_dir, UserRWX).unwrap();
    }

    match write(&out_dir.join("README.md"), template) {
        Err(_) => {
            println!("couldn't write README.md");
            false
        } Ok(_) => {
            println!("DONE");
            true
        }
    }
}

fn compile_run(path: &Path) -> Result<~str, &'static str> {
    match Process::output("rustc", [path.as_str().unwrap().to_owned(), ~"-o", ~"executable"]) {
        Err(_) => return Err("compile"),
        Ok(out) => {
            if !out.status.success() {
                return Ok(str::from_utf8_owned(out.error.move_iter().collect::<~[u8]>()).unwrap());
            }
        }
    }

    match Process::output("./executable", []) {
        Err(_) => Err("run"),
        Ok(out) => {
            fs::unlink(&Path::new("./executable")).unwrap();
            let ProcessOutput { status: _, output: out, error: err } = out;
            let stdout = str::from_utf8_owned(out.move_iter().collect::<~[u8]>()).unwrap();
            let stderr = str::from_utf8_owned(err.move_iter().collect::<~[u8]>()).unwrap();

            Ok(vec!(stdout, stderr).concat())
        }
    }
}

fn main() {
    let src_dir = Path::new("src");

    let examples: Vec<Example> = match read(&src_dir.join("order.json")) {
        Err(err) => fail!("couldn't read order.json: {}", err),
        Ok(string) => match json::from_str(string) {
            Err(err) => fail!("order.json is invalid json: {}", err),
            Ok(json) => match Decodable::decode(&mut json::Decoder::new(json)) {
                Err(err) => fail!("error decoding order.json: {}", err),
                Ok(data) => data,
            }
        }
    };

    let mut indent = false;
    let summary = examples.move_iter().map(|example| {
        if example.id.as_slice() == "staging" {
            indent = true;
        }

        let chapter = if update(&example) {
            format!("* [{}](examples/{}/README.md)", example.title, example.id)
        } else {
            format!("* {}", example.title)
        };

        if indent &&
            example.id.as_slice() != "staging" &&
            example.id.as_slice() != "todo" {
            format!("  {}", chapter)
        } else {
            chapter
        }
    }).collect::<Vec<~str>>().connect("\n");

    if write(&Path::new("output/SUMMARY.md"), summary).is_err() {
        fail!("failed to write SUMMARY.md");
    }
}
<commit_msg>update.rs: ~"" is gone in latest rust<commit_after>extern crate serialize;

use serialize::{Decodable,json};
use std::io::Process;
use std::io::fs::File;
use std::io::process::ProcessOutput;
use std::io::{fs,IoResult,Truncate,UserRWX,Write};
use std::str;

#[deriving(Decodable,Show)]
struct Example {
    id: ~str,
    title: ~str,
}

fn read(file: &Path) -> IoResult<~str> {
    let mut file = try!(File::open(file));

    Ok(try!(file.read_to_str()))
}

fn write(file: &Path, contents: &str) -> IoResult<()> {
    let mut file = try!(File::open_mode(file, Truncate, Write));

    Ok(try!(file.write_str(contents)))
}

fn update(example: &Example) -> bool {
    print!("{}... ", example.id);

    let src_dir = Path::new(format!("src/{}", example.id));
    let out_dir = Path::new(format!("output/examples/{}", example.id));

    let sources: Vec<Path> = match fs::readdir(&src_dir) {
        Err(_) => {
            println!("couldn't read {}", src_dir.display());
            return false
        } Ok(contents) => contents.move_iter().filter(|path| match path.extension_str() {
            None => false,
            Some(extension) => extension == "rs",
        }).collect(),
    };

    let mut template = match read(&src_dir.join("input.md")) {
        Err(_) => {
            println!("couldn't read input.md");
            return false
        } Ok(contents) => format!("\\# {}\n\n{}", example.title, contents),
    };

    // insert source code in markdown
    for source in sources.iter() {
        let filename = source.filename_str().unwrap();
        let code = match read(source) {
            Err(_) => {
                println!("couldn't read {}", filename);
                return false;
            }, Ok(contents) => format!("``` rust\n// {}\n{}```", filename, contents),
        };

        template = template.replace(format!("\\{{}\\}", filename), code);
    }

    // insert program output in markdown
    for source in sources.iter() {
        let filename = source.filename_str().unwrap();
        let token = format!("\\{{}\\}", source.with_extension("out").filename_str().unwrap());

        if template.contains(token) {
            match compile_run(source) {
                Err(action) => {
                    println!("couldn't {} {}", action, filename);
                    return false;
                }, Ok(output) => {
                    let output = format!("```\n$ rustc {} && ./{}\n{}```",
                                         filename,
                                         filename.split('.').nth(0).unwrap(),
                                         output);

                    template = template.replace(token, output);
                }
            }
        }
    }

    if !out_dir.exists() {
        fs::mkdir(&out_dir, UserRWX).unwrap();
    }

    match write(&out_dir.join("README.md"), template) {
        Err(_) => {
            println!("couldn't write README.md");
            false
        } Ok(_) => {
            println!("DONE");
            true
        }
    }
}

fn compile_run(path: &Path) -> Result<~str, &'static str> {
    match Process::output("rustc", [path.as_str().unwrap().to_owned(),
                                    "-o".to_owned(),
                                    "executable".to_owned()]) {
        Err(_) => return Err("compile"),
        Ok(out) => {
            if !out.status.success() {
                return Ok(str::from_utf8_owned(out.error.move_iter().collect::<~[u8]>()).unwrap());
            }
        }
    }

    match Process::output("./executable", []) {
        Err(_) => Err("run"),
        Ok(out) => {
            fs::unlink(&Path::new("./executable")).unwrap();
            let ProcessOutput { status: _, output: out, error: err } = out;
            let stdout = str::from_utf8_owned(out.move_iter().collect::<~[u8]>()).unwrap();
            let stderr = str::from_utf8_owned(err.move_iter().collect::<~[u8]>()).unwrap();

            Ok(vec!(stdout, stderr).concat())
        }
    }
}

fn main() {
    let src_dir = Path::new("src");

    let examples: Vec<Example> = match read(&src_dir.join("order.json")) {
        Err(err) => fail!("couldn't read order.json: {}", err),
        Ok(string) => match json::from_str(string) {
            Err(err) => fail!("order.json is invalid json: {}", err),
            Ok(json) => match Decodable::decode(&mut json::Decoder::new(json)) {
                Err(err) => fail!("error decoding order.json: {}", err),
                Ok(data) => data,
            }
        }
    };

    let mut indent = false;
    let summary = examples.move_iter().map(|example| {
        if example.id.as_slice() == "staging" {
            indent = true;
        }

        let chapter = if update(&example) {
            format!("* [{}](examples/{}/README.md)", example.title, example.id)
        } else {
            format!("* {}", example.title)
        };

        if indent &&
            example.id.as_slice() != "staging" &&
            example.id.as_slice() != "todo" {
            format!("  {}", chapter)
        } else {
            chapter
        }
    }).collect::<Vec<~str>>().connect("\n");

    if write(&Path::new("output/SUMMARY.md"), summary).is_err() {
        fail!("failed to write SUMMARY.md");
    }
}
<|endoftext|>


<commit_before>extern crate libc;
extern crate std;

use super::liblua;
use super::Index;
use super::Lua;
use super::Pushable;
use super::Readable;

macro_rules! integer_impl(
    ($t:ident) => (
        impl Pushable for $t {
            fn push_to_lua(&self, lua: &mut Lua) {
                unsafe { liblua::lua_pushinteger(lua.lua, *self as liblua::lua_Integer) }
            }
        }
        impl Readable for $t {
            fn read_from_lua(lua: &mut Lua, index: i32) -> Option<$t> {
                let success: libc::c_int = unsafe { std::mem::uninitialized() };
                let val = unsafe { liblua::lua_tointegerx(lua.lua, index, &success) };
                match success {
                    0 => None,
                    _ => Some(val as $t)
                }
            }
        }
        impl Index for $t {
        }
    );
)

integer_impl!(int)
integer_impl!(i8)
integer_impl!(i16)
integer_impl!(i32)
//integer_impl!(i64)   // data loss

macro_rules! unsigned_impl(
    ($t:ident) => (
        impl Pushable for $t {
            fn push_to_lua(&self, lua: &mut Lua) {
                unsafe { liblua::lua_pushunsigned(lua.lua, *self as liblua::lua_Unsigned) }
            }
        }
        impl Readable for $t {
            fn read_from_lua(lua: &mut Lua, index: i32) -> Option<$t> {
                let success: libc::c_int = unsafe { std::mem::uninitialized() };
                let val = unsafe { liblua::lua_tounsignedx(lua.lua, index, &success) };
                match success {
                    0 => None,
                    _ => Some(val as $t)
                }
            }
        }
        impl Index for $t {
        }
    );
)

unsigned_impl!(uint)
unsigned_impl!(u8)
unsigned_impl!(u16)
unsigned_impl!(u32)
//unsigned_impl!(u64)   // data loss

macro_rules! numeric_impl(
    ($t:ident) => (
        impl Pushable for $t {
            fn push_to_lua(&self, lua: &mut Lua) {
                unsafe { liblua::lua_pushnumber(lua.lua, *self as f64) }
            }
        }
        impl Readable for $t {
            fn read_from_lua(lua: &mut Lua, index: i32) -> Option<$t> {
                let success: libc::c_int = unsafe { std::mem::uninitialized() };
                let val = unsafe { liblua::lua_tonumberx(lua.lua, index, &success) };
                match success {
                    0 => None,
                    _ => Some(val as $t)
                }
            }
        }
        impl Index for $t {
        }
    );
)

numeric_impl!(f32)
numeric_impl!(f64)

impl Pushable for std::string::String {
    fn push_to_lua(&self, lua: &mut Lua) {
        unsafe { liblua::lua_pushstring(lua.lua, self.to_c_str().unwrap()) }
    }
}

impl Readable for String {
    fn read_from_lua(lua: &mut Lua, index: i32) -> Option<std::string::String> {
        let mut size: libc::size_t = unsafe { std::mem::uninitialized() };
        let cStrRaw = unsafe { liblua::lua_tolstring(lua.lua, index, &mut size) };
        if cStrRaw.is_null() {
            return None;
        }

        unsafe { std::c_str::CString::new(cStrRaw, false) }.as_str().map(|s| s.to_string())
    }
}

impl Index for String {
}

impl<'a> Pushable for &'a str {
    fn push_to_lua(&self, lua: &mut Lua) {
        unsafe { liblua::lua_pushstring(lua.lua, self.to_c_str().unwrap()) }
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn readwrite_ints() {
        let mut lua = super::super::Lua::new();

        lua.set("a", 2).unwrap();
        let x: int = lua.get("a").unwrap();
        assert_eq!(x, 2);
    }
}
<commit_msg>Add pushable/readable traits for bool<commit_after>extern crate libc;
extern crate std;

use super::liblua;
use super::Index;
use super::Lua;
use super::Pushable;
use super::Readable;

macro_rules! integer_impl(
    ($t:ident) => (
        impl Pushable for $t {
            fn push_to_lua(&self, lua: &mut Lua) {
                unsafe { liblua::lua_pushinteger(lua.lua, *self as liblua::lua_Integer) }
            }
        }
        impl Readable for $t {
            fn read_from_lua(lua: &mut Lua, index: i32) -> Option<$t> {
                let success: libc::c_int = unsafe { std::mem::uninitialized() };
                let val = unsafe { liblua::lua_tointegerx(lua.lua, index, &success) };
                match success {
                    0 => None,
                    _ => Some(val as $t)
                }
            }
        }
        impl Index for $t {
        }
    );
)

integer_impl!(int)
integer_impl!(i8)
integer_impl!(i16)
integer_impl!(i32)
//integer_impl!(i64)   // data loss

macro_rules! unsigned_impl(
    ($t:ident) => (
        impl Pushable for $t {
            fn push_to_lua(&self, lua: &mut Lua) {
                unsafe { liblua::lua_pushunsigned(lua.lua, *self as liblua::lua_Unsigned) }
            }
        }
        impl Readable for $t {
            fn read_from_lua(lua: &mut Lua, index: i32) -> Option<$t> {
                let success: libc::c_int = unsafe { std::mem::uninitialized() };
                let val = unsafe { liblua::lua_tounsignedx(lua.lua, index, &success) };
                match success {
                    0 => None,
                    _ => Some(val as $t)
                }
            }
        }
        impl Index for $t {
        }
    );
)

unsigned_impl!(uint)
unsigned_impl!(u8)
unsigned_impl!(u16)
unsigned_impl!(u32)
//unsigned_impl!(u64)   // data loss

macro_rules! numeric_impl(
    ($t:ident) => (
        impl Pushable for $t {
            fn push_to_lua(&self, lua: &mut Lua) {
                unsafe { liblua::lua_pushnumber(lua.lua, *self as f64) }
            }
        }
        impl Readable for $t {
            fn read_from_lua(lua: &mut Lua, index: i32) -> Option<$t> {
                let success: libc::c_int = unsafe { std::mem::uninitialized() };
                let val = unsafe { liblua::lua_tonumberx(lua.lua, index, &success) };
                match success {
                    0 => None,
                    _ => Some(val as $t)
                }
            }
        }
        impl Index for $t {
        }
    );
)

numeric_impl!(f32)
numeric_impl!(f64)

impl Pushable for std::string::String {
    fn push_to_lua(&self, lua: &mut Lua) {
        unsafe { liblua::lua_pushstring(lua.lua, self.to_c_str().unwrap()) }
    }
}

impl Readable for String {
    fn read_from_lua(lua: &mut Lua, index: i32) -> Option<std::string::String> {
        let mut size: libc::size_t = unsafe { std::mem::uninitialized() };
        let cStrRaw = unsafe { liblua::lua_tolstring(lua.lua, index, &mut size) };
        if cStrRaw.is_null() {
            return None;
        }

        unsafe { std::c_str::CString::new(cStrRaw, false) }.as_str().map(|s| s.to_string())
    }
}

impl Index for String {
}

impl<'a> Pushable for &'a str {
    fn push_to_lua(&self, lua: &mut Lua) {
        unsafe { liblua::lua_pushstring(lua.lua, self.to_c_str().unwrap()) }
    }
}

impl Pushable for bool {
    fn push_to_lua(&self, lua: &mut Lua) {
        unsafe { liblua::lua_pushboolean(lua.lua, self.clone() as libc::c_int) }
    }
}

impl Readable for bool {
    fn read_from_lua(lua: &mut Lua, index: i32) -> Option<bool> {
        if unsafe { liblua::lua_isboolean(lua.lua, index) } != true {
            return None;
        }

        Some(unsafe { liblua::lua_toboolean(lua.lua, index) != 0 })
    }
}

impl Index for bool {
}

#[cfg(test)]
mod tests {
    #[test]
    fn readwrite_ints() {
        let mut lua = super::super::Lua::new();

        lua.set("a", 2).unwrap();
        let x: int = lua.get("a").unwrap();
        assert_eq!(x, 2);
    }
}
<|endoftext|>


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

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

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

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

use helpers::random01;

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

pub type FloatT = f64;

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

// TODO Dimension type alias
// TODO OwnedArray

pub struct OrthogonalNMFBlas {
    pub hidden: ArrayBase<Vec<FloatT>, (usize, usize)>,
    pub weights: ArrayBase<Vec<FloatT>, (usize, usize)>,

    // these hold temporary results during an iteration.
    // kept in struct to prevent unnecessary memory allocations.
    // TODO dont call these tmp
    pub tmp_weights_dividend: ArrayBase<Vec<FloatT>, (usize, usize)>,
    pub tmp_weights_divisor: ArrayBase<Vec<FloatT>, (usize, usize)>,
    pub tmp_weights_divisor_reconstruction: ArrayBase<Vec<FloatT>, (usize, usize)>,

    pub tmp_hidden_dividend: ArrayBase<Vec<FloatT>, (usize, usize)>,
    pub tmp_hidden_divisor: ArrayBase<Vec<FloatT>, (usize, usize)>,
    pub tmp_hidden_divisor_partial: ArrayBase<Vec<FloatT>, (usize, usize)>,
}

impl OrthogonalNMFBlas
    // where FloatT: 'a + Float + Mul + Zero + Clone + Gemm,
          // ArrayBase<Vec<FloatT>, (usize, usize)>: 'a + AsBlas<FloatT, ArrayBase<Vec<FloatT>, (usize, usize)>, (usize, usize)> + DataOwned<Elem=FloatT> + DataMut<Elem=FloatT>,
          // BlasArrayViewMut<'a, FloatT, (usize, usize)>: Matrix<FloatT>,
          // Closed01<FloatT>: Rand
{
    pub fn init_random01<R: Rng>(nhidden: usize, nobserved: usize, nsamples: usize, rng: &mut R) -> OrthogonalNMFBlas {
        let mut hidden = ArrayBase::zeros((nhidden, nobserved));
        for x in hidden.iter_mut() {
            *x = random01(rng);
        }

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

        Self::init(hidden, weights)
    }

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

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

        let samples_shape = (nsamples, nobserved);

        OrthogonalNMFBlas {
            hidden: hidden,
            weights: weights,
            tmp_weights_dividend: ArrayBase::zeros(weights_shape),
            tmp_weights_divisor: ArrayBase::zeros(weights_shape),
            tmp_weights_divisor_reconstruction: ArrayBase::zeros(samples_shape),
            tmp_hidden_dividend: ArrayBase::zeros(hidden_shape),
            tmp_hidden_divisor: ArrayBase::zeros(hidden_shape),
            tmp_hidden_divisor_partial: ArrayBase::zeros((nhidden, nhidden)),
        }
    }

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

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

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

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

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

    }

    // TODO docstring
    #[inline]
    pub fn iterate_weights_divisor(&mut self) {
        Gemm::gemm(
            &1.,
            Transpose::NoTrans, &self.weights.blas(),
            Transpose::NoTrans, &self.hidden.blas(),
            &0.,
            &mut self.tmp_weights_divisor_reconstruction.blas());
        Gemm::gemm(
            &1.,
            Transpose::NoTrans, &self.tmp_weights_divisor_reconstruction.blas(),
            Transpose::Trans, &self.hidden.blas(),
            &0.,
            &mut self.tmp_weights_divisor.blas());
    }

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

    #[inline]
    pub fn iterate_hidden_divisor(&mut self, alpha: FloatT, samples: &mut ArrayBase<Vec<FloatT>, (usize, usize)>) {
        // // gamma is a symetric matrix with diagonal elements equal to zero
        // // and other elements = alpha
        // let gamma_size = self.nhidden();
        // let mut gamma = DMat::from_elem(gamma_size, gamma_size, alpha);
        //
        // // set diagonal to zero
        // for i in 0..gamma_size {
        //     gamma[(i, i)] = FloatT::zero();
        // }
    }

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

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

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

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

        OrthogonalNMFBlas::update(
            &self.tmp_weights_dividend,
            &self.tmp_weights_divisor,
            &mut self.weights);
        OrthogonalNMFBlas::update(
            &self.tmp_hidden_dividend,
            &self.tmp_hidden_divisor,
            &mut self.hidden);
    }
}
<commit_msg>ortho nmf blas: finish implementation<commit_after>use std::ops::{Mul, Add};

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

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

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

use helpers::random01;

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

pub type FloatT = f64;

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

// TODO Dimension type alias
// TODO OwnedArray

pub struct OrthogonalNMFBlas {
    pub hidden: ArrayBase<Vec<FloatT>, (usize, usize)>,
    pub weights: ArrayBase<Vec<FloatT>, (usize, usize)>,

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

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

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

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

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

        Self::init(hidden, weights)
    }

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

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

        let samples_shape = (nsamples, nobserved);

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

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

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

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

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

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

    }

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

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

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

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

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

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

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

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

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


<commit_before>use std::ops::{
    Add,
    Sub,
    Mul,
    Div,
    Deref,
    DerefMut,
};

use num::{
    Zero,
};

pub trait Vector: Sized + Copy
    + Dot + Normalize + Length
    + Add<Output=Self> + Add<f32, Output=Self>
    + Sub<Output=Self> + Sub<f32, Output=Self>
    + Div<f32, Output=Self> + Mul<f32, Output=Self>
{
    type Buffer;

    fn from_array(ary: Self::Buffer) -> Self;
}

pub trait Dot {
    fn dot(&self, other: Self) -> f32;
}

pub trait Cross {
    fn cross(&self, other: Self) -> Self;
}

pub trait Normalize {
    fn normalize(&self) -> Self;
}

pub trait Length {
    fn length(&self) -> f32;
}

impl<T> Length for T
    where T: Dot + Copy
{
    fn length(&self) -> f32 {
        (self.dot(*self)).sqrt()
    }
}

impl<T> Normalize for T
    where T: Length + Mul<f32, Output=T> + Copy
{
    fn normalize(&self) -> Self {
        let scale = 1.0 / self.length();
        *self * scale
    }
}

#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
pub struct Vec2(pub [f32; 2]);

impl Vector for Vec2 {
    type Buffer = [f32; 2];

    fn from_array(ary: Self::Buffer) -> Self {
        Vec2(ary)
    }
}

impl Add for Vec2 {
    type Output = Self;

    fn add(self, other: Self) -> Self {
        let mut result = Self::zero();
        for i in 0..self.len() {
            result[i] = self[i] + other[i];
        }
        result
    }
}

impl Add<f32> for Vec2 {
    type Output = Self;

    fn add(self, other: f32) -> Self {
        let mut result = Self::zero();
        for i in 0..self.len() {
            result[i] = self[i] + other;
        }
        result
    }
}

impl Sub for Vec2 {
    type Output = Self;

    fn sub(self, other: Self) -> Self {
        let mut result = Self::zero();
        for i in 0..self.len() {
            result[i] = self[i] - other[i];
        }
        result
    }
}

impl Sub<f32> for Vec2 {
    type Output = Self;

    fn sub(self, other: f32) -> Self {
        let mut result = Self::zero();
        for i in 0..self.len() {
            result[i] = self[i] - other;
        }
        result
    }
}

impl Mul<f32> for Vec2 {
    type Output = Self;

    fn mul(self, other: f32) -> Self {
        let mut result = Self::zero();
        for i in 0..self.len() {
            result[i] = self[i] * other;
        }
        result
    }
}

impl Div<f32> for Vec2 {
    type Output = Self;

    fn div(self, other: f32) -> Self {
         let mut result = Self::zero();
        for i in 0..self.len() {
            result[i] = self[i] + other;
        }
        result
    }
}

impl Dot for Vec2 {
    fn dot(&self, other: Self) -> f32 {
        let mut result = f32::zero();
        for i in 0..self.len() {
            result += self[i] * other[i];
        }
        result
    }
}

impl Zero for Vec2 {
    fn zero() -> Self {
        Self::from_array([f32::zero(); 2])
    }

    fn is_zero(&self) -> bool {
        *self == Self::zero()
    }
}

impl Deref for Vec2 {
    type Target = <Self as Vector>::Buffer;

    fn deref<'a>(&'a self) -> &'a Self::Target {
        &self.0
    }
}

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

#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
pub struct Vec3(pub [f32; 3]);

impl Vector for Vec3 {
    type Buffer = [f32; 3];

    fn from_array(ary: Self::Buffer) -> Self {
        Vec3(ary)
    }
}

impl Add for Vec3 {
    type Output = Self;

    fn add(self, other: Self) -> Self {
        let mut result = Self::zero();
        for i in 0..self.len() {
            result[i] = self[i] + other[i];
        }
        result
    }
}

impl Add<f32> for Vec3 {
    type Output = Self;

    fn add(self, other: f32) -> Self {
        let mut result = Self::zero();
        for i in 0..self.len() {
            result[i] = self[i] + other;
        }
        result
    }
}

impl Sub for Vec3 {
    type Output = Self;

    fn sub(self, other: Self) -> Self {
        let mut result = Self::zero();
        for i in 0..self.len() {
            result[i] = self[i] - other[i];
        }
        result
    }
}

impl Sub<f32> for Vec3 {
    type Output = Self;

    fn sub(self, other: f32) -> Self {
        let mut result = Self::zero();
        for i in 0..self.len() {
            result[i] = self[i] - other;
        }
        result
    }
}

impl Mul<f32> for Vec3 {
    type Output = Self;

    fn mul(self, other: f32) -> Self {
        let mut result = Self::zero();
        for i in 0..self.len() {
            result[i] = self[i] * other;
        }
        result
    }
}

impl Div<f32> for Vec3 {
    type Output = Self;

    fn div(self, other: f32) -> Self {
         let mut result = Self::zero();
        for i in 0..self.len() {
            result[i] = self[i] + other;
        }
        result
    }
}

impl Dot for Vec3 {
    fn dot(&self, other: Self) -> f32 {
        let mut result = f32::zero();
        for i in 0..self.len() {
            result += self[i] * other[i];
        }
        result
    }
}

impl Cross for Vec3 {
    fn cross(&self, other: Self) -> Self {
        let mut result = Vec3::zero();
        result[0] = self[1] * other[2] - self[2] * other[1];
        result[1] = self[2] * other[0] - self[0] * other[2];
        result[2] = self[0] * other[1] - self[1] * other[0];
        result
    }
}

impl Zero for Vec3 {
    fn zero() -> Self {
        Self::from_array([f32::zero(); 3])
    }

    fn is_zero(&self) -> bool {
        *self == Self::zero()
    }
}

impl Deref for Vec3 {
    type Target = <Self as Vector>::Buffer;

    fn deref<'a>(&'a self) -> &'a Self::Target {
        &self.0
    }
}

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

#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
pub struct Vec4(pub [f32; 4]);

impl Vector for Vec4 {
    type Buffer = [f32; 4];

    fn from_array(ary: Self::Buffer) -> Self {
        Vec4(ary)
    }
}

impl Add for Vec4 {
    type Output = Self;

    fn add(self, other: Self) -> Self {
        let mut result = Self::zero();
        for i in 0..self.len() {
            result[i] = self[i] + other[i];
        }
        result
    }
}

impl Add<f32> for Vec4 {
    type Output = Self;

    fn add(self, other: f32) -> Self {
        let mut result = Self::zero();
        for i in 0..self.len() {
            result[i] = self[i] + other;
        }
        result
    }
}

impl Sub for Vec4 {
    type Output = Self;

    fn sub(self, other: Self) -> Self {
        let mut result = Self::zero();
        for i in 0..self.len() {
            result[i] = self[i] - other[i];
        }
        result
    }
}

impl Sub<f32> for Vec4 {
    type Output = Self;

    fn sub(self, other: f32) -> Self {
        let mut result = Self::zero();
        for i in 0..self.len() {
            result[i] = self[i] - other;
        }
        result
    }
}

impl Mul<f32> for Vec4 {
    type Output = Self;

    fn mul(self, other: f32) -> Self {
        let mut result = Self::zero();
        for i in 0..self.len() {
            result[i] = self[i] * other;
        }
        result
    }
}

impl Div<f32> for Vec4 {
    type Output = Self;

    fn div(self, other: f32) -> Self {
         let mut result = Self::zero();
        for i in 0..self.len() {
            result[i] = self[i] + other;
        }
        result
    }
}

impl Dot for Vec4 {
    fn dot(&self, other: Self) -> f32 {
        let mut result = f32::zero();
        for i in 0..self.len() {
            result += self[i] * other[i];
        }
        result
    }
}

impl Zero for Vec4 {
    fn zero() -> Self {
        Self::from_array([f32::zero(); 4])
    }

    fn is_zero(&self) -> bool {
        *self == Self::zero()
    }
}

impl Deref for Vec4 {
    type Target = <Self as Vector>::Buffer;

    fn deref<'a>(&'a self) -> &'a Self::Target {
        &self.0
    }
}

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

<commit_msg>more things<commit_after>use std::ops::{
    Add,
    Sub,
    Mul,
    Div,
    Deref,
    DerefMut,
};
use std::mem;

use num::{
    Zero,
};

pub trait Vector: Sized + Copy
    + Dot + Normalize + Length
    + Add<Output=Self> + Add<f32, Output=Self>
    + Sub<Output=Self> + Sub<f32, Output=Self>
    + Div<f32, Output=Self> + Mul<f32, Output=Self>
{
    type Buffer;
}

pub trait Dot {
    fn dot(&self, other: Self) -> f32;
}

pub trait Cross {
    fn cross(&self, other: Self) -> Self;
}

pub trait Normalize {
    fn normalize(&self) -> Self;
}

pub trait Length {
    fn length(&self) -> f32;
}

impl<T> Length for T
    where T: Dot + Copy
{
    fn length(&self) -> f32 {
        (self.dot(*self)).sqrt()
    }
}

impl<T> Normalize for T
    where T: Length + Mul<f32, Output=T> + Copy
{
    fn normalize(&self) -> Self {
        let scale = 1.0 / self.length();
        *self * scale
    }
}

#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
pub struct Vec2 {
    pub x: f32,
    pub y: f32,
}

impl Vector for Vec2 {
    type Buffer = [f32; 2];
}

impl Add for Vec2 {
    type Output = Self;

    fn add(self, other: Self) -> Self {
        let mut result = Self::zero();
        for i in 0..self.len() {
            result[i] = self[i] + other[i];
        }
        result
    }
}

impl Add<f32> for Vec2 {
    type Output = Self;

    fn add(self, other: f32) -> Self {
        let mut result = Self::zero();
        for i in 0..self.len() {
            result[i] = self[i] + other;
        }
        result
    }
}

impl Sub for Vec2 {
    type Output = Self;

    fn sub(self, other: Self) -> Self {
        let mut result = Self::zero();
        for i in 0..self.len() {
            result[i] = self[i] - other[i];
        }
        result
    }
}

impl Sub<f32> for Vec2 {
    type Output = Self;

    fn sub(self, other: f32) -> Self {
        let mut result = Self::zero();
        for i in 0..self.len() {
            result[i] = self[i] - other;
        }
        result
    }
}

impl Mul<f32> for Vec2 {
    type Output = Self;

    fn mul(self, other: f32) -> Self {
        let mut result = Self::zero();
        for i in 0..self.len() {
            result[i] = self[i] * other;
        }
        result
    }
}

impl Div<f32> for Vec2 {
    type Output = Self;

    fn div(self, other: f32) -> Self {
         let mut result = Self::zero();
        for i in 0..self.len() {
            result[i] = self[i] + other;
        }
        result
    }
}

impl Dot for Vec2 {
    fn dot(&self, other: Self) -> f32 {
        let mut result = f32::zero();
        for i in 0..self.len() {
            result += self[i] * other[i];
        }
        result
    }
}

impl Zero for Vec2 {
    fn zero() -> Self {
        Self::from([f32::zero(); 2])
    }

    fn is_zero(&self) -> bool {
        *self == Self::zero()
    }
}

impl From<[f32; 2]> for Vec2 {
    fn from(ary: [f32; 2]) -> Self {
        unsafe {
            mem::transmute(ary)
        }
    }
}

impl Deref for Vec2 {
    type Target = <Self as Vector>::Buffer;

    fn deref<'a>(&'a self) -> &'a Self::Target {
        unsafe {
            mem::transmute(self)
        }
    }
}

impl DerefMut for Vec2 {
    fn deref_mut<'a>(&'a mut self) -> &'a mut Self::Target {
        unsafe {
            mem::transmute(self)
        }
    }
}

#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
pub struct Vec3 {
    pub x: f32,
    pub y: f32,
    pub z: f32,
}

impl Vector for Vec3 {
    type Buffer = [f32; 3];
}

impl Add for Vec3 {
    type Output = Self;

    fn add(self, other: Self) -> Self {
        let mut result = Self::zero();
        for i in 0..self.len() {
            result[i] = self[i] + other[i];
        }
        result
    }
}

impl Add<f32> for Vec3 {
    type Output = Self;

    fn add(self, other: f32) -> Self {
        let mut result = Self::zero();
        for i in 0..self.len() {
            result[i] = self[i] + other;
        }
        result
    }
}

impl Sub for Vec3 {
    type Output = Self;

    fn sub(self, other: Self) -> Self {
        let mut result = Self::zero();
        for i in 0..self.len() {
            result[i] = self[i] - other[i];
        }
        result
    }
}

impl Sub<f32> for Vec3 {
    type Output = Self;

    fn sub(self, other: f32) -> Self {
        let mut result = Self::zero();
        for i in 0..self.len() {
            result[i] = self[i] - other;
        }
        result
    }
}

impl Mul<f32> for Vec3 {
    type Output = Self;

    fn mul(self, other: f32) -> Self {
        let mut result = Self::zero();
        for i in 0..self.len() {
            result[i] = self[i] * other;
        }
        result
    }
}

impl Div<f32> for Vec3 {
    type Output = Self;

    fn div(self, other: f32) -> Self {
         let mut result = Self::zero();
        for i in 0..self.len() {
            result[i] = self[i] + other;
        }
        result
    }
}

impl Dot for Vec3 {
    fn dot(&self, other: Self) -> f32 {
        let mut result = f32::zero();
        for i in 0..self.len() {
            result += self[i] * other[i];
        }
        result
    }
}

impl Cross for Vec3 {
    fn cross(&self, other: Self) -> Self {
        let mut result = Vec3::zero();
        result[0] = self[1] * other[2] - self[2] * other[1];
        result[1] = self[2] * other[0] - self[0] * other[2];
        result[2] = self[0] * other[1] - self[1] * other[0];
        result
    }
}

impl Zero for Vec3 {
    fn zero() -> Self {
        Self::from([f32::zero(); 3])
    }

    fn is_zero(&self) -> bool {
        *self == Self::zero()
    }
}

impl From<[f32; 3]> for Vec3 {
    fn from(ary: [f32; 3]) -> Self {
        unsafe {
            mem::transmute(ary)
        }
    }
}

impl Deref for Vec3 {
    type Target = <Self as Vector>::Buffer;

    fn deref<'a>(&'a self) -> &'a Self::Target {
        unsafe {
            mem::transmute(self)
        }
    }
}

impl DerefMut for Vec3 {
    fn deref_mut<'a>(&'a mut self) -> &'a mut Self::Target {
        unsafe {
            mem::transmute(self)
        }
    }
}

#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
pub struct Vec4 {
    pub x: f32,
    pub y: f32,
    pub z: f32,
    pub w: f32,
}

impl Vector for Vec4 {
    type Buffer = [f32; 4];
}

impl Add for Vec4 {
    type Output = Self;

    fn add(self, other: Self) -> Self {
        let mut result = Self::zero();
        for i in 0..self.len() {
            result[i] = self[i] + other[i];
        }
        result
    }
}

impl Add<f32> for Vec4 {
    type Output = Self;

    fn add(self, other: f32) -> Self {
        let mut result = Self::zero();
        for i in 0..self.len() {
            result[i] = self[i] + other;
        }
        result
    }
}

impl Sub for Vec4 {
    type Output = Self;

    fn sub(self, other: Self) -> Self {
        let mut result = Self::zero();
        for i in 0..self.len() {
            result[i] = self[i] - other[i];
        }
        result
    }
}

impl Sub<f32> for Vec4 {
    type Output = Self;

    fn sub(self, other: f32) -> Self {
        let mut result = Self::zero();
        for i in 0..self.len() {
            result[i] = self[i] - other;
        }
        result
    }
}

impl Mul<f32> for Vec4 {
    type Output = Self;

    fn mul(self, other: f32) -> Self {
        let mut result = Self::zero();
        for i in 0..self.len() {
            result[i] = self[i] * other;
        }
        result
    }
}

impl Div<f32> for Vec4 {
    type Output = Self;

    fn div(self, other: f32) -> Self {
         let mut result = Self::zero();
        for i in 0..self.len() {
            result[i] = self[i] + other;
        }
        result
    }
}

impl Dot for Vec4 {
    fn dot(&self, other: Self) -> f32 {
        let mut result = f32::zero();
        for i in 0..self.len() {
            result += self[i] * other[i];
        }
        result
    }
}

impl Zero for Vec4 {
    fn zero() -> Self {
        Self::from([f32::zero(); 4])
    }

    fn is_zero(&self) -> bool {
        *self == Self::zero()
    }
}

impl From<[f32; 4]> for Vec4 {
    fn from(ary: [f32; 4]) -> Self {
        unsafe {
            mem::transmute(ary)
        }
    }
}

impl Deref for Vec4 {
    type Target = <Self as Vector>::Buffer;

    fn deref<'a>(&'a self) -> &'a Self::Target {
        unsafe {
            mem::transmute(self)
        }
    }
}

impl DerefMut for Vec4 {
    fn deref_mut<'a>(&'a mut self) -> &'a mut Self::Target {
        unsafe {
            mem::transmute(self)
        }
    }
}

<|endoftext|>


<commit_before>// Copyright 2015 Nicholas Bishop
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::ops::{Add, Div, Mul, Sub};

/// Vector with three f32 components
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Vec3f {
    pub x: f32,
    pub y: f32,
    pub z: f32
}

impl Vec3f {
    pub fn new(x: f32, y: f32, z: f32) -> Vec3f {
        Vec3f { x: x,
                y: y,
                z: z }
    }

    pub fn from_scalar<T: CastF32>(s: T) -> Vec3f {
        let f = s.as_f32();
        Vec3f {
            x: f,
            y: f,
            z: f
        }
    }

    pub fn magnitude_squared(&self) -> f32 {
        dot3(*self, *self)
    }

    pub fn magnitude(&self) -> f32 {
        self.magnitude_squared().sqrt()
    }
}

/// Vec3f(0.0, 0.0, 0.0)
pub const ZERO_3F: Vec3f = Vec3f { x: 0.0, y: 0.0, z: 0.0 };

pub trait CastF32 { fn as_f32(&self) -> f32; }

impl CastF32 for f32 { fn as_f32(&self) -> f32 { *self } }
impl CastF32 for f64 { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for i8  { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for i16 { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for i32 { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for u8  { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for u16 { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for u32 { fn as_f32(&self) -> f32 { *self as f32 } }

/// Create a Vec3f from x, y, and z inputs
///
/// This is a convenience function that provides a little more
/// flexibility than Vec3f::new in that it will happily take numbers
/// that aren't f32 (including a mix of different types for each
/// component). Vec3f is such a common type that it seems reasonable
/// to provide a little extra ease of use.
pub fn vec3f<X: CastF32, Y: CastF32, Z: CastF32>(x: X, y: Y, z: Z) -> Vec3f {
    Vec3f { x: x.as_f32(), y: y.as_f32(), z: z.as_f32() }
}

/// Inner product of two Vec3f inputs
pub fn dot3(a: Vec3f, b: Vec3f) -> f32 {
    let v = a * b;
    v.x + v.y + v.z
}

/// Cross product of two Vec3f inputs
pub fn cross(a: Vec3f, b: Vec3f) -> Vec3f {
    Vec3f::new(a.y * b.z - a.z * b.y,
               a.z * b.x - a.x * b.z,
               a.x * b.y - a.y * b.x)
}

/// Distance between two vectors
pub fn distance3(a: Vec3f, b: Vec3f) -> f32 {
    (a - b).magnitude()
}

impl Add for Vec3f {
    type Output = Vec3f;
    fn add(self, v: Vec3f) -> Vec3f {
        Vec3f::new(self.x + v.x, self.y + v.y, self.z + v.z)
    }
}

impl Div for Vec3f {
    type Output = Vec3f;
    fn div(self, v: Vec3f) -> Vec3f {
        Vec3f::new(self.x / v.x, self.y / v.y, self.z / v.z)
    }
}

impl Mul<Vec3f> for Vec3f {
    type Output = Vec3f;
    fn mul(self, v: Vec3f) -> Vec3f {
        Vec3f::new(self.x * v.x, self.y * v.y, self.z * v.z)
    }
}

impl Mul<f32> for Vec3f {
    type Output = Vec3f;
    fn mul(self, f: f32) -> Vec3f {
        Vec3f::new(self.x * f, self.y * f, self.z * f)
    }
}

impl Sub for Vec3f {
    type Output = Vec3f;
    fn sub(self, v: Vec3f) -> Vec3f {
        Vec3f::new(self.x - v.x, self.y - v.y, self.z - v.z)
    }
}

#[test]
fn test_vec3f_create() {
    vec3f(1.0f32, 2, 3i32);
    assert!(Vec3f::from_scalar(1) == vec3f(1, 1, 1));
}

#[test]
fn test_vec3f_magnitude() {
    let v = vec3f(-4, 0, 0);
    assert!(v.magnitude_squared() == 16.0);
    assert!(v.magnitude() == 4.0);
}

#[test]
fn test_vec3f_distance3() {
    assert!(distance3(vec3f(0, -4, 0), vec3f(0, 4, 0)) == 8.0);
}

#[test]
fn test_vec3f_arithmetic() {
    let a = vec3f(1, 2, 3);
    let b = vec3f(4, 5, 6);
    assert!(a + b == vec3f(5, 7, 9));
    assert!(a - b == vec3f(-3, -3, -3));
    assert!(a * b == vec3f(4, 10, 18));
    assert!(a / b == vec3f(0.25, 2.0 / 5.0, 0.5));
}

#[test]
fn test_vec3f_dot() {
    assert!(dot3(vec3f(1, 2, 3), vec3f(4, 5, 6)) == 32.0);
}

#[test]
fn test_vec3f_cross() {
    assert!(cross(vec3f(1, 0, 0), vec3f(0, 1, 0)) == vec3f(0, 0, 1));
}
<commit_msg>Fix docstring<commit_after>// Copyright 2015 Nicholas Bishop
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::ops::{Add, Div, Mul, Sub};

/// Vector with three f32 components
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Vec3f {
    pub x: f32,
    pub y: f32,
    pub z: f32
}

impl Vec3f {
    pub fn new(x: f32, y: f32, z: f32) -> Vec3f {
        Vec3f { x: x,
                y: y,
                z: z }
    }

    pub fn from_scalar<T: CastF32>(s: T) -> Vec3f {
        let f = s.as_f32();
        Vec3f {
            x: f,
            y: f,
            z: f
        }
    }

    pub fn magnitude_squared(&self) -> f32 {
        dot3(*self, *self)
    }

    pub fn magnitude(&self) -> f32 {
        self.magnitude_squared().sqrt()
    }
}

/// Vec3f(0.0, 0.0, 0.0)
pub const ZERO_3F: Vec3f = Vec3f { x: 0.0, y: 0.0, z: 0.0 };

pub trait CastF32 { fn as_f32(&self) -> f32; }

impl CastF32 for f32 { fn as_f32(&self) -> f32 { *self } }
impl CastF32 for f64 { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for i8  { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for i16 { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for i32 { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for u8  { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for u16 { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for u32 { fn as_f32(&self) -> f32 { *self as f32 } }

/// Create a Vec3f from x, y, and z inputs
///
/// This is a convenience function that provides a little more
/// flexibility than Vec3f::new in that it will happily take numbers
/// that aren't f32 (including a mix of different types for each
/// component). Vec3f is such a common type that it seems reasonable
/// to provide a little extra ease of use.
pub fn vec3f<X: CastF32, Y: CastF32, Z: CastF32>(x: X, y: Y, z: Z) -> Vec3f {
    Vec3f { x: x.as_f32(), y: y.as_f32(), z: z.as_f32() }
}

/// Inner product of two Vec3f inputs
pub fn dot3(a: Vec3f, b: Vec3f) -> f32 {
    let v = a * b;
    v.x + v.y + v.z
}

/// Cross product of two Vec3f inputs
pub fn cross(a: Vec3f, b: Vec3f) -> Vec3f {
    Vec3f::new(a.y * b.z - a.z * b.y,
               a.z * b.x - a.x * b.z,
               a.x * b.y - a.y * b.x)
}

/// Distance between two points
pub fn distance3(a: Vec3f, b: Vec3f) -> f32 {
    (a - b).magnitude()
}

impl Add for Vec3f {
    type Output = Vec3f;
    fn add(self, v: Vec3f) -> Vec3f {
        Vec3f::new(self.x + v.x, self.y + v.y, self.z + v.z)
    }
}

impl Div for Vec3f {
    type Output = Vec3f;
    fn div(self, v: Vec3f) -> Vec3f {
        Vec3f::new(self.x / v.x, self.y / v.y, self.z / v.z)
    }
}

impl Mul<Vec3f> for Vec3f {
    type Output = Vec3f;
    fn mul(self, v: Vec3f) -> Vec3f {
        Vec3f::new(self.x * v.x, self.y * v.y, self.z * v.z)
    }
}

impl Mul<f32> for Vec3f {
    type Output = Vec3f;
    fn mul(self, f: f32) -> Vec3f {
        Vec3f::new(self.x * f, self.y * f, self.z * f)
    }
}

impl Sub for Vec3f {
    type Output = Vec3f;
    fn sub(self, v: Vec3f) -> Vec3f {
        Vec3f::new(self.x - v.x, self.y - v.y, self.z - v.z)
    }
}

#[test]
fn test_vec3f_create() {
    vec3f(1.0f32, 2, 3i32);
    assert!(Vec3f::from_scalar(1) == vec3f(1, 1, 1));
}

#[test]
fn test_vec3f_magnitude() {
    let v = vec3f(-4, 0, 0);
    assert!(v.magnitude_squared() == 16.0);
    assert!(v.magnitude() == 4.0);
}

#[test]
fn test_vec3f_distance3() {
    assert!(distance3(vec3f(0, -4, 0), vec3f(0, 4, 0)) == 8.0);
}

#[test]
fn test_vec3f_arithmetic() {
    let a = vec3f(1, 2, 3);
    let b = vec3f(4, 5, 6);
    assert!(a + b == vec3f(5, 7, 9));
    assert!(a - b == vec3f(-3, -3, -3));
    assert!(a * b == vec3f(4, 10, 18));
    assert!(a / b == vec3f(0.25, 2.0 / 5.0, 0.5));
}

#[test]
fn test_vec3f_dot() {
    assert!(dot3(vec3f(1, 2, 3), vec3f(4, 5, 6)) == 32.0);
}

#[test]
fn test_vec3f_cross() {
    assert!(cross(vec3f(1, 0, 0), vec3f(0, 1, 0)) == vec3f(0, 0, 1));
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */

<%namespace name="helpers" file="/helpers.mako.rs" />

// Box-shadow, etc.
<% data.new_style_struct("Effects", inherited=False) %>

${helpers.predefined_type(
    "opacity",
    "Opacity",
    "1.0",
    engines="gecko servo-2013 servo-2020",
    animation_value_type="ComputedValue",
    flags="CREATES_STACKING_CONTEXT CAN_ANIMATE_ON_COMPOSITOR",
    spec="https://drafts.csswg.org/css-color/#transparency",
    servo_restyle_damage = "reflow_out_of_flow",
)}

${helpers.predefined_type(
    "box-shadow",
    "BoxShadow",
    None,
    engines="gecko servo-2013 servo-2020",
    servo_2020_pref="layout.2020.unimplemented",
    vector=True,
    simple_vector_bindings=True,
    animation_value_type="AnimatedBoxShadowList",
    vector_animation_type="with_zero",
    extra_prefixes="webkit",
    ignored_when_colors_disabled=True,
    spec="https://drafts.csswg.org/css-backgrounds/#box-shadow",
)}

${helpers.predefined_type(
    "clip",
    "ClipRectOrAuto",
    "computed::ClipRectOrAuto::auto()",
    engines="gecko servo-2013 servo-2020",
    servo_2020_pref="layout.2020.unimplemented",
    animation_value_type="ComputedValue",
    boxed=True,
    allow_quirks="Yes",
    spec="https://drafts.fxtf.org/css-masking/#clip-property",
)}

${helpers.predefined_type(
    "filter",
    "Filter",
    None,
    engines="gecko servo-2013 servo-2020",
    vector=True,
    simple_vector_bindings=True,
    gecko_ffi_name="mFilters",
    separator="Space",
    animation_value_type="AnimatedFilterList",
    vector_animation_type="with_zero",
    extra_prefixes="webkit",
    flags="CREATES_STACKING_CONTEXT FIXPOS_CB",
    spec="https://drafts.fxtf.org/filters/#propdef-filter",
)}

${helpers.predefined_type(
    "backdrop-filter",
    "Filter",
    None,
    engines="gecko",
    vector=True,
    simple_vector_bindings=True,
    gecko_ffi_name="mBackdropFilters",
    separator="Space",
    animation_value_type="AnimatedFilterList",
    vector_animation_type="with_zero",
    flags="CREATES_STACKING_CONTEXT FIXPOS_CB",
    gecko_pref="layout.css.backdrop-filter.enabled",
    spec="https://drafts.fxtf.org/filter-effects-2/#propdef-backdrop-filter",
)}

${helpers.single_keyword(
    "mix-blend-mode",
    """normal multiply screen overlay darken lighten color-dodge
    color-burn hard-light soft-light difference exclusion hue
    saturation color luminosity""",
    engines="gecko servo-2013 servo-2020",
    gecko_enum_prefix="StyleBlend",
    animation_value_type="discrete",
    flags="CREATES_STACKING_CONTEXT",
    spec="https://drafts.fxtf.org/compositing/#propdef-mix-blend-mode",
)}
<commit_msg>Enable clip property in layout 2020<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */

<%namespace name="helpers" file="/helpers.mako.rs" />

// Box-shadow, etc.
<% data.new_style_struct("Effects", inherited=False) %>

${helpers.predefined_type(
    "opacity",
    "Opacity",
    "1.0",
    engines="gecko servo-2013 servo-2020",
    animation_value_type="ComputedValue",
    flags="CREATES_STACKING_CONTEXT CAN_ANIMATE_ON_COMPOSITOR",
    spec="https://drafts.csswg.org/css-color/#transparency",
    servo_restyle_damage = "reflow_out_of_flow",
)}

${helpers.predefined_type(
    "box-shadow",
    "BoxShadow",
    None,
    engines="gecko servo-2013 servo-2020",
    servo_2020_pref="layout.2020.unimplemented",
    vector=True,
    simple_vector_bindings=True,
    animation_value_type="AnimatedBoxShadowList",
    vector_animation_type="with_zero",
    extra_prefixes="webkit",
    ignored_when_colors_disabled=True,
    spec="https://drafts.csswg.org/css-backgrounds/#box-shadow",
)}

${helpers.predefined_type(
    "clip",
    "ClipRectOrAuto",
    "computed::ClipRectOrAuto::auto()",
    engines="gecko servo-2013 servo-2020",
    animation_value_type="ComputedValue",
    boxed=True,
    allow_quirks="Yes",
    spec="https://drafts.fxtf.org/css-masking/#clip-property",
)}

${helpers.predefined_type(
    "filter",
    "Filter",
    None,
    engines="gecko servo-2013 servo-2020",
    vector=True,
    simple_vector_bindings=True,
    gecko_ffi_name="mFilters",
    separator="Space",
    animation_value_type="AnimatedFilterList",
    vector_animation_type="with_zero",
    extra_prefixes="webkit",
    flags="CREATES_STACKING_CONTEXT FIXPOS_CB",
    spec="https://drafts.fxtf.org/filters/#propdef-filter",
)}

${helpers.predefined_type(
    "backdrop-filter",
    "Filter",
    None,
    engines="gecko",
    vector=True,
    simple_vector_bindings=True,
    gecko_ffi_name="mBackdropFilters",
    separator="Space",
    animation_value_type="AnimatedFilterList",
    vector_animation_type="with_zero",
    flags="CREATES_STACKING_CONTEXT FIXPOS_CB",
    gecko_pref="layout.css.backdrop-filter.enabled",
    spec="https://drafts.fxtf.org/filter-effects-2/#propdef-backdrop-filter",
)}

${helpers.single_keyword(
    "mix-blend-mode",
    """normal multiply screen overlay darken lighten color-dodge
    color-burn hard-light soft-light difference exclusion hue
    saturation color luminosity""",
    engines="gecko servo-2013 servo-2020",
    gecko_enum_prefix="StyleBlend",
    animation_value_type="discrete",
    flags="CREATES_STACKING_CONTEXT",
    spec="https://drafts.fxtf.org/compositing/#propdef-mix-blend-mode",
)}
<|endoftext|>


<commit_before>// binary.rs

pub use BASE16       = base16::BASE16;
pub use BASE32       = base32::BASE32_STD;
pub use BASE64       = base64::BASE64_STD;
pub use BASE32_HEX   = base32::BASE32_HEX;
pub use BASE64_URL   = base64::BASE64_URL;
pub use Base16Writer = base16::Base16Writer;
pub use Base32Writer = base32::Base32Writer;
pub use Base64Writer = base64::Base64Writer;
pub use Base32Reader = base32::Base32Reader;
pub use Base64Reader = base64::Base64Reader;

pub mod base16;
pub mod base32;
pub mod base64;

pub trait Encode {
    fn encode(&self, buf: &[const u8]) -> ~[u8];
}

pub trait Decode {
    fn decode(&self, buf: &[const u8]) -> ~[u8];
}

pub trait Convert {
    static fn convert(buf: &[const u8], to: self, from: self) -> ~[u8];
}

pub trait Codec : Encode Decode Convert {
}

// `end` indicates whether the Decode method have encountered paddings or not.
struct DecodeResult {
    end: bool,
    ndecoded: uint,
}

trait BinaryEncoder {
    fn encode(&self, dst: &[mut u8], src: &[const u8]);
    fn encoded_len(&self, src_length: uint) -> uint;
    fn encode_bytes(&self, src: &[const u8]) -> ~[u8];
}

trait BinaryDecoder {
    fn decode(&self, dst: &[mut u8], src: &[const u8]) -> DecodeResult;
    fn decoded_len(&self, src_length: uint) -> uint;
    fn decode_bytes(&self, src: &[const u8]) -> ~[u8];
}

pub enum Binary {
    Base16,
    Base32,
    Base64,
    Base32Hex,
    Base64Url,
}

pub impl Binary : Encode {
    fn encode(&self, buf: &[const u8]) -> ~[u8] {
        match *self {
            Base16    => base16::encode(buf),
            Base32    => base32::encode(buf),
            Base64    => base64::encode(buf),
            Base32Hex => base32::hex_encode(buf),
            Base64Url => base64::urlsafe_encode(buf)
        }
    }
}

pub impl Binary : Decode {
    fn decode(&self, buf: &[const u8]) -> ~[u8] {
        match *self {
            Base16    => base16::decode(buf),
            Base32    => base32::decode(buf),
            Base64    => base64::decode(buf),
            Base32Hex => base32::hex_decode(buf),
            Base64Url => base64::urlsafe_decode(buf)
        }
    }
}

pub impl Binary : Convert {
    static fn convert(buf: &[const u8], to: Binary, from: Binary) -> ~[u8] {
        let buf = from.decode(buf);
        let buf = to.encode(buf);
        buf
    }
}

pub impl Binary : Codec;
<commit_msg>Update for language changes<commit_after>// binary.rs

pub use BASE16       = binary::base16::BASE16;
pub use BASE32       = binary::base32::BASE32_STD;
pub use BASE64       = binary::base64::BASE64_STD;
pub use BASE32_HEX   = binary::base32::BASE32_HEX;
pub use BASE64_URL   = binary::base64::BASE64_URL;
pub use Base16Writer = binary::base16::Base16Writer;
pub use Base32Writer = binary::base32::Base32Writer;
pub use Base64Writer = binary::base64::Base64Writer;
pub use Base32Reader = binary::base32::Base32Reader;
pub use Base64Reader = binary::base64::Base64Reader;

pub mod base16;
pub mod base32;
pub mod base64;

pub trait Encode {
    fn encode(&self, buf: &[const u8]) -> ~[u8];
}

pub trait Decode {
    fn decode(&self, buf: &[const u8]) -> ~[u8];
}

pub trait Convert {
    static fn convert(buf: &[const u8], to: self, from: self) -> ~[u8];
}

pub trait Codec : Encode Decode Convert {
}

// `end` indicates whether the Decode method have encountered paddings or not.
struct DecodeResult {
    end: bool,
    ndecoded: uint,
}

trait BinaryEncoder {
    fn encode(&self, dst: &[mut u8], src: &[const u8]);
    fn encoded_len(&self, src_length: uint) -> uint;
    fn encode_bytes(&self, src: &[const u8]) -> ~[u8];
}

trait BinaryDecoder {
    fn decode(&self, dst: &[mut u8], src: &[const u8]) -> DecodeResult;
    fn decoded_len(&self, src_length: uint) -> uint;
    fn decode_bytes(&self, src: &[const u8]) -> ~[u8];
}

pub enum Binary {
    Base16,
    Base32,
    Base64,
    Base32Hex,
    Base64Url,
}

pub impl Binary : Encode {
    fn encode(&self, buf: &[const u8]) -> ~[u8] {
        match *self {
            Base16    => base16::encode(buf),
            Base32    => base32::encode(buf),
            Base64    => base64::encode(buf),
            Base32Hex => base32::hex_encode(buf),
            Base64Url => base64::urlsafe_encode(buf)
        }
    }
}

pub impl Binary : Decode {
    fn decode(&self, buf: &[const u8]) -> ~[u8] {
        match *self {
            Base16    => base16::decode(buf),
            Base32    => base32::decode(buf),
            Base64    => base64::decode(buf),
            Base32Hex => base32::hex_decode(buf),
            Base64Url => base64::urlsafe_decode(buf)
        }
    }
}

pub impl Binary : Convert {
    static fn convert(buf: &[const u8], to: Binary, from: Binary) -> ~[u8] {
        let buf = from.decode(buf);
        let buf = to.encode(buf);
        buf
    }
}

pub impl Binary : Codec;
<|endoftext|>