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
[email protected]
https://lists.sourceforge.net/lists/listinfo/felix-language