7
7
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8
8
// option. This file may not be copied, modified, or distributed
9
9
// except according to those terms.
10
+ #![ feature( macro_rules) ]
10
11
11
12
// ignore-pretty very bad with line comments
12
13
@@ -18,41 +19,72 @@ use sync::Future;
18
19
static ITER : int = 50 ;
19
20
static LIMIT : f64 = 2.0 ;
20
21
22
+ macro_rules! core_loop(
23
+ ( $pow: expr ~ $mask: expr: $ctx: ident, $b: ident) => (
24
+ {
25
+ let r = $ctx. r;
26
+ let i = $ctx. i;
27
+
28
+ $ctx. r = r * r - i * i + $ctx. init_r;
29
+ $ctx. i = 2.0 * r * i + $ctx. init_i;
30
+
31
+ if r * r + i * i > LIMIT * LIMIT {
32
+ $b |= $pow;
33
+ if $b == $mask { break ; }
34
+ }
35
+ }
36
+ ) ;
37
+ )
38
+
39
+ #[ inline( always) ]
21
40
fn write_line ( init_i : f64 , vec_init_r : & [ f64 ] , res : & mut Vec < u8 > ) {
41
+ struct Context { r : f64 , i : f64 , init_i : f64 , init_r : f64 }
42
+ impl Context {
43
+ #[ inline( always) ]
44
+ fn new ( i : f64 , r : f64 ) -> Context {
45
+ Context { r : r, i : i, init_r : r, init_i : i }
46
+ }
47
+ }
48
+
49
+ let mut cur_byte;
50
+ let mut i;
51
+ let mut bit_1;
52
+ let mut bit_2;
53
+ let mut b;
22
54
for chunk_init_r in vec_init_r. chunks ( 8 ) {
23
- let mut cur_byte = 0xff ;
24
- let mut cur_bitmask = 0x80 ;
25
- for & init_r in chunk_init_r. iter ( ) {
26
- let mut cur_r = init_r;
27
- let mut cur_i = init_i;
55
+ cur_byte = 0xff ;
56
+ i = 0 ;
57
+
58
+ while i < 8 {
59
+ bit_1 = Context :: new ( init_i, chunk_init_r[ i] ) ;
60
+ bit_2 = Context :: new ( init_i, chunk_init_r[ i + 1 ] ) ;
61
+
62
+ b = 0 ;
28
63
for _ in range ( 0 , ITER ) {
29
- let r = cur_r;
30
- let i = cur_i;
31
- cur_r = r * r - i * i + init_r;
32
- cur_i = 2.0 * r * i + init_i;
33
-
34
- if r * r + i * i > LIMIT * LIMIT {
35
- cur_byte &= !cur_bitmask;
36
- break ;
37
- }
64
+ core_loop ! ( 2 ~ 3 : bit_1, b) ;
65
+ core_loop ! ( 1 ~ 3 : bit_2, b) ;
38
66
}
39
- cur_bitmask >>= 1 ;
67
+
68
+ cur_byte = ( cur_byte << 2 ) + b;
69
+ i += 2 ;
40
70
}
41
- res. push ( cur_byte) ;
71
+ res. push ( cur_byte^- 1 ) ;
42
72
}
43
73
}
44
74
45
75
fn mandelbrot < W : io:: Writer > ( w : uint , mut out : W ) -> io:: IoResult < ( ) > {
46
76
// Ensure w and h are multiples of 8.
47
77
let w = ( w + 7 ) / 8 * 8 ;
48
78
let h = w;
49
- let chunk_size = h / 8 ;
79
+ let inverse_w_doubled = 2.0 / w as f64 ;
80
+ let inverse_h_doubled = 2.0 / h as f64 ;
81
+ let chunk_size = h / 16 ;
50
82
51
- let data: Vec < Future < Vec < u8 > > > = range ( 0 u, 8 ) . map ( |i| Future :: spawn ( proc ( ) {
52
- let vec_init_r = Vec :: from_fn ( w, |x| 2.0 * ( x as f64 ) / ( w as f64 ) - 1.5 ) ;
83
+ let data: Vec < Future < Vec < u8 > > > = range ( 0 u, 16 ) . map ( |i| Future :: spawn ( proc ( ) {
84
+ let vec_init_r = Vec :: from_fn ( w, |x| ( x as f64 ) * inverse_w_doubled - 1.5 ) ;
53
85
let mut res: Vec < u8 > = Vec :: with_capacity ( ( chunk_size * w) / 8 ) ;
54
86
for y in range ( i * chunk_size, ( i + 1 ) * chunk_size) {
55
- let init_i = 2.0 * ( y as f64 ) / ( h as f64 ) - 1.0 ;
87
+ let init_i = ( y as f64 ) * inverse_h_doubled - 1.0 ;
56
88
write_line ( init_i, vec_init_r. as_slice ( ) , & mut res) ;
57
89
}
58
90
res
0 commit comments