{-# OPTIONS -fglasgow-exts #-} -- glasgow-exts for multi-parameter type class instances {- | Copyright : (c) Henning Thielemann 2008 License : GPL Maintainer : numericprelude@henning-thielemann.de Stability : provisional Portability : portable See "Algebra.DimensionTerm". -} module Number.DimensionTerm where import qualified Algebra.DimensionTerm as Dim import qualified Algebra.OccasionallyScalar as OccScalar import qualified Algebra.Module as Module import qualified Algebra.Algebraic as Algebraic import qualified Algebra.Field as Field import qualified Algebra.Real as Real import qualified Algebra.Ring as Ring import qualified Algebra.Additive as Additive import Algebra.Field ((/), fromRational', ) import Algebra.Ring ((*), one, fromInteger, ) import Algebra.Additive ((+), (-), zero, negate, ) import Algebra.Module ((*>), ) import System.Random (Random, randomR, random) import NumericPrelude.Tuple (mapFst, ) import PreludeBase import Prelude () {- * Number type -} newtype T u a = Cons a deriving (Eq, Ord) instance (Dim.C u, Show a) => Show (T u a) where showsPrec p x = let disect :: T u a -> (u,a) disect (Cons y) = (undefined, y) (u,z) = disect x in showParen (p >= Dim.appPrec) (showString "DimensionNumber.fromNumberWithDimension " . showsPrec Dim.appPrec u . showString " " . showsPrec Dim.appPrec z) fromNumber :: a -> Scalar a fromNumber = Cons toNumber :: Scalar a -> a toNumber (Cons x) = x fromNumberWithDimension :: Dim.C u => u -> a -> T u a fromNumberWithDimension _ = Cons toNumberWithDimension :: Dim.C u => u -> T u a -> a toNumberWithDimension _ (Cons x) = x instance (Dim.C u, Additive.C a) => Additive.C (T u a) where zero = Cons zero (Cons a) + (Cons b) = Cons (a+b) (Cons a) - (Cons b) = Cons (a-b) negate (Cons a) = Cons (negate a) instance (Dim.C u, Module.C a b) => Module.C a (T u b) where a *> (Cons b) = Cons (a *> b) instance (Dim.IsScalar u, Ring.C a) => Ring.C (T u a) where one = Cons one (Cons a) * (Cons b) = Cons (a*b) fromInteger a = Cons (fromInteger a) instance (Dim.IsScalar u, Field.C a) => Field.C (T u a) where (Cons a) / (Cons b) = Cons (a/b) recip (Cons a) = Cons (Field.recip a) fromRational' a = Cons (fromRational' a) instance (OccScalar.C a b) => OccScalar.C a (Scalar b) where toScalar = OccScalar.toScalar . toNumber toMaybeScalar = OccScalar.toMaybeScalar . toNumber fromScalar = fromNumber . OccScalar.fromScalar instance (Dim.C u, Random a) => Random (T u a) where randomR (Cons l, Cons u) = mapFst Cons . randomR (l,u) random = mapFst Cons . random infixl 7 &*&, *& infixl 7 &/& (&*&) :: (Dim.C u, Dim.C v, Ring.C a) => T u a -> T v a -> T (Dim.Mul u v) a (&*&) (Cons x) (Cons y) = Cons (x Ring.* y) (&/&) :: (Dim.C u, Dim.C v, Field.C a) => T u a -> T v a -> T (Dim.Mul u (Dim.Recip v)) a (&/&) (Cons x) (Cons y) = Cons (x Field./ y) mulToScalar :: (Dim.C u, Ring.C a) => T u a -> T (Dim.Recip u) a -> a mulToScalar x y = cancelToScalar (x &*& y) divToScalar :: (Dim.C u, Field.C a) => T u a -> T u a -> a divToScalar x y = cancelToScalar (x &/& y) cancelToScalar :: (Dim.C u) => T (Dim.Mul u (Dim.Recip u)) a -> a cancelToScalar = toNumber . rewriteDimension Dim.cancelRight recip :: (Dim.C u, Field.C a) => T u a -> T (Dim.Recip u) a recip (Cons x) = Cons (Field.recip x) unrecip :: (Dim.C u, Field.C a) => T (Dim.Recip u) a -> T u a unrecip (Cons x) = Cons (Field.recip x) sqr :: (Dim.C u, Ring.C a) => T u a -> T (Dim.Sqr u) a sqr x = x &*& x sqrt :: (Dim.C u, Algebraic.C a) => T (Dim.Sqr u) a -> T u a sqrt (Cons x) = Cons (Algebraic.sqrt x) abs :: (Dim.C u, Real.C a) => T u a -> T u a abs (Cons x) = Cons (Real.abs x) absSignum :: (Dim.C u, Real.C a) => T u a -> (T u a, a) absSignum x0@(Cons x) = (abs x0, Real.signum x) scale, (*&) :: (Dim.C u, Ring.C a) => a -> T u a -> T u a scale x (Cons y) = Cons (x Ring.* y) (*&) = scale rewriteDimension :: (Dim.C u, Dim.C v) => (u -> v) -> T u a -> T v a rewriteDimension _ (Cons x) = Cons x {- type class for converting Dim types to Dim value is straight-forward class SIDimensionType u where dynamic :: DimensionNumber u a -> SIValue a instance SIDimensionType Scalar where dynamic (DimensionNumber.Cons x) = SIValue.scalar x instance SIDimensionType Length where dynamic (DimensionNumber.Cons x) = SIValue.meter * dynamic x -} {- * Example constructors -} type Scalar a = T Dim.Scalar a type Length a = T Dim.Length a type Time a = T Dim.Time a type Mass a = T Dim.Mass a type Charge a = T Dim.Charge a type Angle a = T Dim.Angle a type Temperature a = T Dim.Temperature a type Information a = T Dim.Information a type Frequency a = T Dim.Frequency a type Voltage a = T Dim.Voltage a scalar :: a -> Scalar a scalar = fromNumber length :: a -> Length a length = Cons time :: a -> Time a time = Cons mass :: a -> Mass a mass = Cons charge :: a -> Charge a charge = Cons frequency :: a -> Frequency a frequency = Cons angle :: a -> Angle a angle = Cons temperature :: a -> Temperature a temperature = Cons information :: a -> Information a information = Cons voltage :: a -> Voltage a voltage = Cons