]>
Commit | Line | Data |
---|---|---|
1 | // The Computer Language Benchmarks Game | |
2 | // http://benchmarksgame.alioth.debian.org/ | |
3 | // | |
4 | // contributed by the Rust Project Developers | |
5 | ||
6 | // Copyright (c) 2012-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. | |
40 | ||
41 | use std::cmp::min; | |
42 | use std::env; | |
43 | use std::fs::File; | |
44 | use std::io::{self, BufWriter}; | |
45 | use std::io::prelude::*; | |
46 | ||
47 | const LINE_LENGTH: usize = 60; | |
48 | const IM: u32 = 139968; | |
49 | ||
50 | struct MyRandom { | |
51 | last: u32 | |
52 | } | |
53 | impl MyRandom { | |
54 | fn new() -> MyRandom { MyRandom { last: 42 } } | |
55 | fn normalize(p: f32) -> u32 {(p * IM as f32).floor() as u32} | |
56 | fn gen(&mut self) -> u32 { | |
57 | self.last = (self.last * 3877 + 29573) % IM; | |
58 | self.last | |
59 | } | |
60 | } | |
61 | ||
62 | struct AAGen<'a> { | |
63 | rng: &'a mut MyRandom, | |
64 | data: Vec<(u32, u8)> | |
65 | } | |
66 | impl<'a> AAGen<'a> { | |
67 | fn new<'b>(rng: &'b mut MyRandom, aa: &[(char, f32)]) -> AAGen<'b> { | |
68 | let mut cum = 0.; | |
69 | let data = aa.iter() | |
70 | .map(|&(ch, p)| { cum += p; (MyRandom::normalize(cum), ch as u8) }) | |
71 | .collect(); | |
72 | AAGen { rng: rng, data: data } | |
73 | } | |
74 | } | |
75 | impl<'a> Iterator for AAGen<'a> { | |
76 | type Item = u8; | |
77 | ||
78 | fn next(&mut self) -> Option<u8> { | |
79 | let r = self.rng.gen(); | |
80 | self.data.iter() | |
81 | .skip_while(|pc| pc.0 < r) | |
82 | .map(|&(_, c)| c) | |
83 | .next() | |
84 | } | |
85 | } | |
86 | ||
87 | fn make_fasta<W: Write, I: Iterator<Item=u8>>( | |
88 | wr: &mut W, header: &str, mut it: I, mut n: usize) | |
89 | -> io::Result<()> | |
90 | { | |
91 | try!(wr.write(header.as_bytes())); | |
92 | let mut line = [0; LINE_LENGTH + 1]; | |
93 | while n > 0 { | |
94 | let nb = min(LINE_LENGTH, n); | |
95 | for i in 0..nb { | |
96 | line[i] = it.next().unwrap(); | |
97 | } | |
98 | n -= nb; | |
99 | line[nb] = '\n' as u8; | |
100 | try!(wr.write(&line[..nb+1])); | |
101 | } | |
102 | Ok(()) | |
103 | } | |
104 | ||
105 | fn run<W: Write>(writer: &mut W) -> io::Result<()> { | |
106 | let mut args = env::args(); | |
107 | let n = if env::var_os("RUST_BENCH").is_some() { | |
108 | 25000000 | |
109 | } else if args.len() <= 1 { | |
110 | 1000 | |
111 | } else { | |
112 | args.nth(1).unwrap().parse().unwrap() | |
113 | }; | |
114 | ||
115 | let rng = &mut MyRandom::new(); | |
116 | let alu = | |
117 | "GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGG\ | |
118 | GAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGA\ | |
119 | CCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAAT\ | |
120 | ACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCA\ | |
121 | GCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGG\ | |
122 | AGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCC\ | |
123 | AGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAA"; | |
124 | let iub = &[('a', 0.27), ('c', 0.12), ('g', 0.12), | |
125 | ('t', 0.27), ('B', 0.02), ('D', 0.02), | |
126 | ('H', 0.02), ('K', 0.02), ('M', 0.02), | |
127 | ('N', 0.02), ('R', 0.02), ('S', 0.02), | |
128 | ('V', 0.02), ('W', 0.02), ('Y', 0.02)]; | |
129 | let homosapiens = &[('a', 0.3029549426680), | |
130 | ('c', 0.1979883004921), | |
131 | ('g', 0.1975473066391), | |
132 | ('t', 0.3015094502008)]; | |
133 | ||
134 | try!(make_fasta(writer, ">ONE Homo sapiens alu\n", | |
135 | alu.as_bytes().iter().cycle().cloned(), n * 2)); | |
136 | try!(make_fasta(writer, ">TWO IUB ambiguity codes\n", | |
137 | AAGen::new(rng, iub), n * 3)); | |
138 | try!(make_fasta(writer, ">THREE Homo sapiens frequency\n", | |
139 | AAGen::new(rng, homosapiens), n * 5)); | |
140 | ||
141 | writer.flush() | |
142 | } | |
143 | ||
144 | fn main() { | |
145 | let res = if env::var_os("RUST_BENCH").is_some() { | |
146 | let mut file = BufWriter::new(File::create("./shootout-fasta.data").unwrap()); | |
147 | run(&mut file) | |
148 | } else { | |
149 | run(&mut io::stdout()) | |
150 | }; | |
151 | res.unwrap() | |
152 | } |