-- |
-- Module      : Math.Rotations.Class
-- Copyright   : (c) Justus Sagemüller 2018
-- License     : GPL v3
-- 
-- Maintainer  : (@) jsagemue $ uni-koeln.de
-- Stability   : experimental
-- Portability : portable
-- 

{-# LANGUAGE TypeFamilies             #-}
{-# LANGUAGE FlexibleInstances        #-}

module Math.Rotations.Class ( Rotatable (..)
                            , xAxis, yAxis, zAxis
                            , (°)
                            -- * Utility
                            , rotateViaEulerAnglesYZ
                            , rotateℝ³AboutCenteredAxis
                            -- * Internals
                            , rotmatrixForAxis
                            , eulerAnglesZYZForMatrix
                            , rotmatrixForEulerAnglesZYZ
                            ) where

import Math.Manifold.Core.Types
import Math.Manifold.Core.PseudoAffine
import Data.VectorSpace
import Linear.V3 (V3(V3))

class Rotatable m where
  type AxisSpace m :: *
  rotateAbout :: AxisSpace m ->  -> m -> m

instance (Rotatable m) => Rotatable (m -> Double) where
  type AxisSpace (m -> Double) = AxisSpace m
  rotateAbout :: AxisSpace (m -> Double) -> S¹ -> (m -> Double) -> m -> Double
rotateAbout AxisSpace (m -> Double)
ax (S¹Polar Double
δφ) m -> Double
f = m -> Double
f (m -> Double) -> (m -> m) -> m -> Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AxisSpace m -> S¹ -> m -> m
forall m. Rotatable m => AxisSpace m -> S¹ -> m -> m
rotateAbout AxisSpace m
AxisSpace (m -> Double)
ax (Double -> S¹
forall r. r -> S¹_ r
S¹Polar (Double -> S¹) -> Double -> S¹
forall a b. (a -> b) -> a -> b
$ -Double
δφ)

instance Rotatable  where
  type AxisSpace  = ℝP⁰
  rotateAbout :: AxisSpace S¹ -> S¹ -> S¹ -> S¹
rotateAbout AxisSpace S¹
ℝPZero (S¹Polar Double
δφ) (S¹Polar Double
φ)
    | Double
φ' Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
> Double
forall a. Floating a => a
pi    = Double -> S¹
forall r. r -> S¹_ r
S¹Polar (Double -> S¹) -> Double -> S¹
forall a b. (a -> b) -> a -> b
$ Double
φ'Double -> Double -> Double
forall a. Num a => a -> a -> a
-Double
forall r. RealFloat r => r
tau
    | Double
φ' Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< -Double
forall a. Floating a => a
pi   = Double -> S¹
forall r. r -> S¹_ r
S¹Polar (Double -> S¹) -> Double -> S¹
forall a b. (a -> b) -> a -> b
$ Double
φ'Double -> Double -> Double
forall a. Num a => a -> a -> a
+Double
forall r. RealFloat r => r
tau
    | Bool
otherwise  = Double -> S¹
forall r. r -> S¹_ r
S¹Polar Double
φ'
   where φ' :: Double
φ' = Double
φ Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
δφ

rotateViaEulerAnglesYZ
  :: ( -> m -> m)        -- ^ Y-axis rotation method
  -> ( -> m -> m)        -- ^ Z-axis rotation method
  -> (ℝP² ->  -> m -> m) -- ^ Suitable definition for 'rotateAbout'
rotateViaEulerAnglesYZ :: (S¹ -> m -> m) -> (S¹ -> m -> m) -> ℝP² -> S¹ -> m -> m
rotateViaEulerAnglesYZ S¹ -> m -> m
yRot S¹ -> m -> m
zRot ℝP²
ax = [[Double]] -> m -> m
rotAroundAxis ([[Double]] -> m -> m) -> (S¹ -> [[Double]]) -> S¹ -> m -> m
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ℝP² -> S¹ -> [[Double]]
rotmatrixForAxis ℝP²
ax
 where rotAroundAxis :: [[Double]] -> m -> m
rotAroundAxis [[Double]]
mat = case [[Double]] -> [Double]
eulerAnglesZYZForMatrix [[Double]]
mat of
          [Double
θz₀, Double
θy, Double
θz₁] -> S¹ -> m -> m
zRot (Double -> S¹
forall r. r -> S¹_ r
S¹Polar Double
θz₁) (m -> m) -> (m -> m) -> m -> m
forall b c a. (b -> c) -> (a -> b) -> a -> c
. S¹ -> m -> m
yRot (Double -> S¹
forall r. r -> S¹_ r
S¹Polar Double
θy) (m -> m) -> (m -> m) -> m -> m
forall b c a. (b -> c) -> (a -> b) -> a -> c
. S¹ -> m -> m
zRot (Double -> S¹
forall r. r -> S¹_ r
S¹Polar Double
θz₀)

rotmatrixForAxis :: ℝP² ->  -> [[]]
rotmatrixForAxis :: ℝP² -> S¹ -> [[Double]]
rotmatrixForAxis (HemisphereℝP²Polar Double
θax Double
φax) = S¹ -> [[Double]]
rotAroundAxis
 where rotAroundAxis :: S¹ -> [[Double]]
rotAroundAxis (S¹Polar Double
θ) = [[Double
r₀₀,Double
r₀₁,Double
r₀₂]
                                   ,[Double
r₁₀,Double
r₁₁,Double
r₁₂]
                                   ,[Double
r₂₀,Double
r₂₁,Double
r₂₂]]
         -- https://en.wikipedia.org/w/index.php?title=Rotation_formalisms_in_three_dimensions&oldid=823164970#Rotation_matrix_%E2%86%94_Euler_axis/angle
        where r₀₀ :: Double
r₀₀ = Double
one_cosθDouble -> Double -> Double
forall a. Num a => a -> a -> a
*Double
e₀Double -> Integer -> Double
forall a b. (Num a, Integral b) => a -> b -> a
^Integer
2  Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
cosθ
              r₀₁ :: Double
r₀₁ = Double
one_cosθDouble -> Double -> Double
forall a. Num a => a -> a -> a
*Double
e₀Double -> Double -> Double
forall a. Num a => a -> a -> a
*Double
e₁ Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
e₂Double -> Double -> Double
forall a. Num a => a -> a -> a
*Double
sinθ
              r₀₂ :: Double
r₀₂ = Double
one_cosθDouble -> Double -> Double
forall a. Num a => a -> a -> a
*Double
e₀Double -> Double -> Double
forall a. Num a => a -> a -> a
*Double
e₂ Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
e₁Double -> Double -> Double
forall a. Num a => a -> a -> a
*Double
sinθ
              r₁₀ :: Double
r₁₀ = Double
one_cosθDouble -> Double -> Double
forall a. Num a => a -> a -> a
*Double
e₁Double -> Double -> Double
forall a. Num a => a -> a -> a
*Double
e₀ Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
e₂Double -> Double -> Double
forall a. Num a => a -> a -> a
*Double
sinθ
              r₁₁ :: Double
r₁₁ = Double
one_cosθDouble -> Double -> Double
forall a. Num a => a -> a -> a
*Double
e₁Double -> Integer -> Double
forall a b. (Num a, Integral b) => a -> b -> a
^Integer
2  Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
cosθ
              r₁₂ :: Double
r₁₂ = Double
one_cosθDouble -> Double -> Double
forall a. Num a => a -> a -> a
*Double
e₁Double -> Double -> Double
forall a. Num a => a -> a -> a
*Double
e₂ Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
e₀Double -> Double -> Double
forall a. Num a => a -> a -> a
*Double
sinθ
              r₂₀ :: Double
r₂₀ = Double
one_cosθDouble -> Double -> Double
forall a. Num a => a -> a -> a
*Double
e₂Double -> Double -> Double
forall a. Num a => a -> a -> a
*Double
e₀ Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
e₁Double -> Double -> Double
forall a. Num a => a -> a -> a
*Double
sinθ
              r₂₁ :: Double
r₂₁ = Double
one_cosθDouble -> Double -> Double
forall a. Num a => a -> a -> a
*Double
e₂Double -> Double -> Double
forall a. Num a => a -> a -> a
*Double
e₁ Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
e₀Double -> Double -> Double
forall a. Num a => a -> a -> a
*Double
sinθ
              r₂₂ :: Double
r₂₂ = Double
one_cosθDouble -> Double -> Double
forall a. Num a => a -> a -> a
*Double
e₂Double -> Integer -> Double
forall a b. (Num a, Integral b) => a -> b -> a
^Integer
2  Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
cosθ
              cosθ :: Double
cosθ = Double -> Double
forall a. Floating a => a -> a
cos Double
θ
              sinθ :: Double
sinθ = Double -> Double
forall a. Floating a => a -> a
sin Double
θ
              one_cosθ :: Double
one_cosθ = Double
1 Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double -> Double
forall a. Floating a => a -> a
cos Double
θ
       
       e₀ :: Double
e₀ = Double -> Double
forall a. Floating a => a -> a
cos Double
φax Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double -> Double
forall a. Floating a => a -> a
sin Double
θax
       e₁ :: Double
e₁ = Double -> Double
forall a. Floating a => a -> a
sin Double
φax Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double -> Double
forall a. Floating a => a -> a
sin Double
θax
       e₂ :: Double
e₂ = Double -> Double
forall a. Floating a => a -> a
cos Double
θax

rotmatrixForEulerAnglesZYZ :: [] -> [[]]
rotmatrixForEulerAnglesZYZ :: [Double] -> [[Double]]
rotmatrixForEulerAnglesZYZ [Double]
angles
              = [[ Double
cyDouble -> Double -> Double
forall a. Num a => a -> a -> a
*Double
cz₀Double -> Double -> Double
forall a. Num a => a -> a -> a
*Double
cz₁Double -> Double -> Double
forall a. Num a => a -> a -> a
-Double
sz₀Double -> Double -> Double
forall a. Num a => a -> a -> a
*Double
sz₁, -Double
cyDouble -> Double -> Double
forall a. Num a => a -> a -> a
*Double
sz₀Double -> Double -> Double
forall a. Num a => a -> a -> a
*Double
cz₁Double -> Double -> Double
forall a. Num a => a -> a -> a
-Double
cz₀Double -> Double -> Double
forall a. Num a => a -> a -> a
*Double
sz₁,  Double
syDouble -> Double -> Double
forall a. Num a => a -> a -> a
*Double
cz₁ ]
                ,[ Double
cyDouble -> Double -> Double
forall a. Num a => a -> a -> a
*Double
cz₀Double -> Double -> Double
forall a. Num a => a -> a -> a
*Double
sz₁Double -> Double -> Double
forall a. Num a => a -> a -> a
+Double
cz₁Double -> Double -> Double
forall a. Num a => a -> a -> a
*Double
sz₀,  Double
cz₀Double -> Double -> Double
forall a. Num a => a -> a -> a
*Double
cz₁Double -> Double -> Double
forall a. Num a => a -> a -> a
-Double
cyDouble -> Double -> Double
forall a. Num a => a -> a -> a
*Double
sz₀Double -> Double -> Double
forall a. Num a => a -> a -> a
*Double
sz₁,  Double
syDouble -> Double -> Double
forall a. Num a => a -> a -> a
*Double
sz₁ ]
                ,[      -Double
syDouble -> Double -> Double
forall a. Num a => a -> a -> a
*Double
cz₀      ,        Double
syDouble -> Double -> Double
forall a. Num a => a -> a -> a
*Double
sz₀      ,    Double
cy   ]]
 where [Double
cz₀,Double
cy,Double
cz₁] = Double -> Double
forall a. Floating a => a -> a
cos(Double -> Double) -> [Double] -> [Double]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>[Double]
angles
       [Double
sz₀,Double
sy,Double
sz₁] = Double -> Double
forall a. Floating a => a -> a
sin(Double -> Double) -> [Double] -> [Double]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>[Double]
angles

eulerAnglesZYZForMatrix :: [[]] -> []             
eulerAnglesZYZForMatrix :: [[Double]] -> [Double]
eulerAnglesZYZForMatrix [[Double
r₀₀,Double
r₀₁,Double
r₀₂]
                        ,[Double
r₁₀,Double
r₁₁,Double
r₁₂]
                        ,[Double
r₂₀,Double
r₂₁,Double
r₂₂]]
           = [Double
θz₀,Double
θy,Double
θz₁]
 where
         -- Rotation matrix for z₀-y-z₁ rotation, with cy := cos θy etc.:
         --
         -- ⎛ r₀₀ r₀₁ r₀₂ ⎞   ⎛ cz₁ -sz₁ 0 ⎞   ⎛ cy  0  sy ⎞   ⎛ cz₀ -sz₀ 0 ⎞
         -- ⎜ r₁₀ r₁₁ r₁₂ ⎟ = ⎜ sz₁  cz₁ 0 ⎟ · ⎜ 0   1  0  ⎟ · ⎜ sz₀  cz₀ 0 ⎟
         -- ⎝ r₂₀ r₂₁ r₂₂ ⎠   ⎝ 0    0   1 ⎠   ⎝-sy  0  cy ⎠   ⎝ 0    0   1 ⎠
         --
         --      ⎛ cz₁ -sz₁ 0 ⎞   ⎛ cy·cz₀ -cy·sz₀  sy ⎞
         --    = ⎜ sz₁  cz₁ 0 ⎟ · ⎜  sz₀     cz₀    0  ⎟
         --      ⎝  0    0  1 ⎠   ⎝-sy·cz₀  sy·sz₀  cy ⎠
         --
         --      ⎛ cy·cz₀·cz₁−sz₀·sz₁ -cy·sz₀·cz₁−cz₀·sz₁   sy·cz₁ ⎞
         --    = ⎜ cy·cz₀·sz₁+cz₁·sz₀  cz₀·cz₁−cy·sz₀·sz₁   sy·sz₁ ⎟
         --      ⎝      -sy·cz₀              sy·sz₀           cy   ⎠
         --
         -- Here, one can immediately read off
              cy :: Double
cy = Double
r₂₂
         -- ...but the naïve choice
         --    θy = acos cy = acos r₂₂
         -- is unstable. Better:
         --  sqrt(r₂₀²+r₂₁²) = |sy|·(cz₁²+sz₁²) = sy
              sy :: Double
sy = Double -> Double
forall a. Floating a => a -> a
sqrt (Double -> Double) -> Double -> Double
forall a b. (a -> b) -> a -> b
$ Double
r₂₀Double -> Integer -> Double
forall a b. (Num a, Integral b) => a -> b -> a
^Integer
2Double -> Double -> Double
forall a. Num a => a -> a -> a
+Double
r₂₁Double -> Integer -> Double
forall a b. (Num a, Integral b) => a -> b -> a
^Integer
2
              θy :: Double
θy = Double -> Double -> Double
forall a. RealFloat a => a -> a -> a
atan2 Double
sy Double
cy
         -- We can always choose
         --   θz₀ = atan2 sz₀ cz₀
         --       = atan2 (sy·sz₀) (sy·cz₀)  ∀sy‡0
              θz₀ :: Double
θz₀ = Double -> Double -> Double
forall a. RealFloat a => a -> a -> a
atan2 Double
r₂₁ (-Double
r₂₀)  ; sz₀ :: Double
sz₀ = Double -> Double
forall a. Floating a => a -> a
sin Double
θz₀; cz₀ :: Double
cz₀ = Double -> Double
forall a. Floating a => a -> a
cos Double
θz₀
         -- ...noting however that this becomes underconstrained for small |sy|, so
         -- the analogous θz₁ = atan2 r₂₁ (-r₂₀) should /not/ be used. Instead, put
         -- in the y unit vector turned back by θz₀ (θy has no effect):
         -- ⎛ r₀₀ r₀₁ r₀₂ ⎞   ⎛ cy·cz₀ -cy·sz₀  sy ⎞⁻¹  ⎛0⎞   ⎛ cz₁ -sz₁ 0 ⎞⎛0⎞   ⎛-sz₁⎞
         -- ⎜ r₁₀ r₁₁ r₁₂ ⎟ · ⎜  sz₀     cz₀    0  ⎟  $ ⎜1⎟ = ⎜ sz₁  cz₁ 0 ⎟⎜1⎟ = ⎜ cz₁⎟
         -- ⎝ r₂₀ r₂₁ r₂₂ ⎠   ⎝-sy·cz₀  sy·sz₀  cy ⎠    ⎝0⎠   ⎝  0    0  1 ⎠⎝0⎠   ⎝  0 ⎠
         --
         -- Here we have, using orthogonality,
         -- ⎛ cy·cz₀ -cy·sz₀  sy ⎞⁻¹⎛0⎞   ⎛  cy·cz₀  sz₀ -sy·cz₀ ⎞⎛0⎞   ⎛sz₀⎞
         -- ⎜  sz₀     cz₀    0  ⎟  ⎜1⎟ = ⎜ -cy·sz₀  cz₀  sy·sz₀ ⎟⎜1⎟ = ⎜cz₀⎟
         -- ⎝-sy·cz₀  sy·sz₀  cy ⎠  ⎝0⎠   ⎝    sy     0     cy   ⎠⎝0⎠   ⎝ 0 ⎠
              θz₁ :: Double
θz₁ = Double -> Double -> Double
forall a. RealFloat a => a -> a -> a
atan2 (-Double
r₀₀Double -> Double -> Double
forall a. Num a => a -> a -> a
*Double
sz₀ Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
r₀₁Double -> Double -> Double
forall a. Num a => a -> a -> a
*Double
cz₀)
                          ( Double
r₁₀Double -> Double -> Double
forall a. Num a => a -> a -> a
*Double
sz₀ Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
r₁₁Double -> Double -> Double
forall a. Num a => a -> a -> a
*Double
cz₀)

instance Rotatable  where
  type AxisSpace  = ℝP²
  rotateAbout :: AxisSpace S² -> S¹ -> S² -> S²
rotateAbout = (S¹ -> S² -> S²) -> (S¹ -> S² -> S²) -> ℝP² -> S¹ -> S² -> S²
forall m. (S¹ -> m -> m) -> (S¹ -> m -> m) -> ℝP² -> S¹ -> m -> m
rotateViaEulerAnglesYZ
       (\(S¹Polar Double
β) (S²Polar Double
θ Double
φ)
           -> let x₀ :: Double
x₀ = Double -> Double
forall a. Floating a => a -> a
cos Double
φ Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double -> Double
forall a. Floating a => a -> a
sin Double
θ
                  y :: Double
y  = Double -> Double
forall a. Floating a => a -> a
sin Double
φ Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double -> Double
forall a. Floating a => a -> a
sin Double
θ
                  z₀ :: Double
z₀ = Double -> Double
forall a. Floating a => a -> a
cos Double
θ
                  x₁ :: Double
x₁ =  Double
x₀ Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double -> Double
forall a. Floating a => a -> a
cos Double
β Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
z₀ Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double -> Double
forall a. Floating a => a -> a
sin Double
β
                  z₁ :: Double
z₁ = -Double
x₀ Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double -> Double
forall a. Floating a => a -> a
sin Double
β Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
z₀ Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double -> Double
forall a. Floating a => a -> a
cos Double
β
                  rxy :: Double
rxy = Double -> Double
forall a. Floating a => a -> a
sqrt (Double -> Double) -> Double -> Double
forall a b. (a -> b) -> a -> b
$ Double
x₁Double -> Integer -> Double
forall a b. (Num a, Integral b) => a -> b -> a
^Integer
2 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
yDouble -> Integer -> Double
forall a b. (Num a, Integral b) => a -> b -> a
^Integer
2
              in Double -> Double -> S²
forall r. r -> r -> S²_ r
S²Polar (Double -> Double -> Double
forall a. RealFloat a => a -> a -> a
atan2 Double
rxy Double
z₁) (Double -> Double -> Double
forall a. RealFloat a => a -> a -> a
atan2 Double
y Double
x₁) )
       (\γ (S²Polar Double
θ Double
φ) -> case AxisSpace S¹ -> S¹ -> S¹ -> S¹
forall m. Rotatable m => AxisSpace m -> S¹ -> m -> m
rotateAbout AxisSpace S¹
forall r. ℝP⁰_ r
ℝPZero γ (Double -> S¹
forall r. r -> S¹_ r
S¹Polar Double
φ) of
                              S¹Polar Double
φ' -> Double -> Double -> S²
forall r. r -> r -> S²_ r
S²Polar Double
θ Double
φ')

xAxis, yAxis, zAxis :: ℝP²
xAxis :: ℝP²
xAxis = Double -> Double -> ℝP²
forall r. r -> r -> ℝP²_ r
HemisphereℝP²Polar (Double
forall a. Floating a => a
piDouble -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
2) Double
0
yAxis :: ℝP²
yAxis = Double -> Double -> ℝP²
forall r. r -> r -> ℝP²_ r
HemisphereℝP²Polar (Double
forall a. Floating a => a
piDouble -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
2) (Double
forall a. Floating a => a
piDouble -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
2)
zAxis :: ℝP²
zAxis = Double -> Double -> ℝP²
forall r. r -> r -> ℝP²_ r
HemisphereℝP²Polar Double
0      Double
0

infix 5 °

-- | Rotate by an angle specified in degrees.
(°) :: Rotatable m =>  -> AxisSpace m -> m -> m
Double
angle° :: Double -> AxisSpace m -> m -> m
° AxisSpace m
axis = AxisSpace m -> S¹ -> m -> m
forall m. Rotatable m => AxisSpace m -> S¹ -> m -> m
rotateAbout AxisSpace m
axis (S¹ -> m -> m) -> (Double -> S¹) -> Double -> m -> m
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Double -> S¹
forall r. r -> S¹_ r
S¹Polar (Double -> m -> m) -> Double -> m -> m
forall a b. (a -> b) -> a -> b
$ Double
angle Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
forall a. Floating a => a
piDouble -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
180


rotateℝ³AboutCenteredAxis :: ℝP² ->  -> V3  -> V3 
rotateℝ³AboutCenteredAxis :: ℝP² -> S¹ -> V3 Double -> V3 Double
rotateℝ³AboutCenteredAxis ℝP²
axis angle = case ℝP² -> S¹ -> [[Double]]
rotmatrixForAxis ℝP²
axis angle of
     [ [Double
r₀₀,Double
r₀₁,Double
r₀₂]
      ,[Double
r₁₀,Double
r₁₁,Double
r₁₂]
      ,[Double
r₂₀,Double
r₂₁,Double
r₂₂] ] -> \(V3 Double
x Double
y Double
z) -> Double -> Double -> Double -> V3 Double
forall a. a -> a -> a -> V3 a
V3 (Double
r₀₀Double -> Double -> Double
forall a. Num a => a -> a -> a
*Double
x Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
r₀₁Double -> Double -> Double
forall a. Num a => a -> a -> a
*Double
y Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
r₀₂Double -> Double -> Double
forall a. Num a => a -> a -> a
*Double
z)
                                            (Double
r₁₀Double -> Double -> Double
forall a. Num a => a -> a -> a
*Double
x Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
r₁₁Double -> Double -> Double
forall a. Num a => a -> a -> a
*Double
y Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
r₁₂Double -> Double -> Double
forall a. Num a => a -> a -> a
*Double
z)
                                            (Double
r₂₀Double -> Double -> Double
forall a. Num a => a -> a -> a
*Double
x Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
r₂₁Double -> Double -> Double
forall a. Num a => a -> a -> a
*Double
y Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
r₂₂Double -> Double -> Double
forall a. Num a => a -> a -> a
*Double
z)