read tools/basis.anubis read tools/maybefloat.anubis define Maybe(Float) Int x / Maybe(Float) y = success(to_Float(x)) / y. define Int Word32 x / Int y = if (Maybe((Int,Int)))(to_Int(x)/y) is { failure then 0, success(p) then if p is (q,r) then q }. define Int Int x / Int y = if (Maybe((Int,Int)))(x/y) is { failure then 0, success(p) then if p is (q,r) then q }. define Int integral_part ( Maybe(Float) x ) = if x is { failure then 0, success(f) then integral_part(f) }. define Maybe(Float) Maybe(Float) x * Int y = x * success(to_Float(y)). The computed image is just an array of Int, because for each point we just need the number of iterations. define (Maybe(Float) x, Maybe(Float) y, Int n) -> Int compute_iterations_function ( Maybe(Float) cx, Maybe(Float) cy ) = (Maybe(Float) x, Maybe(Float) y, Int n) |-f-> with x2 = x*x, y2 = y*y, with sqnorm = x2 + y2, if sqnorm > success(4.0) then n else if n >= 256 then 0 else f(x2 - y2 + cx, success(2.0)*x*y + cy, n+1). define Int compute_iterations ( Maybe(Float) cx, Maybe(Float) cy ) = compute_iterations_function(cx,cy)(cx,cy,0). define (Int x, Int y, Int n) -> Int compute_iterations_function ( Int cx, Int cy ) = (Int x, Int y, Int n) |-f-> with x2 = x*x, y2 = y*y, with sqnorm = x2 + y2, if sqnorm > 4 then n else if n >= 256 then 0 else f(x2 - y2 + cx, 2*x*y + cy, n+1). define Int compute_iterations ( Int cx, Int cy ) = compute_iterations_function(cx,cy)(cx,cy,0). define RGB my_palette_1 ( Word8 t ) = rgb(255-t,0,t). define RGB my_palette_2 ( Word8 t ) = rgb((t&15)<<4,(t&63)<<2,t). define RGB my_palette_3 ( Word8 t ) = rgb((t&7)<<5,((t>>3)&7)<<5,((t>>6)&3)<<6). define RGB my_palette_4 ( Word8 t ) = rgb((t&7)<<5,((t>>3)&7)<<5,t). define RGB my_palette_5 ( Word8 t ) = rgb(((t>>5)&7)<<5,((t>>2)&7)<<5,(t&3)<<6). define One paint_palette ( HostWindow w, Word8 -> RGB pal, Word8 i ) = with j = to_Word32(i), paint_rectangle(w,rect(0,j,100,j+1),pal(i)); if i = 255 then unique else paint_palette(w,pal,i+1). define (HostWindow w, List(Rectangle) l) -> One palette_paint_method ( Word8 -> RGB palette ) = (HostWindow w, List(Rectangle) l) |-> paint_palette(w,palette,0). define One show_palette ( Word8 -> RGB palette ) = if open_host_window(rect((Int)0,100,100,356), "Palette", managed(not_resizable), palette_paint_method(palette), (HostWindow w, HostWindowEvent(One) e) |-> [], identity) is { failure then print("Cannot open palette window.\n"), success(pw) then show(pw) }. type ImageToolBox: tool_box(HostWindow window, HostImage buffer, Word8 -> RGB palette, ByteArray image, Int window_width, Int window_height, Maybe(Float) center_x, Maybe(Float) center_y, Maybe(Float) scale, Var(Bool) close_v). define Int to_Int ( Maybe(Float) mbf ) = if mbf is { failure then 0, success(f) then integral_part(f) }. define One draw_pixel ( ImageToolBox tb, Int position_x, // position in window (pixels) Int position_y, ) = if tb is tool_box(window,buffer,_,image,window_width,window_height,center_x,center_y,scale,c_v) then // // Compute the coordinates of pixel to be drawn in complex plane // with s = to_Int(scale), x = to_Int(center_x) + ((position_x - window_width\2)) \ (s), y = to_Int(center_y) + ((position_y - window_height\2)) \ (s), // // Compute the color (number of iterations) // iterations = compute_iterations(x,y), // // Draw the pixel // forget(put(image,position_x + window_width * position_y,truncate_to_Word8(iterations))). define One copy_line_to_buffer_and_window ( ImageToolBox tb, Int position_y, Int position_x ) = if tb is tool_box(window,buffer,pal,image,window_width,window_height,center_x,center_y,scale,c_v) then if position_x >= window_width then paint_image(window, //rect(0,position_y,window_width,position_y+1), rect(0,0,window_width,window_height), 0,0, buffer) else (with color = pal( force_nth(position_x + window_width*position_y,image) ), draw_pixel(buffer,truncate_to_Word32(position_x),truncate_to_Word32(position_y),color); copy_line_to_buffer_and_window(tb,position_y,position_x+1)). define One draw_line ( ImageToolBox tb, Int position_x, Int position_y ) = if tb is tool_box(window,buffer,_,image,window_width,window_height,center_x,center_y,scale,c_v) then if *c_v then unique else if position_x >= window_width then copy_line_to_buffer_and_window(tb,position_y,0) else draw_pixel(tb,position_x,position_y); draw_line(tb,position_x+1,position_y). define One draw_all_lines ( ImageToolBox tb, Int position_y ) = if tb is tool_box(_,_,_,image,window_width,window_height,center_x,center_y,scale,c_v) then if *c_v then unique else if position_y >= window_height then unique else draw_line(tb,0,position_y); draw_all_lines(tb,position_y+1). The next function runs within a delegated machine. define One make_drawing ( HostWindow window, HostImage buffer, Word8 -> RGB palette, Var(Maybe(Float)) scale_v, Var(Maybe(Float)) center_x_v, Var(Maybe(Float)) center_y_v, Var(Bool) close_v ) = if size(window) is (window_width,window_height) then with tb = tool_box(window,buffer, palette, constant_byte_array(to_Int(window_width*window_height),0), to_Int(window_width),to_Int(window_height), *center_x_v, *center_y_v, *scale_v, close_v), draw_all_lines(tb,0). define One paint_small_rectangle ( HostWindow window, Int new_center_x, Int new_center_y, Maybe(Float) scale ) = if size(window) is (window_width,window_height) then with int_scale = integral_part(scale), small_window_width = (Int)(window_width/int_scale), small_window_height = (Int)(window_height/int_scale), x = new_center_x - small_window_width/2, y = new_center_y - small_window_height/2, u = x + small_window_width, v = y + small_window_height, white = rgb(255,255,255), paint_rectangle(window,rect(x,y,u,y+1),white); paint_rectangle(window,rect(x,y,x+1,v),white); paint_rectangle(window,rect(u,y,u+1,v),white); paint_rectangle(window,rect(x,v,u,v+1),white). define (HostWindow window, List(Rectangle) clip) -> One paint_method ( HostImage buffer, Var(Int) new_center_x_v, Var(Int) new_center_y_v, Var(Maybe(Float)) scale_v, Var(Maybe(Float)) new_scale_v ) = (HostWindow window, List(Rectangle) clip) |-> if size(window) is (window_width,window_height) then paint_image(window, rect(0,0,window_width,window_height), 0,0, buffer); paint_small_rectangle(window, *new_center_x_v, *new_center_y_v, (*new_scale_v)/(*scale_v)). define One new_window ( Int window_width, Int window_height, Word8 -> RGB palette, Maybe(Float) scale, Maybe(Float) center_x, Maybe(Float) center_y ). define (HostWindow window, HostWindowEvent(One) e) -> List(Rectangle) event_handler ( HostImage buffer, Word8 -> RGB palette, Var(Maybe(Float)) scale_v, Var(Maybe(Float)) new_scale_v, Var(Maybe(Float)) center_x_v, Var(Maybe(Float)) center_y_v, Var(Int) new_center_x_v, Var(Int) new_center_y_v, Var(Bool) close_v ) = (HostWindow window , HostWindowEvent(One) e) |-> if e is { quit then print("closing\n"); close_v <- true; [], expose then if size(window) is (window_width,window_height) then [rect(0,0,window_width,window_height)], pointer_entering then [], pointer_leaving then [], key_down(ks,kk) then [], mouse_move(ks,mx,my) then if size(window) is (window_width,window_height) then new_center_x_v <- to_Int(mx); new_center_y_v <- to_Int(my); [rect(0,0,window_width,window_height)], mouse_click(ks,mc,mx,my) then (if mc is left_down then (if size(window) is (window_width,window_height) then new_window(to_Int(window_width),to_Int(window_height), palette, *new_scale_v, (*new_center_x_v - window_width/2)/(*scale_v) + *center_x_v, (*new_center_y_v - window_height/2)/(*scale_v) + *center_y_v)) else unique); [], mouse_wheel(ks,md,mx,my) then if size(window) is (window_width,window_height) then (with sww = (*scale_v) * to_Int(window_width), ns = *new_scale_v, (if md >- 0 then new_scale_v <- (sww * ns)/(sww + success(2)*ns) else new_scale_v <- (sww * ns)/(sww - success(2)*ns))); [rect(0,0,window_width,window_height)], tick then [], repaint(_) then [], specific(_) then [] }. (if ((*new_scale_v) / (*scale_v)) > success(integer_to_float(window_height/2)) then unique else define One new_window ( Int window_width, Int window_height, Word8 -> RGB palette, Maybe(Float) scale, Maybe(Float) center_x, Maybe(Float) center_y ) = with buffer = to_host_image(create_rgba_image(window_width,window_height,rgba(255,255,255,255)),1), if screen_size is (screen_width,screen_height) then with wx = to_Int(random(screen_width - truncate_to_Word32(window_width))), wy = to_Int(random(screen_height - truncate_to_Word32(window_height))), scale_v = var(scale), new_scale_v = var((*scale_v)*success(8)), center_x_v = var(center_x), center_y_v = var(center_y), new_center_x_v = var((Int)0), new_center_y_v = var((Int)0), close_v = var((Bool)false), if open_host_window(rect(wx,wy,wx+window_width,wy+window_height), "Mandelbrot", managed(not_resizable), paint_method(buffer, new_center_x_v,new_center_y_v, scale_v,new_scale_v), event_handler(buffer, palette, scale_v,new_scale_v, center_x_v,center_y_v, new_center_x_v,new_center_y_v, close_v), identity) is { failure then print("Cannot open new window.\n"), success(window) then delegate make_drawing(window,buffer,palette,scale_v,center_x_v,center_y_v,close_v), show(window) }. global define One mandelbrot_set ( List(String) args ) = with palette = my_palette_5, map_forget(show_palette,[ /* my_palette_1, my_palette_2, my_palette_3, my_palette_4, */ my_palette_5 ]); new_window(300,200, palette, success(70), success(0.0),success(0.0)).