]>
Commit | Line | Data |
---|---|---|
1a4d82fc JJ |
1 | // The Computer Language Benchmarks Game |
2 | // http://benchmarksgame.alioth.debian.org/ | |
3 | // | |
4 | // contributed by the Rust Project Developers | |
5 | ||
6 | // Copyright (c) 2013-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 | ||
c34b1796 AL |
41 | #![feature(core, old_io, io, core)] |
42 | ||
1a4d82fc | 43 | use std::cmp::min; |
c34b1796 | 44 | use std::old_io::*; |
1a4d82fc | 45 | use std::iter::repeat; |
85aaf69f | 46 | use std::env; |
1a4d82fc | 47 | use std::slice::bytes::copy_memory; |
970d7e83 | 48 | |
85aaf69f SL |
49 | const LINE_LEN: usize = 60; |
50 | const LOOKUP_SIZE: usize = 4 * 1024; | |
1a4d82fc | 51 | const LOOKUP_SCALE: f32 = (LOOKUP_SIZE - 1) as f32; |
970d7e83 LB |
52 | |
53 | // Random number generator constants | |
1a4d82fc JJ |
54 | const IM: u32 = 139968; |
55 | const IA: u32 = 3877; | |
56 | const IC: u32 = 29573; | |
970d7e83 | 57 | |
1a4d82fc | 58 | const ALU: &'static str = "GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTG\ |
970d7e83 LB |
59 | GGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGA\ |
60 | GACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAA\ | |
61 | AATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAAT\ | |
62 | CCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAAC\ | |
63 | CCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTG\ | |
64 | CACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAA"; | |
65 | ||
1a4d82fc | 66 | const NULL_AMINO_ACID: AminoAcid = AminoAcid { c: ' ' as u8, p: 0.0 }; |
970d7e83 | 67 | |
1a4d82fc | 68 | static IUB: [AminoAcid;15] = [ |
970d7e83 LB |
69 | AminoAcid { c: 'a' as u8, p: 0.27 }, |
70 | AminoAcid { c: 'c' as u8, p: 0.12 }, | |
71 | AminoAcid { c: 'g' as u8, p: 0.12 }, | |
72 | AminoAcid { c: 't' as u8, p: 0.27 }, | |
73 | AminoAcid { c: 'B' as u8, p: 0.02 }, | |
74 | AminoAcid { c: 'D' as u8, p: 0.02 }, | |
75 | AminoAcid { c: 'H' as u8, p: 0.02 }, | |
76 | AminoAcid { c: 'K' as u8, p: 0.02 }, | |
77 | AminoAcid { c: 'M' as u8, p: 0.02 }, | |
78 | AminoAcid { c: 'N' as u8, p: 0.02 }, | |
79 | AminoAcid { c: 'R' as u8, p: 0.02 }, | |
80 | AminoAcid { c: 'S' as u8, p: 0.02 }, | |
81 | AminoAcid { c: 'V' as u8, p: 0.02 }, | |
82 | AminoAcid { c: 'W' as u8, p: 0.02 }, | |
83 | AminoAcid { c: 'Y' as u8, p: 0.02 }, | |
84 | ]; | |
85 | ||
1a4d82fc | 86 | static HOMO_SAPIENS: [AminoAcid;4] = [ |
970d7e83 LB |
87 | AminoAcid { c: 'a' as u8, p: 0.3029549426680 }, |
88 | AminoAcid { c: 'c' as u8, p: 0.1979883004921 }, | |
89 | AminoAcid { c: 'g' as u8, p: 0.1975473066391 }, | |
90 | AminoAcid { c: 't' as u8, p: 0.3015094502008 }, | |
91 | ]; | |
92 | ||
1a4d82fc JJ |
93 | // FIXME: Use map(). |
94 | fn sum_and_scale(a: &'static [AminoAcid]) -> Vec<AminoAcid> { | |
95 | let mut result = Vec::new(); | |
970d7e83 | 96 | let mut p = 0f32; |
85aaf69f | 97 | for a_i in a { |
970d7e83 LB |
98 | let mut a_i = *a_i; |
99 | p += a_i.p; | |
100 | a_i.p = p * LOOKUP_SCALE; | |
101 | result.push(a_i); | |
102 | } | |
1a4d82fc JJ |
103 | let result_len = result.len(); |
104 | result[result_len - 1].p = LOOKUP_SCALE; | |
970d7e83 LB |
105 | result |
106 | } | |
107 | ||
c34b1796 | 108 | #[derive(Copy, Clone)] |
970d7e83 LB |
109 | struct AminoAcid { |
110 | c: u8, | |
111 | p: f32, | |
112 | } | |
113 | ||
1a4d82fc | 114 | struct RepeatFasta<'a, W:'a> { |
970d7e83 | 115 | alu: &'static str, |
1a4d82fc | 116 | out: &'a mut W |
970d7e83 LB |
117 | } |
118 | ||
1a4d82fc JJ |
119 | impl<'a, W: Writer> RepeatFasta<'a, W> { |
120 | fn new(alu: &'static str, w: &'a mut W) -> RepeatFasta<'a, W> { | |
121 | RepeatFasta { alu: alu, out: w } | |
970d7e83 LB |
122 | } |
123 | ||
85aaf69f | 124 | fn make(&mut self, n: usize) -> IoResult<()> { |
1a4d82fc | 125 | let alu_len = self.alu.len(); |
c34b1796 | 126 | let mut buf = repeat(0).take(alu_len + LINE_LEN).collect::<Vec<_>>(); |
1a4d82fc JJ |
127 | let alu: &[u8] = self.alu.as_bytes(); |
128 | ||
c34b1796 | 129 | copy_memory(alu, &mut buf); |
1a4d82fc | 130 | let buf_len = buf.len(); |
c34b1796 | 131 | copy_memory(&alu[..LINE_LEN], &mut buf[alu_len..buf_len]); |
1a4d82fc JJ |
132 | |
133 | let mut pos = 0; | |
134 | let mut bytes; | |
135 | let mut n = n; | |
136 | while n > 0 { | |
137 | bytes = min(LINE_LEN, n); | |
85aaf69f | 138 | try!(self.out.write(&buf[pos..pos + bytes])); |
1a4d82fc JJ |
139 | try!(self.out.write_u8('\n' as u8)); |
140 | pos += bytes; | |
141 | if pos > alu_len { | |
142 | pos -= alu_len; | |
970d7e83 | 143 | } |
1a4d82fc | 144 | n -= bytes; |
970d7e83 | 145 | } |
1a4d82fc | 146 | Ok(()) |
970d7e83 LB |
147 | } |
148 | } | |
149 | ||
1a4d82fc JJ |
150 | fn make_lookup(a: &[AminoAcid]) -> [AminoAcid;LOOKUP_SIZE] { |
151 | let mut lookup = [ NULL_AMINO_ACID;LOOKUP_SIZE ]; | |
152 | let mut j = 0; | |
153 | for (i, slot) in lookup.iter_mut().enumerate() { | |
154 | while a[j].p < (i as f32) { | |
155 | j += 1; | |
156 | } | |
157 | *slot = a[j]; | |
158 | } | |
159 | lookup | |
160 | } | |
161 | ||
162 | struct RandomFasta<'a, W:'a> { | |
970d7e83 | 163 | seed: u32, |
1a4d82fc JJ |
164 | lookup: [AminoAcid;LOOKUP_SIZE], |
165 | out: &'a mut W, | |
970d7e83 LB |
166 | } |
167 | ||
1a4d82fc JJ |
168 | impl<'a, W: Writer> RandomFasta<'a, W> { |
169 | fn new(w: &'a mut W, a: &[AminoAcid]) -> RandomFasta<'a, W> { | |
970d7e83 LB |
170 | RandomFasta { |
171 | seed: 42, | |
1a4d82fc JJ |
172 | out: w, |
173 | lookup: make_lookup(a), | |
970d7e83 | 174 | } |
970d7e83 LB |
175 | } |
176 | ||
177 | fn rng(&mut self, max: f32) -> f32 { | |
178 | self.seed = (self.seed * IA + IC) % IM; | |
179 | max * (self.seed as f32) / (IM as f32) | |
180 | } | |
181 | ||
182 | fn nextc(&mut self) -> u8 { | |
183 | let r = self.rng(1.0); | |
85aaf69f | 184 | for a in &self.lookup[..] { |
970d7e83 LB |
185 | if a.p >= r { |
186 | return a.c; | |
187 | } | |
188 | } | |
189 | 0 | |
190 | } | |
191 | ||
85aaf69f | 192 | fn make(&mut self, n: usize) -> IoResult<()> { |
1a4d82fc JJ |
193 | let lines = n / LINE_LEN; |
194 | let chars_left = n % LINE_LEN; | |
195 | let mut buf = [0;LINE_LEN + 1]; | |
196 | ||
85aaf69f SL |
197 | for _ in 0..lines { |
198 | for i in 0..LINE_LEN { | |
970d7e83 LB |
199 | buf[i] = self.nextc(); |
200 | } | |
1a4d82fc JJ |
201 | buf[LINE_LEN] = '\n' as u8; |
202 | try!(self.out.write(&buf)); | |
203 | } | |
85aaf69f | 204 | for i in 0..chars_left { |
1a4d82fc | 205 | buf[i] = self.nextc(); |
970d7e83 | 206 | } |
85aaf69f | 207 | self.out.write(&buf[..chars_left]) |
970d7e83 LB |
208 | } |
209 | } | |
210 | ||
970d7e83 | 211 | fn main() { |
85aaf69f | 212 | let mut args = env::args(); |
1a4d82fc | 213 | let n = if args.len() > 1 { |
85aaf69f | 214 | args.nth(1).unwrap().parse::<usize>().unwrap() |
1a4d82fc JJ |
215 | } else { |
216 | 5 | |
217 | }; | |
218 | ||
219 | let mut out = stdout(); | |
220 | ||
221 | out.write_line(">ONE Homo sapiens alu").unwrap(); | |
222 | { | |
223 | let mut repeat = RepeatFasta::new(ALU, &mut out); | |
224 | repeat.make(n * 2).unwrap(); | |
225 | } | |
970d7e83 | 226 | |
1a4d82fc JJ |
227 | out.write_line(">TWO IUB ambiguity codes").unwrap(); |
228 | let iub = sum_and_scale(&IUB); | |
85aaf69f | 229 | let mut random = RandomFasta::new(&mut out, &iub); |
1a4d82fc | 230 | random.make(n * 3).unwrap(); |
970d7e83 | 231 | |
1a4d82fc JJ |
232 | random.out.write_line(">THREE Homo sapiens frequency").unwrap(); |
233 | let homo_sapiens = sum_and_scale(&HOMO_SAPIENS); | |
85aaf69f | 234 | random.lookup = make_lookup(&homo_sapiens); |
1a4d82fc | 235 | random.make(n * 5).unwrap(); |
970d7e83 | 236 | |
1a4d82fc | 237 | random.out.write_str("\n").unwrap(); |
970d7e83 | 238 | } |