LPFP-core-1.1.1: src/LPFPCore/SimpleVec.hs
{-# OPTIONS -Wall #-}
{- |
Module : LPFPCore.SimpleVec
Copyright : (c) Scott N. Walck 2023
License : BSD3 (see LICENSE)
Maintainer : Scott N. Walck <walck@lvc.edu>
Stability : stable
Code from chapter 10 of the book Learn Physics with Functional Programming
-}
module LPFPCore.SimpleVec where
infixl 6 ^+^
infixl 6 ^-^
infixr 7 *^
infixl 7 ^*
infixr 7 ^/
infixr 7 <.>
infixl 7 ><
-- | A vector derivative takes a vector-valued function of a real variable (usually time) as input,
-- and produces a vector-valued function of a real variable as output.
type VecDerivative = (R -> Vec) -> R -> Vec
-- | Given a step size, calculate the vector derivative of a vector-valued function of a real variable
-- (usually time).
vecDerivative :: R -> VecDerivative
vecDerivative dt v t = (v (t + dt/2) ^-^ v (t - dt/2)) ^/ dt
v1 :: R -> Vec
v1 t = 2 *^ t**2 *^ iHat ^+^ 3 *^ t**3 *^ jHat ^+^ t**4 *^ kHat
xCompFunc :: (R -> Vec) -> R -> R
xCompFunc v t = xComp (v t)
-- | A derivative takes a real-valued function of a real variable (often time) as input,
-- and produces a real-valued function of a real variable as output.
type Derivative = (R -> R) -> R -> R
-- | Given a step size, calculate the derivative of a real-valued function of a real variable
-- (often time).
derivative :: R -> Derivative
derivative dt x t = (x (t + dt/2) - x (t - dt/2)) / dt
-- | Time is a real number.
type Time = R
-- | The position of a particle can be represented as a vector.
type PosVec = Vec
-- | Velocity is a vector.
type Velocity = Vec
-- | Acceleration is a vector.
type Acceleration = Vec
-- | Given a time step and a position function, return a velocity function.
velFromPos :: R -- ^ dt
-> (Time -> PosVec ) -- ^ position function
-> (Time -> Velocity) -- ^ velocity function
velFromPos = vecDerivative
-- | Given a time step and a velocity function, return an acceleration function.
accFromVel :: R -- dt
-> (Time -> Velocity) -- velocity function
-> (Time -> Acceleration) -- acceleration function
accFromVel = vecDerivative
-- | Given initial position and a constant velocity, return a position function.
positionCV :: PosVec -> Velocity -> Time -> PosVec
positionCV r0 v0 t = v0 ^* t ^+^ r0
-- | Given initial velocity and a constant acceleration, return a velocity function.
velocityCA :: Velocity -> Acceleration -> Time -> Velocity
velocityCA v0 a0 t = a0 ^* t ^+^ v0
-- | Given initial position, initial velocity, and a constant acceleration, return a position function.
positionCA :: PosVec -> Velocity -> Acceleration
-> Time -> PosVec
positionCA r0 v0 a0 t = 0.5 *^ t**2 *^ a0 ^+^ v0 ^* t ^+^ r0
-- | Given a nonzero velocity and an acceleration, return the component of acceleration
-- parallel to the velocity.
aParallel :: Vec -> Vec -> Vec
aParallel v a = let vHat = v ^/ magnitude v
in (vHat <.> a) *^ vHat
-- | Given a nonzero velocity and an acceleration, return the component of acceleration
-- perpendicular to the velocity.
aPerp :: Vec -> Vec -> Vec
aPerp v a = a ^-^ aParallel v a
-- | Given velocity and acceleration, return the rate at which speed is changing.
speedRateChange :: Vec -> Vec -> R
speedRateChange v a = (v <.> a) / magnitude v
radiusOfCurvature :: Vec -> Vec -> R
radiusOfCurvature v a = (v <.> v) / magnitude (aPerp v a)
projectilePos :: PosVec -> Velocity -> Time -> PosVec
projectilePos r0 v0 = positionCA r0 v0 (9.81 *^ negateV kHat)
-- | An approximation to a real number.
type R = Double
data Mass = Mass R
deriving (Eq,Show)
data Grade = Grade String Int
deriving (Eq,Show)
grades :: [Grade]
grades = [Grade "Albert Einstein" 89
,Grade "Isaac Newton" 95
,Grade "Alan Turing" 91
]
data GradeRecord = GradeRecord { name :: String
, grade :: Int
} deriving (Eq,Show)
gradeRecords1 :: [GradeRecord]
gradeRecords1 = [GradeRecord "Albert Einstein" 89
,GradeRecord "Isaac Newton" 95
,GradeRecord "Alan Turing" 91
]
gradeRecords2 :: [GradeRecord]
gradeRecords2 = [GradeRecord {name = "Albert Einstein", grade = 89}
,GradeRecord {name = "Isaac Newton" , grade = 95}
,GradeRecord {name = "Alan Turing" , grade = 91}
]
data MyBool = MyFalse | MyTrue
deriving (Eq,Show)
data MyMaybe a = MyNothing
| MyJust a
deriving (Eq,Show)
-- | A type for three-dimensional vectors.
data Vec = Vec { xComp :: R -- ^ x component of a vector
, yComp :: R -- ^ y component of a vector
, zComp :: R -- ^ z component of a vector
} deriving (Eq)
instance Show Vec where
show (Vec x y z) = "vec " ++ showDouble x ++ " "
++ showDouble y ++ " "
++ showDouble z
showDouble :: R -> String
showDouble x
| x < 0 = "(" ++ show x ++ ")"
| otherwise = show x
-- | Form a vector by giving its x, y, and z components.
vec :: R -- ^ x component
-> R -- ^ y component
-> R -- ^ z component
-> Vec
vec = Vec
-- | A unit vector in the x direction.
iHat :: Vec
iHat = vec 1 0 0
-- | A unit vector in the y direction.
jHat :: Vec
jHat = vec 0 1 0
-- | A unit vector in the z direction.
kHat :: Vec
kHat = vec 0 0 1
-- | The zero vector.
zeroV :: Vec
zeroV = vec 0 0 0
-- | Negate a vector.
negateV :: Vec -> Vec
negateV (Vec ax ay az) = Vec (-ax) (-ay) (-az)
-- | Vector addition.
(^+^) :: Vec -> Vec -> Vec
Vec ax ay az ^+^ Vec bx by bz = Vec (ax+bx) (ay+by) (az+bz)
-- | Vector subtraction.
(^-^) :: Vec -> Vec -> Vec
Vec ax ay az ^-^ Vec bx by bz = Vec (ax-bx) (ay-by) (az-bz)
-- | Add a list of vectors.
sumV :: [Vec] -> Vec
sumV = foldr (^+^) zeroV
-- | Scalar multiplication of a number and a vector.
(*^) :: R -> Vec -> Vec
c *^ Vec ax ay az = Vec (c*ax) (c*ay) (c*az)
-- | Scalar multiplication of a vector and a number.
(^*) :: Vec -> R -> Vec
Vec ax ay az ^* c = Vec (c*ax) (c*ay) (c*az)
-- | Dot product of two vectors.
(<.>) :: Vec -> Vec -> R
Vec ax ay az <.> Vec bx by bz = ax*bx + ay*by + az*bz
-- | Cross product of two vectors.
(><) :: Vec -> Vec -> Vec
Vec ax ay az >< Vec bx by bz
= Vec (ay*bz - az*by) (az*bx - ax*bz) (ax*by - ay*bx)
-- | Division of a vector by a number.
(^/) :: Vec -> R -> Vec
Vec ax ay az ^/ c = Vec (ax/c) (ay/c) (az/c)
-- | Magnitude of a vector.
magnitude :: Vec -> R
magnitude v = sqrt(v <.> v)
-- | Definite integral of a vector-valued function of a real number.
vecIntegral :: R -- ^ step size dt
-> (R -> Vec) -- ^ vector-valued function
-> R -- ^ lower limit
-> R -- ^ upper limit
-> Vec -- ^ result
vecIntegral = undefined
maxHeight :: PosVec -> Velocity -> R
maxHeight = undefined
speedCA :: Velocity -> Acceleration -> Time -> R
speedCA = undefined
xyProj :: Vec -> Vec
xyProj = undefined
magAngles :: Vec -> (R,R,R)
magAngles = undefined
gEarth :: Vec
gEarth = undefined
vBall :: R -> Vec
vBall t = undefined t
speedRateChangeBall :: R -> R
speedRateChangeBall t = undefined t
rNCM :: (R, R -> R) -> R -> Vec
rNCM (radius, theta) t = undefined radius theta t
aPerpFromPosition :: R -> (R -> Vec) -> R -> Vec
aPerpFromPosition epsilon r t
= let v = vecDerivative epsilon r
a = vecDerivative epsilon v
in aPerp (v t) (a t)