-- | -- Module : Mandelbrot -- Copyright : (c) Philipps Universitaet Marburg 2009-2010 -- License : BSD-style (see the file LICENSE) -- -- Maintainer : eden@mathematik.uni-marburg.de -- Stability : beta -- Portability : not portable -- -- The following Haskell module implements Mandelbrot fractals with Eden. -- -- Depends on the Eden Compiler. -- -- Eden Project -------------------------------------------------------------------------------- -- -- Mandelbrot fractal computation -- -- Arguments: 1. Example-coordinates (0 or 1) -- 2. number of pixels per image row -- 3. Skeleton selection (0=farm (unshuffle), -- 1=farm (splitIntoN), -- 2=Workpool (erroneous!) -- -- Output: PPM-Format to Stdout, only if 5th argument is "-out" -- otherwise output is suppressed, return value: "Done" -- -------------------------------------------------------------------------------- import System.Environment import Control.Seq import Control.Parallel (pseq) import Control.Parallel.Eden import Data.Complex import Data.List import ParMap usage = "Mandelbrot fractal computation\n" ++ " Arguments: 1. Example-coordinates (0 or 1)\n" ++ " 2. number of pixels per image row\n" ++ " 3. Skeleton selection (incomplete!)\n" ++ "\n" ++ " Output: PPM-Format to Stdout, only if 4th argument is \"-out\"\n" ++ " otherwise output is suppressed, return value: \"Done\"\n" -- Parallel -------------------------------------------------------------------- -- instance NFData a => NFData (Complex a) instance (RealFloat a, Trans a) => Trans (Complex a) -- Main ------------------------------------------------------------------------ main = do args <- getArgs if length args < 3 then putStrLn $ "Arguments missing...\n" ++ usage else do let (ul, lr) = examples!!(read (args!!0)) let dimx = read (args!!1) let np = noPe let skel = if length args > 2 then read (args!!2) else 2 let b = pic 5.0 ul lr dimx np skel if length args > 3 && (args!!3) == "-out" then putStr b else rnf b `seq` putStrLn "Done (no output)" -- examples, given by upper left and lower right corner examples = [ ((-0.75104) :+ (0.10511), (-0.74080) :+ (0.11441)), ((-2.5) :+ (-1.5), (1.5) :+ (1.5)) ] -- Compute image (pic) ------------------------------------------------- pic :: Double -> Complex Double -> Complex Double -> Integer -> Int -> Int -> String pic threshold ul lr dimx np s = header ++ concat (parMap computeRow tasks) where parMap = (cycle [map, parMapEden, farm0, parMapWP] )!!s -------------------------------------------------------- tasks :: [[Complex Double]] tasks = lines computeRow :: [Complex Double] -> String computeRow t = concatMap (rgb . (iter 255 threshold (0.0 :+ 0.0) 0)) t header = "P3\n"++(show (dimx+1))++" "++(show dimy)++"\n255\n" (dimy, lines) = coord ul lr dimx -- rgb mapping for pixel values rgb :: Integer -> String rgb i = (show ri) ++ " " ++ (show gi) ++ " " ++ (show bi) ++ "\n" where ri = (i*26) `mod` 255 gi = (i*2) `mod` 255 bi = (i*35) `mod` 255 {-gi | i < 170 = (i `mod` 85) * 3 | otherwise = 255 bi | i < 170 = 0 | otherwise = (i `mod` 170)*3-} -- Coordinates and iteration ------------------------------------------- coord :: Complex Double -> Complex Double -> Integer -> (Integer, [[Complex Double]]) coord (x1 :+ y1) (x2 :+ y2) dimx = (dimy, ks) where breadth = abs (x2 - x1) height = abs (y2 - y1) stepx = breadth / ((fromInteger dimx)::Double) stepy = height / ((fromInteger dimy)::Double) sx2 = stepx / 2.0 sy2 = stepy / 2.0 dimy = round ((((fromInteger dimx)::Double)*height)/breadth) ks = [ [(x+sx2) :+ (y+sy2) | x <- [x1,x1+stepx..x2]] | y <- [y1,y1+stepy..y2] ] iter :: Integer -> Double -> Complex Double -> Integer -> Complex Double -> Integer iter limit threshold x it c | it > limit = limit | (magnitude x) >= threshold = it | otherwise = iter limit threshold (x*x+c) (it+1) c