{-# LANGUAGE RebindableSyntax #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FlexibleInstances #-}

{- |
Abstraction of normed vector spaces
-}

module Algebra.NormedSpace.Maximum where

import NumericPrelude.Base
import NumericPrelude.Numeric
import qualified Prelude as P

import qualified Number.Ratio as Ratio

import qualified Algebra.PrincipalIdealDomain as PID
import qualified Algebra.ToInteger as ToInteger
import qualified Algebra.RealRing as RealRing
import qualified Algebra.Module   as Module

import qualified Data.Complex as Complex98
import qualified Data.Foldable as Fold


class (RealRing.C a, Module.C a v) => C a v where
  norm :: v -> a

{- |
Default definition for 'norm' that is based on 'Fold.Foldable' class.
-}
{-# INLINE normFoldable #-}
normFoldable ::
   (C a v, Fold.Foldable f) => f v -> a
normFoldable :: f v -> a
normFoldable =
   (a -> v -> a) -> a -> f v -> a
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
Fold.foldl (\a
a v
v -> a -> a -> a
forall a. Ord a => a -> a -> a
max a
a (v -> a
forall a v. C a v => v -> a
norm v
v)) a
forall a. C a => a
zero

{- |
Default definition for 'norm' that is based on 'Fold.Foldable' class
and the argument vector has at least one component.
-}
{-# INLINE normFoldable1 #-}
normFoldable1 ::
   (C a v, Fold.Foldable f, Functor f) => f v -> a
normFoldable1 :: f v -> a
normFoldable1 =
   (a -> a -> a) -> f a -> a
forall (t :: * -> *) a. Foldable t => (a -> a -> a) -> t a -> a
Fold.foldl1 a -> a -> a
forall a. Ord a => a -> a -> a
max (f a -> a) -> (f v -> f a) -> f v -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (v -> a) -> f v -> f a
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap v -> a
forall a v. C a v => v -> a
norm

{-
instance (Ring.C a, Algebra.Module a a) => C a a where
  norm = abs
-}
instance C Float Float where
  norm :: Float -> Float
norm = Float -> Float
forall a. C a => a -> a
abs

instance C Double Double where
  norm :: Double -> Double
norm = Double -> Double
forall a. C a => a -> a
abs

instance C Int Int where
  norm :: Int -> Int
norm = Int -> Int
forall a. C a => a -> a
abs

instance C Integer Integer where
  norm :: Integer -> Integer
norm = Integer -> Integer
forall a. C a => a -> a
abs


instance (RealRing.C a, ToInteger.C a, PID.C a) => C (Ratio.T a) (Ratio.T a) where
  norm :: T a -> T a
norm = T a -> T a
forall a. C a => a -> a
abs

instance (Ord a, C a v0, C a v1) => C a (v0, v1) where
  norm :: (v0, v1) -> a
norm (v0
x0,v1
x1) = a -> a -> a
forall a. Ord a => a -> a -> a
max (v0 -> a
forall a v. C a v => v -> a
norm v0
x0) (v1 -> a
forall a v. C a v => v -> a
norm v1
x1)

instance (Ord a, C a v0, C a v1, C a v2) => C a (v0, v1, v2) where
  norm :: (v0, v1, v2) -> a
norm (v0
x0,v1
x1,v2
x2) = (v0 -> a
forall a v. C a v => v -> a
norm v0
x0) a -> a -> a
forall a. Ord a => a -> a -> a
`max` (v1 -> a
forall a v. C a v => v -> a
norm v1
x1) a -> a -> a
forall a. Ord a => a -> a -> a
`max` (v2 -> a
forall a v. C a v => v -> a
norm v2
x2)

instance (Ord a, C a v) => C a [v] where
  norm :: [v] -> a
norm = (a -> a -> a) -> a -> [a] -> a
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl a -> a -> a
forall a. Ord a => a -> a -> a
max a
forall a. C a => a
zero ([a] -> a) -> ([v] -> [a]) -> [v] -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (v -> a) -> [v] -> [a]
forall a b. (a -> b) -> [a] -> [b]
map v -> a
forall a v. C a v => v -> a
norm
{-
Since the norm is always non-negative,
we can use zero as identity element.
  norm = maximum . map norm
-}


instance (C a v, P.RealFloat v) => C a (Complex98.Complex v) where
  norm :: Complex v -> a
norm (v
x0 Complex98.:+ v
x1) = a -> a -> a
forall a. Ord a => a -> a -> a
max (v -> a
forall a v. C a v => v -> a
norm v
x0) (v -> a
forall a v. C a v => v -> a
norm v
x1)