Last active
February 9, 2019 02:37
-
-
Save nasser/c8c3e15b2733e68a5397bbcfabf14e02 to your computer and use it in GitHub Desktop.
Mandelbrot Renderer Script in Jn
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;; based on https://rosettacode.org/wiki/Mandelbrot_set#C.23 | |
;; no idea why System.Drawing.dll is not normally findable, this should be | |
;; (import "System.Drawing") | |
(import-from "/lib/mono/gac/System.Drawing/4.0.0.0__b03f5f7f11d50a3a/System.Drawing.dll") | |
(use "System.Drawing") | |
(use "System.Drawing.Imaging") | |
;; should be in stdlib | |
(defn jn.core/- [^Double a ^Double b] | |
(cil* Double (ldarg-0) (ldarg-1) (sub))) | |
(defn jn.core/- [^Double a ^Int32 b] | |
(cil* Double (ldarg-0) (ldarg-1) (conv-r8) (sub))) | |
(defn jn.core/- [^Int32 a ^Double b] | |
(cil* Double (ldarg-0) (conv-r8) (ldarg-1) (sub))) | |
(defn jn.core/multiply [^Double x ^Int32 y] | |
(cil* Double (ldarg-0) (ldarg-1) (conv-r8) (mul))) | |
(defn jn.core/multiply [^Int64 x ^Double y] | |
(cil* Double (ldarg-0) (conv-r8) (ldarg-1) (mul))) | |
;; blah name resolution on / is being weird, so just div for now | |
(defn div [^Int64 a ^Int64 b] | |
(cil* Double (ldarg-0) (conv-r8) (ldarg-1) (conv-r8) (div))) | |
(defn div [^Int32 a ^Int32 b] | |
(cil* Double (ldarg-0) (conv-r8) (ldarg-1) (conv-r8) (div))) | |
(defn div [^Double a ^Double b] | |
(cil* Double (ldarg-0) (ldarg-1) (div))) | |
(defn div [^Double a ^Int32 b] | |
(cil* Double (ldarg-0) (ldarg-1) (conv-r8) (div))) | |
(defn int [^Double x] | |
(cil* Int32 (ldarg-0) (conv-i4))) | |
(defn clamp [^Double x ^Double min ^Double max] | |
(cond | |
(< x min) min | |
(< max x) max | |
x)) | |
;; complex type + methods | |
(def complex (type [^Double re ^Double im])) | |
(defn jn.core/add [^complex x ^complex y] | |
(complex (+ (.re x) (.re y)) | |
(+ (.im x) (.im y)))) | |
(defn jn.core/multiply [^complex x ^complex y] | |
(complex (- (* (.re x) (.re y)) | |
(* (.im x) (.im y))) | |
(+ (* (.re x) (.im y)) | |
(* (.im x) (.re y))))) | |
(defn norm [^complex c] | |
(+ (* (.re c) (.re c)) | |
(* (.im c) (.im c)))) | |
;; mandelbrot algorithms | |
(defn mandelbrot-color [^complex c] | |
(let [iterations 1000 | |
max-extent 2. | |
max-norm (* max-extent max-extent) | |
max-color 255. | |
contrast .2] | |
(loop [z (complex) iteration 0] | |
(cond | |
(and (< (norm z) max-norm) (< iteration iterations)) | |
(recur (+ (* z z) c) (inc iteration)) | |
(< iteration iterations) | |
(let [v (div iteration iterations)] | |
(Color/FromArgb | |
(int (* max-color (- 1. (Math/Pow v .25)))) | |
0i | |
(int (* max-color (Math/Pow v contrast))))) | |
Color/Black)))) | |
;; whoa this kind of sucks. let and loop dont have macros that handle | |
;; the implicit do yet, and a built in forloop/dotimes macro is maybe not a | |
;; bad idea either | |
(defn render [^Int32 width ^Int32 height] | |
(let [bmp (Bitmap width height) | |
max-extent 2. | |
scale (* 2 (div max-extent (Math/Min width height)))] | |
(do | |
(loop [i 0i] | |
(let [y (* scale (- (div height 2i) i))] | |
(do | |
(loop [j 0i] | |
(do | |
(let [x (* scale (- j (div width 2i))) | |
c (mandelbrot-color (complex x y))] | |
(.SetPixel bmp j i c)) | |
(when (< j width) (recur (inc j))))) | |
(when (< i height) (recur (inc i)))))) | |
bmp))) | |
(let [bmp (render 500i 500i)] | |
(.Save bmp "/home/nasser/projects/jn/fs/out.png" ImageFormat/Png)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using jn; | |
using Jn; | |
using System; | |
using System.Drawing; | |
using System.Drawing.Imaging; | |
using System.Reflection; | |
using System.Runtime.InteropServices; | |
[assembly: System.Reflection.AssemblyVersion("0.0.0.0")] | |
public static class user | |
{ | |
[System.Runtime.InteropServices.StructLayout(LayoutKind.Auto)] | |
public struct complex | |
{ | |
public readonly double re; | |
public readonly double im; | |
public complex(double re, double im) | |
{ | |
this.re = re; | |
this.im = im; | |
} | |
} | |
static user() | |
{ | |
// Note: this type is marked as 'beforefieldinit'. | |
Journal.importAssembly(System.Reflection.Assembly.LoadFile("/lib/mono/gac/System.Drawing/4.0.0.0__b03f5f7f11d50a3a/System.Drawing.dll")); | |
core.use("System.Drawing"); | |
core.use("System.Drawing.Imaging"); | |
Bitmap bitmap = user.render(500, 500); | |
bitmap.Save("/home/nasser/projects/jn/fs/out.png", ImageFormat.Png); | |
} | |
public static double div(long a, long b) | |
{ | |
return (double)a / (double)b; | |
} | |
public static double div(int a, int b) | |
{ | |
return (double)a / (double)b; | |
} | |
public static double div(double a, double b) | |
{ | |
return a / b; | |
} | |
public static double div(double a, int b) | |
{ | |
return a / (double)b; | |
} | |
public static int @int(double x) | |
{ | |
return (int)x; | |
} | |
public static double clamp(double x, double min, double max) | |
{ | |
return (x >= min) ? ((max >= x) ? x : max) : min; | |
} | |
public static double norm(user.complex c) | |
{ | |
return c.re * c.re + c.im * c.im; | |
} | |
public static Color mandelbrot-color(user.complex c) | |
{ | |
long num = 1000L; | |
double num2 = 2.0; | |
double num3 = num2 * num2; | |
double num4 = 255.0; | |
double y = 0.2; | |
user.complex complex = default(user.complex); | |
long num5 = 0L; | |
while (core.and(user.norm(complex) < num3, num5 < num)) | |
{ | |
user.complex arg_66_0 = jn.core.add(jn.core.multiply(complex, complex), c); | |
num5 += 1L; | |
complex = arg_66_0; | |
} | |
Color arg_B3_0; | |
if (num5 < num) | |
{ | |
double x = user.div(num5, num); | |
arg_B3_0 = Color.FromArgb((int)(num4 * (1.0 - System.Math.Pow(x, 0.25))), 0, (int)(num4 * System.Math.Pow(x, y))); | |
} | |
else | |
{ | |
arg_B3_0 = Color.Black; | |
} | |
return arg_B3_0; | |
} | |
public static Bitmap render(int width, int height) | |
{ | |
Bitmap bitmap = new Bitmap(width, height); | |
double num = 2.0; | |
double num2 = jn.core.multiply(2L, num / (double)System.Math.Min(width, height)); | |
int num3 = 0; | |
while (true) | |
{ | |
double im = num2 * (user.div(height, 2) - (double)num3); | |
int num4 = 0; | |
while (true) | |
{ | |
double re = num2 * jn.core.-(num4, user.div(width, 2)); | |
Color color = user.mandelbrot-color(new user.complex(re, im)); | |
bitmap.SetPixel(num4, num3, color); | |
if (num4 >= width) | |
{ | |
break; | |
} | |
num4++; | |
} | |
if (num3 >= height) | |
{ | |
break; | |
} | |
num3++; | |
} | |
return bitmap; | |
} | |
} | |
public static class jn | |
{ | |
public static class core | |
{ | |
public static double -(double a, double b) | |
{ | |
return a - b; | |
} | |
public static double -(double a, int b) | |
{ | |
return a - (double)b; | |
} | |
public static double -(int a, double b) | |
{ | |
return (double)a - b; | |
} | |
public static double multiply(double x, int y) | |
{ | |
return x * (double)y; | |
} | |
public static double multiply(long x, double y) | |
{ | |
return (double)x * y; | |
} | |
public static user.complex add(user.complex x, user.complex y) | |
{ | |
return new user.complex(x.re + y.re, x.im + y.im); | |
} | |
public static user.complex multiply(user.complex x, user.complex y) | |
{ | |
return new user.complex(x.re * y.re - x.im * y.im, x.re * y.im + x.im * y.re); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment