{-# LANGUAGE FlexibleInstances #-}
{-# OPTIONS_GHC -Wno-orphans #-}
module Reanimate.Math.Common
(
Ring(..)
, ringSize
, ringAccess
, ringClamp
, ringUnpack
, ringPack
, ringMap
, ringRayIntersect
, area
, area2X
, isLeftTurn
, isLeftTurnOrLinear
, isRightTurn
, isRightTurnOrLinear
, direction
, isInside
, isInsideStrict
, barycentricCoords
, rayIntersect
, isBetween
, lineIntersect
, distSquared
, approxDist
, distance'
, triangleAngles
, Epsilon(..)
) where
import Data.Vector (Vector)
import qualified Data.Vector as V
import Linear.Matrix (det33)
import Linear.Metric
import Linear.V2
import Linear.V3
import Linear.Vector
import Linear.Epsilon
instance Epsilon Rational where
nearZero :: Rational -> Bool
nearZero Rational
r = Rational
rRational -> Rational -> Bool
forall a. Eq a => a -> a -> Bool
==Rational
0
newtype Ring a = Ring (Vector (V2 a))
ringSize :: Ring a -> Int
ringSize :: Ring a -> Int
ringSize (Ring Vector (V2 a)
v) = Vector (V2 a) -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length Vector (V2 a)
v
ringAccess :: Ring a -> Int -> V2 a
ringAccess :: Ring a -> Int -> V2 a
ringAccess (Ring Vector (V2 a)
v) Int
i = Vector (V2 a)
v Vector (V2 a) -> Int -> V2 a
forall a. Vector a -> Int -> a
V.! Int -> Int -> Int
forall a. Integral a => a -> a -> a
mod Int
i (Vector (V2 a) -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length Vector (V2 a)
v)
ringClamp :: Ring a -> Int -> Int
ringClamp :: Ring a -> Int -> Int
ringClamp (Ring Vector (V2 a)
v) Int
i = Int -> Int -> Int
forall a. Integral a => a -> a -> a
mod Int
i (Vector (V2 a) -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length Vector (V2 a)
v)
ringUnpack :: Ring a -> Vector (V2 a)
ringUnpack :: Ring a -> Vector (V2 a)
ringUnpack (Ring Vector (V2 a)
v) = Vector (V2 a)
v
ringPack :: Vector (V2 a) -> Ring a
ringPack :: Vector (V2 a) -> Ring a
ringPack = Vector (V2 a) -> Ring a
forall a. Vector (V2 a) -> Ring a
Ring
ringMap :: (V2 a -> V2 b) -> Ring a -> Ring b
ringMap :: (V2 a -> V2 b) -> Ring a -> Ring b
ringMap V2 a -> V2 b
fn (Ring Vector (V2 a)
v) = Vector (V2 b) -> Ring b
forall a. Vector (V2 a) -> Ring a
Ring ((V2 a -> V2 b) -> Vector (V2 a) -> Vector (V2 b)
forall a b. (a -> b) -> Vector a -> Vector b
V.map V2 a -> V2 b
fn Vector (V2 a)
v)
ringRayIntersect :: Ring Rational -> (Int, Int) -> (Int,Int) -> Maybe (V2 Rational)
ringRayIntersect :: Ring Rational -> (Int, Int) -> (Int, Int) -> Maybe (V2 Rational)
ringRayIntersect Ring Rational
p (Int
a,Int
b) (Int
c,Int
d) =
(V2 Rational, V2 Rational)
-> (V2 Rational, V2 Rational) -> Maybe (V2 Rational)
forall a.
(Fractional a, Ord a) =>
(V2 a, V2 a) -> (V2 a, V2 a) -> Maybe (V2 a)
rayIntersect (Ring Rational -> Int -> V2 Rational
forall a. Ring a -> Int -> V2 a
ringAccess Ring Rational
p Int
a, Ring Rational -> Int -> V2 Rational
forall a. Ring a -> Int -> V2 a
ringAccess Ring Rational
p Int
b) (Ring Rational -> Int -> V2 Rational
forall a. Ring a -> Int -> V2 a
ringAccess Ring Rational
p Int
c, Ring Rational -> Int -> V2 Rational
forall a. Ring a -> Int -> V2 a
ringAccess Ring Rational
p Int
d)
area :: Fractional a => V2 a -> V2 a -> V2 a -> a
area :: V2 a -> V2 a -> V2 a -> a
area V2 a
a V2 a
b V2 a
c = a
1a -> a -> a
forall a. Fractional a => a -> a -> a
/a
2 a -> a -> a
forall a. Num a => a -> a -> a
* V2 a -> V2 a -> V2 a -> a
forall a. Fractional a => V2 a -> V2 a -> V2 a -> a
area2X V2 a
a V2 a
b V2 a
c
area2X :: Fractional a => V2 a -> V2 a -> V2 a -> a
area2X :: V2 a -> V2 a -> V2 a -> a
area2X (V2 a
a1 a
a2) (V2 a
b1 a
b2) (V2 a
c1 a
c2) =
M33 a -> a
forall a. Num a => M33 a -> a
det33 (V3 a -> V3 a -> V3 a -> M33 a
forall a. a -> a -> a -> V3 a
V3 (a -> a -> a -> V3 a
forall a. a -> a -> a -> V3 a
V3 a
a1 a
a2 a
1)
(a -> a -> a -> V3 a
forall a. a -> a -> a -> V3 a
V3 a
b1 a
b2 a
1)
(a -> a -> a -> V3 a
forall a. a -> a -> a -> V3 a
V3 a
c1 a
c2 a
1))
compareEpsZero :: (Ord a, Fractional a, Epsilon a) => a -> Ordering
compareEpsZero :: a -> Ordering
compareEpsZero a
val
| a -> Bool
forall a. Epsilon a => a -> Bool
nearZero a
val = Ordering
EQ
| Bool
otherwise = a -> a -> Ordering
forall a. Ord a => a -> a -> Ordering
compare a
val a
0
{-# INLINE isLeftTurn #-}
isLeftTurn :: (Fractional a, Ord a, Epsilon a) => V2 a -> V2 a -> V2 a -> Bool
isLeftTurn :: V2 a -> V2 a -> V2 a -> Bool
isLeftTurn V2 a
p1 V2 a
p2 V2 a
p3 =
case a -> Ordering
forall a. (Ord a, Fractional a, Epsilon a) => a -> Ordering
compareEpsZero (V2 a -> V2 a -> V2 a -> a
forall a. Num a => V2 a -> V2 a -> V2 a -> a
direction V2 a
p1 V2 a
p2 V2 a
p3) of
Ordering
LT -> Bool
True
Ordering
EQ -> Bool
False
Ordering
GT -> Bool
False
{-# INLINE isLeftTurnOrLinear #-}
isLeftTurnOrLinear :: (Fractional a, Ord a, Epsilon a) => V2 a -> V2 a -> V2 a -> Bool
isLeftTurnOrLinear :: V2 a -> V2 a -> V2 a -> Bool
isLeftTurnOrLinear V2 a
p1 V2 a
p2 V2 a
p3 =
case a -> Ordering
forall a. (Ord a, Fractional a, Epsilon a) => a -> Ordering
compareEpsZero (V2 a -> V2 a -> V2 a -> a
forall a. Num a => V2 a -> V2 a -> V2 a -> a
direction V2 a
p1 V2 a
p2 V2 a
p3) of
Ordering
LT -> Bool
True
Ordering
EQ -> Bool
True
Ordering
GT -> Bool
False
{-# INLINE isRightTurn #-}
isRightTurn :: (Fractional a, Ord a, Epsilon a) => V2 a -> V2 a -> V2 a -> Bool
isRightTurn :: V2 a -> V2 a -> V2 a -> Bool
isRightTurn V2 a
a V2 a
b V2 a
c = Bool -> Bool
not (V2 a -> V2 a -> V2 a -> Bool
forall a.
(Fractional a, Ord a, Epsilon a) =>
V2 a -> V2 a -> V2 a -> Bool
isLeftTurnOrLinear V2 a
a V2 a
b V2 a
c)
{-# INLINE isRightTurnOrLinear #-}
isRightTurnOrLinear :: (Fractional a, Ord a, Epsilon a) => V2 a -> V2 a -> V2 a -> Bool
isRightTurnOrLinear :: V2 a -> V2 a -> V2 a -> Bool
isRightTurnOrLinear V2 a
a V2 a
b V2 a
c = Bool -> Bool
not (V2 a -> V2 a -> V2 a -> Bool
forall a.
(Fractional a, Ord a, Epsilon a) =>
V2 a -> V2 a -> V2 a -> Bool
isLeftTurn V2 a
a V2 a
b V2 a
c)
{-# INLINE direction #-}
direction :: Num a => V2 a -> V2 a -> V2 a -> a
direction :: V2 a -> V2 a -> V2 a -> a
direction V2 a
p1 V2 a
p2 V2 a
p3 = V2 a -> V2 a -> a
forall a. Num a => V2 a -> V2 a -> a
crossZ (V2 a
p3V2 a -> V2 a -> V2 a
forall a. Num a => a -> a -> a
-V2 a
p1) (V2 a
p2V2 a -> V2 a -> V2 a
forall a. Num a => a -> a -> a
-V2 a
p1)
{-# INLINE isInside #-}
isInside :: (Fractional a, Ord a) => V2 a -> V2 a -> V2 a -> V2 a -> Bool
isInside :: V2 a -> V2 a -> V2 a -> V2 a -> Bool
isInside V2 a
a V2 a
b V2 a
c V2 a
d =
a
s a -> a -> Bool
forall a. Ord a => a -> a -> Bool
>= a
0 Bool -> Bool -> Bool
&& a
s a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= a
1 Bool -> Bool -> Bool
&& a
t a -> a -> Bool
forall a. Ord a => a -> a -> Bool
>= a
0 Bool -> Bool -> Bool
&& a
t a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= a
1 Bool -> Bool -> Bool
&& a
i a -> a -> Bool
forall a. Ord a => a -> a -> Bool
>= a
0 Bool -> Bool -> Bool
&& a
i a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= a
1
where
(a
s, a
t, a
i) = V2 a -> V2 a -> V2 a -> V2 a -> (a, a, a)
forall a. Fractional a => V2 a -> V2 a -> V2 a -> V2 a -> (a, a, a)
barycentricCoords V2 a
a V2 a
b V2 a
c V2 a
d
{-# INLINE isInsideStrict #-}
isInsideStrict :: (Fractional a, Ord a) => V2 a -> V2 a -> V2 a -> V2 a -> Bool
isInsideStrict :: V2 a -> V2 a -> V2 a -> V2 a -> Bool
isInsideStrict V2 a
a V2 a
b V2 a
c V2 a
d =
a
s a -> a -> Bool
forall a. Ord a => a -> a -> Bool
> a
0 Bool -> Bool -> Bool
&& a
s a -> a -> Bool
forall a. Ord a => a -> a -> Bool
< a
1 Bool -> Bool -> Bool
&& a
t a -> a -> Bool
forall a. Ord a => a -> a -> Bool
> a
0 Bool -> Bool -> Bool
&& a
t a -> a -> Bool
forall a. Ord a => a -> a -> Bool
< a
1 Bool -> Bool -> Bool
&& a
i a -> a -> Bool
forall a. Ord a => a -> a -> Bool
> a
0 Bool -> Bool -> Bool
&& a
i a -> a -> Bool
forall a. Ord a => a -> a -> Bool
< a
1
where
(a
s, a
t, a
i) = V2 a -> V2 a -> V2 a -> V2 a -> (a, a, a)
forall a. Fractional a => V2 a -> V2 a -> V2 a -> V2 a -> (a, a, a)
barycentricCoords V2 a
a V2 a
b V2 a
c V2 a
d
{-# INLINE barycentricCoords #-}
barycentricCoords :: Fractional a => V2 a -> V2 a -> V2 a -> V2 a -> (a, a, a)
barycentricCoords :: V2 a -> V2 a -> V2 a -> V2 a -> (a, a, a)
barycentricCoords (V2 a
x1 a
y1) (V2 a
x2 a
y2) (V2 a
x3 a
y3) (V2 a
x a
y) =
(a
lam1, a
lam2, a
lam3)
where
lam1 :: a
lam1 = ((a
y2a -> a -> a
forall a. Num a => a -> a -> a
-a
y3)a -> a -> a
forall a. Num a => a -> a -> a
*(a
xa -> a -> a
forall a. Num a => a -> a -> a
-a
x3) a -> a -> a
forall a. Num a => a -> a -> a
+ (a
x3 a -> a -> a
forall a. Num a => a -> a -> a
- a
x2)a -> a -> a
forall a. Num a => a -> a -> a
*(a
ya -> a -> a
forall a. Num a => a -> a -> a
-a
y3)) a -> a -> a
forall a. Fractional a => a -> a -> a
/
((a
y2a -> a -> a
forall a. Num a => a -> a -> a
-a
y3)a -> a -> a
forall a. Num a => a -> a -> a
*(a
x1a -> a -> a
forall a. Num a => a -> a -> a
-a
x3) a -> a -> a
forall a. Num a => a -> a -> a
+ (a
x3a -> a -> a
forall a. Num a => a -> a -> a
-a
x2)a -> a -> a
forall a. Num a => a -> a -> a
*(a
y1a -> a -> a
forall a. Num a => a -> a -> a
-a
y3))
lam2 :: a
lam2 = ((a
y3a -> a -> a
forall a. Num a => a -> a -> a
-a
y1)a -> a -> a
forall a. Num a => a -> a -> a
*(a
xa -> a -> a
forall a. Num a => a -> a -> a
-a
x3) a -> a -> a
forall a. Num a => a -> a -> a
+ (a
x1a -> a -> a
forall a. Num a => a -> a -> a
-a
x3)a -> a -> a
forall a. Num a => a -> a -> a
*(a
ya -> a -> a
forall a. Num a => a -> a -> a
-a
y3)) a -> a -> a
forall a. Fractional a => a -> a -> a
/
((a
y2a -> a -> a
forall a. Num a => a -> a -> a
-a
y3)a -> a -> a
forall a. Num a => a -> a -> a
*(a
x1a -> a -> a
forall a. Num a => a -> a -> a
-a
x3) a -> a -> a
forall a. Num a => a -> a -> a
+ (a
x3a -> a -> a
forall a. Num a => a -> a -> a
-a
x2)a -> a -> a
forall a. Num a => a -> a -> a
*(a
y1a -> a -> a
forall a. Num a => a -> a -> a
-a
y3))
lam3 :: a
lam3 = a
1 a -> a -> a
forall a. Num a => a -> a -> a
- a
lam1 a -> a -> a
forall a. Num a => a -> a -> a
- a
lam2
{-# INLINE rayIntersect #-}
rayIntersect :: (Fractional a, Ord a) => (V2 a,V2 a) -> (V2 a,V2 a) -> Maybe (V2 a)
rayIntersect :: (V2 a, V2 a) -> (V2 a, V2 a) -> Maybe (V2 a)
rayIntersect (V2 a
x1 a
y1,V2 a
x2 a
y2) (V2 a
x3 a
y3, V2 a
x4 a
y4)
| a
yBot a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
0 = Maybe (V2 a)
forall a. Maybe a
Nothing
| Bool
otherwise = V2 a -> Maybe (V2 a)
forall a. a -> Maybe a
Just (V2 a -> Maybe (V2 a)) -> V2 a -> Maybe (V2 a)
forall a b. (a -> b) -> a -> b
$
a -> a -> V2 a
forall a. a -> a -> V2 a
V2 (a
xTopa -> a -> a
forall a. Fractional a => a -> a -> a
/a
xBot) (a
yTopa -> a -> a
forall a. Fractional a => a -> a -> a
/a
yBot)
where
xTop :: a
xTop = (a
x1a -> a -> a
forall a. Num a => a -> a -> a
*a
y2 a -> a -> a
forall a. Num a => a -> a -> a
- a
y1a -> a -> a
forall a. Num a => a -> a -> a
*a
x2)a -> a -> a
forall a. Num a => a -> a -> a
*(a
x3a -> a -> a
forall a. Num a => a -> a -> a
-a
x4) a -> a -> a
forall a. Num a => a -> a -> a
- (a
x1 a -> a -> a
forall a. Num a => a -> a -> a
- a
x2)a -> a -> a
forall a. Num a => a -> a -> a
*(a
x3a -> a -> a
forall a. Num a => a -> a -> a
*a
y4a -> a -> a
forall a. Num a => a -> a -> a
-a
y3a -> a -> a
forall a. Num a => a -> a -> a
*a
x4)
xBot :: a
xBot = (a
x1a -> a -> a
forall a. Num a => a -> a -> a
-a
x2)a -> a -> a
forall a. Num a => a -> a -> a
*(a
y3a -> a -> a
forall a. Num a => a -> a -> a
-a
y4)a -> a -> a
forall a. Num a => a -> a -> a
-(a
y1a -> a -> a
forall a. Num a => a -> a -> a
-a
y2)a -> a -> a
forall a. Num a => a -> a -> a
*(a
x3a -> a -> a
forall a. Num a => a -> a -> a
-a
x4)
yTop :: a
yTop = (a
x1a -> a -> a
forall a. Num a => a -> a -> a
*a
y2 a -> a -> a
forall a. Num a => a -> a -> a
- a
y1a -> a -> a
forall a. Num a => a -> a -> a
*a
x2)a -> a -> a
forall a. Num a => a -> a -> a
*(a
y3a -> a -> a
forall a. Num a => a -> a -> a
-a
y4) a -> a -> a
forall a. Num a => a -> a -> a
- (a
y1a -> a -> a
forall a. Num a => a -> a -> a
-a
y2)a -> a -> a
forall a. Num a => a -> a -> a
*(a
x3a -> a -> a
forall a. Num a => a -> a -> a
*a
y4a -> a -> a
forall a. Num a => a -> a -> a
-a
y3a -> a -> a
forall a. Num a => a -> a -> a
*a
x4)
yBot :: a
yBot = (a
x1a -> a -> a
forall a. Num a => a -> a -> a
-a
x2)a -> a -> a
forall a. Num a => a -> a -> a
*(a
y3a -> a -> a
forall a. Num a => a -> a -> a
-a
y4) a -> a -> a
forall a. Num a => a -> a -> a
- (a
y1a -> a -> a
forall a. Num a => a -> a -> a
-a
y2)a -> a -> a
forall a. Num a => a -> a -> a
*(a
x3a -> a -> a
forall a. Num a => a -> a -> a
-a
x4)
{-# INLINE isBetween #-}
isBetween :: (Ord a, Fractional a) => V2 a -> (V2 a, V2 a) -> Bool
isBetween :: V2 a -> (V2 a, V2 a) -> Bool
isBetween (V2 a
x a
y) (V2 a
x1 a
y1, V2 a
x2 a
y2) =
((a
y1 a -> a -> Bool
forall a. Ord a => a -> a -> Bool
> a
y) Bool -> Bool -> Bool
forall a. Eq a => a -> a -> Bool
/= (a
y2 a -> a -> Bool
forall a. Ord a => a -> a -> Bool
> a
y) Bool -> Bool -> Bool
|| a
y a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
y1 Bool -> Bool -> Bool
|| a
y a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
y2) Bool -> Bool -> Bool
&&
((a
x1 a -> a -> Bool
forall a. Ord a => a -> a -> Bool
> a
x) Bool -> Bool -> Bool
forall a. Eq a => a -> a -> Bool
/= (a
x2 a -> a -> Bool
forall a. Ord a => a -> a -> Bool
> a
x) Bool -> Bool -> Bool
|| a
x a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
x1 Bool -> Bool -> Bool
|| a
x a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
x2)
{-# INLINE lineIntersect #-}
lineIntersect :: (Ord a, Fractional a) => (V2 a, V2 a) -> (V2 a, V2 a) -> Maybe (V2 a)
lineIntersect :: (V2 a, V2 a) -> (V2 a, V2 a) -> Maybe (V2 a)
lineIntersect (V2 a, V2 a)
a (V2 a, V2 a)
b =
case (V2 a, V2 a) -> (V2 a, V2 a) -> Maybe (V2 a)
forall a.
(Fractional a, Ord a) =>
(V2 a, V2 a) -> (V2 a, V2 a) -> Maybe (V2 a)
rayIntersect (V2 a, V2 a)
a (V2 a, V2 a)
b of
Just V2 a
u
| V2 a -> (V2 a, V2 a) -> Bool
forall a. (Ord a, Fractional a) => V2 a -> (V2 a, V2 a) -> Bool
isBetween V2 a
u (V2 a, V2 a)
a Bool -> Bool -> Bool
&& V2 a -> (V2 a, V2 a) -> Bool
forall a. (Ord a, Fractional a) => V2 a -> (V2 a, V2 a) -> Bool
isBetween V2 a
u (V2 a, V2 a)
b -> V2 a -> Maybe (V2 a)
forall a. a -> Maybe a
Just V2 a
u
Maybe (V2 a)
_ -> Maybe (V2 a)
forall a. Maybe a
Nothing
distSquared :: (Num a) => V2 a -> V2 a -> a
distSquared :: V2 a -> V2 a -> a
distSquared V2 a
a V2 a
b = V2 a -> a
forall (f :: * -> *) a. (Metric f, Num a) => f a -> a
quadrance (V2 a
a V2 a -> V2 a -> V2 a
forall (f :: * -> *) a. (Additive f, Num a) => f a -> f a -> f a
^-^ V2 a
b)
approxDist :: (Real a, Fractional a) => V2 a -> V2 a -> a
approxDist :: V2 a -> V2 a -> a
approxDist V2 a
a V2 a
b = Double -> a
forall a b. (Real a, Fractional b) => a -> b
realToFrac (Double -> Double
forall a. Floating a => a -> a
sqrt (a -> Double
forall a b. (Real a, Fractional b) => a -> b
realToFrac (V2 a -> V2 a -> a
forall a. Num a => V2 a -> V2 a -> a
distSquared V2 a
a V2 a
b) :: Double))
distance' :: (Real a, Fractional a) => V2 a -> V2 a -> Double
distance' :: V2 a -> V2 a -> Double
distance' V2 a
a V2 a
b = Double -> Double
forall a. Floating a => a -> a
sqrt (a -> Double
forall a b. (Real a, Fractional b) => a -> b
realToFrac (V2 a -> V2 a -> a
forall a. Num a => V2 a -> V2 a -> a
distSquared V2 a
a V2 a
b))
triangleAngles :: V2 Double -> V2 Double -> V2 Double -> (Double, Double, Double)
triangleAngles :: V2 Double -> V2 Double -> V2 Double -> (Double, Double, Double)
triangleAngles V2 Double
a V2 Double
b V2 Double
c =
(V2 Double -> V2 Double -> Double
forall a. RealFloat a => V2 a -> V2 a -> a
findAngle (V2 Double
bV2 Double -> V2 Double -> V2 Double
forall a. Num a => a -> a -> a
-V2 Double
a) (V2 Double
cV2 Double -> V2 Double -> V2 Double
forall a. Num a => a -> a -> a
-V2 Double
a)
,V2 Double -> V2 Double -> Double
forall a. RealFloat a => V2 a -> V2 a -> a
findAngle (V2 Double
cV2 Double -> V2 Double -> V2 Double
forall a. Num a => a -> a -> a
-V2 Double
b) (V2 Double
aV2 Double -> V2 Double -> V2 Double
forall a. Num a => a -> a -> a
-V2 Double
b)
,V2 Double -> V2 Double -> Double
forall a. RealFloat a => V2 a -> V2 a -> a
findAngle (V2 Double
aV2 Double -> V2 Double -> V2 Double
forall a. Num a => a -> a -> a
-V2 Double
c) (V2 Double
bV2 Double -> V2 Double -> V2 Double
forall a. Num a => a -> a -> a
-V2 Double
c))
where
findAngle :: V2 a -> V2 a -> a
findAngle V2 a
v1 V2 a
v2 = a -> a
forall a. Num a => a -> a
abs (a -> a -> a
forall a. RealFloat a => a -> a -> a
atan2 (V2 a -> V2 a -> a
forall a. Num a => V2 a -> V2 a -> a
crossZ V2 a
v1 V2 a
v2) (V2 a -> V2 a -> a
forall (f :: * -> *) a. (Metric f, Num a) => f a -> f a -> a
dot V2 a
v1 V2 a
v2))