packages feed

PDBtools-0.0.2: PDButil/Vectors.hs

module PDButil.Vectors where

-- A minimal implementation of vector operations for pdb calculations. 
-- These vector operations are NOT safe... they will not verify dimensionality requirements
-- TODO; matrix multiplication, factorizations.

import Data.List

dot :: (Num a) => [a] -> [a] -> a
dot a b = foldr1 (+) $ zipWith (*) a b

-- Only defined on 3 dimensional vectors; no obvious generalization
cross :: (Num a) => [a] -> [a] -> [a]
cross [a1,a2,a3] [b1,b2,b3] = [c1,c2,c3] where
	c1 = a2*b3 - a3*b2
	c2 = a3*b1 - a1*b3
	c3 = a1*b2 - a2*b1

vAdd :: (Num a) => [a] -> [a] -> [a]
vAdd = zipWith (+)

vSub :: (Num a) => [a] -> [a] -> [a]
vSub = zipWith (-)

magnitude :: (Num a) => [a] -> a
magnitude = sum . (map (^2))

norm :: (Floating a) => [a] -> a
norm = sqrt . magnitude

unit :: (Floating a) => [a] -> [a]
unit vec = map (/ (norm vec)) vec

angle :: (Floating a) => [a] -> [a] -> a
angle a b
	| norm a == 0 || norm b == 0 = 0
  | otherwise = acos $ (a `dot` b) / ((norm a) * (norm b))

-- Two Dimensions
{-
vRotate :: (Floating a) => a -> [a] -> [a]
vRotate degs [x,y] = mtimes rMatrix [x,y] where
  rMatrix = [[cos(degs),-sin(degs)],[sin(degs),cos(degs)]]
-}

vRotate3d :: (Floating a) => a -> a -> a -> [a] -> [a]
vRotate3d theta phi psi vect = [r1 `dot` vect, r2 `dot` vect, r3 `dot` vect] where
  rMatrix = [r1,r2,r3]
  r1 = [cos(theta)*cos(psi),-cos(phi)*sin(psi)+sin(phi)*sin(theta)*cos(psi),sin(phi)*sin(psi)+cos(phi)*sin(theta)*cos(psi)]
  r2 = [cos(theta)*sin(psi),cos(phi)*cos(psi)+sin(phi)*sin(theta)*sin(psi),-sin(phi)*cos(psi)+cos(phi)*sin(theta)*sin(psi)]
  r3 = [-sin(theta),sin(phi)*cos(theta),cos(phi)*cos(theta)]