Explained and use UNPACK

This commit is contained in:
Yann Esposito 2012-06-25 10:56:10 +02:00
parent 4f126cbba6
commit 51ca9d211b
3 changed files with 30 additions and 22 deletions

View file

@ -20,7 +20,7 @@ And the second part more focused on OpenGL and content.
For efficiency reason[^010001], I will not use the default Haskell `Complex` data type.
[^010001]: I tried `Complex Double`, `Complex Float`, this current data type with `Double` and the actual version `Float`. For rendering a 1024x1024 Mandelbrot set it takes `Complex Double` about 6.8s, for `Complex Float` about 5.1s, for the actual version with `Double` and `Float` it takes about `1.6` sec. See these sources for testing yourself: [https://gist.github.com/2945043](https://gist.github.com/2945043). I haven't tried to use unpacked data type because it looks weird in a tutorial. But I might try it in a sequel.
[^010001]: I tried `Complex Double`, `Complex Float`, this current data type with `Double` and the actual version `Float`. For rendering a 1024x1024 Mandelbrot set it takes `Complex Double` about 6.8s, for `Complex Float` about 5.1s, for the actual version with `Double` and `Float` it takes about `1.6` sec. See these sources for testing yourself: [https://gist.github.com/2945043](https://gist.github.com/2945043). If you really want to things to go faster, use `data Complex = C {-# UNPACK #-} !Float {-# UNPACK #-} !Float`. It takes only one second instead of 1.6s.
> data Complex = C (Float,Float) deriving (Show,Eq)

View file

@ -5,21 +5,25 @@
> import Graphics.Rendering.OpenGL
> import Graphics.UI.GLUT
> import Data.IORef
> data Complex = C (Float,Float) deriving (Show,Eq)
> -- Use UNPACK data because it is faster
> -- The ! is for strict instead of lazy
> data Complex = C {-# UNPACK #-} !Float
> {-# UNPACK #-} !Float
> deriving (Show,Eq)
> instance Num Complex where
> fromInteger n = C (fromIntegral n,0.0)
> C (x,y) * C (z,t) = C (z*x - y*t, y*z + x*t)
> C (x,y) + C (z,t) = C (x+z, y+t)
> abs (C (x,y)) = C (sqrt (x*x + y*y),0.0)
> signum (C (x,y)) = C (signum x , 0.0)
> fromInteger n = C (fromIntegral n) 0.0
> (C x y) * (C z t) = C (z*x - y*t) (y*z + x*t)
> (C x y) + (C z t) = C (x+z) (y+t)
> abs (C x y) = C (sqrt (x*x + y*y)) 0.0
> signum (C x y) = C (signum x) 0.0
> complex :: Float -> Float -> Complex
> complex x y = C (x,y)
> complex x y = C x y
>
> real :: Complex -> Float
> real (C (x,y)) = x
> real (C x y) = x
>
> im :: Complex -> Float
> im (C (x,y)) = y
> im (C x y) = y
>
> magnitude :: Complex -> Float
> magnitude = real.abs

View file

@ -2,32 +2,36 @@ module ExtComplex where
import Graphics.Rendering.OpenGL
data ExtComplex = C (GLfloat,GLfloat,GLfloat)
-- This time I use unpacked strict data type
-- Far faster when compiled.
data ExtComplex = C {-# UNPACK #-} !GLfloat
{-# UNPACK #-} !GLfloat
{-# UNPACK #-} !GLfloat
deriving (Show,Eq)
instance Num ExtComplex where
-- The shape of the 3D mandelbrot
-- will depend on this formula
C (x,y,z) * C (x',y',z') = C (x*x' - y*y' - z*z',
x*y' + y*x' + z*z',
x*z' + z*x' )
(C x y z) * (C x' y' z') = C (x*x' - y*y' - z*z')
(x*y' + y*x' + z*z')
(x*z' + z*x' )
-- The rest is straightforward
fromInteger n = C (fromIntegral n, 0, 0)
C (x,y,z) + C (x',y',z') = C (x+x', y+y', z+z')
abs (C (x,y,z)) = C (sqrt (x*x + y*y + z*z), 0, 0)
signum (C (x,_,_)) = C (signum x, 0, 0)
fromInteger n = C (fromIntegral n) 0 0
(C x y z) + (C x' y' z') = C (x+x') (y+y') (z+z')
abs (C x y z) = C (sqrt (x*x + y*y + z*z)) 0 0
signum (C x y z) = C (signum x) (signum y) (signum z)
extcomplex :: GLfloat -> GLfloat -> GLfloat -> ExtComplex
extcomplex x y z = C (x,y,z)
extcomplex x y z = C x y z
real :: ExtComplex -> GLfloat
real (C (x,_,_)) = x
real (C x _ _) = x
im :: ExtComplex -> GLfloat
im (C (_,y,_)) = y
im (C _ y _) = y
strange :: ExtComplex -> GLfloat
strange (C (_,_,z)) = z
strange (C _ _ z) = z
magnitude :: ExtComplex -> GLfloat
magnitude = real.abs