]> git.lizzy.rs Git - rust.git/blob - src/test/bench/shootout-fasta-redux.rs
579b88a7e0e72c0231fb22f17a8c7a407cbfb83b
[rust.git] / src / test / bench / shootout-fasta-redux.rs
1 use std::cast::transmute;
2 use std::from_str::FromStr;
3 use std::libc::{FILE, STDOUT_FILENO, c_int, fdopen, fputc, fputs, fwrite, size_t};
4 use std::os;
5 use std::uint::min;
6 use std::vec::bytes::copy_memory;
7 use std::vec;
8
9 static LINE_LEN: uint = 60;
10 static LOOKUP_SIZE: uint = 4 * 1024;
11 static LOOKUP_SCALE: f32 = (LOOKUP_SIZE - 1) as f32;
12
13 // Random number generator constants
14 static IM: u32 = 139968;
15 static IA: u32 = 3877;
16 static IC: u32 = 29573;
17
18 static ALU: &'static str = "GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTG\
19                             GGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGA\
20                             GACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAA\
21                             AATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAAT\
22                             CCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAAC\
23                             CCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTG\
24                             CACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAA";
25
26 static NULL_AMINO_ACID: AminoAcid = AminoAcid { c: ' ' as u8, p: 0.0 };
27
28 static MESSAGE_1: &'static str = ">ONE Homo sapiens alu\n";
29 static MESSAGE_2: &'static str = ">TWO IUB ambiguity codes\n";
30 static MESSAGE_3: &'static str = ">THREE Homo sapiens frequency\n";
31
32 static IUB: [AminoAcid, ..15] = [
33     AminoAcid { c: 'a' as u8, p: 0.27 },
34     AminoAcid { c: 'c' as u8, p: 0.12 },
35     AminoAcid { c: 'g' as u8, p: 0.12 },
36     AminoAcid { c: 't' as u8, p: 0.27 },
37     AminoAcid { c: 'B' as u8, p: 0.02 },
38     AminoAcid { c: 'D' as u8, p: 0.02 },
39     AminoAcid { c: 'H' as u8, p: 0.02 },
40     AminoAcid { c: 'K' as u8, p: 0.02 },
41     AminoAcid { c: 'M' as u8, p: 0.02 },
42     AminoAcid { c: 'N' as u8, p: 0.02 },
43     AminoAcid { c: 'R' as u8, p: 0.02 },
44     AminoAcid { c: 'S' as u8, p: 0.02 },
45     AminoAcid { c: 'V' as u8, p: 0.02 },
46     AminoAcid { c: 'W' as u8, p: 0.02 },
47     AminoAcid { c: 'Y' as u8, p: 0.02 },
48 ];
49
50 static HOMO_SAPIENS: [AminoAcid, ..4] = [
51     AminoAcid { c: 'a' as u8, p: 0.3029549426680 },
52     AminoAcid { c: 'c' as u8, p: 0.1979883004921 },
53     AminoAcid { c: 'g' as u8, p: 0.1975473066391 },
54     AminoAcid { c: 't' as u8, p: 0.3015094502008 },
55 ];
56
57 // XXX: Use map().
58 fn sum_and_scale(a: &'static [AminoAcid]) -> ~[AminoAcid] {
59     let mut result = ~[];
60     let mut p = 0f32;
61     for a_i in a.iter() {
62         let mut a_i = *a_i;
63         p += a_i.p;
64         a_i.p = p * LOOKUP_SCALE;
65         result.push(a_i);
66     }
67     result[result.len() - 1].p = LOOKUP_SCALE;
68     result
69 }
70
71 struct AminoAcid {
72     c: u8,
73     p: f32,
74 }
75
76 struct RepeatFasta {
77     alu: &'static str,
78     stdout: *FILE,
79 }
80
81 impl RepeatFasta {
82     fn new(stdout: *FILE, alu: &'static str) -> RepeatFasta {
83         RepeatFasta {
84             alu: alu,
85             stdout: stdout,
86         }
87     }
88
89     fn make(&mut self, n: uint) {
90         unsafe {
91             let stdout = self.stdout;
92             let alu_len = self.alu.len();
93             let mut buf = vec::from_elem(alu_len + LINE_LEN, 0u8);
94             let alu: &[u8] = self.alu.as_bytes();
95
96             copy_memory(buf, alu, alu_len);
97             let buf_len = buf.len();
98             copy_memory(buf.mut_slice(alu_len, buf_len),
99                         alu,
100                         LINE_LEN);
101
102             let mut pos = 0;
103             let mut bytes;
104             let mut n = n;
105             while n > 0 {
106                 bytes = min(LINE_LEN, n);
107                 fwrite(transmute(&buf[pos]), bytes as size_t, 1, stdout);
108                 fputc('\n' as c_int, stdout);
109                 pos += bytes;
110                 if pos > alu_len {
111                     pos -= alu_len;
112                 }
113                 n -= bytes;
114             }
115         }
116     }
117 }
118
119 struct RandomFasta {
120     seed: u32,
121     stdout: *FILE,
122     lookup: [AminoAcid, ..LOOKUP_SIZE],
123 }
124
125 impl RandomFasta {
126     fn new(stdout: *FILE, a: &[AminoAcid]) -> RandomFasta {
127         RandomFasta {
128             seed: 42,
129             stdout: stdout,
130             lookup: RandomFasta::make_lookup(a),
131         }
132     }
133
134     fn make_lookup(a: &[AminoAcid]) -> [AminoAcid, ..LOOKUP_SIZE] {
135         let mut lookup = [ NULL_AMINO_ACID, ..LOOKUP_SIZE ];
136         let mut j = 0;
137         for (i, slot) in lookup.mut_iter().enumerate() {
138             while a[j].p < (i as f32) {
139                 j += 1;
140             }
141             *slot = a[j];
142         }
143         lookup
144     }
145
146     fn rng(&mut self, max: f32) -> f32 {
147         self.seed = (self.seed * IA + IC) % IM;
148         max * (self.seed as f32) / (IM as f32)
149     }
150
151     fn nextc(&mut self) -> u8 {
152         let r = self.rng(1.0);
153         for a in self.lookup.iter() {
154             if a.p >= r {
155                 return a.c;
156             }
157         }
158         0
159     }
160
161     fn make(&mut self, n: uint) {
162         unsafe {
163             let lines = n / LINE_LEN;
164             let chars_left = n % LINE_LEN;
165             let mut buf = [0, ..LINE_LEN + 1];
166
167             do lines.times {
168                 for i in range(0u, LINE_LEN) {
169                     buf[i] = self.nextc();
170                 }
171                 buf[LINE_LEN] = '\n' as u8;
172                 fwrite(transmute(&buf[0]),
173                        LINE_LEN as size_t + 1,
174                        1,
175                        self.stdout);
176             }
177             for i in range(0u, chars_left) {
178                 buf[i] = self.nextc();
179             }
180             fwrite(transmute(&buf[0]), chars_left as size_t, 1, self.stdout);
181         }
182     }
183 }
184
185 #[fixed_stack_segment]
186 fn main() {
187     let n: uint = FromStr::from_str(os::args()[1]).unwrap();
188
189     unsafe {
190         let mode = "w";
191         let stdout = fdopen(STDOUT_FILENO as c_int, transmute(&mode[0]));
192
193         fputs(transmute(&MESSAGE_1[0]), stdout);
194         let mut repeat = RepeatFasta::new(stdout, ALU);
195         repeat.make(n * 2);
196
197         fputs(transmute(&MESSAGE_2[0]), stdout);
198         let iub = sum_and_scale(IUB);
199         let mut random = RandomFasta::new(stdout, iub);
200         random.make(n * 3);
201
202         fputs(transmute(&MESSAGE_3[0]), stdout);
203         let homo_sapiens = sum_and_scale(HOMO_SAPIENS);
204         random.lookup = RandomFasta::make_lookup(homo_sapiens);
205         random.make(n * 5);
206
207         fputc('\n' as c_int, stdout);
208     }
209 }