mirror of
				https://github.com/KevinMidboe/linguist.git
				synced 2025-10-29 17:50:22 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			189 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			Pony
		
	
	
	
	
	
			
		
		
	
	
			189 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			Pony
		
	
	
	
	
	
| use "files"
 | |
| use "options"
 | |
| use "collections"
 | |
| 
 | |
| actor Worker
 | |
|   new mandelbrot(main: Main, x: U64, y: U64, width: U64, iterations: U64,
 | |
|     limit: F32, real: Array[F32] val, imaginary: Array[F32] val)
 | |
|   =>
 | |
|     var view: Array[U8] iso =
 | |
|       recover
 | |
|         Array[U8]((y - x) * (width >> 3))
 | |
|       end
 | |
| 
 | |
|     let group_r = Array[F32].undefined(8)
 | |
|     let group_i = Array[F32].undefined(8)
 | |
| 
 | |
|     var row = x
 | |
| 
 | |
|     try
 | |
|       while row < y do
 | |
|         let prefetch_i = imaginary(row)
 | |
| 
 | |
|         var col: U64 = 0
 | |
| 
 | |
|         while col < width do
 | |
|           var j: U64 = 0
 | |
| 
 | |
|           while j < 8 do
 | |
|             group_r.update(j, real(col + j))
 | |
|             group_i.update(j, prefetch_i)
 | |
|             j = j + 1
 | |
|           end
 | |
| 
 | |
|           var bitmap: U8 = 0xFF
 | |
|           var n = iterations
 | |
| 
 | |
|           repeat
 | |
|             var mask: U8 = 0x80
 | |
|             var k: U64 = 0
 | |
| 
 | |
|             while k < 8 do
 | |
|               let r = group_r(k)
 | |
|               let i = group_i(k)
 | |
| 
 | |
|               group_r.update(k, ((r * r) - (i * i)) + real(col + k))
 | |
|               group_i.update(k, (2.0 * r * i) + prefetch_i)
 | |
| 
 | |
|               if ((r * r) + (i * i)) > limit then
 | |
|                 bitmap = bitmap and not mask
 | |
|               end
 | |
| 
 | |
|               mask = mask >> 1
 | |
|               k = k + 1
 | |
|             end
 | |
|           until (bitmap == 0) or ((n = n - 1) == 1) end
 | |
| 
 | |
|           view.push(bitmap)
 | |
| 
 | |
|           col = col + 8
 | |
|         end
 | |
|         row = row + 1
 | |
|       end
 | |
| 
 | |
|       main.draw(x * (width >> 3), consume view)
 | |
|     end
 | |
| 
 | |
| actor Main
 | |
|   var iterations: U64 = 50
 | |
|   var limit: F32 = 4.0
 | |
|   var chunks: U64 = 16
 | |
|   var width: U64 = 16000
 | |
|   var actors: U64 = 0
 | |
|   var header: U64 = 0
 | |
|   var real: Array[F32] val = recover Array[F32] end
 | |
|   var imaginary: Array[F32] val = recover Array[F32] end
 | |
|   var outfile: (File | None) = None
 | |
| 
 | |
|   new create(env: Env) =>
 | |
|     try
 | |
|       arguments(env)
 | |
| 
 | |
|       let length = width
 | |
|       let recip_width = 2.0 / width.f32()
 | |
| 
 | |
|       var r = recover Array[F32](length) end
 | |
|       var i = recover Array[F32](length) end
 | |
| 
 | |
|       for j in Range(0, width) do
 | |
|         r.push((recip_width * j.f32()) - 1.5)
 | |
|         i.push((recip_width * j.f32()) - 1.0)
 | |
|       end
 | |
| 
 | |
|       real = consume r
 | |
|       imaginary = consume i
 | |
| 
 | |
|       spawn_actors()
 | |
|       create_outfile()
 | |
|     end
 | |
| 
 | |
|   be draw(offset: U64, pixels: Array[U8] val) =>
 | |
|     match outfile
 | |
|     | var out: File =>
 | |
|       out.seek_start(header + offset)
 | |
|       out.write(pixels)
 | |
|       if (actors = actors - 1) == 1 then
 | |
|         out.dispose()
 | |
|       end
 | |
|     end
 | |
| 
 | |
|   fun ref create_outfile() =>
 | |
|     match outfile
 | |
|     | var f: File =>
 | |
|       f.print("P4\n " + width.string() + " " + width.string() + "\n")
 | |
|       header = f.size()
 | |
|       f.set_length((width * (width >> 3)) + header)
 | |
|     end
 | |
| 
 | |
|   fun ref spawn_actors() =>
 | |
|     actors = ((width + (chunks - 1)) / chunks)
 | |
| 
 | |
|     var rest = width % chunks
 | |
| 
 | |
|     if rest == 0 then rest = chunks end
 | |
| 
 | |
|     var x: U64 = 0
 | |
|     var y: U64 = 0
 | |
| 
 | |
|     for i in Range(0, actors - 1) do
 | |
|       x = i * chunks
 | |
|       y = x + chunks
 | |
|       Worker.mandelbrot(this, x, y, width, iterations, limit, real, imaginary)
 | |
|     end
 | |
| 
 | |
|     Worker.mandelbrot(this, y, y + rest, width, iterations, limit, real,
 | |
|       imaginary)
 | |
| 
 | |
|   fun ref arguments(env: Env) ? =>
 | |
|     let options = Options(env)
 | |
| 
 | |
|     options
 | |
|       .add("iterations", "i", I64Argument)
 | |
|       .add("limit", "l", F64Argument)
 | |
|       .add("chunks", "c", I64Argument)
 | |
|       .add("width", "w", I64Argument)
 | |
|       .add("output", "o", StringArgument)
 | |
| 
 | |
|     for option in options do
 | |
|       match option
 | |
|       | ("iterations", var arg: I64) => iterations = arg.u64()
 | |
|       | ("limit", var arg: F64) => limit = arg.f32()
 | |
|       | ("chunks", var arg: I64) => chunks = arg.u64()
 | |
|       | ("width", var arg: I64) => width = arg.u64()
 | |
|       | ("output", var arg: String) =>
 | |
|         outfile = try File(FilePath(env.root, arg)) end
 | |
|       | let err: ParseError => err.report(env.out) ; usage(env) ; error
 | |
|       end
 | |
|     end
 | |
| 
 | |
|   fun tag usage(env: Env) =>
 | |
|     env.out.print(
 | |
|       """
 | |
|       mandelbrot [OPTIONS]
 | |
| 
 | |
|       The binary output can be converted to a BMP with the following command
 | |
|       (ImageMagick Tools required):
 | |
| 
 | |
|         convert <output> JPEG:<output>.jpg
 | |
| 
 | |
|       Available options:
 | |
| 
 | |
|       --iterations, -i  Maximum amount of iterations to be done for each pixel.
 | |
|                         Defaults to 50.
 | |
| 
 | |
|       --limit, -l       Square of the limit that pixels need to exceed in order
 | |
|                         to escape from the Mandelbrot set.
 | |
|                         Defaults to 4.0.
 | |
| 
 | |
|       --chunks, -c      Maximum line count of chunks the image should be
 | |
|                         divided into for divide & conquer processing.
 | |
|                         Defaults to 16.
 | |
| 
 | |
|       --width, -w       Lateral length of the resulting mandelbrot image.
 | |
|                         Defaults to 16000.
 | |
| 
 | |
|       --output, -o      File to write the output to.
 | |
| 
 | |
|       """
 | |
|       )
 |