X-Git-Url: http://gitweb.michael.orlitzky.com/?a=blobdiff_plain;f=src%2FNormed.hs;h=6f34a8dca406c13393896179b6b08c023874e9a3;hb=be2ec3ca8e6fda229e3ca608dcc75e085b3a0b0f;hp=8554bd97f2eba0bd66a4b458a05cdb334f2e4f87;hpb=fe73028041fe3becce6ce1ff268181d55d54a011;p=numerical-analysis.git diff --git a/src/Normed.hs b/src/Normed.hs index 8554bd9..6f34a8d 100644 --- a/src/Normed.hs +++ b/src/Normed.hs @@ -1,5 +1,6 @@ {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE RebindableSyntax #-} + -- | The 'Normed' class represents elements of a normed vector -- space. We define instances for all common numeric types. module Normed @@ -7,28 +8,29 @@ where import BigFloat -import NumericPrelude hiding (abs) -import Algebra.Absolute -import Algebra.Field -import Algebra.Ring -import Algebra.ToInteger - --- Since the norm is defined on a vector space, we should be able to --- add and subtract anything on which a norm is defined. Of course --- 'Num' is a bad choice here, but we really prefer to use the normal --- addition and subtraction operators. -class (Algebra.Ring.C a, Algebra.Absolute.C a) => Normed a where - norm_p :: (Algebra.ToInteger.C c, - Algebra.Field.C b, - Algebra.Absolute.C b) - => c -> a -> b - - norm_infty :: (Algebra.Field.C b, - Algebra.Absolute.C b) - => a -> b +import NumericPrelude hiding ( abs ) +import Algebra.Absolute ( abs ) +import qualified Algebra.Absolute as Absolute +import qualified Algebra.Algebraic as Algebraic +import Algebra.Algebraic ( root ) +import qualified Algebra.RealField as RealField +import qualified Algebra.ToInteger as ToInteger +import qualified Algebra.ToRational as ToRational ( C ) +import Data.Vector.Fixed ( S, Z ) +import qualified Data.Vector.Fixed as V ( + Arity, + map, + maximum ) +import Data.Vector.Fixed.Boxed ( Vec ) + +import Linear.Vector ( element_sum ) + +class Normed a where + norm_p :: (ToInteger.C c, Algebraic.C b, Absolute.C b) => c -> a -> b + norm_infty :: (RealField.C b) => a -> b -- | The "usual" norm. Defaults to the Euclidean norm. - norm :: (Algebra.Field.C b, Algebra.Absolute.C b) => a -> b + norm :: (Algebraic.C b, Absolute.C b) => a -> b norm = norm_p (2 :: Integer) -- Define instances for common numeric types. @@ -51,3 +53,38 @@ instance Normed Float where instance Normed Double where norm_p _ = abs . fromRational' . toRational norm_infty = abs . fromRational' . toRational + + +-- | 'Normed' instance for vectors of length zero. These are easy. +instance Normed (Vec Z a) where + norm_p _ = const (fromInteger 0) + norm_infty = const (fromInteger 0) + + +-- | 'Normed' instance for vectors of length greater than zero. We +-- need to know that the length is non-zero in order to invoke +-- V.maximum. We will generally be working with n-by-1 /matrices/ +-- instead of vectors, but sometimes it's convenient to have these +-- instances anyway. +-- +-- Examples: +-- +-- >>> import Data.Vector.Fixed (mk3) +-- >>> import Linear.Vector (Vec3) +-- >>> let b = mk3 1 2 3 :: Vec3 Double +-- >>> norm_p 1 b :: Double +-- 6.0 +-- >>> norm b == sqrt 14 +-- True +-- >>> norm_infty b :: Double +-- 3.0 +-- +instance (V.Arity n, Absolute.C a, ToRational.C a, Ord a) + => Normed (Vec (S n) a) where + norm_p p x = + (root p') $ element_sum $ V.map element_function x + where + element_function y = fromRational' $ (toRational y)^p' + p' = toInteger p + + norm_infty x = fromRational' $ toRational $ V.maximum $ V.map abs x