e04d4ec4d01692af09c9eb40e6d8fed4f94bb912
[nit.git] / lib / actors / examples / mandelbrot / mandelbrot.nit
1 # This file is part of NIT (http://www.nitlanguage.org).
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14
15 # Example implemented from "The computer Language Benchmarks Game" - Mandelbrot
16 # http://benchmarksgame.alioth.debian.org/
17 #
18 # Complete description of mandelbrot :
19 # https://benchmarksgame.alioth.debian.org/u64q/mandelbrot-description.html#mandelbrot
20 module mandelbrot is no_warning("missing-doc")
21
22 import actors
23
24 class Worker
25 actor
26
27 fun get_byte(x, y: Int): Int do
28 var res = 0
29 for i in [0..8[.step(2) do
30 var zr1 = crb[x + i]
31 var zi1 = cib[y]
32
33 var zr2 = crb [x + i + 1]
34 var zi2 = cib[y]
35
36 var b = 0
37 for j in [0..nb_rounds[ do
38 var nzr1 = zr1 * zr1 - zi1 * zi1 + crb[x+i]
39 var nzi1 = zr1 * zi1 + zr1 * zi1 + cib[y]
40 zr1 = nzr1
41 zi1 = nzi1
42
43 var nzr2 = zr2 * zr2 - zi2 * zi2 + crb[x + i + 1]
44 var nzi2 = zr2 * zi2 + zr2 * zi2 + cib[y]
45 zr2 = nzr2
46 zi2 = nzi2
47
48 if zr1 * zr1 + zi1 * zi1 > 4.0 then b = b | 2
49 if zr2 * zr2 + zi2 * zi2 > 4.0 then b = b | 1
50 if b == 3 then break
51 end
52 res = (res << 2) + b
53 end
54 return res ^-1
55 end
56
57 fun put_line(y: Int, line: Array[Byte]) do
58 for i in [0..line.length[ do line[i] = get_byte(i * 8, y).to_b
59 end
60
61 fun work do
62 var line = 0
63 loop
64 line = atomic.get_and_increment
65 if line < n then put_line(line, data[line]) else break
66 end
67 end
68 end
69
70 redef class Sys
71 var n = 0
72 var inv_n: Float is noautoinit
73 var data: Array[Array[Byte]] is noautoinit
74 var crb: Array[Float] is noautoinit
75 var cib: Array[Float] is noautoinit
76 var atomic = new AtomicInt(0)
77 var nb_threads = 8
78 # How many time do we iterate before deciding if the number
79 # is in the mandelbrot set or not
80 var nb_rounds = 49
81 end
82
83 n = if args.is_empty then 200 else args[0].to_i
84
85 sys.crb = new Array[Float].with_capacity(n)
86 sys.cib = new Array[Float].with_capacity(n)
87 sys.inv_n = 2.0 / n.to_f
88 for i in [0..n[ do
89 sys.cib[i] = i.to_f * inv_n - 1.0
90 sys.crb[i] = i.to_f * inv_n - 1.5
91 end
92 sys.data = new Array[Array[Byte]].with_capacity(n)
93 for i in [0..n[ do sys.data[i] = new Array[Byte].filled_with(0.to_b, (n) / 8)
94
95 # Parallel Approach
96 var actors = new Array[Worker]
97 for i in [0..nb_threads[ do
98 var a = new Worker
99 actors.add(a)
100 a.async.work
101 end
102
103 for a in actors do
104 a.async.terminate
105 a.async.wait_termination
106 end
107
108 var filename = "WRITE".environ
109 if filename == "" then filename = "out"
110 var output = new FileWriter.open(filename)
111 output.write_bytes("P4\n{n} {n}\n".to_bytes)
112 for i in [0..n[ do
113 var length = data[i].length
114 for j in [0..length[ do output.write_byte(data[i][j])
115 end
116 output.close