<commit_before>
use types::{Int, ForthCell};
use error::{ForthResult, ForthError};
use dictionary::{Dictionary, DictionaryExt, Entry};
use statement::{Statement, StatementExt};
use word::ForthWord;

pub type Stack = Vec<Int>;

pub struct Interpreter {
    pub dictionary: Dictionary,
    last_result: Option<Stack>,
}

macro_rules! try_stack {
	($x:expr) => {
		match $x {
			Some(i) => i,
			None => return Err(ForthError::EmptyStack),
		}
	}
}

macro_rules! binary_entry {
	($dict:ident, $name:expr, $f:expr) => {
		$dict.insert_entry(Entry::new($name,
				ForthWord::Native(Box::new(|_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let b = try_stack!(stack.pop());
					let a = try_stack!(stack.pop());
					stack.push($f(a, b));
					Ok(())
				})),
			))
	}
}

macro_rules! unary_entry {
	($dict:ident, $name:expr, $f:expr) => {
		$dict.insert_entry(Entry::new($name,
				ForthWord::Native(Box::new(|_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let a = try_stack!(stack.pop());
					stack.push($f(a));
					Ok(())
				})),
			))
	}
}

macro_rules! nonary_entry {
	($dict:ident, $name:expr, $f:expr) => {
		$dict.insert_entry(Entry::new($name,
				ForthWord::Native(Box::new(|_: &mut Interpreter, _: &mut Stack| -> ForthResult<()> {
					ForthCell::Number($f);
					Ok(())
				})),
			))
	}
}

macro_rules! entry {
	($dict:ident, $name:expr, $f:expr) => {
		$dict.insert_entry(Entry::new($name, ForthWord::Native(Box::new($f))))
	}
}

impl Interpreter {
	pub fn new() -> Interpreter {
		let mut dict = Dictionary::new();

		binary_entry!(dict, "/", ::std::ops::Div::div);
		binary_entry!(dict, "*", ::std::ops::Mul::mul);
		binary_entry!(dict, "+", ::std::ops::Add::add);
		binary_entry!(dict, "-", ::std::ops::Sub::sub);
		binary_entry!(dict, "mod", ::std::ops::Rem::rem);
		binary_entry!(dict, "and", ::std::ops::BitAnd::bitand);
		binary_entry!(dict, "or", ::std::ops::BitOr::bitor);
		binary_entry!(dict, "xor", ::std::ops::BitXor::bitxor);
		binary_entry!(dict, "rshift", ::std::ops::Shr::shr);
		binary_entry!(dict, "lshift", ::std::ops::Shl::shl);

		unary_entry!(dict, "negate", ::std::ops::Neg::neg);
		unary_entry!(dict, "not", ::std::ops::Not::not);

		nonary_entry!(dict, "bye", ::std::process::exit(0));

		entry!(dict, "abs", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let x = try_stack!(stack.pop());
                    stack.push(x.abs());
					Ok(())
				});

        entry!(dict, "min", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
                    let y = try_stack!(stack.pop());
                    let x = try_stack!(stack.pop());
                    stack.push(::std::cmp::min(x, y));
                    Ok(())
                });

        entry!(dict, "max", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
                    let y = try_stack!(stack.pop());
                    let x = try_stack!(stack.pop());
                    stack.push(::std::cmp::max(x, y));
                    Ok(())
                });

		entry!(dict, "$", |interp: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let x = try_stack!(interp.last_result.clone());
					for v in x {
						stack.push(v);
					}
					Ok(())
				});

		entry!(dict, "<", | _: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let y = try_stack!(stack.pop());
					let x = try_stack!(stack.pop());
					stack.push(if x < y { 1 } else { 0 });
					Ok(())
				});

		entry!(dict, ">", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let y = try_stack!(stack.pop());
					let x = try_stack!(stack.pop());
					stack.push(if x > y { 1 } else { 0 });
					Ok(())
				});

		entry!(dict, "=", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let y = try_stack!(stack.pop());
					let x = try_stack!(stack.pop());
					stack.push(if x == y { 1 } else { 0 });
					Ok(())
				});

		entry!(dict, "0<", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let x = try_stack!(stack.pop());
					stack.push(if x < 0 { 1 } else { 0 });
					Ok(())
				});

		entry!(dict, "0=", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let x = try_stack!(stack.pop());
					stack.push(if x == 0 { 1 } else { 0 });
					Ok(())
				});

		entry!(dict, "0>", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let x = try_stack!(stack.pop());
					stack.push(if x > 0 { 1 } else { 0 });
					Ok(())
				});

		entry!(dict, "1+", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let x = try_stack!(stack.pop());
					stack.push(x + 1);
					Ok(())
				});

		entry!(dict, "1-", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let x = try_stack!(stack.pop());
					stack.push(x - 1);
					Ok(())
				});

		entry!(dict, "2+", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let x = try_stack!(stack.pop());
					stack.push(x + 2);
					Ok(())
				});

		entry!(dict, "2-", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let x = try_stack!(stack.pop());
					stack.push(x - 2);
					Ok(())
				});

		entry!(dict, "2/", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let x = try_stack!(stack.pop());
					stack.push(x >> 1); // Per fst83 standard
					Ok(())
				});

		entry!(dict, "dup", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let x = try_stack!(stack.pop());
					stack.push(x.clone());
					stack.push(x);
					Ok(())
				});

		entry!(dict, "?dup", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let x = try_stack!(stack.pop());
					if x != 0 {
						stack.push(x.clone());
						stack.push(x);
					} else {
						stack.push(x);
					}
					Ok(())
				});

		entry!(dict, "drop", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let _ = try_stack!(stack.pop());
					Ok(())
				});

		entry!(dict, "over", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let x = try_stack!(stack.pop());
					let y = try_stack!(stack.pop());
					stack.push(x.clone());
					stack.push(y);
					stack.push(x);
					Ok(())
				});

		entry!(dict, "swap", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let x = try_stack!(stack.pop());
					let y = try_stack!(stack.pop());
					stack.push(x);
					stack.push(y);
					Ok(())
				});

		entry!(dict, "rot", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let x = try_stack!(stack.pop());
					let y = try_stack!(stack.pop());
					let z = try_stack!(stack.pop());
					stack.push(y);
					stack.push(x);
					stack.push(z);
					Ok(())
				});

		entry!(dict, "dump", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					println!("ds =  {:?} ", stack);
					Ok(())
				});

		entry!(dict, "cr", |_: &mut Interpreter, _: &mut Stack| -> ForthResult<()> {
					println!("");
					Ok(())
				});

		entry!(dict, ".", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					println!("{}", try_stack!(stack.pop()));
					Ok(())
				});

		entry!(dict, "branch", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let y = try_stack!(stack.pop());
					let x = try_stack!(stack.pop());
					stack.push(if x == y { 1 } else { 0 });
					Ok(())
				});

		entry!(dict, "emit", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let x = try_stack!(stack.pop());
					if x < 0 || x > 256 { return Err(ForthError::InvalidCharacter) }
					print!("{}", x as u8 as char);
					Ok(())
				});

		let square = {
			let mut s = Statement::new();
			s.push_back(ForthCell::Word(dict.get("dup").unwrap().clone()));
			s.push_back(ForthCell::Word(dict.get("*").unwrap().clone()));
			s
		};
		dict.insert_entry(Entry::from_statement("square", square));

		Interpreter {
			dictionary: dict,
			last_result: None,
		}
	}

	pub fn exec(&mut self, statement: &str) -> ForthResult<()> {
		let mut words = statement.split(|c: char| c.is_whitespace());
		let mut stmt = Statement::new();
		while let Some(word) = words.next() { match word {
			"(" => while let Some(w) = words.next() { if w == ")" { break; } },
			"\\" => while let Some(w) = words.next() { if w == "\n" { break; } },
			":" => {
				let mut comp = Statement::new();
				let name = match words.next() {
					Some(w) => w,
					None => return Err(ForthError::WordNameNotFound),
				};
				while let Some(w) = words.next() {
					if w == ";" {
						self.dictionary.insert_entry(Entry::from_statement(name, comp));
						return Ok(());
					}
					match w.parse::<i32>() {
						Ok(n) => comp.push_back(ForthCell::Number(n)),
						Err(_) => comp.push_back(ForthCell::Word(self.dictionary.get(w).unwrap().clone())),
					}
				}
				return Err(ForthError::UnterminatedWordDefinition);
			},
			_ => match word.parse::<i32>() {
				Ok(n) => {
					stmt.push_back(ForthCell::Number(n));
				},
				Err(_) => {
					if let Some(elem) = self.dictionary.get(word) {
						stmt.push_back(ForthCell::Word(elem.clone()));
					} else {
						return Err(ForthError::WordNotFound)
					}
				},
			},

		}}

		match stmt.run(self) {
			Err(e) => {
				self.last_result = None;
				Err(e)
			},
			Ok(s) => {
				self.last_result = Some(s);
				Ok(())
			}
		}
	}
}<commit_msg>Use binary_entry! for max, min.<commit_after>
use types::{Int, ForthCell};
use error::{ForthResult, ForthError};
use dictionary::{Dictionary, DictionaryExt, Entry};
use statement::{Statement, StatementExt};
use word::ForthWord;

pub type Stack = Vec<Int>;

pub struct Interpreter {
    pub dictionary: Dictionary,
    last_result: Option<Stack>,
}

macro_rules! try_stack {
	($x:expr) => {
		match $x {
			Some(i) => i,
			None => return Err(ForthError::EmptyStack),
		}
	}
}

macro_rules! binary_entry {
	($dict:ident, $name:expr, $f:expr) => {
		$dict.insert_entry(Entry::new($name,
				ForthWord::Native(Box::new(|_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let b = try_stack!(stack.pop());
					let a = try_stack!(stack.pop());
					stack.push($f(a, b));
					Ok(())
				})),
			))
	}
}

macro_rules! unary_entry {
	($dict:ident, $name:expr, $f:expr) => {
		$dict.insert_entry(Entry::new($name,
				ForthWord::Native(Box::new(|_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let a = try_stack!(stack.pop());
					stack.push($f(a));
					Ok(())
				})),
			))
	}
}

macro_rules! nonary_entry {
	($dict:ident, $name:expr, $f:expr) => {
		$dict.insert_entry(Entry::new($name,
				ForthWord::Native(Box::new(|_: &mut Interpreter, _: &mut Stack| -> ForthResult<()> {
					ForthCell::Number($f);
					Ok(())
				})),
			))
	}
}

macro_rules! entry {
	($dict:ident, $name:expr, $f:expr) => {
		$dict.insert_entry(Entry::new($name, ForthWord::Native(Box::new($f))))
	}
}

impl Interpreter {
	pub fn new() -> Interpreter {
		let mut dict = Dictionary::new();

		binary_entry!(dict, "/", ::std::ops::Div::div);
		binary_entry!(dict, "*", ::std::ops::Mul::mul);
		binary_entry!(dict, "+", ::std::ops::Add::add);
		binary_entry!(dict, "-", ::std::ops::Sub::sub);
		binary_entry!(dict, "mod", ::std::ops::Rem::rem);
		binary_entry!(dict, "and", ::std::ops::BitAnd::bitand);
		binary_entry!(dict, "or", ::std::ops::BitOr::bitor);
		binary_entry!(dict, "xor", ::std::ops::BitXor::bitxor);
		binary_entry!(dict, "rshift", ::std::ops::Shr::shr);
		binary_entry!(dict, "lshift", ::std::ops::Shl::shl);
        binary_entry!(dict, "max", ::std::cmp::max);
        binary_entry!(dict, "min", ::std::cmp::min);

		unary_entry!(dict, "negate", ::std::ops::Neg::neg);
		unary_entry!(dict, "not", ::std::ops::Not::not);

		nonary_entry!(dict, "bye", ::std::process::exit(0));

		entry!(dict, "abs", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let x = try_stack!(stack.pop());
                    stack.push(x.abs());
					Ok(())
				});

		entry!(dict, "$", |interp: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let x = try_stack!(interp.last_result.clone());
					for v in x {
						stack.push(v);
					}
					Ok(())
				});

		entry!(dict, "<", | _: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let y = try_stack!(stack.pop());
					let x = try_stack!(stack.pop());
					stack.push(if x < y { 1 } else { 0 });
					Ok(())
				});

		entry!(dict, ">", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let y = try_stack!(stack.pop());
					let x = try_stack!(stack.pop());
					stack.push(if x > y { 1 } else { 0 });
					Ok(())
				});

		entry!(dict, "=", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let y = try_stack!(stack.pop());
					let x = try_stack!(stack.pop());
					stack.push(if x == y { 1 } else { 0 });
					Ok(())
				});

		entry!(dict, "0<", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let x = try_stack!(stack.pop());
					stack.push(if x < 0 { 1 } else { 0 });
					Ok(())
				});

		entry!(dict, "0=", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let x = try_stack!(stack.pop());
					stack.push(if x == 0 { 1 } else { 0 });
					Ok(())
				});

		entry!(dict, "0>", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let x = try_stack!(stack.pop());
					stack.push(if x > 0 { 1 } else { 0 });
					Ok(())
				});

		entry!(dict, "1+", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let x = try_stack!(stack.pop());
					stack.push(x + 1);
					Ok(())
				});

		entry!(dict, "1-", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let x = try_stack!(stack.pop());
					stack.push(x - 1);
					Ok(())
				});

		entry!(dict, "2+", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let x = try_stack!(stack.pop());
					stack.push(x + 2);
					Ok(())
				});

		entry!(dict, "2-", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let x = try_stack!(stack.pop());
					stack.push(x - 2);
					Ok(())
				});

		entry!(dict, "2/", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let x = try_stack!(stack.pop());
					stack.push(x >> 1); // Per fst83 standard
					Ok(())
				});

		entry!(dict, "dup", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let x = try_stack!(stack.pop());
					stack.push(x.clone());
					stack.push(x);
					Ok(())
				});

		entry!(dict, "?dup", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let x = try_stack!(stack.pop());
					if x != 0 {
						stack.push(x.clone());
						stack.push(x);
					} else {
						stack.push(x);
					}
					Ok(())
				});

		entry!(dict, "drop", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let _ = try_stack!(stack.pop());
					Ok(())
				});

		entry!(dict, "over", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let x = try_stack!(stack.pop());
					let y = try_stack!(stack.pop());
					stack.push(x.clone());
					stack.push(y);
					stack.push(x);
					Ok(())
				});

		entry!(dict, "swap", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let x = try_stack!(stack.pop());
					let y = try_stack!(stack.pop());
					stack.push(x);
					stack.push(y);
					Ok(())
				});

		entry!(dict, "rot", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let x = try_stack!(stack.pop());
					let y = try_stack!(stack.pop());
					let z = try_stack!(stack.pop());
					stack.push(y);
					stack.push(x);
					stack.push(z);
					Ok(())
				});

		entry!(dict, "dump", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					println!("ds =  {:?} ", stack);
					Ok(())
				});

		entry!(dict, "cr", |_: &mut Interpreter, _: &mut Stack| -> ForthResult<()> {
					println!("");
					Ok(())
				});

		entry!(dict, ".", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					println!("{}", try_stack!(stack.pop()));
					Ok(())
				});

		entry!(dict, "branch", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let y = try_stack!(stack.pop());
					let x = try_stack!(stack.pop());
					stack.push(if x == y { 1 } else { 0 });
					Ok(())
				});

		entry!(dict, "emit", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let x = try_stack!(stack.pop());
					if x < 0 || x > 256 { return Err(ForthError::InvalidCharacter) }
					print!("{}", x as u8 as char);
					Ok(())
				});

		let square = {
			let mut s = Statement::new();
			s.push_back(ForthCell::Word(dict.get("dup").unwrap().clone()));
			s.push_back(ForthCell::Word(dict.get("*").unwrap().clone()));
			s
		};
		dict.insert_entry(Entry::from_statement("square", square));

		Interpreter {
			dictionary: dict,
			last_result: None,
		}
	}

	pub fn exec(&mut self, statement: &str) -> ForthResult<()> {
		let mut words = statement.split(|c: char| c.is_whitespace());
		let mut stmt = Statement::new();
		while let Some(word) = words.next() { match word {
			"(" => while let Some(w) = words.next() { if w == ")" { break; } },
			"\\" => while let Some(w) = words.next() { if w == "\n" { break; } },
			":" => {
				let mut comp = Statement::new();
				let name = match words.next() {
					Some(w) => w,
					None => return Err(ForthError::WordNameNotFound),
				};
				while let Some(w) = words.next() {
					if w == ";" {
						self.dictionary.insert_entry(Entry::from_statement(name, comp));
						return Ok(());
					}
					match w.parse::<i32>() {
						Ok(n) => comp.push_back(ForthCell::Number(n)),
						Err(_) => comp.push_back(ForthCell::Word(self.dictionary.get(w).unwrap().clone())),
					}
				}
				return Err(ForthError::UnterminatedWordDefinition);
			},
			_ => match word.parse::<i32>() {
				Ok(n) => {
					stmt.push_back(ForthCell::Number(n));
				},
				Err(_) => {
					if let Some(elem) = self.dictionary.get(word) {
						stmt.push_back(ForthCell::Word(elem.clone()));
					} else {
						return Err(ForthError::WordNotFound)
					}
				},
			},

		}}

		match stmt.run(self) {
			Err(e) => {
				self.last_result = None;
				Err(e)
			},
			Ok(s) => {
				self.last_result = Some(s);
				Ok(())
			}
		}
	}
}<|endoftext|>


<commit_before>
use size_hint;
use Itertools;

use std::mem::replace;
use std::fmt;

macro_rules! clone_fields {
    ($name:ident, $base:expr, $($field:ident),+) => (
        $name {
            $(
                $field : $base . $field .clone()
            ),*
        }
    );
}

/// Head element and Tail iterator pair
///
/// `PartialEq`, `Eq`, `PartialOrd` and `Ord` are implemented by comparing sequences based on
/// first items (which are guaranteed to exist).
///
/// The meanings of `PartialOrd` and `Ord` are reversed so as to turn the heap used in
/// `KMerge` into a min-heap.
#[derive(Debug)]
struct HeadTail<I>
    where I: Iterator
{
    head: I::Item,
    tail: I,
}

impl<I> HeadTail<I>
    where I: Iterator
{
    /// Constructs a `HeadTail` from an `Iterator`. Returns `None` if the `Iterator` is empty.
    fn new(mut it: I) -> Option<HeadTail<I>> {
        let head = it.next();
        head.map(|h| {
            HeadTail {
                head: h,
                tail: it,
            }
        })
    }

    /// Get the next element and update `head`, returning the old head in `Some`.
    ///
    /// Returns `None` when the tail is exhausted (only `head` then remains).
    fn next(&mut self) -> Option<I::Item> {
        if let Some(next) = self.tail.next() {
            Some(replace(&mut self.head, next))
        } else {
            None
        }
    }

    /// Hints at the size of the sequence, same as the `Iterator` method.
    fn size_hint(&self) -> (usize, Option<usize>) {
        size_hint::add_scalar(self.tail.size_hint(), 1)
    }
}

impl<I> Clone for HeadTail<I>
    where I: Iterator + Clone,
          I::Item: Clone
{
    fn clone(&self) -> Self {
        clone_fields!(HeadTail, self, head, tail)
    }
}

/// Make `data` a heap (min-heap w.r.t the sorting).
fn heapify<T, S>(data: &mut [T], mut less_than: S)
    where S: FnMut(&T, &T) -> bool
{
    for i in (0..data.len() / 2).rev() {
        sift_down(data, i, &mut less_than);
    }
}

/// Sift down element at `index` (`heap` is a min-heap wrt the ordering)
fn sift_down<T, S>(heap: &mut [T], index: usize, mut less_than: S)
    where S: FnMut(&T, &T) -> bool
{
    debug_assert!(index <= heap.len());
    let mut pos = index;
    let mut child = 2 * pos + 1;
    // the `pos` conditional is to avoid a bounds check
    while pos < heap.len() && child < heap.len() {
        let right = child + 1;

        // pick the smaller of the two children
        if right < heap.len() && less_than(&heap[right], &heap[child]) {
            child = right;
        }

        // sift down is done if we are already in order
        if !less_than(&heap[child], &heap[pos]) {
            return;
        }
        heap.swap(pos, child);
        pos = child;
        child = 2 * pos + 1;
    }
}

/// An iterator adaptor that merges an abitrary number of base iterators in ascending order.
/// If all base iterators are sorted (ascending), the result is sorted.
///
/// Iterator element type is `I::Item`.
///
/// See [`.kmerge()`](../trait.Itertools.html#method.kmerge) for more information.
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub type KMerge<I> = KMergeBy<I, KMergeByLt>;

pub trait KMergePredicate<T> {
    fn kmerge_pred(&mut self, a: &T, b: &T) -> bool;
}

#[derive(Clone)]
pub struct KMergeByLt;

impl<T: PartialOrd> KMergePredicate<T> for KMergeByLt {
    fn kmerge_pred(&mut self, a: &T, b: &T) -> bool {
        a < b
    }
}

impl<T, F: FnMut(&T, &T)->bool> KMergePredicate<T> for F {
    fn kmerge_pred(&mut self, a: &T, b: &T) -> bool {
        self(a, b)
    }
}

/// Create an iterator that merges elements of the contained iterators using
/// the ordering function.
///
/// Equivalent to `iterable.into_iter().kmerge()`.
///
/// ```
/// use itertools::kmerge;
///
/// for elt in kmerge(vec![vec![0, 2, 4], vec![1, 3, 5], vec![6, 7]]) {
///     /* loop body */
/// }
/// ```
pub fn kmerge<I>(iterable: I) -> KMerge<<I::Item as IntoIterator>::IntoIter>
    where I: IntoIterator,
          I::Item: IntoIterator,
          <<I as IntoIterator>::Item as IntoIterator>::Item: PartialOrd
{
    let iter = iterable.into_iter();
    let (lower, _) = iter.size_hint();
    let mut heap = Vec::with_capacity(lower);
    heap.extend(iter.filter_map(|it| HeadTail::new(it.into_iter())));
    heapify(&mut heap, |a, b| a.head < b.head);
    KMerge { heap: heap , less_than: KMergeByLt }
}

/// An iterator adaptor that merges an abitrary number of base iterators
/// according to an ordering function.
///
/// Iterator element type is `I::Item`.
///
/// See [`.kmerge_by()`](../trait.Itertools.html#method.kmerge_by) for more
/// information.
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct KMergeBy<I, F>
    where I: Iterator,
{
    heap: Vec<HeadTail<I>>,
    less_than: F,
}

impl<I, F> fmt::Debug for KMergeBy<I, F>
    where I: Iterator + fmt::Debug,
          I::Item: fmt::Debug,
{
    debug_fmt_fields!(KMergeBy, heap);
}

/// Create an iterator that merges elements of the contained iterators.
///
/// Equivalent to `iterable.into_iter().kmerge_by(less_than)`.
pub fn kmerge_by<I, F>(iterable: I, mut less_than: F)
    -> KMergeBy<<I::Item as IntoIterator>::IntoIter, F>
    where I: IntoIterator,
          I::Item: IntoIterator,
          F: FnMut(&<<I as IntoIterator>::Item as IntoIterator>::Item,
                   &<<I as IntoIterator>::Item as IntoIterator>::Item) -> bool
{
    let iter = iterable.into_iter();
    let (lower, _) = iter.size_hint();
    let mut heap: Vec<_> = Vec::with_capacity(lower);
    heap.extend(iter.filter_map(|it| HeadTail::new(it.into_iter())));
    heapify(&mut heap, |a, b| less_than(&a.head, &b.head));
    KMergeBy { heap: heap, less_than: less_than }
}

impl<I, F> Clone for KMergeBy<I, F>
    where I: Iterator + Clone,
          I::Item: Clone,
          F: Clone,
{
    fn clone(&self) -> KMergeBy<I, F> {
        clone_fields!(KMergeBy, self, heap, less_than)
    }
}

impl<I, F> Iterator for KMergeBy<I, F>
    where I: Iterator,
          F: KMergePredicate<I::Item>
{
    type Item = I::Item;

    fn next(&mut self) -> Option<Self::Item> {
        if self.heap.is_empty() {
            return None;
        }
        let result = if let Some(next) = self.heap[0].next() {
            next
        } else {
            self.heap.swap_remove(0).head
        };
        let less_than = &mut self.less_than;
        sift_down(&mut self.heap, 0, |a, b| less_than.kmerge_pred(&a.head, &b.head));
        Some(result)
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.heap.iter()
                 .map(|i| i.size_hint())
                 .fold1(size_hint::add)
                 .unwrap_or((0, Some(0)))
    }
}
<commit_msg>Define kmerge in terms of kmerge_by<commit_after>
use size_hint;
use Itertools;

use std::mem::replace;
use std::fmt;

macro_rules! clone_fields {
    ($name:ident, $base:expr, $($field:ident),+) => (
        $name {
            $(
                $field : $base . $field .clone()
            ),*
        }
    );
}

/// Head element and Tail iterator pair
///
/// `PartialEq`, `Eq`, `PartialOrd` and `Ord` are implemented by comparing sequences based on
/// first items (which are guaranteed to exist).
///
/// The meanings of `PartialOrd` and `Ord` are reversed so as to turn the heap used in
/// `KMerge` into a min-heap.
#[derive(Debug)]
struct HeadTail<I>
    where I: Iterator
{
    head: I::Item,
    tail: I,
}

impl<I> HeadTail<I>
    where I: Iterator
{
    /// Constructs a `HeadTail` from an `Iterator`. Returns `None` if the `Iterator` is empty.
    fn new(mut it: I) -> Option<HeadTail<I>> {
        let head = it.next();
        head.map(|h| {
            HeadTail {
                head: h,
                tail: it,
            }
        })
    }

    /// Get the next element and update `head`, returning the old head in `Some`.
    ///
    /// Returns `None` when the tail is exhausted (only `head` then remains).
    fn next(&mut self) -> Option<I::Item> {
        if let Some(next) = self.tail.next() {
            Some(replace(&mut self.head, next))
        } else {
            None
        }
    }

    /// Hints at the size of the sequence, same as the `Iterator` method.
    fn size_hint(&self) -> (usize, Option<usize>) {
        size_hint::add_scalar(self.tail.size_hint(), 1)
    }
}

impl<I> Clone for HeadTail<I>
    where I: Iterator + Clone,
          I::Item: Clone
{
    fn clone(&self) -> Self {
        clone_fields!(HeadTail, self, head, tail)
    }
}

/// Make `data` a heap (min-heap w.r.t the sorting).
fn heapify<T, S>(data: &mut [T], mut less_than: S)
    where S: FnMut(&T, &T) -> bool
{
    for i in (0..data.len() / 2).rev() {
        sift_down(data, i, &mut less_than);
    }
}

/// Sift down element at `index` (`heap` is a min-heap wrt the ordering)
fn sift_down<T, S>(heap: &mut [T], index: usize, mut less_than: S)
    where S: FnMut(&T, &T) -> bool
{
    debug_assert!(index <= heap.len());
    let mut pos = index;
    let mut child = 2 * pos + 1;
    // the `pos` conditional is to avoid a bounds check
    while pos < heap.len() && child < heap.len() {
        let right = child + 1;

        // pick the smaller of the two children
        if right < heap.len() && less_than(&heap[right], &heap[child]) {
            child = right;
        }

        // sift down is done if we are already in order
        if !less_than(&heap[child], &heap[pos]) {
            return;
        }
        heap.swap(pos, child);
        pos = child;
        child = 2 * pos + 1;
    }
}

/// An iterator adaptor that merges an abitrary number of base iterators in ascending order.
/// If all base iterators are sorted (ascending), the result is sorted.
///
/// Iterator element type is `I::Item`.
///
/// See [`.kmerge()`](../trait.Itertools.html#method.kmerge) for more information.
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub type KMerge<I> = KMergeBy<I, KMergeByLt>;

pub trait KMergePredicate<T> {
    fn kmerge_pred(&mut self, a: &T, b: &T) -> bool;
}

#[derive(Clone)]
pub struct KMergeByLt;

impl<T: PartialOrd> KMergePredicate<T> for KMergeByLt {
    fn kmerge_pred(&mut self, a: &T, b: &T) -> bool {
        a < b
    }
}

impl<T, F: FnMut(&T, &T)->bool> KMergePredicate<T> for F {
    fn kmerge_pred(&mut self, a: &T, b: &T) -> bool {
        self(a, b)
    }
}

/// Create an iterator that merges elements of the contained iterators using
/// the ordering function.
///
/// Equivalent to `iterable.into_iter().kmerge()`.
///
/// ```
/// use itertools::kmerge;
///
/// for elt in kmerge(vec![vec![0, 2, 4], vec![1, 3, 5], vec![6, 7]]) {
///     /* loop body */
/// }
/// ```
pub fn kmerge<I>(iterable: I) -> KMerge<<I::Item as IntoIterator>::IntoIter>
    where I: IntoIterator,
          I::Item: IntoIterator,
          <<I as IntoIterator>::Item as IntoIterator>::Item: PartialOrd
{
    kmerge_by(iterable, KMergeByLt)
}

/// An iterator adaptor that merges an abitrary number of base iterators
/// according to an ordering function.
///
/// Iterator element type is `I::Item`.
///
/// See [`.kmerge_by()`](../trait.Itertools.html#method.kmerge_by) for more
/// information.
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct KMergeBy<I, F>
    where I: Iterator,
{
    heap: Vec<HeadTail<I>>,
    less_than: F,
}

impl<I, F> fmt::Debug for KMergeBy<I, F>
    where I: Iterator + fmt::Debug,
          I::Item: fmt::Debug,
{
    debug_fmt_fields!(KMergeBy, heap);
}

/// Create an iterator that merges elements of the contained iterators.
///
/// Equivalent to `iterable.into_iter().kmerge_by(less_than)`.
pub fn kmerge_by<I, F>(iterable: I, mut less_than: F)
    -> KMergeBy<<I::Item as IntoIterator>::IntoIter, F>
    where I: IntoIterator,
          I::Item: IntoIterator,
          F: KMergePredicate<<<I as IntoIterator>::Item as IntoIterator>::Item>,
{
    let iter = iterable.into_iter();
    let (lower, _) = iter.size_hint();
    let mut heap: Vec<_> = Vec::with_capacity(lower);
    heap.extend(iter.filter_map(|it| HeadTail::new(it.into_iter())));
    heapify(&mut heap, |a, b| less_than.kmerge_pred(&a.head, &b.head));
    KMergeBy { heap: heap, less_than: less_than }
}

impl<I, F> Clone for KMergeBy<I, F>
    where I: Iterator + Clone,
          I::Item: Clone,
          F: Clone,
{
    fn clone(&self) -> KMergeBy<I, F> {
        clone_fields!(KMergeBy, self, heap, less_than)
    }
}

impl<I, F> Iterator for KMergeBy<I, F>
    where I: Iterator,
          F: KMergePredicate<I::Item>
{
    type Item = I::Item;

    fn next(&mut self) -> Option<Self::Item> {
        if self.heap.is_empty() {
            return None;
        }
        let result = if let Some(next) = self.heap[0].next() {
            next
        } else {
            self.heap.swap_remove(0).head
        };
        let less_than = &mut self.less_than;
        sift_down(&mut self.heap, 0, |a, b| less_than.kmerge_pred(&a.head, &b.head));
        Some(result)
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.heap.iter()
                 .map(|i| i.size_hint())
                 .fold1(size_hint::add)
                 .unwrap_or((0, Some(0)))
    }
}
<|endoftext|>


<commit_before>// TODO: COPYRIGHT, USE & AUTHORS
use super::ga_core::GASolution;
use super::ga_population::{GAPopulation, GAPopulationSortBasis, GAPopulationSortOrder};
use super::ga_random;
use std::cmp;

/// Selector Trait
///
/// Interface to Selection Schemes
pub trait GASelector<'a, T: GASolution>
{
    /// Update internal state.
    /// Some selectors implement an empty update().
    fn update(&mut self, population : &mut GAPopulation<T>) {}

    fn select(&self, population: &'a mut GAPopulation<T>) -> &'a T;
}

pub trait GAScoreTypeBasedSelection<T: GASolution>
{
    fn score(&self, individual: &T) -> f32;

    fn population_sort_basis(&self) -> GAPopulationSortBasis;

    fn max_score(&self, population: &GAPopulation<T>) -> f32
    {
        // TODO: Knowing that best is at 0 is knowing too much.
        self.score(population.individual(0, self.population_sort_basis()))
    }

    fn min_score(&self, population: &GAPopulation<T>) -> f32
    {
        // TODO: Knowing that worst is at size()-1 is knowing too much.
        self.score(population.individual(population.size()-1, self.population_sort_basis()))
    }
}

pub struct GARawScoreBasedSelection;

impl<T: GASolution> GAScoreTypeBasedSelection<T> for GARawScoreBasedSelection
{
    fn score(&self, individual: &T) -> f32
    {
        individual.score()
    }

    fn population_sort_basis(&self) -> GAPopulationSortBasis
    {
        GAPopulationSortBasis::Raw
    }
}

pub struct GAScaledScoreBasedSelection;

impl<T: GASolution> GAScoreTypeBasedSelection<T> for GAScaledScoreBasedSelection
{
    fn score(&self, individual: &T) -> f32
    {
        individual.fitness()
    }

    fn population_sort_basis(&self) -> GAPopulationSortBasis
    {
        GAPopulationSortBasis::Scaled
    }
}

// GASolution-s live as long as the population. Lifetime 'a is bound to the
// population borrowed by the 'population' member, as well as to the enclosed
// GASolution-s, because they share the same memory.
pub struct GARankSelector<'a, T: 'a + GASolution>
{
    // Q: How to make this member common to all GASelectors?
    // Q: Will 'mut' make things more complex? When the rank selector is in
    //    scope and borrowing the population, no other objects will be able
    //    to borrow it, not even in non-mut mode according to the rules.
    // Selectors modify populations (they sort them, for instance), so the
    // reference must be 'mut'.
    // population: &'a mut GAPopulation<T>,

    // TODO: Check correct lifetime.
    score_selection: &'a GAScoreTypeBasedSelection<T>
}

impl<'a, T: GASolution> GARankSelector<'a, T>
{
    pub fn new(s: &'a GAScoreTypeBasedSelection<T>) -> GARankSelector<'a, T>
    {
        GARankSelector
        {
            score_selection: s
        }
    }
}

// TODO: DOC.
impl<'a, T: GASolution> GASelector<'a, T> for GARankSelector<'a, T>
{
    fn update(&mut self, population : &mut GAPopulation<T>)
    {
        population.sort();
    }

    fn select(&self, population : &'a mut GAPopulation<T> ) -> &'a T
    {
        // TODO: Confirm assumption that population has 1 individual at least.
        // Number of individuals that share best score.
        let mut best_count = 1;

        // This is not a move, but a copy.
        let population_sort_basis = self.score_selection.population_sort_basis();

        // TODO: Use best() when implemented.
        // Q: Should individual() (ith_best()) return an optional or
        //    does it guarantee that it will always return something valid?
        //    What if the population is still empty?
        let best_score: f32 = self.score_selection.score(population.individual(0, population_sort_basis));

        // Skip 0th best.
        for i in 1..population.size()
        {
            if self.score_selection.score(population.individual(i, population_sort_basis)) != best_score
            {
                break;
            }

            best_count = best_count + 1;
        }

        // Select any individual from those that share best score.
        population.individual(ga_random::ga_random_range(0, best_count), population_sort_basis)
    }
}

pub struct GAUniformSelector
{
}

impl GAUniformSelector
{
    pub fn new() -> GAUniformSelector
    {
        GAUniformSelector
        {
        }
    }
}

impl<'a, T: GASolution> GASelector<'a, T> for GAUniformSelector
{
    fn update(&mut self, population : &mut GAPopulation<T>)
    {
        // Need to sort first, because GAPopulation.individual() draws individuals
        // from the sorted lists.
        population.sort();
    }

    // Select any individual at random.
    fn select(&self, population : &'a mut GAPopulation<T>) -> &'a T
    {
        // Since selection is at random, it doesn't matter where the individual
        // is drawn from, the Raw/score-sorted or the Scaled/fitness-sorted list.
        population.individual(
            ga_random::ga_random_range(0, population.size()),
            GAPopulationSortBasis::Raw)
    }
}

pub struct GARouletteWheelSelector<'a, T: 'a + GASolution>
{
    // TODO: Check correct lifetime.
    score_selection: &'a GAScoreTypeBasedSelection<T>,

    wheel_proportions: Vec<f32>,

    // TODO: Remove if not useful.
    wheel_is_dirty: bool
}

impl<'a, T: GASolution> GARouletteWheelSelector<'a, T>
{
    // TODO: Check s's lifetime.
    pub fn new(s: &'a GAScoreTypeBasedSelection<T>, p_size : usize) -> GARouletteWheelSelector<'a, T>
    {
        // TODO: Comment doesn't look correct.
        // vec![] borrows references (invocation of size() is through *p, or so the
        // compiler says); since p has already been borrowed as a mutable reference
        // (no data races allowed), p.size() can't be passed to vec![].
        let wheel_size = p_size;

        GARouletteWheelSelector
        {
            score_selection: s,
            wheel_proportions: vec![0.0; wheel_size],
            wheel_is_dirty: false
        }
    }
}

impl<'a, T: GASolution> GASelector<'a, T> for GARouletteWheelSelector<'a, T>
{
/*
    fn assign(&mut self, population: &'a mut GAPopulation<T>)
    {
        self.population = population;

        self.wheel_is_dirty = true;
    }
*/
    fn update(&mut self, population : &mut GAPopulation<T>)
    {
        // TODO: Can a population grow? If it can, need to resize the wheel.
        if population.size() != self.wheel_proportions.len()
        {
            self.wheel_proportions.resize(population.size(), 0.0);
        }

        population.sort();

        let wheel_slots = self.wheel_proportions.len();
        let max_score = self.score_selection.max_score(population);
        let min_score = self.score_selection.min_score(population);

        if max_score == min_score
        {
            // Upper bound is excluded.
            for i in 0 .. wheel_slots
            {
                self.wheel_proportions[i] = ((i+1) as f32)/(wheel_slots as f32);
            }
        }
        else if (max_score > 0.0 && min_score >= 0.0)
                 || (max_score <= 0.0 && min_score < 0.0)
        {
            // This is not a move, but a copy.
            let population_sort_basis = self.score_selection.population_sort_basis();

            match population.order()
            {
                GAPopulationSortOrder::HighIsBest
                =>  {
                        self.wheel_proportions[0]
                          = self.score_selection.score(
                              population.individual(0, population_sort_basis));

                        for i in 1 .. wheel_slots
                        {
                            self.wheel_proportions[i]
                              = self.score_selection.score(
                                  population.individual(i, population_sort_basis))
                                + self.wheel_proportions[i-1];
                        }

                        for i in 0 .. wheel_slots
                        {
                            self.wheel_proportions[i]
                              /= self.wheel_proportions[wheel_slots-1];
                        }
                    },
                GAPopulationSortOrder::LowIsBest
                =>  {
                        self.wheel_proportions[0]
                          = -self.score_selection.score(
                               population.individual(0, population_sort_basis))
                            + max_score + min_score;

                        for i in 1 .. wheel_slots
                        {
                            self.wheel_proportions[i]
                              = -self.score_selection.score(
                                   population.individual(i, population_sort_basis))
                                + max_score + min_score
                                + self.wheel_proportions[i-1];
                        }

                        for i in 0 .. wheel_slots
                        {
                            self.wheel_proportions[i]
                              /= self.wheel_proportions[wheel_slots-1];
                        }
                    }
            }
        }
        else
        {
            // TODO: Raise error.
        }
    }

    fn select(&self, population : &'a mut GAPopulation<T>) -> &'a T
    {
        // TODO: Cache this value? Or Vec already caches it?
        let wheel_slots = self.wheel_proportions.len();
        let cutoff = ga_random::ga_random_float();
        let mut lower = 0;
        let mut upper = wheel_slots-1;
        let mut i;

        while upper > lower
        {
            i = lower + (upper-lower)/2;

            assert!(i < wheel_slots);

            if self.wheel_proportions[i] > cutoff
            {
                if i > 0
                {
                    upper = i-1;
                }
                else
                {
                    upper = 0;
                }
            }
            else
            {
                lower = i+1;
            }
        }

        lower = cmp::min(wheel_slots-1, lower);

        population.individual(lower, self.score_selection.population_sort_basis())
    }
}

pub struct GATournamentSelector<'a, T: 'a + GASolution>
{
    // TODO: Check correct lifetime.
    score_selection: &'a GAScoreTypeBasedSelection<T>,

    roulette_wheel_selector: GARouletteWheelSelector<'a, T>,

    population_sort_order: GAPopulationSortOrder
}

/*
impl<'a, T: GASolution> GATournamentSelector<'a, T>
{
    // TODO: Check s's lifetime.
    pub fn new(p: &'a mut GAPopulation<T>,
               s: &'a GAScoreTypeBasedSelection<T>) -> GATournamentSelector<'a, T>
    {
        GATournamentSelector
        {
            score_selection: s,
            population_sort_order: p.order(),
            roulette_wheel_selector: GARouletteWheelSelector::new(p, s)
        }
    }
}

impl<'a, T: GASolution> GASelector<'a, T> for GATournamentSelector<'a, T>
{
    fn assign(&mut self, population: &'a mut GAPopulation<T>)
    {
        self.population_sort_order = population.order();

        self.roulette_wheel_selector.assign(population);
    }

    fn update(&mut self)
    {
        self.roulette_wheel_selector.update();
    }

    fn select(&self) -> &T
    {
        let low_score_individual;
        let high_score_individual;
        let individual1;
        let individual2;

        individual1 = self.roulette_wheel_selector.select();

        individual2 = self.roulette_wheel_selector.select();

        if self.score_selection.score(individual1)
           >= self.score_selection.score(individual2)
        {
            low_score_individual = individual2;
            high_score_individual = individual1;
        }
        else
        {
            low_score_individual = individual1;
            high_score_individual = individual2;
        }

        match self.population_sort_order
        {
            GAPopulationSortOrder::HighIsBest => high_score_individual,
            GAPopulationSortOrder::LowIsBest  => low_score_individual
        }
    }
}
*/
<commit_msg>Mutability begone, fix Tournament<commit_after>// TODO: COPYRIGHT, USE & AUTHORS
use super::ga_core::GASolution;
use super::ga_population::{GAPopulation, GAPopulationSortBasis, GAPopulationSortOrder};
use super::ga_random;
use std::cmp;

/// Selector Trait
///
/// Interface to Selection Schemes
pub trait GASelector<'a, T: GASolution>
{
    /// Update internal state.
    /// Some selectors implement an empty update().
    fn update(&mut self, population : &mut GAPopulation<T>) {}

    fn select(&self, population: &'a GAPopulation<T>) -> &'a T;
}

pub trait GAScoreTypeBasedSelection<T: GASolution>
{
    fn score(&self, individual: &T) -> f32;

    fn population_sort_basis(&self) -> GAPopulationSortBasis;

    fn max_score(&self, population: &GAPopulation<T>) -> f32
    {
        // TODO: Knowing that best is at 0 is knowing too much.
        self.score(population.individual(0, self.population_sort_basis()))
    }

    fn min_score(&self, population: &GAPopulation<T>) -> f32
    {
        // TODO: Knowing that worst is at size()-1 is knowing too much.
        self.score(population.individual(population.size()-1, self.population_sort_basis()))
    }
}

pub struct GARawScoreBasedSelection;

impl<T: GASolution> GAScoreTypeBasedSelection<T> for GARawScoreBasedSelection
{
    fn score(&self, individual: &T) -> f32
    {
        individual.score()
    }

    fn population_sort_basis(&self) -> GAPopulationSortBasis
    {
        GAPopulationSortBasis::Raw
    }
}

pub struct GAScaledScoreBasedSelection;

impl<T: GASolution> GAScoreTypeBasedSelection<T> for GAScaledScoreBasedSelection
{
    fn score(&self, individual: &T) -> f32
    {
        individual.fitness()
    }

    fn population_sort_basis(&self) -> GAPopulationSortBasis
    {
        GAPopulationSortBasis::Scaled
    }
}

// GASolution-s live as long as the population. Lifetime 'a is bound to the
// population borrowed by the 'population' member, as well as to the enclosed
// GASolution-s, because they share the same memory.
pub struct GARankSelector<'a, T: 'a + GASolution>
{
    // Q: How to make this member common to all GASelectors?
    // Q: Will 'mut' make things more complex? When the rank selector is in
    //    scope and borrowing the population, no other objects will be able
    //    to borrow it, not even in non-mut mode according to the rules.
    // Selectors modify populations (they sort them, for instance), so the
    // reference must be 'mut'.
    // population: &'a mut GAPopulation<T>,

    // TODO: Check correct lifetime.
    score_selection: &'a GAScoreTypeBasedSelection<T>
}

impl<'a, T: GASolution> GARankSelector<'a, T>
{
    pub fn new(s: &'a GAScoreTypeBasedSelection<T>) -> GARankSelector<'a, T>
    {
        GARankSelector
        {
            score_selection: s
        }
    }
}

// TODO: DOC.
impl<'a, T: GASolution> GASelector<'a, T> for GARankSelector<'a, T>
{
    fn update(&mut self, population : &mut GAPopulation<T>)
    {
        population.sort();
    }

    fn select(&self, population : &'a GAPopulation<T> ) -> &'a T
    {
        // TODO: Confirm assumption that population has 1 individual at least.
        // Number of individuals that share best score.
        let mut best_count = 1;

        // This is not a move, but a copy.
        let population_sort_basis = self.score_selection.population_sort_basis();

        // TODO: Use best() when implemented.
        // Q: Should individual() (ith_best()) return an optional or
        //    does it guarantee that it will always return something valid?
        //    What if the population is still empty?
        let best_score: f32 = self.score_selection.score(population.individual(0, population_sort_basis));

        // Skip 0th best.
        for i in 1..population.size()
        {
            if self.score_selection.score(population.individual(i, population_sort_basis)) != best_score
            {
                break;
            }

            best_count = best_count + 1;
        }

        // Select any individual from those that share best score.
        population.individual(ga_random::ga_random_range(0, best_count), population_sort_basis)
    }
}

pub struct GAUniformSelector
{
}

impl GAUniformSelector
{
    pub fn new() -> GAUniformSelector
    {
        GAUniformSelector
        {
        }
    }
}

impl<'a, T: GASolution> GASelector<'a, T> for GAUniformSelector
{
    fn update(&mut self, population : &mut GAPopulation<T>)
    {
        // Need to sort first, because GAPopulation.individual() draws individuals
        // from the sorted lists.
        population.sort();
    }

    // Select any individual at random.
    fn select(&self, population : &'a GAPopulation<T>) -> &'a T
    {
        // Since selection is at random, it doesn't matter where the individual
        // is drawn from, the Raw/score-sorted or the Scaled/fitness-sorted list.
        population.individual(
            ga_random::ga_random_range(0, population.size()),
            GAPopulationSortBasis::Raw)
    }
}

pub struct GARouletteWheelSelector<'a, T: 'a + GASolution>
{
    // TODO: Check correct lifetime.
    score_selection: &'a GAScoreTypeBasedSelection<T>,

    wheel_proportions: Vec<f32>,

    // TODO: Remove if not useful.
    wheel_is_dirty: bool
}

impl<'a, T: GASolution> GARouletteWheelSelector<'a, T>
{
    // TODO: Check s's lifetime.
    pub fn new(s: &'a GAScoreTypeBasedSelection<T>, p_size : usize) -> GARouletteWheelSelector<'a, T>
    {
        // TODO: Comment doesn't look correct.
        // vec![] borrows references (invocation of size() is through *p, or so the
        // compiler says); since p has already been borrowed as a mutable reference
        // (no data races allowed), p.size() can't be passed to vec![].
        let wheel_size = p_size;

        GARouletteWheelSelector
        {
            score_selection: s,
            wheel_proportions: vec![0.0; wheel_size],
            wheel_is_dirty: false
        }
    }
}

impl<'a, T: GASolution> GASelector<'a, T> for GARouletteWheelSelector<'a, T>
{
/*
    fn assign(&mut self, population: &'a mut GAPopulation<T>)
    {
        self.population = population;

        self.wheel_is_dirty = true;
    }
*/
    fn update(&mut self, population : &mut GAPopulation<T>)
    {
        // TODO: Can a population grow? If it can, need to resize the wheel.
        if population.size() != self.wheel_proportions.len()
        {
            self.wheel_proportions.resize(population.size(), 0.0);
        }

        population.sort();

        let wheel_slots = self.wheel_proportions.len();
        let max_score = self.score_selection.max_score(population);
        let min_score = self.score_selection.min_score(population);

        if max_score == min_score
        {
            // Upper bound is excluded.
            for i in 0 .. wheel_slots
            {
                self.wheel_proportions[i] = ((i+1) as f32)/(wheel_slots as f32);
            }
        }
        else if (max_score > 0.0 && min_score >= 0.0)
                 || (max_score <= 0.0 && min_score < 0.0)
        {
            // This is not a move, but a copy.
            let population_sort_basis = self.score_selection.population_sort_basis();

            match population.order()
            {
                GAPopulationSortOrder::HighIsBest
                =>  {
                        self.wheel_proportions[0]
                          = self.score_selection.score(
                              population.individual(0, population_sort_basis));

                        for i in 1 .. wheel_slots
                        {
                            self.wheel_proportions[i]
                              = self.score_selection.score(
                                  population.individual(i, population_sort_basis))
                                + self.wheel_proportions[i-1];
                        }

                        for i in 0 .. wheel_slots
                        {
                            self.wheel_proportions[i]
                              /= self.wheel_proportions[wheel_slots-1];
                        }
                    },
                GAPopulationSortOrder::LowIsBest
                =>  {
                        self.wheel_proportions[0]
                          = -self.score_selection.score(
                               population.individual(0, population_sort_basis))
                            + max_score + min_score;

                        for i in 1 .. wheel_slots
                        {
                            self.wheel_proportions[i]
                              = -self.score_selection.score(
                                   population.individual(i, population_sort_basis))
                                + max_score + min_score
                                + self.wheel_proportions[i-1];
                        }

                        for i in 0 .. wheel_slots
                        {
                            self.wheel_proportions[i]
                              /= self.wheel_proportions[wheel_slots-1];
                        }
                    }
            }
        }
        else
        {
            // TODO: Raise error.
        }
    }

    fn select(&self, population : &'a GAPopulation<T>) -> &'a T
    {
        // TODO: Cache this value? Or Vec already caches it?
        let wheel_slots = self.wheel_proportions.len();
        let cutoff = ga_random::ga_random_float();
        let mut lower = 0;
        let mut upper = wheel_slots-1;
        let mut i;

        while upper > lower
        {
            i = lower + (upper-lower)/2;

            assert!(i < wheel_slots);

            if self.wheel_proportions[i] > cutoff
            {
                if i > 0
                {
                    upper = i-1;
                }
                else
                {
                    upper = 0;
                }
            }
            else
            {
                lower = i+1;
            }
        }

        lower = cmp::min(wheel_slots-1, lower);

        population.individual(lower, self.score_selection.population_sort_basis())
    }
}

pub struct GATournamentSelector<'a, T: 'a + GASolution>
{
    // TODO: Check correct lifetime.
    score_selection: &'a GAScoreTypeBasedSelection<T>,
    roulette_wheel_selector: GARouletteWheelSelector<'a, T>,
}

impl<'a, T: GASolution> GATournamentSelector<'a, T>
{
    // TODO: Check s's lifetime.
    pub fn new(s: &'a GAScoreTypeBasedSelection<T>, p_size : usize) -> GATournamentSelector<'a, T>
    {
        GATournamentSelector
        {
            score_selection: s,
            roulette_wheel_selector: GARouletteWheelSelector::new(s, p_size)
        }
    }
}

impl<'a, T: GASolution> GASelector<'a, T> for GATournamentSelector<'a, T>
{
    fn update(&mut self, population : &mut GAPopulation<T>)
    {
        self.roulette_wheel_selector.update(population);
    }

    fn select(&self, population: &'a GAPopulation<T>) -> &'a T
    {
        let low_score_individual;
        let high_score_individual;
        let individual1;
        let individual2;

        individual1 = self.roulette_wheel_selector.select(population);
        individual2 = self.roulette_wheel_selector.select(population);

        if self.score_selection.score(individual1)
           >= self.score_selection.score(individual2)
        {
            low_score_individual = individual2;
            high_score_individual = individual1;
        }
        else
        {
            low_score_individual = individual1;
            high_score_individual = individual2;
        }

        match population.order()
        {
            GAPopulationSortOrder::HighIsBest => high_score_individual,
            GAPopulationSortOrder::LowIsBest  => low_score_individual
        }
    }
}
<|endoftext|>


<commit_before>/* diosix capsule management
 *
 * (c) Chris Williams, 2019.
 *
 * See LICENSE for usage and copying.
 */

use spin::Mutex;
use hashbrown::hash_map::HashMap;
use hashbrown::hash_map::Entry::{Occupied, Vacant};
use hashbrown::hash_set::HashSet;
use alloc::vec::Vec;
use platform::physmem::PhysMemSize;
use platform::virtmem::VirtMemBase;
use platform::cpu::Entry;
use super::loader;
use super::error::Cause;
use super::physmem::{self, Region};
use super::virtmem::Mapping;
use super::vcore::{self, Priority, VirtualCoreID};
use super::service::ServiceID;
use super::pcore::PhysicalCore;
use super::service;
use super::message;

pub type CapsuleID = usize;

/* needed to assign system-wide unique capsule ID numbers */
lazy_static!
{
    static ref CAPSULE_ID_NEXT: Mutex<CapsuleID> = Mutex::new(0);
}

/* maintain a shared table of capsules */
lazy_static!
{
    /* acquire CAPSULES lock before accessing any capsules */
    static ref CAPSULES: Mutex<HashMap<CapsuleID, Capsule>> = Mutex::new(HashMap::new());
}

struct Capsule
{
    restart: bool,                          /* true to auto-restart on death */
    vcores: HashSet<VirtualCoreID>,         /* set of virtual core IDs assigned to this capsule */
    memory: Vec<Mapping>,                   /* map capsule supervisor virtual addresses to host physical addresses */
    allowed_services: HashSet<ServiceID>    /* set of services this capsule is allowed to provide */
}

impl Capsule
{
    /* create a new empty capsule using the current capsule on this physical CPU core.
    => auto_restart_flag = tue to auto-restart on death by the hypervisor (eg, for the boot capsule)
    <= capsule object, or error code */
    pub fn new(auto_restart_flag: bool) -> Result<Capsule, Cause>
    {
        Ok(Capsule
        {
            restart: auto_restart_flag,
            vcores: HashSet::new(),
            memory: Vec::new(),
            allowed_services: HashSet::new(),
        })
    }

    /* add a mapping to this capsule */
    pub fn set_memory_mapping(&mut self, to_add: Mapping)
    {
        self.memory.push(to_add);
    }

    /* get a copy of the capsule's memory mappings */
    pub fn get_memory_mappings(&self) -> Vec<Mapping> { self.memory.clone() }

    /* boot capsules are auto-restarted by the hypervisor */
    pub fn set_auto_restart(&mut self, flag: bool)
    {
        self.restart = flag;
    }

    /* returns true if this will auto-restart, or false if not */
    pub fn will_auto_restart(&self) -> bool
    {
        self.restart
    }

    /* add a virtual core ID to the capsule */
    pub fn add_vcore(&mut self, id: VirtualCoreID)
    {
        self.vcores.insert(id);
    }

    /* remove a virtual core ID from the capsule. returns true if that
       ID was present in the registered list */
    pub fn remove_vcore(&mut self, id: VirtualCoreID) -> bool
    {
        self.vcores.remove(&id)
    }

    /* return number of registered virtual cores */
    pub fn count_vcores(&self) -> usize
    {
        self.vcores.len()
    }

    /* allow capsule to register service sid */
    pub fn allow_service(&mut self, sid: ServiceID)
    {
        self.allowed_services.insert(sid);
    }

    /* check whether this capsule is allowed to register the given service
        <= true if allowed, false if not */
    pub fn check_service(&self, sid: ServiceID) -> bool
    {
        self.allowed_services.contains(&sid)
    }
}

/* handle the destruction of a capsule */
impl Drop for Capsule
{
    fn drop(&mut self)
    {
        hvdebug!("Tearing down capsule");

        /* free up memory... */
        for mapping in self.memory.clone()
        {
            if let Some(r) = mapping.get_physical()
            {
                physmem::dealloc_region(r);
            }
        }

        /* ...and services held by this capsule */
        for sid in self.allowed_services.iter()
        {
            service::deregister(*sid);
        }
    }
}

/* create the boot capsule, from which all other capsules spawn */
pub fn create_boot_capsule() -> Result<(), Cause>
{
    /* create an auto-restarting capsule */
    let capid = create(true)?;

    /* reserve 128MB of physical RAM for the capsule */
    let size = 128 * 1024 * 1024;
    let cpus = 1;
    let ram = physmem::alloc_region(size)?;

    /* map that physical memory into the capsule */
    let mut mapping = Mapping::new();
    mapping.set_physical(ram);
    mapping.identity_mapping()?;
    map_memory(capid, mapping)?;

    /* parse + copy the boot capsule's binary into its physical memory */
    let phys_binary_location = physmem::boot_supervisor();
    let entry = loader::load(ram, phys_binary_location)?;

    /* create virtual CPU cores for the capsule as required */
    for vcoreid in 0..cpus
    {
        create_and_add_vcore(capid, vcoreid, entry, Priority::High)?;
    }
    Ok(())
}

/* create a virtual core and add it to the given capsule
   => cid = capsule ID
      vid = virtual core ID
      entry = starting address for execution of this virtual core
      prio = priority to run this virtual core
   <= return Ok for success, or error code
*/
pub fn create_and_add_vcore(cid: CapsuleID, vid: VirtualCoreID, entry: Entry, prio: Priority) -> Result<(), Cause>
{
    vcore::VirtualCore::create(cid, vid, entry, prio)?;
    match CAPSULES.lock().get_mut(&cid)
    {
        Some(c) => c.add_vcore(vid),
        None => return Err(Cause::CapsuleBadID)
    };
    Ok(())
}

/* create a new blank capsule
   Once created, it needs to be given a supervisor image, at least.
   then it is ready to be scheduled by assigning it virtual CPU cores.
   => auto_restart = true to be auto-restarted by hypervisor
   <= CapsuleID for this new capsule, or an error code */
fn create(auto_restart: bool) -> Result<CapsuleID, Cause>
{
    let new_capsule = Capsule::new(auto_restart)?;

    /* assign a new ID (in the unlikely event the given ID is already in-use, try again) */
    let mut overflowed_already = false;
    loop
    {
        let mut id = CAPSULE_ID_NEXT.lock();
        let (new_id, overflow) = id.overflowing_add(1);
        *id = new_id;

        /* check to see if this capsule already exists */
        let mut capsules = CAPSULES.lock();
        match capsules.entry(new_id)
        {
            Vacant(_) =>
            {
                /* insert our new capsule */
                capsules.insert(new_id, new_capsule);

                /* we're all done here */
                return Ok(new_id);
            },
            _ => () /* try again */
        };

        /* make sure we don't loop around forever hunting for a valid ID */
        if overflow == true
        {
            /* has this overflow happened before? */
            if overflowed_already == true
            {
                /* not the first time we overflowed, so give up */
                return Err(Cause::CapsuleIDExhaustion);
            }

            overflowed_already = true;
        }
    }
}

/* mark a capsule as dying, meaning its virtual cores will be
   gradually removed and when there are none left, its RAM
   and any other resources will be deallocated.
   => cid = ID of capsule to kill
   <= Ok for success, or an error code
*/
pub fn destroy(cid: CapsuleID) -> Result<(), Cause>
{
    if let Some(victim) = CAPSULES.lock().remove(&cid)
    {
        drop(victim); // see above implementation of drop for Capsule
        Ok(())
    }
    else
    {
        Err(Cause::CapsuleBadID)
    }
}

/* allow a given capsule to offer a given service. if the capsule was already allowed the
   service then this returns without error.
    => cid = capsule ID
       sid = service ID
    <= Ok for success, or an error code */
pub fn allow_service(cid: CapsuleID, sid: ServiceID) -> Result<(), Cause>
{
    match CAPSULES.lock().entry(cid)
    {
        Occupied(mut c) =>
        {
            c.get_mut().allowed_services.insert(sid);
            Ok(())
        },
        Vacant(_) => Err(Cause::CapsuleBadID)
    }
}

/* check whether a capsule is allowed to run the given service
    => cid = capsule ID to check
       sid = service ID to check
    <= Some true if the capsule exists and is allowed, or Some false
        if the capsule exists and is not allowed, or None if
        the capsule doesn't exist */
pub fn is_service_allowed(cid: CapsuleID, sid: ServiceID) -> Option<bool>
{
    match CAPSULES.lock().entry(cid)
    {
        Occupied(c) => Some(c.get().check_service(sid)),
        Vacant(_) => None
    }
}

/* add a memory mapping to a capsule
   cid = ID of capsule to add the mapping to
   to_map = memory mapping object to add
   Ok for success, or an error code
*/
pub fn map_memory(cid: CapsuleID, to_map: Mapping) -> Result<(), Cause>
{
    if let Occupied(mut c) = CAPSULES.lock().entry(cid)
    {
        c.get_mut().set_memory_mapping(to_map);
        return Ok(());
    }
    else
    {
        return Err(Cause::CapsuleBadID);
    }
}

/* enforce hardware security restrictions for the given capsule.
   supervisor-level code will only be able to access the physical
   RAM covered by that assigned to the given capsule. call this
   when switching to a capsule, so that the previous enforcement is
   replaced by enforcement of this capsule.
   => id = capsule to enforce
   <= true for success, or fail for failure
*/
pub fn enforce(id: CapsuleID) -> bool
{
    match CAPSULES.lock().entry(id)
    {
        Occupied(c) =>
        {
            for mapping in c.get().get_memory_mappings()
            {
                if let Some(r) = mapping.get_physical()
                {
                    r.grant_access();
                }
            }
            return true
        },
        _ => false
    }
}
<commit_msg>Add a roadblock to ensure we don't start adding multiple regions to capsules expecting the underlying system to support this. This code needs to be written.<commit_after>/* diosix capsule management
 *
 * (c) Chris Williams, 2019.
 *
 * See LICENSE for usage and copying.
 */

use spin::Mutex;
use hashbrown::hash_map::HashMap;
use hashbrown::hash_map::Entry::{Occupied, Vacant};
use hashbrown::hash_set::HashSet;
use alloc::vec::Vec;
use platform::physmem::PhysMemSize;
use platform::virtmem::VirtMemBase;
use platform::cpu::Entry;
use super::loader;
use super::error::Cause;
use super::physmem::{self, Region};
use super::virtmem::Mapping;
use super::vcore::{self, Priority, VirtualCoreID};
use super::service::ServiceID;
use super::pcore::PhysicalCore;
use super::service;
use super::message;

pub type CapsuleID = usize;

/* needed to assign system-wide unique capsule ID numbers */
lazy_static!
{
    static ref CAPSULE_ID_NEXT: Mutex<CapsuleID> = Mutex::new(0);
}

/* maintain a shared table of capsules */
lazy_static!
{
    /* acquire CAPSULES lock before accessing any capsules */
    static ref CAPSULES: Mutex<HashMap<CapsuleID, Capsule>> = Mutex::new(HashMap::new());
}

struct Capsule
{
    restart: bool,                          /* true to auto-restart on death */
    vcores: HashSet<VirtualCoreID>,         /* set of virtual core IDs assigned to this capsule */
    memory: Vec<Mapping>,                   /* map capsule supervisor virtual addresses to host physical addresses */
    allowed_services: HashSet<ServiceID>    /* set of services this capsule is allowed to provide */
}

impl Capsule
{
    /* create a new empty capsule using the current capsule on this physical CPU core.
    => auto_restart_flag = tue to auto-restart on death by the hypervisor (eg, for the boot capsule)
    <= capsule object, or error code */
    pub fn new(auto_restart_flag: bool) -> Result<Capsule, Cause>
    {
        Ok(Capsule
        {
            restart: auto_restart_flag,
            vcores: HashSet::new(),
            memory: Vec::new(),
            allowed_services: HashSet::new(),
        })
    }

    /* add a mapping to this capsule */
    pub fn set_memory_mapping(&mut self, to_add: Mapping)
    {
        self.memory.push(to_add);
    }

    /* get a copy of the capsule's memory mappings */
    pub fn get_memory_mappings(&self) -> Vec<Mapping> { self.memory.clone() }

    /* boot capsules are auto-restarted by the hypervisor */
    pub fn set_auto_restart(&mut self, flag: bool)
    {
        self.restart = flag;
    }

    /* returns true if this will auto-restart, or false if not */
    pub fn will_auto_restart(&self) -> bool
    {
        self.restart
    }

    /* add a virtual core ID to the capsule */
    pub fn add_vcore(&mut self, id: VirtualCoreID)
    {
        self.vcores.insert(id);
    }

    /* remove a virtual core ID from the capsule. returns true if that
       ID was present in the registered list */
    pub fn remove_vcore(&mut self, id: VirtualCoreID) -> bool
    {
        self.vcores.remove(&id)
    }

    /* return number of registered virtual cores */
    pub fn count_vcores(&self) -> usize
    {
        self.vcores.len()
    }

    /* allow capsule to register service sid */
    pub fn allow_service(&mut self, sid: ServiceID)
    {
        self.allowed_services.insert(sid);
    }

    /* check whether this capsule is allowed to register the given service
        <= true if allowed, false if not */
    pub fn check_service(&self, sid: ServiceID) -> bool
    {
        self.allowed_services.contains(&sid)
    }
}

/* handle the destruction of a capsule */
impl Drop for Capsule
{
    fn drop(&mut self)
    {
        hvdebug!("Tearing down capsule");

        /* free up memory... */
        for mapping in self.memory.clone()
        {
            if let Some(r) = mapping.get_physical()
            {
                physmem::dealloc_region(r);
            }
        }

        /* ...and services held by this capsule */
        for sid in self.allowed_services.iter()
        {
            service::deregister(*sid);
        }
    }
}

/* create the boot capsule, from which all other capsules spawn */
pub fn create_boot_capsule() -> Result<(), Cause>
{
    /* create an auto-restarting capsule */
    let capid = create(true)?;

    /* reserve 128MB of physical RAM for the capsule */
    let size = 128 * 1024 * 1024;
    let cpus = 1;
    let ram = physmem::alloc_region(size)?;

    /* map that physical memory into the capsule */
    let mut mapping = Mapping::new();
    mapping.set_physical(ram);
    mapping.identity_mapping()?;
    map_memory(capid, mapping)?;

    /* parse + copy the boot capsule's binary into its physical memory */
    let phys_binary_location = physmem::boot_supervisor();
    let entry = loader::load(ram, phys_binary_location)?;

    /* create virtual CPU cores for the capsule as required */
    for vcoreid in 0..cpus
    {
        create_and_add_vcore(capid, vcoreid, entry, Priority::High)?;
    }
    Ok(())
}

/* create a virtual core and add it to the given capsule
   => cid = capsule ID
      vid = virtual core ID
      entry = starting address for execution of this virtual core
      prio = priority to run this virtual core
   <= return Ok for success, or error code
*/
pub fn create_and_add_vcore(cid: CapsuleID, vid: VirtualCoreID, entry: Entry, prio: Priority) -> Result<(), Cause>
{
    vcore::VirtualCore::create(cid, vid, entry, prio)?;
    match CAPSULES.lock().get_mut(&cid)
    {
        Some(c) => c.add_vcore(vid),
        None => return Err(Cause::CapsuleBadID)
    };
    Ok(())
}

/* create a new blank capsule
   Once created, it needs to be given a supervisor image, at least.
   then it is ready to be scheduled by assigning it virtual CPU cores.
   => auto_restart = true to be auto-restarted by hypervisor
   <= CapsuleID for this new capsule, or an error code */
fn create(auto_restart: bool) -> Result<CapsuleID, Cause>
{
    let new_capsule = Capsule::new(auto_restart)?;

    /* assign a new ID (in the unlikely event the given ID is already in-use, try again) */
    let mut overflowed_already = false;
    loop
    {
        let mut id = CAPSULE_ID_NEXT.lock();
        let (new_id, overflow) = id.overflowing_add(1);
        *id = new_id;

        /* check to see if this capsule already exists */
        let mut capsules = CAPSULES.lock();
        match capsules.entry(new_id)
        {
            Vacant(_) =>
            {
                /* insert our new capsule */
                capsules.insert(new_id, new_capsule);

                /* we're all done here */
                return Ok(new_id);
            },
            _ => () /* try again */
        };

        /* make sure we don't loop around forever hunting for a valid ID */
        if overflow == true
        {
            /* has this overflow happened before? */
            if overflowed_already == true
            {
                /* not the first time we overflowed, so give up */
                return Err(Cause::CapsuleIDExhaustion);
            }

            overflowed_already = true;
        }
    }
}

/* mark a capsule as dying, meaning its virtual cores will be
   gradually removed and when there are none left, its RAM
   and any other resources will be deallocated.
   => cid = ID of capsule to kill
   <= Ok for success, or an error code
*/
pub fn destroy(cid: CapsuleID) -> Result<(), Cause>
{
    if let Some(victim) = CAPSULES.lock().remove(&cid)
    {
        drop(victim); // see above implementation of drop for Capsule
        Ok(())
    }
    else
    {
        Err(Cause::CapsuleBadID)
    }
}

/* allow a given capsule to offer a given service. if the capsule was already allowed the
   service then this returns without error.
    => cid = capsule ID
       sid = service ID
    <= Ok for success, or an error code */
pub fn allow_service(cid: CapsuleID, sid: ServiceID) -> Result<(), Cause>
{
    match CAPSULES.lock().entry(cid)
    {
        Occupied(mut c) =>
        {
            c.get_mut().allowed_services.insert(sid);
            Ok(())
        },
        Vacant(_) => Err(Cause::CapsuleBadID)
    }
}

/* check whether a capsule is allowed to run the given service
    => cid = capsule ID to check
       sid = service ID to check
    <= Some true if the capsule exists and is allowed, or Some false
        if the capsule exists and is not allowed, or None if
        the capsule doesn't exist */
pub fn is_service_allowed(cid: CapsuleID, sid: ServiceID) -> Option<bool>
{
    match CAPSULES.lock().entry(cid)
    {
        Occupied(c) => Some(c.get().check_service(sid)),
        Vacant(_) => None
    }
}

/* add a memory mapping to a capsule
   cid = ID of capsule to add the mapping to
   to_map = memory mapping object to add
   Ok for success, or an error code
*/
pub fn map_memory(cid: CapsuleID, to_map: Mapping) -> Result<(), Cause>
{
    if let Occupied(mut c) = CAPSULES.lock().entry(cid)
    {
        c.get_mut().set_memory_mapping(to_map);
        return Ok(());
    }
    else
    {
        return Err(Cause::CapsuleBadID);
    }
}

/* enforce hardware security restrictions for the given capsule.
   supervisor-level code will only be able to access the physical
   RAM covered by that assigned to the given capsule. call this
   when switching to a capsule, so that the previous enforcement is
   replaced by enforcement of this capsule.
   => id = capsule to enforce
   <= true for success, or fail for failure
*/
pub fn enforce(id: CapsuleID) -> bool
{
    /* this is a filthy hardcode hack that I hate but it's needed for now */
    let mut index = 0;

    match CAPSULES.lock().entry(id)
    {
        Occupied(c) =>
        {
            for mapping in c.get().get_memory_mappings()
            {
                if let Some(r) = mapping.get_physical()
                {
                    if index > 0
                    {
                        panic!("TODO / FIXME: Capsules can't have more than one physical RAM region");
                    }

                    r.grant_access();
                    index = index + 1;
                }
            }
            return true
        },
        _ => false
    }
}
<|endoftext|>


<commit_before>use fractal::Beta;
use sqlite::{Connection, State};
use std::collections::VecDeque;
use std::rc::Rc;

use config::Config;
use {Result, Source};

pub struct Traffic {
    model: Rc<Beta>,
    source: Source,
    steps: VecDeque<f64>,
}

impl Traffic {
    pub fn new(config: &Config, source: &Source) -> Result<Traffic> {
        let path = path!(config, "a workload pattern database");
        let backend = ok!(Connection::open(&path!(config, "a traffic database")));

        info!(target: "traffic", "Reading {:?}...", &path);
        let data = match config.get::<String>("query") {
            Some(ref query) => try!(read_interarrivals(&backend, query)),
            _ => raise!("an SQL query for reading the traffic data is required"),
        };
        let ncoarse = match (data.len() as f64).log2().floor() {
            ncoarse if ncoarse < 1.0 => raise!("there are not enough data"),
            ncoarse => ncoarse as usize,
        };

        info!(target: "traffic", "Read {} arrivals. Fitting the model...", data.len());
        Ok(Traffic {
            model: Rc::new(ok!(Beta::new(&data, ncoarse))),
            source: source.clone(),
            steps: VecDeque::new(),
        })
    }

    pub fn next(&mut self) -> Option<f64> {
        if self.steps.is_empty() {
            if let Err(error) = self.refill() {
                error!(target: "traffic", "Failed to refill the queue ({}).", error);
                return None;
            }
        }
        self.steps.pop_front()
    }

    fn refill(&mut self) -> Result<()> {
        info!(target: "traffic", "Refilling the queue...");
        self.steps.extend(&ok!(self.model.sample(&mut self.source)));
        info!(target: "traffic", "The queue contains {} interarrivals.", self.steps.len());
        Ok(())
    }
}

fn read_interarrivals(backend: &Connection, query: &str) -> Result<Vec<f64>> {
    let mut statement = ok!(backend.prepare(query));

    let mut data = Vec::new();
    let mut last_time = {
        if State::Row != ok!(statement.step()) {
            return Ok(data);
        }
        ok!(statement.read::<f64>(0))
    };
    while State::Row == ok!(statement.step()) {
        let time = ok!(statement.read::<f64>(0));
        data.push(time - last_time);
        last_time = time;
    }

    Ok(data)
}

#[cfg(test)]
mod tests {
    use sqlite::Connection;

    #[test]
    fn read_interarrivals() {
        let backend = Connection::open("tests/fixtures/google.sqlite3").unwrap();
        let data = super::read_interarrivals(&backend, "
            SELECT 1e-6 * `time` FROM `job_events`
            WHERE `time` IS NOT 0 AND `event type` IS 0
            ORDER BY `time` ASC;
        ").ok().unwrap();
        assert_eq!(data.len(), 19640);
    }
}
<commit_msg>Check it the month-time Google cluster dataset<commit_after>use fractal::Beta;
use sqlite::{Connection, State};
use std::collections::VecDeque;
use std::rc::Rc;

use config::Config;
use {Result, Source};

pub struct Traffic {
    model: Rc<Beta>,
    source: Source,
    steps: VecDeque<f64>,
}

impl Traffic {
    pub fn new(config: &Config, source: &Source) -> Result<Traffic> {
        let path = path!(config, "a workload pattern database");
        let backend = ok!(Connection::open(&path!(config, "a traffic database")));

        info!(target: "traffic", "Reading {:?}...", &path);
        let data = match config.get::<String>("query") {
            Some(ref query) => try!(read_interarrivals(&backend, query)),
            _ => raise!("an SQL query for reading the traffic data is required"),
        };
        let ncoarse = match (data.len() as f64).log2().floor() {
            ncoarse if ncoarse < 1.0 => raise!("there are not enough data"),
            ncoarse => ncoarse as usize,
        };

        info!(target: "traffic", "Read {} arrivals. Fitting the model...", data.len());
        Ok(Traffic {
            model: Rc::new(ok!(Beta::new(&data, ncoarse))),
            source: source.clone(),
            steps: VecDeque::new(),
        })
    }

    pub fn next(&mut self) -> Option<f64> {
        if self.steps.is_empty() {
            if let Err(error) = self.refill() {
                error!(target: "traffic", "Failed to refill the queue ({}).", error);
                return None;
            }
        }
        self.steps.pop_front()
    }

    fn refill(&mut self) -> Result<()> {
        info!(target: "traffic", "Refilling the queue...");
        self.steps.extend(&ok!(self.model.sample(&mut self.source)));
        info!(target: "traffic", "The queue contains {} interarrivals.", self.steps.len());
        Ok(())
    }
}

fn read_interarrivals(backend: &Connection, query: &str) -> Result<Vec<f64>> {
    let mut statement = ok!(backend.prepare(query));

    let mut data = Vec::new();
    let mut last_time = {
        if State::Row != ok!(statement.step()) {
            return Ok(data);
        }
        ok!(statement.read::<f64>(0))
    };
    while State::Row == ok!(statement.step()) {
        let time = ok!(statement.read::<f64>(0));
        data.push(time - last_time);
        last_time = time;
    }

    Ok(data)
}

#[cfg(test)]
mod tests {
    use sqlite::Connection;

    #[test]
    fn read_interarrivals() {
        let backend = Connection::open("tests/fixtures/google.sqlite3").unwrap();
        let data = super::read_interarrivals(&backend, "
            SELECT 1e-6 * `time` FROM `job_events`
            WHERE `time` IS NOT 0 AND `event type` IS 0
            ORDER BY `time` ASC;
        ").ok().unwrap();
        assert_eq!(data.len(), 667926);
    }
}
<|endoftext|>


<commit_before>//! # The Rust Core Library
//!
//! The Rust Core Library is the dependency-free[^free] foundation of [The
//! Rust Standard Library](../std/index.html). It is the portable glue
//! between the language and its libraries, defining the intrinsic and
//! primitive building blocks of all Rust code. It links to no
//! upstream libraries, no system libraries, and no libc.
//!
//! [^free]: Strictly speaking, there are some symbols which are needed but
//!          they aren't always necessary.
//!
//! The core library is *minimal*: it isn't even aware of heap allocation,
//! nor does it provide concurrency or I/O. These things require
//! platform integration, and this library is platform-agnostic.
//!
//! # How to use the core library
//!
//! Please note that all of these details are currently not considered stable.
//!
// FIXME: Fill me in with more detail when the interface settles
//! This library is built on the assumption of a few existing symbols:
//!
//! * `memcpy`, `memcmp`, `memset` - These are core memory routines which are
//!   often generated by LLVM. Additionally, this library can make explicit
//!   calls to these functions. Their signatures are the same as found in C.
//!   These functions are often provided by the system libc, but can also be
//!   provided by the [compiler-builtins crate](https://crates.io/crates/compiler_builtins).
//!
//! * `rust_begin_panic` - This function takes four arguments, a
//!   `fmt::Arguments`, a `&'static str`, and two `u32`'s. These four arguments
//!   dictate the panic message, the file at which panic was invoked, and the
//!   line and column inside the file. It is up to consumers of this core
//!   library to define this panic function; it is only required to never
//!   return. This requires a `lang` attribute named `panic_impl`.
//!
//! * `rust_eh_personality` - is used by the failure mechanisms of the
//!    compiler. This is often mapped to GCC's personality function, but crates
//!    which do not trigger a panic can be assured that this function is never
//!    called. The `lang` attribute is called `eh_personality`.

// Since libcore defines many fundamental lang items, all tests live in a
// separate crate, libcoretest, to avoid bizarre issues.
//
// Here we explicitly #[cfg]-out this whole crate when testing. If we don't do
// this, both the generated test artifact and the linked libtest (which
// transitively includes libcore) will both define the same set of lang items,
// and this will cause the E0152 "found duplicate lang item" error. See
// discussion in #50466 for details.
//
// This cfg won't affect doc tests.
#![cfg(not(test))]
#![stable(feature = "core", since = "1.6.0")]
#![doc(
    html_root_url = "https://doc.rust-lang.org/nightly/",
    html_playground_url = "https://play.rust-lang.org/",
    issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/",
    test(no_crate_inject, attr(deny(warnings))),
    test(attr(allow(dead_code, deprecated, unused_variables, unused_mut)))
)]
#![no_core]
#![warn(deprecated_in_future)]
#![warn(missing_docs)]
#![warn(missing_debug_implementations)]
#![deny(intra_doc_link_resolution_failure)] // rustdoc is run without -D warnings
#![allow(explicit_outlives_requirements)]
#![allow(incomplete_features)]
#![feature(allow_internal_unstable)]
#![feature(arbitrary_self_types)]
#![feature(asm)]
#![feature(bound_cloned)]
#![feature(cfg_target_has_atomic)]
#![feature(concat_idents)]
#![feature(const_ascii_ctype_on_intrinsics)]
#![feature(const_alloc_layout)]
#![feature(const_discriminant)]
#![feature(const_checked_int_methods)]
#![feature(const_euclidean_int_methods)]
#![feature(const_overflowing_int_methods)]
#![feature(const_saturating_int_methods)]
#![feature(const_int_unchecked_arith)]
#![feature(const_int_pow)]
#![feature(constctlz)]
#![feature(const_panic)]
#![feature(const_fn_union)]
#![feature(const_generics)]
#![feature(const_ptr_offset)]
#![feature(const_ptr_offset_from)]
#![feature(const_raw_ptr_comparison)]
#![feature(const_result)]
#![feature(const_slice_from_raw_parts)]
#![feature(const_slice_ptr_len)]
#![feature(const_type_name)]
#![feature(const_likely)]
#![feature(custom_inner_attributes)]
#![feature(decl_macro)]
#![feature(doc_cfg)]
#![cfg_attr(not(bootstrap), feature(doc_spotlight))]
#![feature(duration_consts_2)]
#![feature(extern_types)]
#![feature(fundamental)]
#![feature(intrinsics)]
#![feature(try_find)]
#![feature(is_sorted)]
#![feature(lang_items)]
#![feature(link_llvm_intrinsics)]
#![feature(llvm_asm)]
#![feature(negative_impls)]
#![feature(never_type)]
#![feature(nll)]
#![feature(exhaustive_patterns)]
#![feature(no_core)]
#![feature(optin_builtin_traits)]
#![feature(or_patterns)]
#![feature(prelude_import)]
#![feature(repr_simd, platform_intrinsics)]
#![feature(rustc_attrs)]
#![feature(simd_ffi)]
#![feature(specialization)]
#![feature(staged_api)]
#![feature(std_internals)]
#![feature(stmt_expr_attributes)]
#![feature(transparent_unions)]
#![feature(unboxed_closures)]
#![feature(unsized_locals)]
#![feature(untagged_unions)]
#![feature(unwind_attributes)]
#![feature(variant_count)]
#![feature(doc_alias)]
#![feature(mmx_target_feature)]
#![feature(tbm_target_feature)]
#![feature(sse4a_target_feature)]
#![feature(arm_target_feature)]
#![feature(powerpc_target_feature)]
#![feature(mips_target_feature)]
#![feature(aarch64_target_feature)]
#![feature(wasm_target_feature)]
#![feature(avx512_target_feature)]
#![feature(cmpxchg16b_target_feature)]
#![feature(rtm_target_feature)]
#![feature(f16c_target_feature)]
#![feature(hexagon_target_feature)]
#![feature(const_fn_transmute)]
#![feature(abi_unadjusted)]
#![feature(adx_target_feature)]
#![feature(maybe_uninit_slice)]
#![feature(external_doc)]
#![feature(associated_type_bounds)]
#![feature(const_type_id)]
#![feature(const_caller_location)]
#![feature(slice_ptr_get)]
#![feature(no_niche)] // rust-lang/rust#68303
#![feature(unsafe_block_in_unsafe_fn)]
#![deny(unsafe_op_in_unsafe_fn)]

#[prelude_import]
#[allow(unused)]
use prelude::v1::*;

#[cfg(not(test))] // See #65860
#[macro_use]
mod macros;

#[macro_use]
mod internal_macros;

#[path = "num/int_macros.rs"]
#[macro_use]
mod int_macros;

#[path = "num/i128.rs"]
pub mod i128;
#[path = "num/i16.rs"]
pub mod i16;
#[path = "num/i32.rs"]
pub mod i32;
#[path = "num/i64.rs"]
pub mod i64;
#[path = "num/i8.rs"]
pub mod i8;
#[path = "num/isize.rs"]
pub mod isize;

#[path = "num/u128.rs"]
pub mod u128;
#[path = "num/u16.rs"]
pub mod u16;
#[path = "num/u32.rs"]
pub mod u32;
#[path = "num/u64.rs"]
pub mod u64;
#[path = "num/u8.rs"]
pub mod u8;
#[path = "num/usize.rs"]
pub mod usize;

#[path = "num/f32.rs"]
pub mod f32;
#[path = "num/f64.rs"]
pub mod f64;

#[macro_use]
pub mod num;

/* The libcore prelude, not as all-encompassing as the libstd prelude */

pub mod prelude;

/* Core modules for ownership management */

pub mod hint;
pub mod intrinsics;
pub mod mem;
pub mod ptr;

/* Core language traits */

pub mod borrow;
#[cfg(not(test))] // See #65860
pub mod clone;
#[cfg(not(test))] // See #65860
pub mod cmp;
pub mod convert;
#[cfg(not(test))] // See #65860
pub mod default;
#[cfg(not(test))] // See #65860
pub mod marker;
pub mod ops;

/* Core types and methods on primitives */

pub mod any;
#[cfg(not(test))] // See #65860
pub mod array;
pub mod ascii;
pub mod cell;
pub mod char;
pub mod ffi;
#[cfg(not(test))] // See #65860
pub mod iter;
pub mod option;
pub mod panic;
pub mod panicking;
#[cfg(not(test))] // See #65860
pub mod pin;
pub mod raw;
pub mod result;
pub mod sync;

#[cfg(not(test))] // See #65860
pub mod fmt;
#[cfg(not(test))] // See #65860
pub mod hash;
pub mod slice;
#[cfg(not(test))] // See #65860
pub mod str;
pub mod time;

pub mod unicode;

/* Async */
#[cfg(not(test))] // See #65860
pub mod future;
pub mod task;

/* Heap memory allocator trait */
#[allow(missing_docs)]
pub mod alloc;

// note: does not need to be public
mod bool;
mod tuple;
mod unit;

#[stable(feature = "core_primitive", since = "1.43.0")]
pub mod primitive;

// Pull in the `core_arch` crate directly into libcore. The contents of
// `core_arch` are in a different repository: rust-lang/stdarch.
//
// `core_arch` depends on libcore, but the contents of this module are
// set up in such a way that directly pulling it here works such that the
// crate uses the this crate as its libcore.
#[path = "../stdarch/crates/core_arch/src/mod.rs"]
#[allow(
    missing_docs,
    missing_debug_implementations,
    dead_code,
    unused_imports,
    unsafe_op_in_unsafe_fn
)]
// FIXME: This annotation should be moved into rust-lang/stdarch after clashing_extern_declarations is
// merged. It currently cannot because bootstrap fails as the lint hasn't been defined yet.
#[allow(clashing_extern_declarations)]
#[unstable(feature = "stdsimd", issue = "48556")]
mod core_arch;

#[stable(feature = "simd_arch", since = "1.27.0")]
pub use core_arch::arch;
<commit_msg>Deny intra_doc_link_resolution_failure in libcore<commit_after>//! # The Rust Core Library
//!
//! The Rust Core Library is the dependency-free[^free] foundation of [The
//! Rust Standard Library](../std/index.html). It is the portable glue
//! between the language and its libraries, defining the intrinsic and
//! primitive building blocks of all Rust code. It links to no
//! upstream libraries, no system libraries, and no libc.
//!
//! [^free]: Strictly speaking, there are some symbols which are needed but
//!          they aren't always necessary.
//!
//! The core library is *minimal*: it isn't even aware of heap allocation,
//! nor does it provide concurrency or I/O. These things require
//! platform integration, and this library is platform-agnostic.
//!
//! # How to use the core library
//!
//! Please note that all of these details are currently not considered stable.
//!
// FIXME: Fill me in with more detail when the interface settles
//! This library is built on the assumption of a few existing symbols:
//!
//! * `memcpy`, `memcmp`, `memset` - These are core memory routines which are
//!   often generated by LLVM. Additionally, this library can make explicit
//!   calls to these functions. Their signatures are the same as found in C.
//!   These functions are often provided by the system libc, but can also be
//!   provided by the [compiler-builtins crate](https://crates.io/crates/compiler_builtins).
//!
//! * `rust_begin_panic` - This function takes four arguments, a
//!   `fmt::Arguments`, a `&'static str`, and two `u32`'s. These four arguments
//!   dictate the panic message, the file at which panic was invoked, and the
//!   line and column inside the file. It is up to consumers of this core
//!   library to define this panic function; it is only required to never
//!   return. This requires a `lang` attribute named `panic_impl`.
//!
//! * `rust_eh_personality` - is used by the failure mechanisms of the
//!    compiler. This is often mapped to GCC's personality function, but crates
//!    which do not trigger a panic can be assured that this function is never
//!    called. The `lang` attribute is called `eh_personality`.

// Since libcore defines many fundamental lang items, all tests live in a
// separate crate, libcoretest, to avoid bizarre issues.
//
// Here we explicitly #[cfg]-out this whole crate when testing. If we don't do
// this, both the generated test artifact and the linked libtest (which
// transitively includes libcore) will both define the same set of lang items,
// and this will cause the E0152 "found duplicate lang item" error. See
// discussion in #50466 for details.
//
// This cfg won't affect doc tests.
#![cfg(not(test))]
#![stable(feature = "core", since = "1.6.0")]
#![doc(
    html_root_url = "https://doc.rust-lang.org/nightly/",
    html_playground_url = "https://play.rust-lang.org/",
    issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/",
    test(no_crate_inject, attr(deny(warnings))),
    test(attr(allow(dead_code, deprecated, unused_variables, unused_mut)))
)]
#![no_core]
#![warn(deprecated_in_future)]
#![warn(missing_docs)]
#![warn(missing_debug_implementations)]
#![deny(intra_doc_link_resolution_failure)] // rustdoc is run without -D warnings
#![allow(explicit_outlives_requirements)]
#![allow(incomplete_features)]
#![feature(allow_internal_unstable)]
#![feature(arbitrary_self_types)]
#![feature(asm)]
#![feature(bound_cloned)]
#![feature(cfg_target_has_atomic)]
#![feature(concat_idents)]
#![feature(const_ascii_ctype_on_intrinsics)]
#![feature(const_alloc_layout)]
#![feature(const_discriminant)]
#![feature(const_checked_int_methods)]
#![feature(const_euclidean_int_methods)]
#![feature(const_overflowing_int_methods)]
#![feature(const_saturating_int_methods)]
#![feature(const_int_unchecked_arith)]
#![feature(const_int_pow)]
#![feature(constctlz)]
#![feature(const_panic)]
#![feature(const_fn_union)]
#![feature(const_generics)]
#![feature(const_ptr_offset)]
#![feature(const_ptr_offset_from)]
#![feature(const_raw_ptr_comparison)]
#![feature(const_result)]
#![feature(const_slice_from_raw_parts)]
#![feature(const_slice_ptr_len)]
#![feature(const_type_name)]
#![feature(const_likely)]
#![feature(custom_inner_attributes)]
#![feature(decl_macro)]
#![feature(doc_cfg)]
#![cfg_attr(not(bootstrap), feature(doc_spotlight))]
#![feature(duration_consts_2)]
#![feature(extern_types)]
#![feature(fundamental)]
#![feature(intrinsics)]
#![feature(try_find)]
#![feature(is_sorted)]
#![feature(lang_items)]
#![feature(link_llvm_intrinsics)]
#![feature(llvm_asm)]
#![feature(negative_impls)]
#![feature(never_type)]
#![feature(nll)]
#![feature(exhaustive_patterns)]
#![feature(no_core)]
#![feature(optin_builtin_traits)]
#![feature(or_patterns)]
#![feature(prelude_import)]
#![feature(repr_simd, platform_intrinsics)]
#![feature(rustc_attrs)]
#![feature(simd_ffi)]
#![feature(specialization)]
#![feature(staged_api)]
#![feature(std_internals)]
#![feature(stmt_expr_attributes)]
#![feature(transparent_unions)]
#![feature(unboxed_closures)]
#![feature(unsized_locals)]
#![feature(untagged_unions)]
#![feature(unwind_attributes)]
#![feature(variant_count)]
#![feature(doc_alias)]
#![feature(mmx_target_feature)]
#![feature(tbm_target_feature)]
#![feature(sse4a_target_feature)]
#![feature(arm_target_feature)]
#![feature(powerpc_target_feature)]
#![feature(mips_target_feature)]
#![feature(aarch64_target_feature)]
#![feature(wasm_target_feature)]
#![feature(avx512_target_feature)]
#![feature(cmpxchg16b_target_feature)]
#![feature(rtm_target_feature)]
#![feature(f16c_target_feature)]
#![feature(hexagon_target_feature)]
#![feature(const_fn_transmute)]
#![feature(abi_unadjusted)]
#![feature(adx_target_feature)]
#![feature(maybe_uninit_slice)]
#![feature(external_doc)]
#![feature(associated_type_bounds)]
#![feature(const_type_id)]
#![feature(const_caller_location)]
#![feature(slice_ptr_get)]
#![feature(no_niche)] // rust-lang/rust#68303
#![feature(unsafe_block_in_unsafe_fn)]
#![deny(intra_doc_link_resolution_failure)]
#![deny(unsafe_op_in_unsafe_fn)]

#[prelude_import]
#[allow(unused)]
use prelude::v1::*;

#[cfg(not(test))] // See #65860
#[macro_use]
mod macros;

#[macro_use]
mod internal_macros;

#[path = "num/int_macros.rs"]
#[macro_use]
mod int_macros;

#[path = "num/i128.rs"]
pub mod i128;
#[path = "num/i16.rs"]
pub mod i16;
#[path = "num/i32.rs"]
pub mod i32;
#[path = "num/i64.rs"]
pub mod i64;
#[path = "num/i8.rs"]
pub mod i8;
#[path = "num/isize.rs"]
pub mod isize;

#[path = "num/u128.rs"]
pub mod u128;
#[path = "num/u16.rs"]
pub mod u16;
#[path = "num/u32.rs"]
pub mod u32;
#[path = "num/u64.rs"]
pub mod u64;
#[path = "num/u8.rs"]
pub mod u8;
#[path = "num/usize.rs"]
pub mod usize;

#[path = "num/f32.rs"]
pub mod f32;
#[path = "num/f64.rs"]
pub mod f64;

#[macro_use]
pub mod num;

/* The libcore prelude, not as all-encompassing as the libstd prelude */

pub mod prelude;

/* Core modules for ownership management */

pub mod hint;
pub mod intrinsics;
pub mod mem;
pub mod ptr;

/* Core language traits */

pub mod borrow;
#[cfg(not(test))] // See #65860
pub mod clone;
#[cfg(not(test))] // See #65860
pub mod cmp;
pub mod convert;
#[cfg(not(test))] // See #65860
pub mod default;
#[cfg(not(test))] // See #65860
pub mod marker;
pub mod ops;

/* Core types and methods on primitives */

pub mod any;
#[cfg(not(test))] // See #65860
pub mod array;
pub mod ascii;
pub mod cell;
pub mod char;
pub mod ffi;
#[cfg(not(test))] // See #65860
pub mod iter;
pub mod option;
pub mod panic;
pub mod panicking;
#[cfg(not(test))] // See #65860
pub mod pin;
pub mod raw;
pub mod result;
pub mod sync;

#[cfg(not(test))] // See #65860
pub mod fmt;
#[cfg(not(test))] // See #65860
pub mod hash;
pub mod slice;
#[cfg(not(test))] // See #65860
pub mod str;
pub mod time;

pub mod unicode;

/* Async */
#[cfg(not(test))] // See #65860
pub mod future;
pub mod task;

/* Heap memory allocator trait */
#[allow(missing_docs)]
pub mod alloc;

// note: does not need to be public
mod bool;
mod tuple;
mod unit;

#[stable(feature = "core_primitive", since = "1.43.0")]
pub mod primitive;

// Pull in the `core_arch` crate directly into libcore. The contents of
// `core_arch` are in a different repository: rust-lang/stdarch.
//
// `core_arch` depends on libcore, but the contents of this module are
// set up in such a way that directly pulling it here works such that the
// crate uses the this crate as its libcore.
#[path = "../stdarch/crates/core_arch/src/mod.rs"]
#[allow(
    missing_docs,
    missing_debug_implementations,
    dead_code,
    unused_imports,
    unsafe_op_in_unsafe_fn
)]
// FIXME: This annotation should be moved into rust-lang/stdarch after clashing_extern_declarations is
// merged. It currently cannot because bootstrap fails as the lint hasn't been defined yet.
#[allow(clashing_extern_declarations)]
#[unstable(feature = "stdsimd", issue = "48556")]
mod core_arch;

#[stable(feature = "simd_arch", since = "1.27.0")]
pub use core_arch::arch;
<|endoftext|>