Skip to content

Instantly share code, notes, and snippets.

@jramb
Last active October 3, 2015 04:48
Show Gist options
  • Save jramb/2394146 to your computer and use it in GitHub Desktop.
Save jramb/2394146 to your computer and use it in GitHub Desktop.
Mandelbrot in different languages
all: mandelrs playc playmandel mandel.js
mandelrs: mandelrs.rs
playc: playc.c
%: %.c
gcc $^ -O2 -o $@
playmandel: playmandel.hs
ghc $^ -O3 -o $@
%: %.rs
rustc $^ -O
%.js: %.ls
lsc -c $^
.PHONY: all
(ns nail.core
(:import
[java.io BufferedReader ByteArrayOutputStream InputStreamReader
OutputStreamWriter PrintStream PrintWriter]
clojure.lang.LineNumberingPushbackReader
[com.martiansoftware.nailgun NGContext NGServer])
(:gen-class) ;; needed for the -main below
)
;;;;;;;;;;;;
(defn real-part [c]
(get c 0))
(defn imag-part [c]
(get c 1))
;; Mandelbrot set
;; check if c is still in the set (|c| <= 2)
;; is this version faster
(defn unbound? [c]
(let [r (real-part c)
i (imag-part c)]
(> (+ (* r r) (* i i)) 4)))
;; (x + yi)(u + vi) = (xu – yv) + (xv + yu)i.
(defn cplx-mul [[x y] [u v]]
[(- (* x u) (* y v)) (+ (* x v) (* y u))])
;;(cplx-mul [3 4] [-2 9]) ;-> [-42 19]
(defn cplx-add [[r1 i1] [r2 i2]]
[(+ r1 r2) (+ i1 i2)])
(defn make-rectangular [r i]
[r i])
;; test the depth of a complex point (Mandelbrot set)
;;
(defn mandel-test [c max]
(loop [zi c
i 1]
(cond
(> i max) 0
(unbound? zi) i
:else (recur (cplx-add (cplx-mul zi zi) c) (+ i 1)))))
;;(mandel-test [0.5 0.5] 1000) ;-> 5
;; Perform the whole set
(defn mandel [width height max]
(let [xs (range -2. 1 (/ 3. width))
ys (range -1. 1 (/ 2. height))]
(dorun
(for [y ys]
(println
(apply str
(for [x xs]
(let [c (make-rectangular x y)]
(if (> (mandel-test c max) 0) "-" "*"))
)))))))
;;;;;;;;;;;;
(gen-class :name nailgun.Mandel
:prefix "Mandel-"
:methods [#^{:static true}
[nailMain [com.martiansoftware.nailgun.NGContext] void]]
:main false)
(defn Mandel-nailMain
[#^NGContext context]
(let [ctx (bean context)]
(binding [*in* (-> context
.in
InputStreamReader.
LineNumberingPushbackReader.)
*out* (-> context .out OutputStreamWriter.)
*err* (-> context .err PrintWriter.)]
;;(println "Hej: " (bean context))
(println "Args: " (seq (:args ctx)))
(println "Command: " (:command ctx))
(println "Env (only 2):" (take 2 (:env ctx)))
(println "Inet addr: " (:inetAddress ctx))
(println "Current working directory: " (:workingDirectory ctx))
(apply mandel (map #(Integer. %) (:args ctx)))
(.flush *out*)
(.flush *err*))))
(defn -main [& args]
(println "Starting NGServer!")
(.start (Thread. (NGServer.))))
#!/usr/bin/env groovy
// 2014, hacked together with NO good knowledge of Groovy, really
//println "Hello from the shebang line"
int mandelzahl(double cx, double cy, int max) {
//double zx, zy, x2, y2;
double zx = cx;
double zy = cy;
i = 1;
while (++i <= max && (x2 = zx * zx) + (y2 = zy * zy) < 4.0) {
zy = zx * zy * 2.0 + cy;
zx = x2 - y2 + cx;
}
return (i > max)? -1 : i
}
assert 6 == mandelzahl(0.5, 0.5, 100);
void mandel(int w, int h, int max) {
double step = 2.0 / h, step1 = 3.0 / w
for (y = -1.0; y <= 1.0; y += step) {
sb = "";
for (x = -2.0; x <= 1.0; x += step1) {
sb += mandelzahl(x, y, max) > 0 ? '-' : '*';
}
println sb;
}
}
mandel(140,50, 1e5 as int)
// Generated by LiveScript 1.2.0
/* 2014 by JRamb */
(function(){
var print, mandelzahl, mandel;
if (typeof Packages === "object") {
print = function(it){
return java.lang.System.out.println(it);
};
} else {
print || (print = console.log);
}
mandelzahl = function(cx, cy, max){
/* z -> z^2 + c */
var zx, zy, i, x2, y2;
zx = cx;
zy = cy;
i = 1;
while (++i <= max && (x2 = zx * zx) + (y2 = zy * zy) < 4) {
zy = zx * zy * 2 + cy;
zx = x2 - y2 + cx;
}
if (i > max) {
return -1;
} else {
return i;
}
};
mandel = function(w, h, max){
var i$, step$, y, sb, j$, step1$, x, mz;
for (i$ = -1.0, step$ = 2.0 / h; step$ < 0 ? i$ >= 1.0 : i$ <= 1.0; i$ += step$) {
y = i$;
sb = "";
for (j$ = -2.0, step1$ = 3.0 / w; step1$ < 0 ? j$ >= 1.0 : j$ <= 1.0; j$ += step1$) {
x = j$;
mz = mandelzahl(x, y, max);
sb += mz > 0 ? '-' : '*';
}
print(sb);
}
};
mandel(140, 50, 100000);
}).call(this);
# Mandelbrot in LiveScript
/* 2014 by JRamb */
if typeof Packages=="object" # running in Rhino?
print = -> java.lang.System.out.println it
else
print||=console.log
mandelzahl=(cx, cy, max) ->
/* z -> z^2 + c */
#zx=zy=0.0
zx=cx; zy=cy;
i=1
while ++i<=max and ( (x2=zx*zx) + (y2=zy*zy) ) < 4
zy = zx*zy*2 + cy
zx = x2 - y2 + cx
## The following is not really slower!
#while ++i<=max and (zx*zx+zy*zy)<4
# #THIS is slower: [zx, zy] = [zx*zx - zy*zy + cx, zx*zy*2 + cy]
# tx = zx*zx - zy*zy + cx
# zy = zx*zy*2 + cy
# zx = tx
if i>max then -1 else i
#a + ib * c + id
#ac-bd , (a+b)(c+d)-ac-bd.
#zx * zx - zy*zy + cx, (zx+zy)*(zx+zy) - zx*zx - zy*zy + cy
mandel = (w, h, max) !->
for y from -1.0 to 1.0 by 2.0/h
sb = ""
for x from -2.0 to 1.0 by 3.0/w
mz = mandelzahl(x,y,max)
sb += if mz>0 then \- else \*
print sb
mandel 140, 50, 1e5
#
# Mandelbrot in CoffeeScript
#
print=console.log
mandelzahl=(cx, cy, max) ->
#// z -> z^2 + c
zx=0.0
zy=0.0
i=0
while(++i<=max and (zx*zx+zy*zy)<4)
#slower [zx, zy] = [zx*zx - zy*zy + cx, zx*zy*2 + cy]
tx = zx * zx - zy * zy + cx
zy = zx * zy * 2 + cy
zx = tx
if i>max then -1 else i
mandel = (w, h, max) ->
y = -1.0
for y in [-1.0..1.0] by 2.0/h
sb = ""
for x in [-2.0..1.0] by 3.0/w
mz = mandelzahl x,y,max
if mz>0
sb = sb + '-'
else
sb = sb + '*'
print sb
mandel 140, 50, 10000
// Generated by CoffeeScript 1.6.3
(function() {
var mandel, mandelzahl, print;
print = console.log;
mandelzahl = function(cx, cy, max) {
var i, tx, zx, zy;
zx = 0.0;
zy = 0.0;
i = 0;
while (++i <= max && (zx * zx + zy * zy) < 4) {
tx = zx * zx - zy * zy + cx;
zy = zx * zy * 2 + cy;
zx = tx;
}
if (i > max) {
return -1;
} else {
return i;
}
};
mandel = function(w, h, max) {
var mz, sb, x, y, _i, _j, _ref, _ref1, _results;
y = -1.0;
_results = [];
for (y = _i = -1.0, _ref = 2.0 / h; _ref > 0 ? _i <= 1.0 : _i >= 1.0; y = _i += _ref) {
sb = "";
for (x = _j = -2.0, _ref1 = 3.0 / w; _ref1 > 0 ? _j <= 1.0 : _j >= 1.0; x = _j += _ref1) {
mz = mandelzahl(x, y, max);
if (mz > 0) {
sb = sb + '-';
} else {
sb = sb + '*';
}
}
_results.push(print(sb));
}
return _results;
};
mandel(140, 50, 10000);
}).call(this);
/**
* Mandebrot set in Dart
* 2013 jramb
*/
import 'dart:io' as io; // commandline uses "io", web uses "html"
int mandelzahl(double cx, double cy, int max) {
num zx=0.0, zy=0.0;
int i=0;
while(i<=max && (zx*zx+zy*zy)<4) {
// z -> z^2 +c
num tx = zx*zx - zy*zy + cx;
zy = zx*zy*2 + cy;
zx = tx;
i++;
}
return i>max?-1:i;
}
void mandel(int w, int h, int max) {
double x, y;
for(y=1.0 ; y>=-1.0 ; y-=2.0/h) {
StringBuffer sb = new StringBuffer();
for(x=-2.0 ; x<1.0 ; x+=3.0/w) {
var mz = mandelzahl(x,y,max);
if (mz>0) {
sb.write('-');//stdout.write(' ');
} else {
sb.write('*');//stdout.write('*');
}
}
print(sb);//stdout.writeln();
}
}
typedef void callback(); // or "Functione exec()" in the parameter list
void time(callback exec) {
int timeStart = new DateTime.now().millisecondsSinceEpoch;
exec();
int timeEnd = new DateTime.now().millisecondsSinceEpoch;
print("Execution time: ${(timeEnd-timeStart)/1000.0}");
}
void main(List<String> argv) {
//List<String> argv = (new io.Options()).arguments;
List<int> argvi;
if (argv.length==0) {
argvi = [140, 50, 100000];
} else {
argvi = argv.map((e) => int.parse(e)).toList();
}
print("Mandel: $argvi");
time(()=>
mandel(argvi[0],argvi[1],argvi[2]));
}
// Mandel in Rust
// 2014-06-28 by JRamb
// compile with
// rustc -o mandelrs.rs
use std::os;
type Fl = f32; // f32 is slightly faster than f64
//fn debugvar(s: String, v:int) {
//// extern crate debug;
//println!("Type of {} is {} [{:?}]", s, v, v);
//}
fn mandelzahl(cx: Fl, cy: Fl, max: uint) -> int {
let mut zx = cx; // first iteration, normally starts with (0,0)
let mut zy = cy;
let mut i = 1u;
let mut x2 = zx * zx;
let mut y2 = zy * zy;
while i<max && ( x2 + y2 )<4.0 {
zy = zx*zy*2. + cy;
zx = x2 - y2 + cx;
i += 1;
x2 = zx * zx;
y2 = zy * zy;
}
if i>=max { -1 } else { i as int }
}
//#[allow(unused_variable)]
fn mandel(w: uint, h: uint, max: uint) {
let step_h = 2.0 / h as Fl;
let step_w = 3.0 / w as Fl;
for _h in range(0, h) {
let y = -1.0+((_h as Fl)*step_h);
//let line = ""; //std::string::String.new();
for _w in range(0, w) {
let x = -2.0+((_w as Fl)*step_w);
let mz = mandelzahl(x,y,max);
print!("{}", if mz>0 { '-' } else { '*' });
//line.push_char(if mz>0 { '-' } else { '*' });
}
println!("");
//println!("{}", line);
}
}
fn main() {
let args = os::args();
let args = args.as_slice();
let mut w = 140u;
let mut h = 50u;
let mut max = 100000 as uint;
if args.len()>=4u {
w = from_str::<uint>(args[1].as_slice()).unwrap();
h = from_str::<uint>(args[2].as_slice()).unwrap();
max = from_str::<uint>(args[3].as_slice()).unwrap();
assert!(w>0 && h>0 && max>0);
}
println!("Mandel {} x {}, max={}", w, h, max);
mandel(w,h,max);
println!("done");
}
(ns mandelbrot)
(set! *warn-on-reflection* true)
;; Mandelbrot set
;; check if c is outside the set (|c| > 2)
(defn unbound? [[^Double r ^Double i]]
(> (+ (* r r) (* i i)) 4))
;; (x + yi)(u + vi) = (xu – yv) + (xv + yu)i.
(defn cplx-mul [[^Double x ^Double y] [^Double u ^Double v]]
[(- (* x u) (* y v)) (+ (* x v) (* y u))])
;;(cplx-mul [3 4] [-2 9]) ;-> [-42 19]
(defn cplx-add [[^Double r1 ^Double i1] [^Double r2 ^Double i2]]
[(+ r1 r2) (+ i1 i2)])
;; z^2 + c, slightly faster than (cplx-add (cplx-mul z z) c)
(defn iter [[^Double zr ^Double zi] [^Double cr ^Double ci]]
[(+ (* zr zr) (- (* zi zi)) cr)
(+ (* zr zi 2.0) ci)])
;; test the depth of a complex point (Mandelbrot set)
;;
(defn mandel-test [c max]
(loop [zi [0.0 0.0] ;; c
i 1]
(cond
(> i max) 0
(unbound? zi) i
:else (recur (iter zi c) #_(cplx-add (cplx-mul zi zi) c) (inc i)))))
;;(mandel-test [0.5 0.5] 1000) ;-> 5
;; Perform the whole set
(defn mandel [width height max]
(let [xs (range -2. 1 (/ 3. width))
ys (range -1. 1 (/ 2. height))]
(dorun
(for [y ys]
(println
(apply str
(for [x xs]
(let [c [x y]]
(if (> (mandel-test c max) 0) "-" "*"))
)))))))
(time (mandelbrot/mandel 140 50 10000))
;;;# !/usr/bin/env gosh
;; compile:
;; gsc -link play.scm && gcc -L$GAMBIT_DIR/lib -I$GAMBIT_DIR/include play.c play_.c -lgambc -lm -ldl -lutil -o play
;; call with:
;; ./play 70 30 10000
;; Tested with Stalin, gauche (gosh), guile, gambit
;; compiled gambit was as fast as gosh, Stalin beat them all (times 10 faster than gosh)
;; guile was unbearable slow
;; The dart version was still a bit faster, suck...
(define (dec n) (- n 1))
(define (inc n) (+ n 1))
(define (range l h . step)
(let ((step (if (null? step) 1 (car step))))
(let loop ((res '())
(h (- h step)))
(if (< h l)
res
(loop (cons h res) (- h step))))))
;; same?
(define (reverse1 ls)
(define (rv ls acc)
(if (null? ls)
acc
(rv (cdr ls) (cons (car ls) acc))))
(rv ls '()))
(define (reverse2 ls)
(let rv ((ls ls)
(acc '()))
(if (null? ls)
acc
(rv (cdr ls) (cons (car ls) acc)))))
'(define (take n lst)
(let loop ((res '())
(n n)
(lst lst))
(if (<= n 0)
(reverse res)
(loop (cons (car lst) res) (dec n) (cdr lst)))))
(define (drop n lst)
(if (< n 1)
lst
(drop (dec n) (cdr lst))))
(define (nth lst n)
(car (drop n lst)))
;; Mandelbrot set
; Stalin does not have complex numbers...
(define real-part car)
(define imag-part cdr)
(define c* *)
(define (c* c1 c2)
(let ((r1 (real-part c1))
(i1 (imag-part c1))
(r2 (real-part c2))
(i2 (imag-part c2)))
(cons (- (* r1 r2) (* i1 i2))
(+ (* i1 r2) (* r1 i2)))))
(define make-rectangular cons)
'(define c+ +)
(define (c+ c1 c2)
(cons (+ (real-part c1) (real-part c2))
(+ (imag-part c1) (imag-part c2))))
;; check if c is still in the set (|c| <= 2)
;; is this version faster
(define (unbound? c)
(let ((r (real-part c))
(i (imag-part c)))
(> (+ (* r r) (* i i)) 4)))
;; same, slower (faster in gosh) but more natural?
'(define (unbound? c)
(> (magnitude c) 2))
;; test the depth of a complex point (Mandelbrot set)
'(define (mandel-test c max)
(let loop ((zi c)
(i 1))
(cond ((> i max) max)
((unbound? zi) i)
(else (loop (c+ (c* zi zi) c) (+ i 1))))))
(define (mandel-test c max)
(let ((cx (car c))
(cy (cdr c)))
(let loop ((zx 0)
(zy 0)
(i 0))
(let ((zx2 (* zx zx))
(zy2 (* zy zy)))
(if (and (<= i max) (< (+ zx2 zy2) 4))
(loop
(+ (- zx2 zy2) cx)
(+ (* zx zy 2) cy)
(+ i 1))
i)))))
;; Perform the whole set
(define (mandel width height max)
(let ((xs (range -2. 1 (/ 3. width)))
(ys (range -1. 1 (/ 2. height))))
(for-each
(lambda (y)
(for-each
(lambda (x)
(let ((c (make-rectangular x y)))
(display (if (< (mandel-test c max) max) "-" "*"))
;(display (mandel-test c max))
))
xs)
(newline))
ys)))
'(define (time)
(java.lang.System:currentTimeMillis))
;(display (format "Hello, ~a\n" *program-name*))
;; for Gambit
'(define (main args)
(let ((width (cadr args))
(height (caddr args))
(max (cadddr args)))
(mandel (string->number width)
(string->number height)
(string->number max))))
(mandel 120 40 10000)
;; (mandel 70 30 10000)
;; (main "70" "25" "100")
(newline)
/* C-Programm zur Erzeugung von Bildern aus der */
/* Mandelbrotmenge */
/* 5/91 von O. Linnemann */
/* minimal changes by jramb */
/* compiled with: gcc playc.c -O2 -o playc */
#include <math.h>
#include <stdio.h>
#include <time.h>
//#include <CONSOLE.H> // enthält STDIO.H
//#include "GRAFWINDOW.H"
//#define CLRSCRN() { cgotoxy(1,1,stdout); ccleos(stdout); }
#define SQUARE(x) ((x)*(x))
typedef double REAL; /* zur Berechnung verwendeter Typ */
REAL Realmin, Imagmin, Breite, Hoehe;
int Bx,By,Tiefe;
erz_bild()
{
int x,y,zaehler;
REAL z,zi,c,ci,temp;
//no improvement//REAL z2,zi2;
putchar('\n');
for(y=0;y<By;++y)
{
for(x=0;x<Bx;++x)
{
//z=0; zi=0; zaehler=0;
z=c; zi=ci; zaehler=1;
c=Realmin + x*Breite/Bx; ci=Imagmin + y*Hoehe/By;
//z2=SQUARE(z); zi2=SQUARE(zi);
do {
temp=SQUARE(z)-SQUARE(zi)+c;
//temp=z2-zi2+c;
zi=2*z*zi + ci;
z=temp;
//z2=SQUARE(z); zi2=SQUARE(zi);
//} while((z2+zi2)<4.0 && ++zaehler<Tiefe);
} while((SQUARE(z)+SQUARE(zi))<4 && ++zaehler<Tiefe);
if(zaehler==Tiefe)
{ putchar('*'); }
else
{ putchar('-'); }
}
putchar('\n');
}
}
eingabe()
{
//CLRSCRN();
#ifdef _DO_NOT
printf("\t\tProgramm zur Erzeugung von Bildern\n");
printf("\t\t aus der Mandelbrotmenge\n");
printf("\t\t 5/90 von O. Linnemann\n\n");
printf("Geben Sie die Koordinaten des linken oberen Eckpunktes\n");
printf("und die Seitenlänge des zu berechnenden Bereiches ein:\n");
printf("REALTEIL:\t"); scanf("%lf",&Realmin);
printf("IMAGINÄRTEIL:\t"); scanf("%lf",&Imagmin);
printf("SEITENLÄNGE:\t"); scanf("%lf",&Breite);
putchar('\n'); printf("SUCHTIEFE:\t"); scanf("%d",&Tiefe);
printf("\n");
printf("Geben Sie die Breite und die Höhe des Bildausschnittes an:\n");
printf("BREITE:\t"); scanf("%d",&Bx);
printf("HÖHE:\t"); scanf("%d",&By);
#endif
Realmin = -2.0;
Imagmin = -1.0;
Breite = 3.0;
Hoehe = 2.0;
Bx = 140;
By = 50;
Tiefe = 100000;
}
main()
{
clock_t t1, t2;
eingabe();
// OpenGrafWindow();
t1 = clock();
erz_bild();
t2 = clock();
printf("\n%lf seconds\n", (t2-t1) / (double)CLOCKS_PER_SEC );
// waitUntilKlick();
// DisposeGrafWindow();
}
-- This very impressive Haskell program by jramb
-- this is the Frege version. Also see Haskell version
-------------------------------------
{-import System.Environment -- (getArgs)-}
module mandel.Main where
type Complex = (Double,Double)
complexMul :: Complex -> Complex -> Complex
complexMul (r1,i1) (r2,i2)
= ((r1*r2)-(i1*i2),i1*r2+r1*i2)
-- beware of the - ^
complexSqr :: Complex -> Complex
complexSqr c = complexMul c c
{-complexSqr (r,i) = (r*r-i*i,2*i*r) --faster(?) but boring-}
complexAdd :: Complex -> Complex -> Complex
complexAdd (r1,i1) (r2,i2) = (r1+r2,i1+i2)
largerThan2 :: Complex -> Bool
largerThan2 (r,i) = (r*r + i*i)>4
-- Pc : z |-> z^2 + c
mandelseq :: Complex -> Complex -> [Complex]
mandelseq c z
| largerThan2 z = []
| otherwise = let z' = p c z
in z' : mandelseq c z'
where p c z = complexSqr z `complexAdd` c
isMandelGen :: Int -> Complex -> Int
isMandelGen limit c = length . take limit $ mandelseq c (0,0)
-- lenght ( take limit ( mandelseq c (0,0)))
ranger :: Double -> Double -> Int -> [Double]
{-ranger s e steps = init [s,(s+((e-s)/fromIntegral steps))..e]-}
ranger s e steps =
[s + fromIntegral x*w | x <- [0,1..pred steps]]
where w = (e-s)/fromIntegral steps
concatWithCR :: String -> String -> String
concatWithCR x acc = x ++ "\n" ++ acc
calcMandel :: Int -> Int -> Int -> String
calcMandel width height mx =
foldr1 concatWithCR $ --(\x acc -> x++"\n"++acc) $
{-map calcRow $ ranger (-1) 1 height-}
[ calcRow x | x <- ranger (-1) 1 height ]
where calcRow :: Double -> String
mandelTest c = (isMandelGen mx c) >= mx
-- Frege has this: packed :: [Char] -> String
calcRow y = packed [ calcCell y x | x <- ranger (-2) 1 width ]
{-calcRow y = packed $ map (calcCell y) $ ranger (-2) 1 width-}
calcCell :: Double -> Double -> Char
calcCell y x = if mandelTest (x,y) then '*' else '-'
read :: String -> Int
read s = s.atoi
-- MAIN
main args = do
{-args <- getArgs-}
let (w:h:mx:_) = args
w' = read w::Int
h' = read h::Int
mx' = read mx::Int in do
putStrLn $ show (w', h', mx') --args
let output = calcMandel w' h' mx' in --70 30 1000
putStrLn $ output
#!/usr/bin/runghc
-- This very impressive Haskell program by jramb/2013-03-14 (pi-day)
-- Continued 2015
-- Run uncompiled (much slower):
-- runghc playmandel.hs 140 50 10000
-- Compile: ghc -o playmandel playmandel.hs -O2
-- time ./playmandel 140 50 10000
-- rm playmandel.o && ghc -o playmandel playmandel.hs -O2 && time ./playmandel 140 50 10000
-- Profile: ghc -prof -auto-all -o playmandel playmandel.hs
-- time ./playmandel 140 50 10000 +RTS -p
--
-- TODO Haskell: check out Data.Complex?
-------------------------------------
{-# OPTIONS_GHC -Wall #-}
import System.Environment -- (getArgs)
-- constructor for Complex: r :+ i
infixr 5 :+
data Complex = Float :+ Float
{-deriving (Show)-}
{-type Complex = (Float,Float)-}
instance Show Complex where
show (r :+ i) = show $ show r++" :+ "++show i
{-instance (Num a,Num b) => (a :+ b) where-}
{-(r1 :+ i1) + (r2 :+ i2) = (r1+r2) :+ (i1+i2)-}
{-(r1 :+ i1) * (r2 :+ i2) = (r1*r2 -(i1*i2)) :+ (i1*r2+r1*i2)-}
{-Pair (a,b) + Pair (c,d) = Pair (a+c,b+d)-}
{-Pair (a,b) * Pair (c,d) = Pair (a*c,b*d)-}
{-Pair (a,b) - Pair (c,d) = Pair (a-c,b-d)-}
{-abs (Pair (a,b)) = Pair (abs a, abs b) -}
{-signum (Pair (a,b)) = Pair (signum a, signum b) -}
{-fromInteger i = Pair (fromInteger i, fromInteger i)-}
complexMul :: Complex -> Complex -> Complex
complexMul (r1 :+ i1) (r2 :+ i2)
= (r1*r2 -(i1*i2)) :+ (i1*r2+r1*i2)
complexSqr :: Complex -> Complex
complexSqr c = complexMul c c
complexAdd :: Complex -> Complex -> Complex
(r1 :+ i1) `complexAdd` (r2 :+ i2) = (r1+r2) :+ (i1+i2)
largerThan2 :: Complex -> Bool
largerThan2 (r :+ i) = (r*r + i*i) > 4
-- Pc : z |-> z^2 + c
mandelseq :: Complex -> Complex -> [Complex]
mandelseq c z
| largerThan2 z = []
| otherwise = let z' = complexSqr z `complexAdd` c
in z' : mandelseq c z'
lengthMandelChain :: Int -> Complex -> Int
lengthMandelChain limit c = length . take limit $ mandelseq c (0 :+ 0)
-- lenght ( take limit ( mandelseq c (0,0)))
ranger :: Float -> Float -> Int -> [Float]
{-ranger s e steps = init [s,(s+((e-s)/fromIntegral steps))..e]-}
ranger s e steps =
[s + fromIntegral x*w | x <- [0,1..pred steps]]
where w = (e-s)/fromIntegral steps
concatWithCR :: String -> String -> String
concatWithCR x acc = x ++ "\n" ++ acc
calcMandel :: Int -> Int -> Int -> String
calcMandel width height mx =
foldr1 concatWithCR $ --(\x acc -> x++"\n"++acc) $
( map calcRow $ ranger (-1) 1 height )
{-[ calcRow x | x <- ranger (-1) 1 height ]-}
where calcRow :: Float -> String
mandelTest c = (lengthMandelChain mx c) >= mx
calcRow y = map (calcCell y) $ ranger (-2) 1 width
calcCell :: Float -> Float -> Char
calcCell y x = if mandelTest (x :+ y) then '*' else '-'
-- MAIN
main :: IO ()
main = do
args <- getArgs
{-putStrLn $ show (0.2 :+ (-2.1))-}
let (w:h:mx:_) = args
w' = read w::Int
h' = read h::Int
mx' = read mx::Int in do
putStrLn $ show (w', h', mx') --args
let output = calcMandel w' h' mx' in --70 30 1000
putStrLn $ output
@jramb
Copy link
Author

jramb commented Aug 27, 2014

Funny thing, mandel.groovy is much slower (104 s) than rhino mandel.js (10 s), i.e. the JavaScript-emulation in Java is faster than Java. Would like to know the reason for this... BTW: node mandel.js = 1 s

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment