{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances #-}
module Numeric.Quadrance.Class
  ( Quadrance(..)
  ) where

import Data.Int
import Data.Word
import Numeric.Additive.Class
import Numeric.Algebra.Class
import Numeric.Algebra.Unital
import Numeric.Rig.Class
import Numeric.Natural
import Prelude hiding ((+),(*))

-- a module with a computable squared norm
class Additive r => Quadrance r m where
  quadrance :: m -> r

instance Quadrance () a where 
  quadrance _ = ()

instance (Additive r, Monoidal r) => Quadrance r () where
  quadrance _ = zero

instance (Quadrance r a, Quadrance r b) => Quadrance r (a,b) where
  quadrance (a,b) = quadrance a + quadrance b

instance (Quadrance r a, Quadrance r b, Quadrance r c) => Quadrance r (a,b,c) where
  quadrance (a,b,c) = quadrance a + quadrance b + quadrance c

instance (Quadrance r a, Quadrance r b, Quadrance r c, Quadrance r d) => Quadrance r (a,b,c,d) where
  quadrance (a,b,c,d) = quadrance a + quadrance b + quadrance c + quadrance d

instance (Quadrance r a, Quadrance r b, Quadrance r c, Quadrance r d, Quadrance r e) => Quadrance r (a,b,c,d,e) where
  quadrance (a,b,c,d,e) = quadrance a + quadrance b + quadrance c + quadrance d + quadrance e

instance Rig r => Quadrance r Bool where
  quadrance False = zero
  quadrance True  = one

sq :: Multiplicative r => r -> r
sq r = r * r

instance Rig r => Quadrance r Int where
  quadrance = fromNatural . fromIntegral . sq . toInteger

instance Rig r => Quadrance r Word where
  quadrance = fromNatural . fromIntegral . sq . toInteger

instance Rig r => Quadrance r Natural where
  quadrance = fromNatural . fromIntegral . sq . toInteger

instance Rig r => Quadrance r Integer where 
  quadrance = fromNatural . fromInteger . sq

instance Rig r => Quadrance r Int8 where 
  quadrance = fromNatural . fromIntegral . sq . toInteger

instance Rig r => Quadrance r Int16 where 
  quadrance = fromNatural . fromIntegral . sq . toInteger

instance Rig r => Quadrance r Int32 where
  quadrance = fromNatural . fromIntegral . sq . toInteger

instance Rig r => Quadrance r Int64 where
  quadrance = fromNatural . fromIntegral . sq . toInteger

instance Rig r => Quadrance r Word8 where 
  quadrance = fromNatural . fromIntegral . sq . toInteger

instance Rig r => Quadrance r Word16 where 
  quadrance = fromNatural . fromIntegral . sq . toInteger

instance Rig r => Quadrance r Word32 where
  quadrance = fromNatural . fromIntegral . sq . toInteger

instance Rig r => Quadrance r Word64 where
  quadrance = fromNatural . fromIntegral . sq . toInteger

{-
instance InvolutiveSemiring r => Quadrance r (Complex r) where
  quadrance n = e (adjoint n * n)

instance InvolutiveSemiring r => Quadrance r (Quaternion r) where
  quadrance n = e (adjoint n * n)
-}