From 78357b8852626b510527f3b8d770a7dd8956fcc7 Mon Sep 17 00:00:00 2001 From: "Kartik K. Agaram" Date: Fri, 16 Jul 2021 08:38:43 -0700 Subject: . --- html/apps/mandelbrot.mu.html | 246 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 246 insertions(+) create mode 100644 html/apps/mandelbrot.mu.html (limited to 'html/apps/mandelbrot.mu.html') diff --git a/html/apps/mandelbrot.mu.html b/html/apps/mandelbrot.mu.html new file mode 100644 index 00000000..4f25d91b --- /dev/null +++ b/html/apps/mandelbrot.mu.html @@ -0,0 +1,246 @@ + + + + +Mu - apps/mandelbrot.mu + + + + + + + + + + +https://github.com/akkartik/mu/blob/main/apps/mandelbrot.mu +
+  1 # Mandelbrot set
+  2 #
+  3 # Install:
+  4 #   $ git clone https://github.com/akkartik/mu
+  5 #   $ cd mu
+  6 # Build on Linux:
+  7 #   $ ./translate apps/mandelbrot.mu
+  8 # Build on other platforms (slow):
+  9 #   $ ./translate_emulated apps/mandelbrot.mu
+ 10 # Run:
+ 11 #   $ qemu-system-i386 code.img
+ 12 
+ 13 fn main screen: (addr screen), keyboard: (addr keyboard), data-disk: (addr disk) {
+ 14   # Initially the viewport is centered at 0, 0 in the scene.
+ 15   var zero: float
+ 16   var scene-cx/xmm1: float <- copy zero
+ 17   var scene-cy/xmm2: float <- copy zero
+ 18   # Initially the viewport shows a section of the scene 4 units wide.
+ 19   # scene-width-scale = 0.5
+ 20   var scene-width-scale: float
+ 21   var dest/eax: (addr float) <- address scene-width-scale
+ 22   fill-in-rational dest, 1, 2
+ 23   # scene-width = 4
+ 24   var four: float
+ 25   var dest/eax: (addr float) <- address four
+ 26   fill-in-rational dest, 4, 1
+ 27   var scene-width/xmm3: float <- copy four
+ 28   {
+ 29     mandelbrot screen scene-cx, scene-cy, scene-width
+ 30     # move the center some % of the current screen-width
+ 31     var adj/xmm0: float <- rational 2, 0x1c/28
+ 32     adj <- multiply scene-width
+ 33     scene-cx <- subtract adj
+ 34     scene-cy <- add adj
+ 35     # slowly shrink the scene width to zoom in
+ 36     scene-width <- multiply scene-width-scale
+ 37     loop
+ 38   }
+ 39 }
+ 40 
+ 41 fn mandelbrot screen: (addr screen), scene-cx: float, scene-cy: float, scene-width: float {
+ 42   var a/eax: int <- copy 0
+ 43   var b/ecx: int <- copy 0
+ 44   a, b <- screen-size screen
+ 45   var width/esi: int <- copy a
+ 46   width <- shift-left 3/log2-font-width
+ 47   var height/edi: int <- copy b
+ 48   height <- shift-left 4/log2-font-height
+ 49   var y/ecx: int <- copy 0
+ 50   {
+ 51     compare y, height
+ 52     break-if->=
+ 53     var imaginary/xmm1: float <- viewport-to-imaginary y, width, height, scene-cy, scene-width
+ 54     var x/ebx: int <- copy 0
+ 55     {
+ 56       compare x, width
+ 57       break-if->=
+ 58       var real/xmm0: float <- viewport-to-real x, width, scene-cx, scene-width
+ 59       var iterations/eax: int <- mandelbrot-iterations-for-point real, imaginary, 0x400/max
+ 60       iterations <- shift-right 3
+ 61       var color/edx: int <- copy 0
+ 62       iterations, color <- integer-divide iterations, 0x18/24/size-of-cycle-0
+ 63       color <- add 0x20/cycle-0
+ 64       pixel screen, x, y, color
+ 65       x <- increment
+ 66       loop
+ 67     }
+ 68     y <- increment
+ 69     loop
+ 70   }
+ 71 }
+ 72 
+ 73 fn mandelbrot-iterations-for-point real: float, imaginary: float, max: int -> _/eax: int {
+ 74   var zero: float
+ 75   var x/xmm0: float <- copy zero
+ 76   var y/xmm1: float <- copy zero
+ 77   var iterations/ecx: int <- copy 0
+ 78   {
+ 79     var done?/eax: boolean <- mandelbrot-done? x, y
+ 80     compare done?, 0/false
+ 81     break-if-!=
+ 82     compare iterations, max
+ 83     break-if->=
+ 84     var newx/xmm2: float <- mandelbrot-x x, y, real
+ 85     var newy/xmm3: float <- mandelbrot-y x, y, imaginary
+ 86     x <- copy newx
+ 87     y <- copy newy
+ 88     iterations <- increment
+ 89     loop
+ 90   }
+ 91   return iterations
+ 92 }
+ 93 
+ 94 fn mandelbrot-done? x: float, y: float -> _/eax: boolean {
+ 95   # x*x + y*y > 4
+ 96   var x2/xmm0: float <- copy x
+ 97   x2 <- multiply x
+ 98   var y2/xmm1: float <- copy y
+ 99   y2 <- multiply y
+100   var sum/xmm0: float <- copy x2
+101   sum <- add y2
+102   var four/eax: int <- copy 4
+103   var four-f/xmm1: float <- convert four
+104   compare sum, four-f
+105   {
+106     break-if-float>
+107     return 0/false
+108   }
+109   return 1/true
+110 }
+111 
+112 fn mandelbrot-x x: float, y: float, real: float -> _/xmm2: float {
+113   # x*x - y*y + real
+114   var x2/xmm0: float <- copy x
+115   x2 <- multiply x
+116   var y2/xmm1: float <- copy y
+117   y2 <- multiply y
+118   var result/xmm0: float <- copy x2
+119   result <- subtract y2
+120   result <- add real
+121   return result
+122 }
+123 
+124 fn mandelbrot-y x: float, y: float, imaginary: float -> _/xmm3: float {
+125   # 2*x*y + imaginary
+126   var two/eax: int <- copy 2
+127   var result/xmm0: float <- convert two
+128   result <- multiply x
+129   result <- multiply y
+130   result <- add imaginary
+131   return result
+132 }
+133 
+134 # Scale (x, y) pixel coordinates to a complex plane where the viewport width
+135 # ranges from -2 to +2. Viewport height just follows the viewport's aspect
+136 # ratio.
+137 
+138 fn viewport-to-real x: int, width: int, scene-cx: float, scene-width: float -> _/xmm0: float {
+139   # 0 in the viewport       goes to scene-cx - scene-width/2 
+140   # width in the viewport   goes to scene-cx + scene-width/2
+141   # Therefore:
+142   # x in the viewport       goes to (scene-cx - scene-width/2) + x*scene-width/width
+143   # At most two numbers being multiplied before a divide, so no risk of overflow.
+144   var result/xmm0: float <- convert x
+145   result <- multiply scene-width
+146   var width-f/xmm1: float <- convert width
+147   result <- divide width-f
+148   result <- add scene-cx
+149   var two/eax: int <- copy 2
+150   var two-f/xmm2: float <- convert two
+151   var half-scene-width/xmm1: float <- copy scene-width
+152   half-scene-width <- divide two-f
+153   result <- subtract half-scene-width
+154   return result
+155 }
+156 
+157 fn viewport-to-imaginary y: int, width: int, height: int, scene-cy: float, scene-width: float -> _/xmm1: float {
+158   # 0 in the viewport       goes to scene-cy - scene-width/2*height/width
+159   # height in the viewport  goes to scene-cy + scene-width/2*height/width
+160   # Therefore:
+161   # y in the viewport       goes to (scene-cy - scene-width/2*height/width) + y*scene-width/width
+162   #  scene-cy - scene-width/width * (height/2 + y)
+163   # At most two numbers being multiplied before a divide, so no risk of overflow.
+164   var result/xmm0: float <- convert y
+165   result <- multiply scene-width
+166   var width-f/xmm1: float <- convert width
+167   result <- divide width-f
+168   result <- add scene-cy
+169   var two/eax: int <- copy 2
+170   var two-f/xmm2: float <- convert two
+171   var second-term/xmm1: float <- copy scene-width
+172   second-term <- divide two-f
+173   var height-f/xmm2: float <- convert height
+174   second-term <- multiply height-f
+175   var width-f/xmm2: float <- convert width
+176   second-term <- divide width-f
+177   result <- subtract second-term
+178   return result
+179 }
+
+ + + -- cgit 1.4.1-2-gfad0