Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 324 lines (276 sloc) 8.838 kB
9279224 @TeXitoi Relicense shootout-k-nucleotide.rs
TeXitoi authored
1 // The Computer Language Benchmarks Game
2 // http://benchmarksgame.alioth.debian.org/
730bdb6 @dguenther Added tests to make tidy
dguenther authored
3 //
9279224 @TeXitoi Relicense shootout-k-nucleotide.rs
TeXitoi authored
4 // contributed by the Rust Project Developers
5
6 // Copyright (c) 2014 The Rust Project Developers
7 //
8 // All rights reserved.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions
12 // are met:
13 //
14 // - Redistributions of source code must retain the above copyright
15 // notice, this list of conditions and the following disclaimer.
16 //
17 // - Redistributions in binary form must reproduce the above copyright
18 // notice, this list of conditions and the following disclaimer in
19 // the documentation and/or other materials provided with the
20 // distribution.
21 //
22 // - Neither the name of "The Computer Language Benchmarks Game" nor
23 // the name of "The Computer Language Shootout Benchmarks" nor the
24 // names of its contributors may be used to endorse or promote
25 // products derived from this software without specific prior
26 // written permission.
27 //
28 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
31 // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
32 // COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
33 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
34 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
35 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36 // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
37 // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
39 // OF THE POSSIBILITY OF SUCH DAMAGE.
730bdb6 @dguenther Added tests to make tidy
dguenther authored
40
9768447 @tamird Reference the correct issue and clarify failure
tamird authored
41 // ignore-android: FIXME(#10393) hangs without output
d2b6448 @pcwalton test: xfail some benchmarks that require external libraries or inputs
pcwalton authored
42
ce1a965 @alexcrichton Fallout in tests and docs from feature renamings
alexcrichton authored
43 #![feature(box_syntax, owned_ascii_ext, vec_push_all)]
0dc48b4 @alexcrichton Test fixes and rebase conflicts
alexcrichton authored
44
12e6071 @SimonSapin Fix up remaining usage of `to_ascii`.
SimonSapin authored
45 use std::ascii::OwnedAsciiExt;
94d71f8 @alexcrichton std: Implement stdio for `std::io`
alexcrichton authored
46 use std::env;
47 use std::fs::File;
48 use std::io::prelude::*;
49 use std::io;
ce62032 @thestinger rename std::vec -> std::slice
thestinger authored
50 use std::slice;
7d8d06f @alexcrichton Remove deprecated functionality
alexcrichton authored
51 use std::sync::Arc;
d0de2b4 @aturon Fallout from stabilization
aturon authored
52 use std::thread;
1d32313 @pcwalton test: Add k-nucleotide
pcwalton authored
53
2e86929 @nrc Allow use of `[_ ; n]` syntax for fixed length and repeating arrays.
nrc authored
54 static TABLE: [u8;4] = [ 'A' as u8, 'C' as u8, 'G' as u8, 'T' as u8 ];
94d71f8 @alexcrichton std: Implement stdio for `std::io`
alexcrichton authored
55 static TABLE_SIZE: usize = 2 << 16;
1d32313 @pcwalton test: Add k-nucleotide
pcwalton authored
56
2e86929 @nrc Allow use of `[_ ; n]` syntax for fixed length and repeating arrays.
nrc authored
57 static OCCURRENCES: [&'static str;5] = [
1d32313 @pcwalton test: Add k-nucleotide
pcwalton authored
58 "GGT",
59 "GGTA",
60 "GGTATT",
61 "GGTATTTTAATT",
62 "GGTATTTTAATTTATAGT",
63 ];
64
65 // Code implementation
66
890ed5c @nikomatsakis Fallout in tests
nikomatsakis authored
67 #[derive(Copy, Clone, PartialEq, PartialOrd, Ord, Eq)]
1d32313 @pcwalton test: Add k-nucleotide
pcwalton authored
68 struct Code(u64);
69
70 impl Code {
71 fn hash(&self) -> u64 {
9cc26cf @alexcrichton test: Clean out the test suite a bit
alexcrichton authored
72 let Code(ret) = *self;
73 return ret;
1d32313 @pcwalton test: Add k-nucleotide
pcwalton authored
74 }
75
76 fn push_char(&self, c: u8) -> Code {
9cc26cf @alexcrichton test: Clean out the test suite a bit
alexcrichton authored
77 Code((self.hash() << 2) + (pack_symbol(c) as u64))
1d32313 @pcwalton test: Add k-nucleotide
pcwalton authored
78 }
79
94d71f8 @alexcrichton std: Implement stdio for `std::io`
alexcrichton authored
80 fn rotate(&self, c: u8, frame: usize) -> Code {
e646708 @eddyb Remove integer suffixes where the types in compiled code are identical.
eddyb authored
81 Code(self.push_char(c).hash() & ((1 << (2 * frame)) - 1))
1d32313 @pcwalton test: Add k-nucleotide
pcwalton authored
82 }
83
84 fn pack(string: &str) -> Code {
e646708 @eddyb Remove integer suffixes where the types in compiled code are identical.
eddyb authored
85 string.bytes().fold(Code(0), |a, b| a.push_char(b))
1d32313 @pcwalton test: Add k-nucleotide
pcwalton authored
86 }
87
94d71f8 @alexcrichton std: Implement stdio for `std::io`
alexcrichton authored
88 fn unpack(&self, frame: usize) -> String {
9cc26cf @alexcrichton test: Clean out the test suite a bit
alexcrichton authored
89 let mut key = self.hash();
579eb24 @pcwalton test: Automatically remove all `~[T]` from tests.
pcwalton authored
90 let mut result = Vec::new();
7d661af @japaric `for x in range(a, b)` -> `for x in a..b`
japaric authored
91 for _ in 0..frame {
1d32313 @pcwalton test: Add k-nucleotide
pcwalton authored
92 result.push(unpack_symbol((key as u8) & 3));
93 key >>= 2;
94 }
95
9cc26cf @alexcrichton test: Clean out the test suite a bit
alexcrichton authored
96 result.reverse();
5530745 @richo core: rename strbuf::StrBuf to string::String
richo authored
97 String::from_utf8(result).unwrap()
1d32313 @pcwalton test: Add k-nucleotide
pcwalton authored
98 }
99 }
100
101 // Hash table implementation
102
103 trait TableCallback {
104 fn f(&self, entry: &mut Entry);
105 }
106
107 struct BumpCallback;
108
109 impl TableCallback for BumpCallback {
110 fn f(&self, entry: &mut Entry) {
111 entry.count += 1;
112 }
113 }
114
115 struct PrintCallback(&'static str);
116
117 impl TableCallback for PrintCallback {
118 fn f(&self, entry: &mut Entry) {
9cc26cf @alexcrichton test: Clean out the test suite a bit
alexcrichton authored
119 let PrintCallback(s) = *self;
94d71f8 @alexcrichton std: Implement stdio for `std::io`
alexcrichton authored
120 println!("{}\t{}", entry.count, s);
1d32313 @pcwalton test: Add k-nucleotide
pcwalton authored
121 }
122 }
123
124 struct Entry {
125 code: Code,
94d71f8 @alexcrichton std: Implement stdio for `std::io`
alexcrichton authored
126 count: usize,
090040b @pcwalton librustc: Remove `~EXPR`, `~TYPE`, and `~PAT` from the language, except
pcwalton authored
127 next: Option<Box<Entry>>,
1d32313 @pcwalton test: Add k-nucleotide
pcwalton authored
128 }
129
130 struct Table {
5653b4d @TeXitoi remove shootout warnings
TeXitoi authored
131 items: Vec<Option<Box<Entry>>>
132 }
9cc26cf @alexcrichton test: Clean out the test suite a bit
alexcrichton authored
133
134 struct Items<'a> {
135 cur: Option<&'a Entry>,
f8cfd24 @MrFloya Renaming of the Iter types as in RFC #344
MrFloya authored
136 items: slice::Iter<'a, Option<Box<Entry>>>,
1d32313 @pcwalton test: Add k-nucleotide
pcwalton authored
137 }
138
139 impl Table {
140 fn new() -> Table {
141 Table {
c300d68 @japaric `range(a, b).foo()` -> `(a..b).foo()`
japaric authored
142 items: (0..TABLE_SIZE).map(|_| None).collect()
1d32313 @pcwalton test: Add k-nucleotide
pcwalton authored
143 }
144 }
145
146 fn search_remainder<C:TableCallback>(item: &mut Entry, key: Code, c: C) {
147 match item.next {
148 None => {
270f0ee @pnkfelix Add `: Box<_>` or `::Box<_>` type annotations to various places.
pnkfelix authored
149 let mut entry: Box<_> = box Entry {
1d32313 @pcwalton test: Add k-nucleotide
pcwalton authored
150 code: key,
151 count: 0,
152 next: None,
153 };
f6bfd2c @pcwalton librustc: Remove cross borrowing from mutable `Box`es to `&mut`.
pcwalton authored
154 c.f(&mut *entry);
1d32313 @pcwalton test: Add k-nucleotide
pcwalton authored
155 item.next = Some(entry);
156 }
157 Some(ref mut entry) => {
158 if entry.code == key {
f6bfd2c @pcwalton librustc: Remove cross borrowing from mutable `Box`es to `&mut`.
pcwalton authored
159 c.f(&mut **entry);
1d32313 @pcwalton test: Add k-nucleotide
pcwalton authored
160 return;
161 }
162
f6bfd2c @pcwalton librustc: Remove cross borrowing from mutable `Box`es to `&mut`.
pcwalton authored
163 Table::search_remainder(&mut **entry, key, c)
1d32313 @pcwalton test: Add k-nucleotide
pcwalton authored
164 }
165 }
166 }
167
168 fn lookup<C:TableCallback>(&mut self, key: Code, c: C) {
9cc26cf @alexcrichton test: Clean out the test suite a bit
alexcrichton authored
169 let index = key.hash() % (TABLE_SIZE as u64);
1d32313 @pcwalton test: Add k-nucleotide
pcwalton authored
170
171 {
94d71f8 @alexcrichton std: Implement stdio for `std::io`
alexcrichton authored
172 if self.items[index as usize].is_none() {
270f0ee @pnkfelix Add `: Box<_>` or `::Box<_>` type annotations to various places.
pnkfelix authored
173 let mut entry: Box<_> = box Entry {
1d32313 @pcwalton test: Add k-nucleotide
pcwalton authored
174 code: key,
175 count: 0,
176 next: None,
177 };
f6bfd2c @pcwalton librustc: Remove cross borrowing from mutable `Box`es to `&mut`.
pcwalton authored
178 c.f(&mut *entry);
94d71f8 @alexcrichton std: Implement stdio for `std::io`
alexcrichton authored
179 self.items[index as usize] = Some(entry);
1d32313 @pcwalton test: Add k-nucleotide
pcwalton authored
180 return;
181 }
182 }
183
184 {
94d71f8 @alexcrichton std: Implement stdio for `std::io`
alexcrichton authored
185 let entry = self.items[index as usize].as_mut().unwrap();
1d32313 @pcwalton test: Add k-nucleotide
pcwalton authored
186 if entry.code == key {
f6bfd2c @pcwalton librustc: Remove cross borrowing from mutable `Box`es to `&mut`.
pcwalton authored
187 c.f(&mut **entry);
1d32313 @pcwalton test: Add k-nucleotide
pcwalton authored
188 return;
189 }
190
f6bfd2c @pcwalton librustc: Remove cross borrowing from mutable `Box`es to `&mut`.
pcwalton authored
191 Table::search_remainder(&mut **entry, key, c)
1d32313 @pcwalton test: Add k-nucleotide
pcwalton authored
192 }
193 }
194
6f99a27 @pcwalton librustc: Implement lifetime elision.
pcwalton authored
195 fn iter(&self) -> Items {
9cc26cf @alexcrichton test: Clean out the test suite a bit
alexcrichton authored
196 Items { cur: None, items: self.items.iter() }
197 }
198 }
199
6c0ad5b @japaric bench: fix fallout
japaric authored
200 impl<'a> Iterator for Items<'a> {
201 type Item = &'a Entry;
202
9cc26cf @alexcrichton test: Clean out the test suite a bit
alexcrichton authored
203 fn next(&mut self) -> Option<&'a Entry> {
204 let ret = match self.cur {
205 None => {
206 let i;
207 loop {
208 match self.items.next() {
209 None => return None,
210 Some(&None) => {}
211 Some(&Some(ref a)) => { i = &**a; break }
1d32313 @pcwalton test: Add k-nucleotide
pcwalton authored
212 }
213 }
9cc26cf @alexcrichton test: Clean out the test suite a bit
alexcrichton authored
214 self.cur = Some(&*i);
215 &*i
216 }
217 Some(c) => c
218 };
219 match ret.next {
220 None => { self.cur = None; }
221 Some(ref next) => { self.cur = Some(&**next); }
1d32313 @pcwalton test: Add k-nucleotide
pcwalton authored
222 }
9cc26cf @alexcrichton test: Clean out the test suite a bit
alexcrichton authored
223 return Some(ret);
1d32313 @pcwalton test: Add k-nucleotide
pcwalton authored
224 }
225 }
226
227 // Main program
228
229 fn pack_symbol(c: u8) -> u8 {
9cc26cf @alexcrichton test: Clean out the test suite a bit
alexcrichton authored
230 match c as char {
7c2abe7 @TeXitoi make shootout-k-nucleotide.rs pass official test
TeXitoi authored
231 'A' => 0,
232 'C' => 1,
233 'G' => 2,
234 'T' => 3,
7828c3d @steveklabnik Rename fail! to panic!
steveklabnik authored
235 _ => panic!("{}", c as char),
1d32313 @pcwalton test: Add k-nucleotide
pcwalton authored
236 }
237 }
238
239 fn unpack_symbol(c: u8) -> u8 {
94d71f8 @alexcrichton std: Implement stdio for `std::io`
alexcrichton authored
240 TABLE[c as usize]
1d32313 @pcwalton test: Add k-nucleotide
pcwalton authored
241 }
242
94d71f8 @alexcrichton std: Implement stdio for `std::io`
alexcrichton authored
243 fn generate_frequencies(mut input: &[u8], frame: usize) -> Table {
ba99e4c @TeXitoi parallelisation of shootout-k-nucleotide
TeXitoi authored
244 let mut frequencies = Table::new();
245 if input.len() < frame { return frequencies; }
1d32313 @pcwalton test: Add k-nucleotide
pcwalton authored
246 let mut code = Code(0);
86efd97 @thestinger add gitattributes and fix whitespace issues
thestinger authored
247
1d32313 @pcwalton test: Add k-nucleotide
pcwalton authored
248 // Pull first frame.
7d661af @japaric `for x in range(a, b)` -> `for x in a..b`
japaric authored
249 for _ in 0..frame {
1d32313 @pcwalton test: Add k-nucleotide
pcwalton authored
250 code = code.push_char(input[0]);
77ed497 @nrc Tests
nrc authored
251 input = &input[1..];
1d32313 @pcwalton test: Add k-nucleotide
pcwalton authored
252 }
253 frequencies.lookup(code, BumpCallback);
254
10f15e7 @tamird Negative case of `len()` -> `is_empty()`
tamird authored
255 while !input.is_empty() && input[0] != ('>' as u8) {
1d32313 @pcwalton test: Add k-nucleotide
pcwalton authored
256 code = code.rotate(input[0], frame);
257 frequencies.lookup(code, BumpCallback);
77ed497 @nrc Tests
nrc authored
258 input = &input[1..];
1d32313 @pcwalton test: Add k-nucleotide
pcwalton authored
259 }
ba99e4c @TeXitoi parallelisation of shootout-k-nucleotide
TeXitoi authored
260 frequencies
1d32313 @pcwalton test: Add k-nucleotide
pcwalton authored
261 }
262
94d71f8 @alexcrichton std: Implement stdio for `std::io`
alexcrichton authored
263 fn print_frequencies(frequencies: &Table, frame: usize) {
579eb24 @pcwalton test: Automatically remove all `~[T]` from tests.
pcwalton authored
264 let mut vector = Vec::new();
9cc26cf @alexcrichton test: Clean out the test suite a bit
alexcrichton authored
265 for entry in frequencies.iter() {
7c2abe7 @TeXitoi make shootout-k-nucleotide.rs pass official test
TeXitoi authored
266 vector.push((entry.count, entry.code));
1d32313 @pcwalton test: Add k-nucleotide
pcwalton authored
267 }
17bc7d8 @japaric cleanup: replace `as[_mut]_slice()` calls with deref coercions
japaric authored
268 vector.sort();
1d32313 @pcwalton test: Add k-nucleotide
pcwalton authored
269
270 let mut total_count = 0;
d5d7e65 @japaric `for x in xs.iter()` -> `for x in &xs`
japaric authored
271 for &(count, _) in &vector {
1d32313 @pcwalton test: Add k-nucleotide
pcwalton authored
272 total_count += count;
273 }
274
7c2abe7 @TeXitoi make shootout-k-nucleotide.rs pass official test
TeXitoi authored
275 for &(count, key) in vector.iter().rev() {
4af3494 @alexcrichton std: Stabilize std::fmt
alexcrichton authored
276 println!("{} {:.3}",
17bc7d8 @japaric cleanup: replace `as[_mut]_slice()` calls with deref coercions
japaric authored
277 key.unpack(frame),
9cc26cf @alexcrichton test: Clean out the test suite a bit
alexcrichton authored
278 (count as f32 * 100.0) / (total_count as f32));
1d32313 @pcwalton test: Add k-nucleotide
pcwalton authored
279 }
7c2abe7 @TeXitoi make shootout-k-nucleotide.rs pass official test
TeXitoi authored
280 println!("");
1d32313 @pcwalton test: Add k-nucleotide
pcwalton authored
281 }
282
283 fn print_occurrences(frequencies: &mut Table, occurrence: &'static str) {
284 frequencies.lookup(Code::pack(occurrence), PrintCallback(occurrence))
285 }
286
94d71f8 @alexcrichton std: Implement stdio for `std::io`
alexcrichton authored
287 fn get_sequence<R: BufRead>(r: &mut R, key: &str) -> Vec<u8> {
def90f4 @huonw Fix tests. Add Vec<u8> conversion to StrBuf.
huonw authored
288 let mut res = Vec::new();
94d71f8 @alexcrichton std: Implement stdio for `std::io`
alexcrichton authored
289 for l in r.lines().map(|l| l.unwrap())
bce81e2 @japaric cleanup: s/`v.slice*()`/`&v[a..b]`/g + remove redundant `as_slice()`…
japaric authored
290 .skip_while(|l| key != &l[..key.len()]).skip(1)
7c2abe7 @TeXitoi make shootout-k-nucleotide.rs pass official test
TeXitoi authored
291 {
bce81e2 @japaric cleanup: s/`v.slice*()`/`&v[a..b]`/g + remove redundant `as_slice()`…
japaric authored
292 res.push_all(l.trim().as_bytes());
7c2abe7 @TeXitoi make shootout-k-nucleotide.rs pass official test
TeXitoi authored
293 }
12e6071 @SimonSapin Fix up remaining usage of `to_ascii`.
SimonSapin authored
294 res.into_ascii_uppercase()
7c2abe7 @TeXitoi make shootout-k-nucleotide.rs pass official test
TeXitoi authored
295 }
296
1d32313 @pcwalton test: Add k-nucleotide
pcwalton authored
297 fn main() {
94d71f8 @alexcrichton std: Implement stdio for `std::io`
alexcrichton authored
298 let input = if env::var_os("RUST_BENCH").is_some() {
299 let f = File::open("shootout-k-nucleotide.data").unwrap();
300 get_sequence(&mut io::BufReader::new(f), ">THREE")
7c2abe7 @TeXitoi make shootout-k-nucleotide.rs pass official test
TeXitoi authored
301 } else {
94d71f8 @alexcrichton std: Implement stdio for `std::io`
alexcrichton authored
302 let stdin = io::stdin();
bdb9f3e @pnkfelix shift bindings to accommodate new lifetime/dtor rules.
pnkfelix authored
303 let mut stdin = stdin.lock();
94d71f8 @alexcrichton std: Implement stdio for `std::io`
alexcrichton authored
304 get_sequence(&mut stdin, ">THREE")
7c2abe7 @TeXitoi make shootout-k-nucleotide.rs pass official test
TeXitoi authored
305 };
ba99e4c @TeXitoi parallelisation of shootout-k-nucleotide
TeXitoi authored
306 let input = Arc::new(input);
307
362d713 @nikomatsakis Fix remaining bench/debuginfo tests (and a few stragglers)
nikomatsakis authored
308 let nb_freqs: Vec<_> = (1..3).map(|i| {
ba99e4c @TeXitoi parallelisation of shootout-k-nucleotide
TeXitoi authored
309 let input = input.clone();
a9fd41e @aturon Fallout: move from scoped to spawn
aturon authored
310 (i, thread::spawn(move|| generate_frequencies(&input, i)))
ba99e4c @TeXitoi parallelisation of shootout-k-nucleotide
TeXitoi authored
311 }).collect();
7d8d06f @alexcrichton Remove deprecated functionality
alexcrichton authored
312 let occ_freqs: Vec<_> = OCCURRENCES.iter().map(|&occ| {
ba99e4c @TeXitoi parallelisation of shootout-k-nucleotide
TeXitoi authored
313 let input = input.clone();
a9fd41e @aturon Fallout: move from scoped to spawn
aturon authored
314 thread::spawn(move|| generate_frequencies(&input, occ.len()))
ba99e4c @TeXitoi parallelisation of shootout-k-nucleotide
TeXitoi authored
315 }).collect();
316
fd70270 @japaric `for x in xs.into_iter()` -> `for x in xs`
japaric authored
317 for (i, freq) in nb_freqs {
a9fd41e @aturon Fallout: move from scoped to spawn
aturon authored
318 print_frequencies(&freq.join().unwrap(), i);
ba99e4c @TeXitoi parallelisation of shootout-k-nucleotide
TeXitoi authored
319 }
ca7418b @Veedrac Removed many pointless calls to *iter() and iter_mut()
Veedrac authored
320 for (&occ, freq) in OCCURRENCES.iter().zip(occ_freqs) {
a9fd41e @aturon Fallout: move from scoped to spawn
aturon authored
321 print_occurrences(&mut freq.join().unwrap(), occ);
1d32313 @pcwalton test: Add k-nucleotide
pcwalton authored
322 }
323 }
Something went wrong with that request. Please try again.