I saw an interesting thread on [comp.lang.functional] ( http://groups.google.com/group/comp.lang.functional/browse_frm/thread/99b8230c078d9b44) yesterday comparing the performance of a couple languages generating the mandelbrot fractal, and I thought it'd be interesting to see how felix compared. Turns out it does incredibly well. The times are in seconds when run on my laptop:
| c++ | 1.92488 | | felix | 1.96676 | | ocamlopt | 5.81599 | | scala | 6.555 | | clojure | 12.7324 | | haskell | 96.2044 | Here's the code. I'll see about getting this in our speed tests. Unfortunately, the felix test only runs on a posix system that has `gettimeofday`. I'll make it more generic soon. mandelbrot.cc: {{{ :::cpp #include <iostream> #include <time.h> static const int runs = 1; static const int max_iterations = 99888; long iterate(double ci, double cr) { long count = 1; double zr = 0.0; double zi = 0.0; double zr2 = 0.0; double zi2 = 0.0; while((count <= max_iterations) && (zr2 + zi2 < 4.0)) { zi = zr * zi * 2.0 + ci; zr = zr2 - zi2 + cr; ++count; zr2 = zr * zr; zi2 = zi * zi; } if(count > max_iterations) { return 0; } else { return count; } } void mandelbrot(long n) { long i; for(int y = -39; y <= 38; ++y) { if(n == 1) { std::cout << '\n'; } for(int x = -39; x <= 38; ++x) { i = iterate(x / 40.0, y / 40.0 -0.5); if(n == 1) { if(i == 0) std::cout << '*'; else std::cout << ' '; } } } } int main() { clock_t start, end; double cpu_time_used; start = clock(); for(long iter = 1; iter<= runs; ++iter) { mandelbrot(iter); } end = clock(); cpu_time_used = ((double) (end - start)) / CLOCKS_PER_SEC; std::cout.precision(6); std::cout << cpu_time_used << " seconds" << std::endl; return 0; } }}} mandelbrot.flx: {{{ :::felix module sys::time_h { open C_hack; header "#include <sys/time.h>"; type time_t = "time_t"; type suseconds_t = "suseconds_t"; fun _ctor_float: time_t -> float = "static_cast<float>($1)"; fun _ctor_float: suseconds_t -> float = "static_cast<float>($1)"; fun _ctor_double: time_t -> double = "static_cast<double>($1)"; fun _ctor_double: suseconds_t -> double = "static_cast<double>($1)"; cstruct timeval { tv_sec: time_t; tv_usec: suseconds_t; } proc gettimeofday: ptr[timeval] = "gettimeofday($1, NULL);"; gen get_time () = { var tv:timeval; gettimeofday(addr tv); return _ctor_double(tv.tv_sec) + (_ctor_double(tv.tv_usec) / 1.0e6); } } val runs = 1; val max_iterations = 99888; fun iterate (ci:double, cr:double) = { val bailout = 4.0; fun loop_ (zi:double, zr:double, i:int) => if i <= max_iterations then let ?zr2 = zr * zr in let ?zi2 = zi * zi in if zi2 + zr2 <= bailout then loop_ (zr * zi * 2.0 + ci, zr2 - zi2 + cr, i + 1) else i endif else 0 endif ; return loop_ (0.0, 0.0, 1); } proc mandelbrot (n:int) { var y:int; forall y in -39 upto 38 do if n == 1 do endl; done; var x:int; forall x in -39 upto 38 do val i = iterate (double x / 40.0, double y / 40.0 - 0.5); if n == 1 do print (if 0 == i then "*" else " " endif); done; done; done; } var start_time = sys::time_h::get_time (); var iter:int; forall iter in 1 upto runs do mandelbrot iter; done; endl; println$ (sys::time_h::get_time ()) - start_time; }}} mandelbrot.ml: {{{ :::ocaml let runs = 1 let max_iterations = 99888 let iterate ci cr = let bailout = 4.0 in let rec loop zi zr i = if i <= max_iterations then let zr2 = zr *. zr and zi2 = zi *. zi in if zi2 +. zr2 <= bailout then loop (zr *. zi *. 2.0 +. ci) (zr2 -. zi2 +. cr) (i + 1) else i else 0 in loop 0.0 0.0 1 let mandelbrot n = for y = -39 to 38 do if 1 = n then print_endline ""; for x = -39 to 38 do let i = iterate (float x /. 40.0) (float y /. 40.0 -. 0.5) in if 1 = n then print_string ( if 0 = i then "*" else " " ); done done;; let start_time = Unix.gettimeofday () in for iter = 1 to runs do mandelbrot iter done; print_endline ""; print_float ( Unix.gettimeofday () -. start_time ); print_endline ""; }}} mandelbrot.scala: {{{ :::scala import java.lang.System object Mandelbrot { val max_iterations = 99888 def iterate(ci:Double, cr:Double) = { val bailout = 4.0 def loop(zi:Double, zr:Double, i:Int):Int = if (i <= max_iterations) { val zr2 = zr * zr val zi2 = zi * zi if (zi2 + zr2 <= bailout) { loop(zr * zi * 2.0 + ci, zr2 - zi2 + cr, i + 1) } else { i } } else { 0 } loop(0.0, 0.0, 1) } def main(args:Array[String]) { val time = java.lang.System.currentTimeMillis() for (y <- -39 until 39) { println() for (x <- -39 until 39) { val i = iterate((x:Double) / 40.0, (y:Double) / 40.0 - 0.5) print (if (i == 0) "*" else " ") } } println(java.lang.System.currentTimeMillis() - time) } } }}} mandelbrot.clj: {{{ :::clojure (def runs 1) (def max_iterations 99888) (defn iter [ci cr] (let [max_iter (int max_iterations) ci (double ci) cr (double cr)] (loop [zi (double ci) zr (double cr) i (int 1)] (if (<= i max_iter) (let [zr2 (* zr zr) zi2 (* zi zi)] (if (<= (+ zr2 zi2) (double 4.0)) (recur (+ (* (* zr zi) (double 2.0)) ci) (+ (- zr2 zi2) cr) (inc i)) i)) 0)))) (defn mand [n] (doseq [y (range -39 39)] (when (= 1 n) (print "\n")) (doseq [x (range -39 39)] (let [i (iter (/ x 40.0) (- (/ y 40.0) 0.5))] (when (= 1 n) (print (if (= 0 i) "*" " "))))))) (defn time-mand [] (time (doseq [i (range 1 (inc runs))] (mand i)))) (time-mand) }}} mandelbrot.hs: {{{ :::haskell module Main where import System.Time runs :: Int runs = 1 max_iterations :: Int max_iterations = 99888 iterate :: Double -> Double -> Int iterate ci cr = let bailout = 4.0 loop zi zr i = if i > max_iterations then 0 else let temp = zr * zi zr2 = zr * zr zi2 = zi * zi in if zi2 + zr2 > bailout then i else loop (temp + temp + ci) (zr2 - zi2 + cr) (i + 1) in loop 0.0 0.0 1 mandelbrot n = do let y = [-39..38] x = [-39..38] iter y x = do let res = Main.iterate ((fromIntegral x) / 40.0) ((fromIntegral y) / 40.0 - 0.5) if n == 1 then if res == 0 then putChar '*' else putChar ' ' else return () inner y = do mapM_ (iter y) x if n == 1 then putChar '\n' else return () outer = mapM_ (\i -> inner i) y outer main = do let iter = [1..runs] startTime <- getClockTime mapM_ mandelbrot iter endTime <- getClockTime let diff = show (diffClockTimes endTime startTime) putStrLn $ "Time: " ++ diff }}} ------------------------------------------------------------------------------ Open Source Business Conference (OSBC), March 24-25, 2009, San Francisco, CA -OSBC tackles the biggest issue in open source: Open Sourcing the Enterprise -Strategies to boost innovation and cut costs with open source participation -Receive a $600 discount off the registration fee with the source code: SFAD http://p.sf.net/sfu/XcvMzF8H _______________________________________________ Felix-language mailing list Felix-language@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/felix-language