{-# LANGUAGE FlexibleInstances, TypeFamilies, TypeSynonymInstances #-}
{- |
Module      :  Numeric.QD.Vec
Copyright   :  (c) Claude Heiland-Allen 2011, 2012
License     :  BSD3

Maintainer  :  claude@mathr.co.uk
Stability   :  provisional
Portability :  TypeFamilies, TypeSynonymInstances, FlexibleInstance

Vec instances for QD types.
-}
module Numeric.QD.Vec where
import Data.Vec (NearZero(..), PackedVec(..), Vec2, Vec3, Vec4, (:.)((:.)))
import Numeric.QD (DoubleDouble, QuadDouble)

instance NearZero DoubleDouble where nearZero x = not (abs x > (1e-28))

instance NearZero QuadDouble   where nearZero x = not (abs x > (1e-60))

instance PackedVec (Vec2 DoubleDouble) where
  data Packed (Vec2 DoubleDouble) = Vec2DD {-#UNPACK#-} !DoubleDouble {-#UNPACK#-} !DoubleDouble
  pack (a:.b:.()) = Vec2DD a b
  unpack (Vec2DD a b) = a:.b:.()
  {-# INLINE pack #-}
  {-# INLINE unpack #-}

instance PackedVec (Vec3 DoubleDouble) where
  data Packed (Vec3 DoubleDouble) = Vec3DD {-#UNPACK#-} !DoubleDouble {-#UNPACK#-} !DoubleDouble {-#UNPACK#-} !DoubleDouble
  pack (a:.b:.c:.()) = Vec3DD a b c
  unpack (Vec3DD a b c) = a:.b:.c:.()
  {-# INLINE pack #-}
  {-# INLINE unpack #-}

instance PackedVec (Vec4 DoubleDouble) where
  data Packed (Vec4 DoubleDouble) = Vec4DD {-#UNPACK#-} !DoubleDouble {-#UNPACK#-} !DoubleDouble {-#UNPACK#-} !DoubleDouble {-#UNPACK#-} !DoubleDouble
  pack (a:.b:.c:.d:.()) = Vec4DD a b c d
  unpack (Vec4DD a b c d) = a:.b:.c:.d:.()
  {-# INLINE pack #-}
  {-# INLINE unpack #-}

type Vec2DD = Packed (Vec2 DoubleDouble)
type Vec3DD = Packed (Vec3 DoubleDouble)
type Vec4DD = Packed (Vec4 DoubleDouble)

type Mat22DD = Vec2 (Vec2DD)
type Mat23DD = Vec2 (Vec3DD)
type Mat24DD = Vec2 (Vec4DD)

type Mat32DD = Vec3 (Vec2DD)
type Mat33DD = Vec3 (Vec3DD)
type Mat34DD = Vec3 (Vec4DD)

type Mat42DD = Vec4 (Vec2DD)
type Mat43DD = Vec4 (Vec3DD)
type Mat44DD = Vec4 (Vec4DD)

instance PackedVec (Vec2 QuadDouble) where
  data Packed (Vec2 QuadDouble) = Vec2QD {-#UNPACK#-} !QuadDouble {-#UNPACK#-} !QuadDouble
  pack (a:.b:.()) = Vec2QD a b
  unpack (Vec2QD a b) = a:.b:.()
  {-# INLINE pack #-}
  {-# INLINE unpack #-}

instance PackedVec (Vec3 QuadDouble) where
  data Packed (Vec3 QuadDouble) = Vec3QD {-#UNPACK#-} !QuadDouble {-#UNPACK#-} !QuadDouble {-#UNPACK#-} !QuadDouble
  pack (a:.b:.c:.()) = Vec3QD a b c
  unpack (Vec3QD a b c) = a:.b:.c:.()
  {-# INLINE pack #-}
  {-# INLINE unpack #-}

instance PackedVec (Vec4 QuadDouble) where
  data Packed (Vec4 QuadDouble) = Vec4QD {-#UNPACK#-} !QuadDouble {-#UNPACK#-} !QuadDouble {-#UNPACK#-} !QuadDouble {-#UNPACK#-} !QuadDouble
  pack (a:.b:.c:.d:.()) = Vec4QD a b c d
  unpack (Vec4QD a b c d) = a:.b:.c:.d:.()
  {-# INLINE pack #-}
  {-# INLINE unpack #-}

type Vec2QD = Packed (Vec2 QuadDouble)
type Vec3QD = Packed (Vec3 QuadDouble)
type Vec4QD = Packed (Vec4 QuadDouble)

type Mat22QD = Vec2 (Vec2QD)
type Mat23QD = Vec2 (Vec3QD)
type Mat24QD = Vec2 (Vec4QD)

type Mat32QD = Vec3 (Vec2QD)
type Mat33QD = Vec3 (Vec3QD)
type Mat34QD = Vec3 (Vec4QD)

type Mat42QD = Vec4 (Vec2QD)
type Mat43QD = Vec4 (Vec3QD)
type Mat44QD = Vec4 (Vec4QD)