{- Haskell Dynamics Engine, Copyright (C) 2007 Ruben Henner Zilibowitz All rights reserved. Email: rubenz@cse.unsw.edu.au Web: www.cse.unsw.edu.au/~rubenz This is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License that is include with this package in the file LICENSE-GPL.TXT. -} -- Matrix3x3 -- Code by Ruben Henner Zilibowitz -- Created on 20/3/07 module Matrix3x3 where infixl 7 .*., ./. data (RealFloat a) => Matrix3x3 a = Mat !(a,a,a) !(a,a,a) !(a,a,a) deriving (Eq, Read, Show) data (RealFloat a) => Vector a = Vec !a !a !a deriving (Eq, Read, Show) class Scalar a where (.*.) :: RealFloat b => a b -> b -> a b (./.) :: RealFloat b => a b -> b -> a b instance Scalar Matrix3x3 where (Mat (a,b,c) (d,e,f) (g,h,i)) .*. x = (Mat (a*x,b*x,c*x) (d*x,e*x,f*x) (g*x,h*x,i*x)) m ./. x = let x' = recip x in m .*. x' instance Scalar Vector where (Vec a b c) .*. x = Vec (a*x) (b*x) (c*x) v ./. x = let x' = recip x in v .*. x' --- --- Matrix3x3 --- instance RealFloat a => Num (Matrix3x3 a) where fromInteger a = let x = fromInteger a in Mat (x,0,0) (0,x,0) (0,0,x) (Mat (a,b,c) (d,e,f) (g,h,i)) + (Mat (a',b',c') (d',e',f') (g',h',i')) = Mat (a+a',b+b',c+c') (d+d',e+e',f+f') (g+g',h+h',i+i') (Mat (a,b,c) (d,e,f) (g,h,i)) - (Mat (a',b',c') (d',e',f') (g',h',i')) = Mat (a-a',b-b',c-c') (d-d',e-e',f-f') (g-g',h-h',i-i') (Mat (a,b,c) (d,e,f) (g,h,i)) * (Mat (a',b',c') (d',e',f') (g',h',i')) = Mat (a*a'+b*d'+c*g',a*b'+b*e'+c*h',a*c'+b*f'+c*i') (d*a'+e*d'+f*g',d*b'+e*e'+f*h',d*c'+e*f'+f*i') (g*a'+h*d'+i*g',g*b'+h*e'+i*h',g*c'+h*f'+i*i') abs m = let x = det m in Mat (x,0,0) (0,x,0) (0,0,x) signum m | (d == 0) = 0 | otherwise = m .*. (recip d) where d = det m instance (RealFloat a) => Fractional (Matrix3x3 a) where q / r = q * (inverse r) fromRational a = let x = fromRational a in Mat (x,0,0) (0,x,0) (0,0,x) inverse (Mat (a00,a01,a02) (a10,a11,a12) (a20,a21,a22)) = Mat ((a11*a22-a12*a21)/denom,(a02*a21-a01*a22)/denom,(a01*a12-a02*a11)/denom) ((a12*a20-a10*a22)/denom,(a00*a22-a02*a20)/denom,(a02*a10-a00*a12)/denom) ((a10*a21-a11*a20)/denom,(a01*a20-a00*a21)/denom,(a00*a11-a01*a10)/denom) where denom = a00*(a11*a22-a12*a21)+a01*(a12*a20-a10*a22)+a02*(a10*a21-a11*a20) det (Mat (a00,a01,a02) (a10,a11,a12) (a20,a21,a22)) = a00*(a11*a22-a12*a21)-a01*(a10*a22-a12*a20)+a02*(a10*a21-a11*a20) transposeMat (Mat (a,b,c) (d,e,f) (g,h,i)) = Mat (a,d,g) (b,e,h) (c,f,i) normalise v = v ./. (magnitude v) -- crossMatrix: Vector a becomes matrix A with the property: A*b = cross a b crossMatrix :: (RealFloat a) => Vector a -> Matrix3x3 a crossMatrix (Vec x y z) = Mat (0,-z,y) (z,0,-x) (-y,x,0) -- crossMatrix2: Vector b becomes matrix B with the property: B*a = cross a b crossMatrix2 :: (RealFloat a) => Vector a -> Matrix3x3 a crossMatrix2 b = negate (crossMatrix b) scaleMatrix :: (RealFloat a) => a -> Matrix3x3 a scaleMatrix s = Mat (s,0,0) (0,s,0) (0,0,s) matToList (Mat (a,b,c) (d,e,f) (g,h,i)) = [[a,b,c],[d,e,f],[g,h,i]] catMatrices :: (RealFloat a) => [[Matrix3x3 a]] -> [[a]] catMatrices [] = [] catMatrices (r:rs) = (foldl1 (zipWith (++)) (map matToList r)) ++ (catMatrices rs) --- --- Vector --- dot (Vec a b c) (Vec x y z) = a*x + b*y + c*z cross (Vec a b c) (Vec x y z) = Vec (b*z-c*y) (c*x-a*z) (a*y-b*x) magnitude (Vec a b c) = sqrt (a*a + b*b + c*c) norm v = dot v v instance RealFloat a => Num (Vector a) where fromInteger a = Vec (fromInteger a) 0 0 (Vec a b c) + (Vec x y z) = Vec (a+x) (b+y) (c+z) (Vec a b c) - (Vec x y z) = Vec (a-x) (b-y) (c-z) x * y = cross x y abs m = Vec (magnitude m) 0 0 signum m = error "undefined" matXvec (Mat (a,b,c) (d,e,f) (g,h,i)) (Vec x y z) = Vec (x*a+y*b+z*c) (x*d+y*e+z*f) (x*g+y*h+z*i) toMatrixCols (Vec a b c) (Vec d e f) (Vec g h i) = Mat (a,d,g) (b,e,h) (c,f,i) col 0 (Mat (a,_,_) (d,_,_) (g,_,_)) = Vec a d g col 1 (Mat (_,b,_) (_,e,_) (_,h,_)) = Vec b e h col 2 (Mat (_,_,c) (_,_,f) (_,_,i)) = Vec c f i row 0 (Mat (a,b,c) _ _) = Vec a b c row 1 (Mat _ (a,b,c) _) = Vec a b c row 2 (Mat _ _ (a,b,c)) = Vec a b c coord 0 (Vec x _ _) = x coord 1 (Vec _ y _) = y coord 2 (Vec _ _ z) = z vecAbs (Vec x y z) = Vec (abs x) (abs y) (abs z) matAbs (Mat (a,b,c) (d,e,f) (g,h,i)) = (Mat (abs a,abs b,abs c) (abs d,abs e,abs f) (abs g,abs h,abs i)) vecToList (Vec a b c) = [a,b,c] --- --- tests --- test1 = Mat (2,1,1) (0,-1,2) (0,2,-1)