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

Reply via email to