1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
/*! * The Cythan machine emulator librairy. * * The Cythan machine is a mathematical Turing Complete computer. * The machine is composed of one vector. Each value of the vector is a positive integer, "pointing" to another value. * * ### For every iteration of the machine * * - The first case (the pointer), is incremented by 2. * * - The 2 cases pointed by the first case before the incrementation is "executed". In a pair of executed cases, the case that as for index the second value is set to the value of the case that have as index the first value * * For instance, `1,5,3,0,0,999` will copy the content of the 5th case (999) into the 3rd one. The result after one iteration will be `3,5,3,999,0,999` * * ### Example * * ```rust * use cythan::Cythan; * let mut cythan = Cythan::new( vec![1,9,5,10,1,0,0,11,0,1,20,21] ); * println!("Cythan start:{:?}",cythan); * for a in 0..10 { * cythan.next(); * println!("Cythan iteration {}:{:?}",a,cythan) * } * ``` * */ #![cfg_attr(feature = "nightly", feature(test))] #[cfg(feature = "nightly")] extern crate test; #[cfg(feature = "nightly")] use test::Bencher; /// The main structure of the Cythan machine #[derive(Debug)] pub struct Cythan { cases: Vec<usize> } impl Cythan{ /// The constructor of the Cythan machine /// `cases` is a vector that represent the base code of the Cythan machine /// ### Example /// ```rust /// use cythan::Cythan; /// let mut cythan = Cythan::new( vec![1,9,5,10,1,0,0,11,0,1,20,21] ); /// println!("Cythan start:{:?}",cythan); /// for a in 0..10 { /// cythan.next(); /// println!("Cythan iteration {}:{:?}",a,cythan) /// } /// ``` /// will make an if statement in Cythan, which will jump the pointer to either 20 or 21 accordingly if the 9th case contains an one or a zero. pub fn new(cases: Vec<usize>) -> Cythan { Cythan{ cases } } /// Will execute one iteration of the Cythan machine. /// This method use a step of 2. #[inline] pub fn next(&mut self) { unsafe { let index = { let index = self.get_mut_value(0); *index += 2; *index }; let (c2,c1) = self.get_both_values(index-2); self.set_value(c1,self.get_value(c2)); } } #[inline] fn get_both_values(&self, index: usize) -> (usize,usize) { let mut i = self.cases.iter().skip(index); (*i.next().unwrap_or(&0),*i.next().unwrap_or(&0)) } /// Use this to get a value at an index in the Cythan machine. /// This will return 0 if the index doesn't exists. #[inline] pub fn get_value(&self, index:usize) -> usize { *self.cases.get(index).unwrap_or(&0) } #[inline] unsafe fn get_mut_value(&mut self, index:usize) -> &mut usize { if self.cases.len() <= index { self.cases.extend((self.cases.len()..index+1).map(|_| 0)); } self.cases.get_unchecked_mut(index) } /// Use this to set a value at an index inside of th Cythan machine. /// This will fill the machine with 0 if the index doesn't exists. #[inline] pub fn set_value(&mut self, index:usize, value:usize) { if self.cases.len() <= index { self.cases.extend((self.cases.len()..index).map(|_| 0)); self.cases.push(value); } else { unsafe { *self.cases.get_unchecked_mut(index) = value; } } } } #[cfg(feature = "nightly")] #[bench] fn bench(b: &mut Bencher) { let mut cythan = Cythan::new( vec![1,9,5,10,1,0,0,11,0,1,20,21] ); b.iter(||{ cythan.next() }); println!("{:?}",cythan); }