[Shootout-list] Improved GHC Mandelbrot
Alson Kemp
Alson.Kemp at sloan.mit.edu
Sun Apr 23 22:56:34 UTC 2006
Some small mods to the GHC Mandelbrot code sped it up quite a bit.
Changes
* Added signatures
* handcoded 'magnitude z' because magnitude is slow
* calculate z' before evaluating |z|>limit to match C version
'fractal 400' now runs in about 1.2s instead of 40s
- Alson
--- CUT HERE ---
-- Fractal.hs mandlebrot example
-- dumps a *.ppm graphics file to stdout
-- compile: ghc -O2 -o fractal fractal.hs
-- run: fractal 600 >mandel.pbm
-- by Greg Buchholz
-- modified by Alson Kemp
import Complex
import System(getArgs)
import Char(chr)
import System.IO
limit :: Double
limit = 4.0
iter :: Int
iter = 50
main :: IO ()
main = do [arg] <- getArgs
let width = read arg
--AK:optional;prevent newline mangle on PC
hSetBinaryMode stdout True
putStr $ "P4\n" ++ (show width) ++ " " ++ (show width) ++ "\n"
putStr $ concatMap (makePBM 0 0) (chunk width (fractal (points
width width)))
points :: Int -> Int -> [Complex Double]
points width height = [(2.0*x/w - 1.5) :+ (2.0*y/h - 1) | y<-[0..h-1],
x<-[0..w-1]]
where w = fromIntegral width
h = fromIntegral height
fractal :: [Complex Double] -> [Int]
fractal pts = map (fractal' (0.0 :+ 0.0) iter) pts
--magnitude is sloooooowwwwww, so hand code abs^2
fractal' :: Complex Double -> Int -> Complex Double -> Int
fractal' z i c | (((realPart z')*(realPart z') + (imagPart z')*(imagPart
z')) > limit ) = 0
| (i == 0) = iter
| otherwise = fractal' z' (i-1) c
where z' = z*z+c
makePBM :: Int -> Int -> [Int] -> [Char]
makePBM i acc [] = (chr (acc * 2^(8-i))) : []
makePBM i acc (x:xs) | i==8 = (chr acc) : makePBM 0 0 (x:xs)
| otherwise = makePBM (i+1) n xs
where
n = if x==iter then (acc*2+1) else
(acc*2)
chunk :: Int -> [Int] -> [[Int]]
chunk width [] = []
chunk width c = (fst split) : chunk width (snd split)
where split = splitAt width c
More information about the Shootout-list
mailing list