;;Coded by Denis Duplan for Stash of Code (http://www.stashofcode.fr, stashofcode@gmail.com) in december 2018. ;;This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. (module (memory (import "imports" "memory") 1) (func $mandelbroot (export "mandelbroot") (param $width i32) (param $height i32) (param $minX f64) (param $maxX f64) (param $minY f64) (param $maxY f64) (param $maxN i32) (local $i i32) (local $j i32) (local $dx f64) (local $dy f64) (local $x f64) (local $y f64) (local $a f64) (local $b f64) (local $c f64) (local $n i32) (local $index i32) (set_local $dx (f64.div (f64.sub (get_local $maxX) (get_local $minX)) (f64.convert_u/i32 (get_local $width)))) (set_local $dy (f64.div (f64.sub (get_local $maxY) (get_local $minY)) (f64.convert_u/i32 (get_local $height)))) (set_local $j (get_local $height)) (set_local $y (get_local $minY)) (set_local $index (i32.const 0)) (loop (set_local $i (get_local $width)) (set_local $x (get_local $minX)) (loop (set_local $a (f64.const 0.0)) (set_local $b (f64.const 0.0)) (set_local $n (get_local $maxN)) (block (loop ;; $c = $a (just push it) get_local $a ;; Set $a = $a * $a - $b * $b + $x (f64.mul (get_local $a) (get_local $a)) (f64.sub (f64.mul (get_local $b) (get_local $b))) (set_local $a (f64.add (get_local $x))) ;; Set $b = 2 * $c * $b + y (f64.mul (f64.const 2.0)) ;; This pops $a (f64.mul (get_local $b)) (set_local $b (f64.add (get_local $y))) ;; Set $n -= 1 (set_local $n (i32.sub (get_local $n) (i32.const 1))) ;; Break if $a * $a + $b * $b >= 4.0 (f64.add (f64.mul (get_local $a) (get_local $a)) (f64.mul (get_local $b) (get_local $b))) (br_if 1 (f64.ge (f64.const 4.0))) ;; Break if $n == 0, else loop (br_if 1 (i32.eqz (get_local $n))) br 0 ) ) ;; Store (0xFF000000 | (($n * 255 / ($maxN - 1)) & 0xFF)) at index $index get_local $index (i32.trunc_u/f64 (f64.div (f64.convert_u/i32 (i32.mul (get_local $n) (i32.const 255))) (f64.convert_u/i32 (i32.sub (get_local $maxN) (i32.const 1))))) (i32.or (i32.const 0xFF000000)) i32.store ;; Same thing with S-expressions : ;;(i32.store ;; (get_local $index) ;; (i32.or ;; (i32.const 0xFF000000) ;; (i32.trunc_u/f64 (f64.div (f64.convert_u/i32 (i32.mul (get_local $n) (i32.const 255))) (f64.convert_u/i32 (i32.sub (get_local $maxN) (i32.const 1))))) ;; ) ;;) ;; Set $index += 4 (set_local $index (i32.add (get_local $index) (i32.const 4))) ;; Set $x += $dx (set_local $x (f64.add (get_local $x) (get_local $dx))) ;; Loop if $i -- != 0, else exit (set_local $i (i32.sub (get_local $i) (i32.const 1))) (br_if 0 (i32.ne (get_local $i) (i32.const 0))) ) ;; Set $y += $dy (set_local $y (f64.add (get_local $y) (get_local $dy))) ;; Loop if $j -- != 0, else exit (set_local $j (i32.sub (get_local $j) (i32.const 1))) (br_if 0 (i32.ne (get_local $j) (i32.const 0))) ) ) ) (; // JavaScript Code for testing the Wasm code in wat2wasm var width = 11, height = 11; var importObject = { imports: { memory: new WebAssembly.Memory ({ initial: Math.ceil (width * height * 4 / 65536) }) } }; const wasmInstance = new WebAssembly.Instance (wasmModule, importObject); wasmInstance.exports.mandelbroot (width, height, -2.1, 1.1, -1.4, 1.4, 20); var i, j, pixels; pixels = new Uint32Array (importObject.imports.memory.buffer); for (j = 0; j != height; j ++) { for (i = 0; i != width ; i++) console.log (`(${i}, ${j}) = ${pixels[i + j * width].toString (16)}`); } ;)