packages feed

manifolds 0.1.0.0 → 0.1.0.2

raw patch · 5 files changed

+1438/−33 lines, 5 filesdep +MemoTriedep +taggeddep ~constrained-categoriesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependencies added: MemoTrie, tagged

Dependency ranges changed: constrained-categories

API changes (from Hackage documentation)

- Data.Manifold: S2 :: Double -> Double -> S2
- Data.Manifold: data S2
- Data.Manifold: instance CartesianProxy (:-->)
- Data.Manifold: instance HasBasis ()
- Data.Manifold: instance HasProxy (:-->)
- Data.Manifold: instance InnerSpace ()
- Data.Manifold: instance PointProxy CntnFuncValue (:-->) d c
- Data.Manifold: instance VectorSpace ()
- Data.Manifold: φParamS2 :: S2 -> Double
- Data.Manifold: ϑParamS2 :: S2 -> Double
+ Data.LinearMap.HerMetric: (<.>^) :: HasMetric v => DualSpace v -> v -> Scalar v
+ Data.LinearMap.HerMetric: (^<.>) :: HasMetric v => v -> DualSpace v -> Scalar v
+ Data.LinearMap.HerMetric: adjoint :: (HasMetric v, HasMetric w, Scalar w ~ Scalar v) => (v :-* w) -> DualSpace w :-* DualSpace v
+ Data.LinearMap.HerMetric: class (HasBasis v, VectorSpace (Scalar v), HasTrie (Basis v), VectorSpace (DualSpace v), HasBasis (DualSpace v), Scalar v ~ Scalar (DualSpace v), Basis v ~ Basis (DualSpace v)) => HasMetric v where type family DualSpace v :: * type instance DualSpace v = v
+ Data.LinearMap.HerMetric: data HerMetric v
+ Data.LinearMap.HerMetric: data HerMetric' v
+ Data.LinearMap.HerMetric: doubleDual :: (HasMetric v, HasMetric (DualSpace v)) => v -> DualSpace (DualSpace v)
+ Data.LinearMap.HerMetric: doubleDual' :: (HasMetric v, HasMetric (DualSpace v)) => DualSpace (DualSpace v) -> v
+ Data.LinearMap.HerMetric: dualiseMetric :: (HasMetric v, HasMetric (DualSpace v)) => HerMetric (DualSpace v) -> HerMetric' v
+ Data.LinearMap.HerMetric: dualiseMetric' :: (HasMetric v, HasMetric (DualSpace v)) => HerMetric' v -> HerMetric (DualSpace v)
+ Data.LinearMap.HerMetric: functional :: HasMetric v => (v -> Scalar v) -> DualSpace v
+ Data.LinearMap.HerMetric: instance (HasMetric v, HasMetric w, Scalar v ~ Scalar w, HasMetric (DualSpace v), DualSpace (DualSpace v) ~ v, HasMetric (DualSpace w), DualSpace (DualSpace w) ~ w) => HasMetric (v, w)
+ Data.LinearMap.HerMetric: instance (HasMetric v, v ~ DualSpace v, Num (Scalar v)) => Num (HerMetric v)
+ Data.LinearMap.HerMetric: instance (HasMetric v, v ~ Scalar v, v ~ DualSpace v, Floating v) => Floating (HerMetric v)
+ Data.LinearMap.HerMetric: instance (HasMetric v, v ~ Scalar v, v ~ DualSpace v, Fractional v) => Fractional (HerMetric v)
+ Data.LinearMap.HerMetric: instance HasMetric Double
+ Data.LinearMap.HerMetric: instance HasMetric v => AdditiveGroup (HerMetric v)
+ Data.LinearMap.HerMetric: instance HasMetric v => AdditiveGroup (HerMetric' v)
+ Data.LinearMap.HerMetric: instance HasMetric v => VectorSpace (HerMetric v)
+ Data.LinearMap.HerMetric: instance HasMetric v => VectorSpace (HerMetric' v)
+ Data.LinearMap.HerMetric: instance VectorSpace k => HasMetric (ZeroDim k)
+ Data.LinearMap.HerMetric: metriScale :: (HasMetric v, Floating (Scalar v)) => HerMetric v -> v -> v
+ Data.LinearMap.HerMetric: metriScale' :: (HasMetric v, Floating (Scalar v)) => HerMetric' v -> DualSpace v -> DualSpace v
+ Data.LinearMap.HerMetric: metric :: (HasMetric v, Floating (Scalar v)) => HerMetric v -> v -> Scalar v
+ Data.LinearMap.HerMetric: metric' :: (HasMetric v, Floating (Scalar v)) => HerMetric' v -> DualSpace v -> Scalar v
+ Data.LinearMap.HerMetric: metricSq :: HasMetric v => HerMetric v -> v -> Scalar v
+ Data.LinearMap.HerMetric: metricSq' :: HasMetric v => HerMetric' v -> DualSpace v -> Scalar v
+ Data.LinearMap.HerMetric: metrics :: (HasMetric v, Floating (Scalar v)) => HerMetric v -> [v] -> Scalar v
+ Data.LinearMap.HerMetric: metrics' :: (HasMetric v, Floating (Scalar v)) => HerMetric' v -> [DualSpace v] -> Scalar v
+ Data.LinearMap.HerMetric: projector :: HasMetric v => DualSpace v -> HerMetric v
+ Data.LinearMap.HerMetric: projector' :: HasMetric v => v -> HerMetric' v
+ Data.LinearMap.HerMetric: transformMetric :: (HasMetric v, HasMetric w, Scalar v ~ Scalar w) => (w :-* v) -> HerMetric v -> HerMetric w
+ Data.LinearMap.HerMetric: transformMetric' :: (HasMetric v, HasMetric w, Scalar v ~ Scalar w) => (v :-* w) -> HerMetric' v -> HerMetric' w
+ Data.Manifold: NegativeHalfSphere :: S⁰
+ Data.Manifold: Origin :: ZeroDim k
+ Data.Manifold: PositiveHalfSphere :: S⁰
+ Data.Manifold: S² :: !Double -> !Double -> S²
+ Data.Manifold: S¹ :: Double -> S¹
+ Data.Manifold: class NaturallyEmbedded m v
+ Data.Manifold: coEmbed :: NaturallyEmbedded m v => v -> m
+ Data.Manifold: data S²
+ Data.Manifold: data S⁰
+ Data.Manifold: data ZeroDim k
+ Data.Manifold: embed :: NaturallyEmbedded m v => m -> v
+ Data.Manifold: instance CartesianAgent (:-->)
+ Data.Manifold: instance HasAgent (:-->)
+ Data.Manifold: instance PointAgent CntnFuncValue (:-->) d c
+ Data.Manifold: newtype S¹
+ Data.Manifold: type ℝ² = (ℝ, ℝ)
+ Data.Manifold: type ℝ³ = (ℝ², ℝ)
+ Data.Manifold: φParamS² :: S² -> !Double
+ Data.Manifold: φParamS¹ :: S¹ -> Double
+ Data.Manifold: ϑParamS² :: S² -> !Double
+ Data.Manifold.PseudoAffine: (.+~^) :: PseudoAffine x => x -> PseudoDiff x -> x
+ Data.Manifold.PseudoAffine: (.-~.) :: PseudoAffine x => x -> x -> Option (PseudoDiff x)
+ Data.Manifold.PseudoAffine: class PseudoAffine x where type family PseudoDiff x :: *
+ Data.Manifold.PseudoAffine: data Differentiable s d c
+ Data.Manifold.PseudoAffine: data PWDiffable s d c
+ Data.Manifold.PseudoAffine: data RWDiffable s d c
+ Data.Manifold.PseudoAffine: data Region s m
+ Data.Manifold.PseudoAffine: instance (LinearManifold s v, LocallyScalable s a, Floating s) => AdditiveGroup (DfblFuncValue s a v)
+ Data.Manifold.PseudoAffine: instance (LinearManifold s v, LocallyScalable s a, RealDimension s) => AdditiveGroup (PWDfblFuncValue s a v)
+ Data.Manifold.PseudoAffine: instance (LinearManifold s v, LocallyScalable s a, RealDimension s) => AdditiveGroup (RWDfblFuncValue s a v)
+ Data.Manifold.PseudoAffine: instance (PseudoAffine a, PseudoAffine b) => PseudoAffine (a, b)
+ Data.Manifold.PseudoAffine: instance (PseudoAffine a, PseudoAffine b, PseudoAffine c) => PseudoAffine (a, b, c)
+ Data.Manifold.PseudoAffine: instance (RealDimension n, LocallyScalable n a) => Floating (RWDfblFuncValue n a n)
+ Data.Manifold.PseudoAffine: instance (RealDimension n, LocallyScalable n a) => Fractional (PWDfblFuncValue n a n)
+ Data.Manifold.PseudoAffine: instance (RealDimension n, LocallyScalable n a) => Fractional (RWDfblFuncValue n a n)
+ Data.Manifold.PseudoAffine: instance (RealDimension n, LocallyScalable n a) => Num (DfblFuncValue n a n)
+ Data.Manifold.PseudoAffine: instance (RealDimension n, LocallyScalable n a) => Num (PWDfblFuncValue n a n)
+ Data.Manifold.PseudoAffine: instance (RealDimension n, LocallyScalable n a) => Num (RWDfblFuncValue n a n)
+ Data.Manifold.PseudoAffine: instance (RealDimension s) => Cartesian (PWDiffable s)
+ Data.Manifold.PseudoAffine: instance (RealDimension s) => Cartesian (RWDiffable s)
+ Data.Manifold.PseudoAffine: instance (RealDimension s) => CartesianAgent (PWDiffable s)
+ Data.Manifold.PseudoAffine: instance (RealDimension s) => CartesianAgent (RWDiffable s)
+ Data.Manifold.PseudoAffine: instance (RealDimension s) => Category (PWDiffable s)
+ Data.Manifold.PseudoAffine: instance (RealDimension s) => Category (RWDiffable s)
+ Data.Manifold.PseudoAffine: instance (RealDimension s) => EnhancedCat (PWDiffable s) (Differentiable s)
+ Data.Manifold.PseudoAffine: instance (RealDimension s) => EnhancedCat (RWDiffable s) (Differentiable s)
+ Data.Manifold.PseudoAffine: instance (RealDimension s) => EnhancedCat (RWDiffable s) (PWDiffable s)
+ Data.Manifold.PseudoAffine: instance (RealDimension s) => HasAgent (PWDiffable s)
+ Data.Manifold.PseudoAffine: instance (RealDimension s) => HasAgent (RWDiffable s)
+ Data.Manifold.PseudoAffine: instance (RealDimension s) => Morphism (PWDiffable s)
+ Data.Manifold.PseudoAffine: instance (RealDimension s) => Morphism (RWDiffable s)
+ Data.Manifold.PseudoAffine: instance (RealDimension s) => PointAgent (PWDfblFuncValue s) (PWDiffable s) a x
+ Data.Manifold.PseudoAffine: instance (RealDimension s) => PointAgent (RWDfblFuncValue s) (RWDiffable s) a x
+ Data.Manifold.PseudoAffine: instance (RealDimension s) => PreArrow (PWDiffable s)
+ Data.Manifold.PseudoAffine: instance (RealDimension s) => PreArrow (RWDiffable s)
+ Data.Manifold.PseudoAffine: instance (RealDimension s) => WellPointed (PWDiffable s)
+ Data.Manifold.PseudoAffine: instance (RealDimension s) => WellPointed (RWDiffable s)
+ Data.Manifold.PseudoAffine: instance PseudoAffine (ZeroDim k)
+ Data.Manifold.PseudoAffine: instance PseudoAffine Double
+ Data.Manifold.PseudoAffine: instance PseudoAffine Rational
+ Data.Manifold.PseudoAffine: instance PseudoAffine S²
+ Data.Manifold.PseudoAffine: instance PseudoAffine S¹
+ Data.Manifold.PseudoAffine: instance VectorSpace s => Cartesian (Differentiable s)
+ Data.Manifold.PseudoAffine: instance VectorSpace s => CartesianAgent (Differentiable s)
+ Data.Manifold.PseudoAffine: instance VectorSpace s => Category (Differentiable s)
+ Data.Manifold.PseudoAffine: instance VectorSpace s => HasAgent (Differentiable s)
+ Data.Manifold.PseudoAffine: instance VectorSpace s => Morphism (Differentiable s)
+ Data.Manifold.PseudoAffine: instance VectorSpace s => PointAgent (DfblFuncValue s) (Differentiable s) a x
+ Data.Manifold.PseudoAffine: instance VectorSpace s => PreArrow (Differentiable s)
+ Data.Manifold.PseudoAffine: instance VectorSpace s => WellPointed (Differentiable s)

Files

+ Data/LinearMap/HerMetric.hs view
@@ -0,0 +1,269 @@+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE FlexibleContexts           #-}+{-# LANGUAGE TypeOperators              #-}+{-# LANGUAGE TupleSections              #-}+{-# LANGUAGE TypeFamilies               #-}+{-# LANGUAGE UndecidableInstances       #-}+{-# LANGUAGE StandaloneDeriving         #-}+{-# LANGUAGE ConstraintKinds            #-}+{-# LANGUAGE ScopedTypeVariables        #-}+++++module Data.LinearMap.HerMetric (+  -- * Metric operator types+    HerMetric, HerMetric'+  -- * Evaluating metrics+  , metricSq, metricSq', metric, metric', metrics, metrics'+  -- * Defining metrics by projectors+  , projector, projector'+  -- * Utility+  , adjoint+  , transformMetric, transformMetric'+  , dualiseMetric, dualiseMetric'+  , HasMetric(..)+  , (^<.>)+  , metriScale, metriScale'+  ) where+    ++    ++import Prelude hiding ((^))++import Data.VectorSpace+import Data.LinearMap+import Data.Basis+import Data.MemoTrie++import Control.Applicative+    +import Data.Manifold.Types+++infixr 7 <.>^, ^<.>+++-- | 'HerMetric' is a portmanteau of /Hermitian/ and /metric/ (in the sense as+--   used in e.g. general relativity &#x2013; though those particular ones aren't positive+--   definite and thus not really metrics).+-- +--   Mathematically, there are two directly equivalent ways to describe such a metric:+--   as a bilinear mapping of two vectors to a scalar, or as a linear mapping from+--   a vector space to its dual space. We choose the latter, though you can always+--   as well think of metrics as &#x201c;quadratic dual vectors&#x201d;.+--   +--   Yet other possible interpretations of this type include /density matrix/ (as in+--   quantum mechanics), /standard range of statistical fluctuations/, and /volume element/.+newtype HerMetric v = HerMetric { getHerMetric :: v :-* DualSpace v }+++instance HasMetric v => AdditiveGroup (HerMetric v) where+  zeroV = HerMetric zeroV+  negateV (HerMetric m) = HerMetric $ negateV m+  HerMetric m ^+^ HerMetric n = HerMetric $ m ^+^ n+instance HasMetric v => VectorSpace (HerMetric v) where+  type Scalar (HerMetric v) = Scalar v+  s *^ (HerMetric m) = HerMetric $ s *^ m ++-- | A metric on the dual space; equivalent to a linear mapping from the dual space+--   to the original vector space.+-- +--   Prime-versions of the functions in this module target those dual-space metrics, so+--   we can avoid some explicit handling of double-dual spaces.+newtype HerMetric' v = HerMetric' { dualMetric :: DualSpace v :-* v }+instance (HasMetric v) => AdditiveGroup (HerMetric' v) where+  zeroV = HerMetric' zeroV+  negateV (HerMetric' m) = HerMetric' $ negateV m+  HerMetric' m ^+^ HerMetric' n = HerMetric' $ m ^+^ n+instance (HasMetric v) => VectorSpace (HerMetric' v) where+  type Scalar (HerMetric' v) = Scalar v+  s *^ (HerMetric' m) = HerMetric' $ s *^ m +    ++-- | A metric on @v@ that simply yields the squared overlap of a vector with the+--   given dual-space reference.+--   +--   It will perhaps be the most common way of defining 'HerMetric' values to start+--   with such dual-space vectors and superimpose the projectors using the 'VectorSpace'+--   instance; e.g. @'projector' (1,0) '^+^' 'projector' (0,2)@ yields a hermitian operator+--   describing the ellipsoid span of the vectors /e/&#x2080; and 2&#x22c5;/e/&#x2081;.+--   Metrics generated this way are positive definite if no negative coefficients have+--   been introduced with the '*^' scaling operator or with '^-^'.+projector :: HasMetric v => DualSpace v -> HerMetric v+projector u = HerMetric (linear $ \v -> u ^* (u<.>^v))++projector' :: HasMetric v => v -> HerMetric' v+projector' v = HerMetric' . linear $ \u -> v ^* (v^<.>u)++++-- | Evaluate a vector through a metric. For the canonical metric on a Hilbert space,+--   this will be simply 'magnitudeSq'.+metricSq :: HasMetric v => HerMetric v -> v -> Scalar v+metricSq (HerMetric m) v = lapply m v <.>^ v++metricSq' :: HasMetric v => HerMetric' v -> DualSpace v -> Scalar v+metricSq' (HerMetric' m) u = lapply m u ^<.> u++-- | Evaluate a vector's &#x201c;magnitude&#x201d; through a metric. This assumes an actual+--   mathematical metric, i.e. positive definite &#x2013; otherwise the internally used+--   square root may get negative arguments (though it can still produce results if the+--   scalars are complex; however, complex spaces aren't supported yet).+metric :: (HasMetric v, Floating (Scalar v)) => HerMetric v -> v -> Scalar v+metric (HerMetric m) v = sqrt $ lapply m v <.>^ v++metric' :: (HasMetric v, Floating (Scalar v)) => HerMetric' v -> DualSpace v -> Scalar v+metric' (HerMetric' m) u = sqrt $ lapply m u ^<.> u++metriScale :: (HasMetric v, Floating (Scalar v)) => HerMetric v -> v -> v+metriScale m v = metric m v *^ v++metriScale' :: (HasMetric v, Floating (Scalar v))+                 => HerMetric' v -> DualSpace v -> DualSpace v+metriScale' m v = metric' m v *^ v+++-- | Square-sum over the metrics for each dual-space vector.+-- +-- @+-- metrics m vs &#x2261; sqrt . sum $ metricSq m '<$>' vs+-- @+metrics :: (HasMetric v, Floating (Scalar v)) => HerMetric v -> [v] -> Scalar v+metrics m vs = sqrt . sum $ metricSq m <$> vs++metrics' :: (HasMetric v, Floating (Scalar v)) => HerMetric' v -> [DualSpace v] -> Scalar v+metrics' m vs = sqrt . sum $ metricSq' m <$> vs+++transformMetric :: (HasMetric v, HasMetric w, Scalar v ~ Scalar w)+           => (w :-* v) -> HerMetric v -> HerMetric w+transformMetric t (HerMetric m) = HerMetric $ adjoint t *.* m *.* t++transformMetric' :: ( HasMetric v, HasMetric w, Scalar v ~ Scalar w )+           => (v :-* w) -> HerMetric' v -> HerMetric' w+transformMetric' t (HerMetric' m)+    = HerMetric' $ t *.* m *.* adjoint t++dualiseMetric :: (HasMetric v, HasMetric (DualSpace v))+      => HerMetric (DualSpace v) -> HerMetric' v+dualiseMetric (HerMetric m) = HerMetric' $ linear doubleDual' *.* m++dualiseMetric' :: (HasMetric v, HasMetric (DualSpace v))+      => HerMetric' v -> HerMetric (DualSpace v)+dualiseMetric' (HerMetric' m) = HerMetric $ linear doubleDual *.* m+++-- | While the main purpose of this class is to express 'HerMetric', it's actually+--   all about dual spaces.+class ( HasBasis v, VectorSpace (Scalar v), HasTrie (Basis v)+      , VectorSpace (DualSpace v), HasBasis (DualSpace v)+      , Scalar v ~ Scalar (DualSpace v), Basis v ~ Basis (DualSpace v) )+    => HasMetric v where+        +  -- | @'DualSpace' v@ is isomorphic to the space of linear functionals on @v@, i.e.+  --   @v ':-*' 'Scalar' v@.+  --   Typically (for all Hilbert- / 'InnerSpace's) this is in turn isomorphic to @v@+  --   itself, which will be rather more efficient (hence the distinction between a+  --   vector space and its dual is often neglected or reduced to &#x201c;column vs row+  --   vectors&#x201d;).+  --   Mathematically though, it makes sense to keep the concepts apart, even if ultimately+  --   @'DualSpace' v ~ v@ (which needs not /always/ be the case, though!).+  type DualSpace v :: *+  type DualSpace v = v+      +  -- | Apply a dual space vector (aka linear functional) to a vector.+  (<.>^) :: DualSpace v -> v -> Scalar v+            +  -- | Interpret a functional as a dual-space vector. Like 'linear', this /assumes/+  --   (completely unchecked) that the supplied function is linear.+  functional :: (v -> Scalar v) -> DualSpace v+  +  -- | While isomorphism between a space and its dual isn't generally canonical,+  --   the /double-dual/ space should be canonically isomorphic in pretty much+  --   all relevant cases. Indeed, it is recommended that they are the very same type;+  --   the tuple instance actually assumes this to be able to offer an efficient+  --   implementation (namely, 'id') of the isomorphisms.+  doubleDual :: HasMetric (DualSpace v) => v -> DualSpace (DualSpace v)+  doubleDual' :: HasMetric (DualSpace v) => DualSpace (DualSpace v) -> v+  +  ++-- | Simple flipped version of '<.>^'.+(^<.>) :: HasMetric v => v -> DualSpace v -> Scalar v+ket ^<.> bra = bra <.>^ ket++instance (VectorSpace k) => HasMetric (ZeroDim k) where+  Origin<.>^Origin = zeroV+  functional _ = Origin+  doubleDual = id; doubleDual'= id+instance HasMetric Double where+  (<.>^) = (<.>)+  functional f = f 1+  doubleDual = id; doubleDual'= id+instance ( HasMetric v, HasMetric w, Scalar v ~ Scalar w+         , HasMetric (DualSpace v), DualSpace (DualSpace v) ~ v+         , HasMetric (DualSpace w), DualSpace (DualSpace w) ~ w+         ) => HasMetric (v,w) where+  type DualSpace (v,w) = (DualSpace v, DualSpace w)+  (v,w)<.>^(v',w') = v<.>^v' ^+^ w<.>^w'+  functional f = (functional $ f . (,zeroV), functional $ f . (zeroV,))+  doubleDual = id; doubleDual'= id++++++-- | Transpose a linear operator. Contrary to popular belief, this does not+--   just inverse the direction of mapping between the spaces, but also switch to+--   their duals.+adjoint :: (HasMetric v, HasMetric w, Scalar w ~ Scalar v)+     => (v :-* w) -> DualSpace w :-* DualSpace v+adjoint m = linear $ \w -> functional $ \v+                     -> w <.>^lapply m v++++metrConst :: (HasMetric v, v ~ DualSpace v, Num (Scalar v)) => Scalar v -> HerMetric v+metrConst = HerMetric . linear . (*^)++instance (HasMetric v, v ~ DualSpace v, Num (Scalar v)) => Num (HerMetric v) where+  fromInteger = metrConst . fromInteger+  (+) = (^+^)+  negate = negateV+           +  -- | This does /not/ work correctly if the metrics don't share an eigenbasis!+  HerMetric m * HerMetric n = HerMetric $ m *.* n+                              +  -- | Undefined, though it could actually be done.+  abs = error "abs undefined for HerMetric"+  signum = error "signum undefined for HerMetric"+++metrNumFun :: (HasMetric v, v ~ Scalar v, v ~ DualSpace v, Num v)+      => (v -> v) -> HerMetric v -> HerMetric v+metrNumFun f (HerMetric m) = HerMetric . linear . (*^) . f $ lapply m 1++instance (HasMetric v, v ~ Scalar v, v ~ DualSpace v, Fractional v) +            => Fractional (HerMetric v) where+  fromRational = metrConst . fromRational+  recip = metrNumFun recip++instance (HasMetric v, v ~ Scalar v, v ~ DualSpace v, Floating v)+            => Floating (HerMetric v) where+  pi = metrConst pi+  sqrt = metrNumFun sqrt+  exp = metrNumFun exp+  log = metrNumFun log+  sin = metrNumFun sin+  cos = metrNumFun cos+  tan = metrNumFun tan+  asin = metrNumFun asin+  acos = metrNumFun acos+  atan = metrNumFun atan+  sinh = metrNumFun sinh+  cosh = metrNumFun cosh+  asinh = metrNumFun asinh+  atanh = metrNumFun atanh+  acosh = metrNumFun acosh
Data/Manifold.hs view
@@ -29,7 +29,7 @@ {-# LANGUAGE RecordWildCards          #-}  -module Data.Manifold where+module Data.Manifold (module Data.Manifold, module Data.Manifold.Types) where  import Data.List import Data.Maybe@@ -41,6 +41,7 @@ import Data.Basis import Data.Complex hiding (magnitude) import Data.Void+import Data.Manifold.Types  import qualified Prelude @@ -180,8 +181,6 @@   -type EuclidSpace v = (HasBasis v, EqFloating(Scalar v), Eq v)-type EqFloating f = (Eq f, Ord f, Floating f)   -- | A chart is a homeomorphism from a connected, open subset /Q/ ⊂ /M/ of@@ -368,18 +367,18 @@ data CntnFuncValue d c = CntnFuncValue { runCntnFuncValue :: d :--> c }                        | CntnFuncConst c -instance HasProxy (:-->) where-  type ProxyVal (:-->) d c = CntnFuncValue d c+instance HasAgent (:-->) where+  type AgentVal (:-->) d c = CntnFuncValue d c   alg f = case f $ CntnFuncValue id of                            CntnFuncValue q -> q                           CntnFuncConst c -> const__ c   f $~ CntnFuncValue g = CntnFuncValue $ f . g   f $~ CntnFuncConst c = CntnFuncConst $ f $ c -instance PointProxy CntnFuncValue (:-->) d c where+instance PointAgent CntnFuncValue (:-->) d c where   point = CntnFuncConst -instance CartesianProxy (:-->) where+instance CartesianAgent (:-->) where   alg1to2 f = case f $ CntnFuncValue id of        (CntnFuncConst c₁, CntnFuncConst c₂) -> const__ (c₁, c₂)        (CntnFuncConst c₁, CntnFuncValue f₂)@@ -523,10 +522,6 @@   -data GraphWindowSpec = GraphWindowSpec {-    lBound, rBound, bBound, tBound :: Double-  , xResolution, yResolution :: Int-  }  finiteGraphContinℝtoℝ :: GraphWindowSpec -> (Double:-->Double) -> [(Double, Double)] finiteGraphContinℝtoℝ (GraphWindowSpec{..}) fc@@ -606,10 +601,6 @@   -data S2 = S2 { ϑParamS2 :: Double -- [0, π[-             , φParamS2 :: Double -- [0, 2π[-             }-   -- instance Manifold S2 where --   type TangentSpace S2 = (Double, Double)@@ -633,7 +624,6 @@   -type Endomorphism a = a->a   (.:) :: (c->d) -> (a->b->c) -> a->b->d @@ -645,20 +635,8 @@   -type ℝ = Double -instance VectorSpace () where-  type Scalar () = ℝ-  _ *^ () = () -instance HasBasis () where-  type Basis () = Void-  basisValue = absurd-  decompose () = []-  decompose' () = absurd-instance InnerSpace () where-  () <.> () = 0- class (RealFloat (Metric v), InnerSpace v) => MetricSpace v where   type Metric v :: *   type Metric v = ℝ@@ -697,6 +675,4 @@   -(^) :: Num a => a -> Int -> a-(^) = (Prelude.^) 
+ Data/Manifold/PseudoAffine.hs view
@@ -0,0 +1,1015 @@+-- |+-- Module      : Data.Manifold.PseudoAffine+-- Copyright   : (c) Justus Sagemüller 2015+-- License     : GPL v3+-- +-- Maintainer  : (@) sagemueller $ geo.uni-koeln.de+-- Stability   : experimental+-- Portability : portable+-- +-- This is the second prototype of a manifold class. It appears to give considerable+-- advantages over 'Data.Manifold.Manifold', so that class will probably soon be replaced+-- with the one we define here (though 'PseudoAffine' does not follow the standard notion+-- of a manifold very closely, it should work quite equivalently for pretty much all+-- Haskell types that qualify as manifolds).+-- +-- Manifolds are interesting as objects of various categories, from continuous to+-- diffeomorphic. At the moment, we mainly focus on /region-wise differentiable functions/,+-- which are a promising compromise between flexibility of definition and provability of+-- analytic properties. In particular, they are well-suited for visualisation purposes.++{-# LANGUAGE FlexibleInstances        #-}+{-# LANGUAGE UndecidableInstances     #-}+{-# LANGUAGE TypeFamilies             #-}+{-# LANGUAGE FunctionalDependencies   #-}+{-# LANGUAGE FlexibleContexts         #-}+{-# LANGUAGE GADTs                    #-}+{-# LANGUAGE RankNTypes               #-}+{-# LANGUAGE TupleSections            #-}+{-# LANGUAGE ConstraintKinds          #-}+{-# LANGUAGE PatternGuards            #-}+{-# LANGUAGE TypeOperators            #-}+{-# LANGUAGE ScopedTypeVariables      #-}+{-# LANGUAGE RecordWildCards          #-}+{-# LANGUAGE CPP                      #-}+++module Data.Manifold.PseudoAffine (+            -- * Manifold class+              PseudoAffine(..)+            -- * Regions within a manifold+            , Region+            -- * Hierarchy of manifold-categories+            , Differentiable+            , PWDiffable, RWDiffable+            ) where+    +++import Data.List+import Data.Maybe+import Data.Semigroup+import Data.Function (on)+import Data.Fixed++import Data.VectorSpace+import Data.LinearMap+import Data.LinearMap.HerMetric+import Data.MemoTrie (HasTrie)+import Data.AffineSpace+import Data.Basis+import Data.Complex hiding (magnitude)+import Data.Void+import Data.Tagged+import Data.Manifold.Types++import qualified Prelude++import Control.Category.Constrained.Prelude hiding ((^))+import Control.Arrow.Constrained+import Control.Monad.Constrained+import Data.Foldable.Constrained+++++infix 6 .-~.+infixl 6 .+~^++-- | 'PseudoAffine' is intended as an alternative class for 'Data.Manifold.Manifold's.+--   The interface is almost identical to the better-known 'AffineSpace' class, but unlike+--   in the mathematical definition of affine spaces we don't require associativity +--   of '.+~^' with '^+^' &#x2013; except in an asymptotic sense for small vectors.+--   +--   That innocent-looking change makes the class applicable to vastly more general types:+--   while an affine space is basically nothing but a vector space without particularly+--   designated origin, a pseudo-affine space can have nontrivial topology on the global+--   scale, and yet be used in practically the same way as an affine space. At least the+--   usual spheres and tori make good instances, perhaps the class is in fact equivalent to+--   /parallelisable manifolds/.+class PseudoAffine x where+  type PseudoDiff x :: *+  (.-~.) :: x -> x -> Option (PseudoDiff x)+  (.+~^) :: x -> PseudoDiff x -> x+++type LocallyScalable s x = ( PseudoAffine x, (PseudoDiff x) ~ PseudoDiff x+                           , HasMetric (PseudoDiff x)+                           , DualSpace (PseudoDiff x) ~ DualSpace (PseudoDiff x)+                           , HasMetric (DualSpace (PseudoDiff x))+                           , PseudoDiff x ~ DualSpace (DualSpace (PseudoDiff x))+                           , s ~ Scalar (PseudoDiff x)+                           , s ~ Scalar (DualSpace (PseudoDiff x)) )+type LinearManifold s x = ( PseudoAffine x, PseudoDiff x ~ x+                          , HasMetric x, HasMetric (DualSpace x)+                          , DualSpace (DualSpace x) ~ x+                          , s ~ Scalar x, s ~ Scalar (DualSpace x) )+type RealDimension r = ( PseudoAffine r, PseudoDiff r ~ r+                       , HasMetric r, DualSpace r ~ r, Scalar r ~ r+                       , RealFloat r )++++palerp :: (PseudoAffine x, VectorSpace (PseudoDiff x))+    => x -> x -> Option (Scalar (PseudoDiff x) -> x)+palerp p1 p2 = fmap (\v t -> p1 .+~^ t *^ v) $ p2 .-~. p1++++#define deriveAffine(t)          \+instance PseudoAffine t where {   \+  type PseudoDiff t = Diff t;      \+  a.-~.b = pure (a.-.b);            \+  (.+~^) = (.+^)  }++deriveAffine(Double)+deriveAffine(Rational)++instance PseudoAffine (ZeroDim k) where+  type PseudoDiff (ZeroDim k) = ZeroDim k+  Origin .-~. Origin = pure Origin+  Origin .+~^ Origin = Origin+instance (PseudoAffine a, PseudoAffine b) => PseudoAffine (a,b) where+  type PseudoDiff (a,b) = (PseudoDiff a, PseudoDiff b)+  (a,b).-~.(c,d) = liftA2 (,) (a.-~.c) (b.-~.d)+  (a,b).+~^(v,w) = (a.+~^v, b.+~^w)+instance (PseudoAffine a, PseudoAffine b, PseudoAffine c) => PseudoAffine (a,b,c) where+  type PseudoDiff (a,b,c) = (PseudoDiff a, PseudoDiff b, PseudoDiff c)+  (a,b,c).-~.(d,e,f) = liftA3 (,,) (a.-~.d) (b.-~.e) (c.-~.f)+  (a,b,c).+~^(v,w,x) = (a.+~^v, b.+~^w, c.+~^x)+++instance PseudoAffine S¹ where+  type PseudoDiff S¹ = ℝ+  S¹ φ₁ .-~. S¹ φ₀+     | δφ > pi     = pure (δφ - 2*pi)+     | δφ < (-pi)  = pure (δφ + 2*pi)+     | otherwise   = pure δφ+   where δφ = φ₁ - φ₀+  S¹ φ₀ .+~^ δφ+     | φ' < 0     = S¹ $ φ' + tau+     | otherwise  = S¹ $ φ'+   where φ' = (φ₀ + δφ)`mod'`tau++instance PseudoAffine S² where+  type PseudoDiff S² = ℝ²+  S² ϑ₁ φ₁ .-~. S² ϑ₀ φ₀+     | ϑ₀ < pi/2  = pure ( ϑ₁*^embed(S¹ φ₁) ^-^ ϑ₀*^embed(S¹ φ₀) )+     | otherwise  = pure ( (pi-ϑ₁)*^embed(S¹ φ₁) ^-^ (pi-ϑ₀)*^embed(S¹ φ₀) )+  S² ϑ₀ φ₀ .+~^ δv+     | ϑ₀ < pi/2  = sphereFold PositiveHalfSphere $ ϑ₀*^embed(S¹ φ₀) ^+^ δv+     | otherwise  = sphereFold NegativeHalfSphere $ (pi-ϑ₀)*^embed(S¹ φ₀) ^+^ δv++sphereFold :: S⁰ -> ℝ² -> S²+sphereFold hfSphere v+   | ϑ₀ > pi     = S² (inv $ tau - ϑ₀) ((φ₀+pi)`mod'`tau)+   | otherwise  = S² (inv ϑ₀) φ₀+ where S¹ φ₀ = coEmbed v+       ϑ₀ = magnitude v `mod'` tau+       inv ϑ = case hfSphere of PositiveHalfSphere -> ϑ+                                NegativeHalfSphere -> pi - ϑ++++tau :: Double+tau = 2 * pi++++++type LinDevPropag d c = HerMetric (PseudoDiff c) -> HerMetric (PseudoDiff d)++dev_ε_δ :: RealDimension a+                => (a -> a) -> LinDevPropag a a+dev_ε_δ f d = let ε = 1 / metric d 1 in projector $ 1 / sqrt (f ε)++-- | The category of differentiable functions between manifolds over scalar @s@.+--   +--   As you might guess, these offer /automatic differentiation/ of sorts (basically,+--   simple forward AD), but that's in itself is not really the killer feature here.+--   More interestingly, we actually have the (à la Curry-Howard) /proof/+--   built in: the function /f/ has at /x/&#x2080; derivative /f'&#x2093;/&#x2080;,+--   if, for&#xb9; /&#x3b5;/>0, there exists /&#x3b4;/ such that+--   |/f/ /x/ &#x2212; (/f/ /x/&#x2080; + /x/&#x22c5;/f'&#x2093;/&#x2080;)| < /&#x3b5;/+--   for all |/x/ &#x2212; /x/&#x2080;| < /&#x3b4;/.+-- +--   Observe that, though this looks quite similar to the standard definition+--   of differentiability, it is not equivalent thereto &#x2013; in fact it does+--   not prove any analytic properties at all. To make it equivalent, we need+--   a lower bound on /&#x3b4;/: simply /&#x3b4;/ gives us continuity, and for+--   continuous differentiability, /&#x3b4;/ must grow at least like &#x221a;/&#x3b5;/+--   for small /&#x3b5;/. Neither of these conditions are enforced by the type system,+--   but we do require them for any allowed values because these proofs are obviously+--   tremendously useful &#x2013; for instance, you can have a root-finding algorithm+--   and actually be sure you get /all/ solutions correctly, not just /some/ that are+--   (hopefully) the closest to some reference point you'd need to laborously define!+-- +--   Unfortunately however, this also prevents doing any serious algebra etc. with the+--   category, because even something as simple as division necessary introduces singularities+--   where the derivatives must diverge.+--   Not to speak of many trigonometric e.g. trigonometric functions that+--   are undefined on whole regions. The 'PWDiffable' and 'RWDiffable' categories have explicit+--   handling for those issues built in; you may simply use these categories even when+--   you know the result will be smooth in your relevant domain (or must be, for e.g.+--   physics reasons).+--   +--   &#xb9;(The implementation does not deal with /&#x3b5;/ and /&#x3b4;/ as difference-bounding+--   reals, but rather as metric tensors that define a boundary by prohibiting the+--   overlap from exceeding one; this makes the concept actually work on general manifolds.)+newtype Differentiable s d c+   = Differentiable { runDifferentiable ::+                        d -> ( c, PseudoDiff d :-* PseudoDiff c, LinDevPropag d c ) }+type (-->) = Differentiable ℝ+++instance (VectorSpace s) => Category (Differentiable s) where+  type Object (Differentiable s) o = LocallyScalable s o+  id = Differentiable $ \x -> (x, idL, const zeroV)+  Differentiable f . Differentiable g = Differentiable $+     \x -> let (y, g', devg) = g x+               (z, f', devf) = f y+               devfg δz = let δy = transformMetric f' δz+                              εy = devf δz+                          in transformMetric g' εy ^+^ devg δy ^+^ devg εy+           in (z, f'*.*g', devfg)+++instance (VectorSpace s) => Cartesian (Differentiable s) where+  type UnitObject (Differentiable s) = ZeroDim s+  swap = Differentiable $ \(x,y) -> ((y,x), lSwap, const zeroV)+   where lSwap = linear swap+  attachUnit = Differentiable $ \x -> ((x, Origin), lAttachUnit, const zeroV)+   where lAttachUnit = linear $ \x ->  (x, Origin)+  detachUnit = Differentiable $ \(x, Origin) -> (x, lDetachUnit, const zeroV)+   where lDetachUnit = linear $ \(x, Origin) ->  x+  regroup = Differentiable $ \(x,(y,z)) -> (((x,y),z), lRegroup, const zeroV)+   where lRegroup = linear regroup+  regroup' = Differentiable $ \((x,y),z) -> ((x,(y,z)), lRegroup, const zeroV)+   where lRegroup = linear regroup'+++instance (VectorSpace s) => Morphism (Differentiable s) where+  Differentiable f *** Differentiable g = Differentiable h+   where h (x,y) = ((fx, gy), lPar, devfg)+          where (fx, f', devf) = f x+                (gy, g', devg) = g y+                devfg δs = transformMetric lfst δx +                           ^+^ transformMetric lsnd δy+                  where δx = devf $ transformMetric lcofst δs+                        δy = devg $ transformMetric lcosnd δs+                lPar = linear $ lapply f'***lapply g'+         lfst = linear fst; lsnd = linear snd+         lcofst = linear (,zeroV); lcosnd = linear (zeroV,)+++instance (VectorSpace s) => PreArrow (Differentiable s) where+  terminal = Differentiable $ \_ -> (Origin, zeroV, const zeroV)+  fst = Differentiable $ \(x,_) -> (x, lfst, const zeroV)+   where lfst = linear fst+  snd = Differentiable $ \(_,y) -> (y, lsnd, const zeroV)+   where lsnd = linear snd+  Differentiable f &&& Differentiable g = Differentiable h+   where h x = ((fx, gx), lFanout, devfg)+          where (fx, f', devf) = f x+                (gx, g', devg) = g x+                devfg δs = (devf $ transformMetric lcofst δs)+                           ^+^ (devg $ transformMetric lcosnd δs)+                lFanout = linear $ lapply f'&&&lapply g'+         lcofst = linear (,zeroV); lcosnd = linear (zeroV,)+++instance (VectorSpace s) => WellPointed (Differentiable s) where+  unit = Tagged Origin+  globalElement x = Differentiable $ \Origin -> (x, zeroV, const zeroV)+  const x = Differentiable $ \_ -> (x, zeroV, const zeroV)++++type DfblFuncValue s = GenericAgent (Differentiable s)++instance (VectorSpace s) => HasAgent (Differentiable s) where+  alg = genericAlg+  ($~) = genericAgentMap+instance (VectorSpace s) => CartesianAgent (Differentiable s) where+  alg1to2 = genericAlg1to2+  alg2to1 = genericAlg2to1+  alg2to2 = genericAlg2to2+instance (VectorSpace s)+      => PointAgent (DfblFuncValue s) (Differentiable s) a x where+  point = genericPoint++++actuallyLinear :: ( LinearManifold s x, LinearManifold s y )+            => (x:-*y) -> Differentiable s x y+actuallyLinear f = Differentiable $ \x -> (lapply f x, f, const zeroV)++actuallyAffine :: ( LinearManifold s x, LinearManifold s y )+            => y -> (x:-*y) -> Differentiable s x y+actuallyAffine y₀ f = Differentiable $ \x -> (y₀ ^+^ lapply f x, f, const zeroV)+++dfblFnValsFunc :: ( LocallyScalable s c, LocallyScalable s c', LocallyScalable s d+                  , v ~ PseudoDiff c, v' ~ PseudoDiff c'+                  , ε ~ HerMetric v, ε ~ HerMetric v' )+             => (c' -> (c, v':-*v, ε->ε)) -> DfblFuncValue s d c' -> DfblFuncValue s d c+dfblFnValsFunc f = (Differentiable f $~)++dfblFnValsCombine :: forall d c c' c'' v v' v'' ε ε' ε'' s. +         ( LocallyScalable s c,  LocallyScalable s c',  LocallyScalable s c''+         ,  LocallyScalable s d+         , v ~ PseudoDiff c, v' ~ PseudoDiff c', v'' ~ PseudoDiff c''+         , ε ~ HerMetric v  , ε' ~ HerMetric v'  , ε'' ~ HerMetric v'', ε~ε', ε~ε''  )+       => (  c' -> c'' -> (c, (v',v''):-*v, ε -> (ε',ε''))  )+         -> DfblFuncValue s d c' -> DfblFuncValue s d c'' -> DfblFuncValue s d c+dfblFnValsCombine cmb (GenericAgent (Differentiable f))+                      (GenericAgent (Differentiable g)) +    = GenericAgent . Differentiable $+        \d -> let (c', f', devf) = f d+                  (c'', g', devg) = g d+                  (c, h', devh) = cmb c' c''+                  h'l = h' *.* lcofst; h'r = h' *.* lcosnd+              in ( c+                 , h' *.* linear (lapply f' &&& lapply g')+                 , \εc -> let εc' = transformMetric h'l εc+                              εc'' = transformMetric h'r εc+                              (δc',δc'') = devh εc +                          in devf εc' ^+^ devg εc''+                               ^+^ transformMetric f' δc'+                               ^+^ transformMetric g' δc''+                 )+ where lcofst = linear(,zeroV)+       lcosnd = linear(zeroV,) ++++++instance (LinearManifold s v, LocallyScalable s a, Floating s)+    => AdditiveGroup (DfblFuncValue s a v) where+  zeroV = point zeroV+  (^+^) = dfblFnValsCombine $ \a b -> (a^+^b, lPlus, const zeroV)+      where lPlus = linear $ uncurry (^+^)+  negateV = dfblFnValsFunc $ \a -> (negateV a, lNegate, const zeroV)+      where lNegate = linear negateV+  +instance (RealDimension n, LocallyScalable n a)+            => Num (DfblFuncValue n a n) where+  fromInteger i = point $ fromInteger i+  (+) = dfblFnValsCombine $ \a b -> (a+b, lPlus, const zeroV)+      where lPlus = linear $ uncurry (+)+  (*) = dfblFnValsCombine $+          \a b -> ( a*b+                  , linear $ \(da,db) -> a*db + b*da+                  , \d -> let d¹₂ = sqrt d in (d¹₂,d¹₂)+                           -- ε δa δb = (a+δa)·(b+δb) - (a·b + (a·δa + b·δb)) +                           --         = δa·δb+                           --   so choose δa = δb = √ε+                  )+  negate = dfblFnValsFunc $ \a -> (negate a, lNegate, const zeroV)+      where lNegate = linear negate+  abs = dfblFnValsFunc dfblAbs+   where dfblAbs a+          | a>0        = (a, idL, dev_ε_δ $ \ε -> a + ε/2) +          | a<0        = (-a, negateV idL, dev_ε_δ $ \ε -> ε/2 - a)+          | otherwise  = (0, zeroV, (^/ sqrt 2))+  signum = dfblFnValsFunc dfblSgn+   where dfblSgn a+          | a>0        = (1, zeroV, dev_ε_δ $ const a)+          | a<0        = (-1, zeroV, dev_ε_δ $ \_ -> -a)+          | otherwise  = (0, zeroV, const $ projector 1)++++-- VectorSpace instance is more problematic than you'd think: multiplication+-- requires the allowed-deviation backpropagators to be split as square+-- roots, but the square root of a nontrivial-vector-space metric requires+-- an eigenbasis transform, which we have not implemented yet.+-- +-- instance (LinearManifold s v, LocallyScalable s a, Floating s)+--       => VectorSpace (DfblFuncValue s a v) where+--   type Scalar (DfblFuncValue s a v) = DfblFuncValue s a (Scalar v)+--   (*^) = dfblFnValsCombine $ \μ v -> (μ*^v, lScl, \ε -> (ε ^* sqrt 2, ε ^* sqrt 2))+--       where lScl = linear $ uncurry (*^)+++-- | Important special operator needed to compute intersection of 'Region's.+minDblfuncs :: (LocallyScalable s m, RealDimension s)+     => Differentiable s m s -> Differentiable s m s -> Differentiable s m s+minDblfuncs (Differentiable f) (Differentiable g) = Differentiable h+ where h x+         | fx==gx   = ( fx, (f'^+^g')^/2+                      , \d -> devf d ^+^ devg d+                               ^+^ transformMetric (f'^-^g')+                                                   (projector $ metric d 1) )+         | fx < gx   = ( fx, f'+                       , \d -> devf d+                               ^+^ transformMetric (f'^-^g')+                                                   (projector $ metric d 1 + gx - fx) )+        where (fx, f', devf) = f x+              (gx, g', devg) = g x++++-- | A pathwise connected subset of a manifold @m@, whose tangent space has scalar @s@.+data Region s m = Region { regionRefPoint :: m+                         , regionRDef :: PreRegion s m }++-- | A 'PreRegion' needs to be associated with a certain reference point ('Region'+--   includes that point) to define a connected subset of a manifold.+data PreRegion s m where+  GlobalRegion :: PreRegion s m+  PreRegion :: (Differentiable s m s) -- A function that is positive at reference point /p/,+                                      -- decreases and crosses zero at the region's+                                      -- boundaries. (If it goes positive again somewhere+                                      -- else, these areas shall /not/ be considered+                                      -- belonging to the (by definition connected) region.)+         -> PreRegion s m++-- | Set-intersection of regions would not be guaranteed to yield a connected result+--   or even have the reference point of one region contained in the other. This+--   combinator assumes (unchecked) that the references are in a connected+--   sub-intersection, which is used as the result.+unsafePreRegionIntersect :: (RealDimension s, LocallyScalable s a)+                  => PreRegion s a -> PreRegion s a -> PreRegion s a+unsafePreRegionIntersect GlobalRegion r = r+unsafePreRegionIntersect r GlobalRegion = r+unsafePreRegionIntersect (PreRegion ra) (PreRegion rb) = PreRegion $ minDblfuncs ra rb++-- | Cartesian product of two regions.+regionProd :: (RealDimension s, LocallyScalable s a, LocallyScalable s b)+                  => Region s a -> Region s b -> Region s (a,b)+regionProd (Region a₀ ra) (Region b₀ rb) = Region (a₀,b₀) (preRegionProd ra rb)++-- | Cartesian product of two pre-regions.+preRegionProd :: (RealDimension s, LocallyScalable s a, LocallyScalable s b)+                  => PreRegion s a -> PreRegion s b -> PreRegion s (a,b)+preRegionProd GlobalRegion GlobalRegion = GlobalRegion+preRegionProd GlobalRegion (PreRegion rb) = PreRegion $ rb . snd+preRegionProd (PreRegion ra) GlobalRegion = PreRegion $ ra . fst+preRegionProd (PreRegion ra) (PreRegion rb) = PreRegion $ minDblfuncs (ra.fst) (rb.snd)+++positivePreRegion, negativePreRegion :: (RealDimension s) => PreRegion s s+positivePreRegion = PreRegion $ Differentiable prr+ where prr x = (1 - 1/xp1, (1/xp1²) *^ idL, dev_ε_δ δ )+                 -- ε = (1 − 1/(1+x)) + (-δ · 1/(x+1)²) − (1 − 1/(1+x−δ))+                 --   = 1/(1+x−δ) − 1/(1+x) − δ · 1/(x+1)²+                 -- ε·(1+x−δ) = 1 − (1+x−δ)/(1+x) − δ·(1+x-δ)/(x+1)²+                 -- ε + ε·x − ε·δ = 1 − 1/(1+x) − x/(1+x) + δ/(1+x) − δ/(x+1) + δ²/(x+1)²+                 --               = 1 − 1/(1+x) − x/(1+x) + δ²/(x+1)²+                 --               = (1+x − 1 − x)/(1+x) + δ²/(x+1)²+                 -- 0 = δ² + ε·(x+1)²·δ + ε·(x+1)³+                 -- δ = let mph = -ε·(x+1)²/2+                 --     in mph + sqrt(mph² - ε·(x+1)³)+        where δ ε = let mph = -ε*xp1²/2+                    in mph + sqrt(mph^2 - ε * xp1² * xp1)+              xp1 = (x+1)+              xp1² = xp1 ^ 2+negativePreRegion = PreRegion $ ppr . ngt+ where PreRegion ppr = positivePreRegion+       ngt = actuallyLinear $ linear negate++preRegionToInfFrom, preRegionFromMinInfTo :: RealDimension s => s -> PreRegion s s+preRegionToInfFrom xs = PreRegion $ ppr . trl+ where PreRegion ppr = positivePreRegion+       trl = actuallyAffine (-xs) idL+preRegionFromMinInfTo xe = PreRegion $ ppr . flp+ where PreRegion ppr = positivePreRegion+       flp = actuallyAffine (-xe) (linear negate)++intervalPreRegion :: RealDimension s => (s,s) -> PreRegion s s+intervalPreRegion (lb,rb) = PreRegion $ Differentiable prr+ where m = lb + radius; radius = (rb - lb)/2+       prr x = ( 1 - ((x-m)/radius)^2+               , (2*(m-x)/radius^2) *^ idL+               , dev_ε_δ $ (*radius) . sqrt )+++++-- | Category of functions that almost everywhere have an open region in+--   which they are continuously differentiable, i.e. /PieceWiseDiff'able/.+newtype PWDiffable s d c+   = PWDiffable {+        getDfblDomain :: d -> (PreRegion s d, Differentiable s d c) }++++instance (RealDimension s) => Category (PWDiffable s) where+  type Object (PWDiffable s) o = LocallyScalable s o+  id = PWDiffable $ \x -> (GlobalRegion, id)+  PWDiffable f . PWDiffable g = PWDiffable h+   where h x₀ = case g x₀ of+                 (GlobalRegion, gr)+                  -> let (y₀,_,_) = runDifferentiable gr x₀+                     in case f y₀ of+                         (GlobalRegion, fr) -> (GlobalRegion, fr . gr)+                         (PreRegion ry, fr)+                               -> ( PreRegion $ ry . gr, fr . gr )+                 (PreRegion rx, gr)+                  -> let (y₀,_,_) = runDifferentiable gr x₀+                     in case f y₀ of+                         (GlobalRegion, fr) -> (PreRegion rx, fr . gr)+                         (PreRegion ry, fr)+                               -> ( PreRegion $ minDblfuncs (ry . gr) rx+                                  , fr . gr )+          where (rx, gr) = g x₀++globalDiffable :: Differentiable s a b -> PWDiffable s a b+globalDiffable f = PWDiffable $ const (GlobalRegion, f)++instance (RealDimension s) => EnhancedCat (PWDiffable s) (Differentiable s) where+  arr = globalDiffable+                +instance (RealDimension s) => Cartesian (PWDiffable s) where+  type UnitObject (PWDiffable s) = ZeroDim s+  swap = globalDiffable swap+  attachUnit = globalDiffable attachUnit+  detachUnit = globalDiffable detachUnit+  regroup = globalDiffable regroup+  regroup' = globalDiffable regroup'+  +instance (RealDimension s) => Morphism (PWDiffable s) where+  PWDiffable f *** PWDiffable g = PWDiffable h+   where h (x,y) = (preRegionProd rfx rgy, dff *** dfg)+          where (rfx, dff) = f x+                (rgy, dfg) = g y++instance (RealDimension s) => PreArrow (PWDiffable s) where+  PWDiffable f &&& PWDiffable g = PWDiffable h+   where h x = (unsafePreRegionIntersect rfx rgx, dff &&& dfg)+          where (rfx, dff) = f x+                (rgx, dfg) = g x+  terminal = globalDiffable terminal+  fst = globalDiffable fst+  snd = globalDiffable snd+++instance (RealDimension s) => WellPointed (PWDiffable s) where+  unit = Tagged Origin+  globalElement x = PWDiffable $ \Origin -> (GlobalRegion, globalElement x)+  const x = PWDiffable $ \_ -> (GlobalRegion, const x)+++type PWDfblFuncValue s = GenericAgent (PWDiffable s)++instance RealDimension s => HasAgent (PWDiffable s) where+  alg = genericAlg+  ($~) = genericAgentMap+instance RealDimension s => CartesianAgent (PWDiffable s) where+  alg1to2 = genericAlg1to2+  alg2to1 = genericAlg2to1+  alg2to2 = genericAlg2to2+instance (RealDimension s)+      => PointAgent (PWDfblFuncValue s) (PWDiffable s) a x where+  point = genericPoint++gpwDfblFnValsFunc+     :: ( RealDimension s+        , LocallyScalable s c, LocallyScalable s c', LocallyScalable s d+        , v ~ PseudoDiff c, v' ~ PseudoDiff c'+        , ε ~ HerMetric v, ε ~ HerMetric v' )+             => (c' -> (c, v':-*v, ε->ε)) -> PWDfblFuncValue s d c' -> PWDfblFuncValue s d c+gpwDfblFnValsFunc f = (PWDiffable (\_ -> (GlobalRegion, Differentiable f)) $~)++gpwDfblFnValsCombine :: forall d c c' c'' v v' v'' ε ε' ε'' s. +         ( LocallyScalable s c,  LocallyScalable s c',  LocallyScalable s c''+         , LocallyScalable s d, RealDimension s+         , v ~ PseudoDiff c, v' ~ PseudoDiff c', v'' ~ PseudoDiff c''+         , ε ~ HerMetric v  , ε' ~ HerMetric v'  , ε'' ~ HerMetric v'', ε~ε', ε~ε''  )+       => (  c' -> c'' -> (c, (v',v''):-*v, ε -> (ε',ε''))  )+         -> PWDfblFuncValue s d c' -> PWDfblFuncValue s d c'' -> PWDfblFuncValue s d c+gpwDfblFnValsCombine cmb (GenericAgent (PWDiffable fpcs))+                         (GenericAgent (PWDiffable gpcs)) +    = GenericAgent . PWDiffable $+        \d₀ -> let (rc', Differentiable f) = fpcs d₀+                   (rc'',Differentiable g) = gpcs d₀+               in (unsafePreRegionIntersect rc' rc'',) . Differentiable $+                    \d -> let (c', f', devf) = f d+                              (c'',g', devg) = g d+                              (c, h', devh) = cmb c' c''+                              h'l = h' *.* lcofst; h'r = h' *.* lcosnd+                          in ( c+                             , h' *.* linear (lapply f' &&& lapply g')+                             , \εc -> let εc' = transformMetric h'l εc+                                          εc'' = transformMetric h'r εc+                                          (δc',δc'') = devh εc +                                      in devf εc' ^+^ devg εc''+                                           ^+^ transformMetric f' δc'+                                           ^+^ transformMetric g' δc''+                             )+ where lcofst = linear(,zeroV)+       lcosnd = linear(zeroV,) +++instance (LinearManifold s v, LocallyScalable s a, RealDimension s)+    => AdditiveGroup (PWDfblFuncValue s a v) where+  zeroV = point zeroV+  (^+^) = gpwDfblFnValsCombine $ \a b -> (a^+^b, lPlus, const zeroV)+      where lPlus = linear $ uncurry (^+^)+  negateV = gpwDfblFnValsFunc $ \a -> (negateV a, lNegate, const zeroV)+      where lNegate = linear negateV++instance (RealDimension n, LocallyScalable n a)+            => Num (PWDfblFuncValue n a n) where+  fromInteger i = point $ fromInteger i+  (+) = gpwDfblFnValsCombine $ \a b -> (a+b, lPlus, const zeroV)+      where lPlus = linear $ uncurry (+)+  (*) = gpwDfblFnValsCombine $+          \a b -> ( a*b+                  , linear $ \(da,db) -> a*db + b*da+                  , \d -> let d¹₂ = sqrt d in (d¹₂,d¹₂)+                  )+  negate = gpwDfblFnValsFunc $ \a -> (negate a, lNegate, const zeroV)+      where lNegate = linear negate+  abs = (PWDiffable absPW $~)+   where absPW a₀+          | a₀<0       = (negativePreRegion, desc)+          | otherwise  = (positivePreRegion, asc)+         desc = actuallyLinear $ linear negate+         asc = actuallyLinear idL+  signum = (PWDiffable sgnPW $~)+   where sgnPW a₀+          | a₀<0       = (negativePreRegion, const 1)+          | otherwise  = (positivePreRegion, const $ -1)++instance (RealDimension n, LocallyScalable n a)+            => Fractional (PWDfblFuncValue n a n) where+  fromRational i = point $ fromRational i+  recip = (PWDiffable rcipPW $~)+   where rcipPW a₀+          | a₀<0       = (negativePreRegion, Differentiable negp)+          | otherwise  = (positivePreRegion, Differentiable posp)+         negp x = (x'¹, (- x'¹^2) *^ idL, dev_ε_δ δ)+                 -- ε = 1/x − δ/x² − 1/(x+δ)+                 -- ε·x + ε·δ = 1 + δ/x − δ/x − δ²/x² − 1+                 --           = -δ²/x²+                 -- 0 = δ² + ε·x²·δ + ε·x³+                 -- δ = let mph = -ε·x²/2 in mph + sqrt (mph² − ε·x³)+          where δ ε = let mph = -ε*x^2/2 in mph + sqrt (mph^2 - ε*x^3)+                x'¹ = recip x+         posp x = (x'¹, (- x'¹^2) *^ idL, dev_ε_δ δ)+          where δ ε = let mph = -ε*x^2/2 in mph + sqrt (mph^2 + ε*x^3)+                x'¹ = recip x+++++++-- | Category of functions that, where defined, have an open region in+--   which they are continuously differentiable. Hence /RegionWiseDiff'able/.+--   Basically these are the partial version of `PWDiffable`.+-- +--   Though the possibility of undefined regions is of course not too nice+--   (we don't need Java to demonstrate this with its everywhere-looming @null@ values...),+--   this category will propably be the &#x201c;workhorse&#x201d; for most serious+--   calculus applications, because it contains all the usual trig etc. functions+--   and of course everything algebraic you can do in the reals.+-- +--   The easiest way to define ordinary functions in this category is hence+--   with its 'AgentVal'ues, which have instances of the standard classes 'Num'+--   through 'Floating'. For instance, the following defines the /binary entropy/+--   as a differentiable function on the interval @]0,1[@: (it will+--   actually /know/ where it's defined and where not! &#x2013; and I don't mean you+--   need to exhaustively 'isNaN'-check all results...)+-- +-- @+-- hb :: RWDiffable R R R+-- hb = alg (\\p -> - p * logBase 2 p - (1-p) * logBase 2 (1-p) )+-- @+newtype RWDiffable s d c+   = RWDiffable {+        tryDfblDomain :: d -> (PreRegion s d, Option (Differentiable s d c)) }++notDefinedHere :: Option (Differentiable s d c)+notDefinedHere = Option Nothing++++instance (RealDimension s) => Category (RWDiffable s) where+  type Object (RWDiffable s) o = LocallyScalable s o+  id = RWDiffable $ \x -> (GlobalRegion, pure id)+  RWDiffable f . RWDiffable g = RWDiffable h+   where h x₀ = case g x₀ of+                 (GlobalRegion, Option Nothing)+                  -> (GlobalRegion, notDefinedHere)+                 (GlobalRegion, Option (Just gr))+                  -> let (y₀,_,_) = runDifferentiable gr x₀+                     in case f y₀ of+                         (GlobalRegion, Option Nothing)+                               -> (GlobalRegion, notDefinedHere)+                         (GlobalRegion, Option (Just fr))+                               -> (GlobalRegion, pure (fr . gr))+                         (PreRegion ry, Option Nothing)+                               -> ( PreRegion $ ry . gr, Option Nothing )+                         (PreRegion ry, Option (Just fr))+                               -> ( PreRegion $ ry . gr, pure (fr . gr) )+                 (PreRegion rx, Option Nothing)+                  -> (PreRegion rx, notDefinedHere)+                 (PreRegion rx, Option (Just gr))+                  -> let (y₀,_,_) = runDifferentiable gr x₀+                     in case f y₀ of+                         (GlobalRegion, Option Nothing)+                               -> (PreRegion rx, notDefinedHere)+                         (GlobalRegion, Option (Just fr))+                               -> (PreRegion rx, pure (fr . gr))+                         (PreRegion ry, Option Nothing)+                               -> ( PreRegion $ minDblfuncs (ry . gr) rx+                                  , notDefinedHere )+                         (PreRegion ry, Option (Just fr))+                               -> ( PreRegion $ minDblfuncs (ry . gr) rx+                                  , pure (fr . gr) )+          where (rx, gr) = g x₀+++globalDiffable' :: Differentiable s a b -> RWDiffable s a b+globalDiffable' f = RWDiffable $ const (GlobalRegion, pure f)++pwDiffable :: PWDiffable s a b -> RWDiffable s a b+pwDiffable (PWDiffable q) = RWDiffable $ \x₀ -> let (r₀,f₀) = q x₀ in (r₀, pure f₀)++++instance (RealDimension s) => EnhancedCat (RWDiffable s) (Differentiable s) where+  arr = globalDiffable'+instance (RealDimension s) => EnhancedCat (RWDiffable s) (PWDiffable s) where+  arr = pwDiffable+                +instance (RealDimension s) => Cartesian (RWDiffable s) where+  type UnitObject (RWDiffable s) = ZeroDim s+  swap = globalDiffable' swap+  attachUnit = globalDiffable' attachUnit+  detachUnit = globalDiffable' detachUnit+  regroup = globalDiffable' regroup+  regroup' = globalDiffable' regroup'+  +instance (RealDimension s) => Morphism (RWDiffable s) where+  RWDiffable f *** RWDiffable g = RWDiffable h+   where h (x,y) = (preRegionProd rfx rgy, liftA2 (***) dff dfg)+          where (rfx, dff) = f x+                (rgy, dfg) = g y++instance (RealDimension s) => PreArrow (RWDiffable s) where+  RWDiffable f &&& RWDiffable g = RWDiffable h+   where h x = (unsafePreRegionIntersect rfx rgx, liftA2 (&&&) dff dfg)+          where (rfx, dff) = f x+                (rgx, dfg) = g x+  terminal = globalDiffable' terminal+  fst = globalDiffable' fst+  snd = globalDiffable' snd+++instance (RealDimension s) => WellPointed (RWDiffable s) where+  unit = Tagged Origin+  globalElement x = RWDiffable $ \Origin -> (GlobalRegion, pure (globalElement x))+  const x = RWDiffable $ \_ -> (GlobalRegion, pure (const x))+++type RWDfblFuncValue s = GenericAgent (RWDiffable s)++instance RealDimension s => HasAgent (RWDiffable s) where+  alg = genericAlg+  ($~) = genericAgentMap+instance RealDimension s => CartesianAgent (RWDiffable s) where+  alg1to2 = genericAlg1to2+  alg2to1 = genericAlg2to1+  alg2to2 = genericAlg2to2+instance (RealDimension s)+      => PointAgent (RWDfblFuncValue s) (RWDiffable s) a x where+  point = genericPoint++grwDfblFnValsFunc+     :: ( RealDimension s+        , LocallyScalable s c, LocallyScalable s c', LocallyScalable s d+        , v ~ PseudoDiff c, v' ~ PseudoDiff c'+        , ε ~ HerMetric v, ε ~ HerMetric v' )+             => (c' -> (c, v':-*v, ε->ε)) -> RWDfblFuncValue s d c' -> RWDfblFuncValue s d c+grwDfblFnValsFunc f = (RWDiffable (\_ -> (GlobalRegion, pure (Differentiable f))) $~)++grwDfblFnValsCombine :: forall d c c' c'' v v' v'' ε ε' ε'' s. +         ( LocallyScalable s c,  LocallyScalable s c',  LocallyScalable s c''+         , LocallyScalable s d, RealDimension s+         , v ~ PseudoDiff c, v' ~ PseudoDiff c', v'' ~ PseudoDiff c''+         , ε ~ HerMetric v  , ε' ~ HerMetric v'  , ε'' ~ HerMetric v'', ε~ε', ε~ε''  )+       => (  c' -> c'' -> (c, (v',v''):-*v, ε -> (ε',ε''))  )+         -> RWDfblFuncValue s d c' -> RWDfblFuncValue s d c'' -> RWDfblFuncValue s d c+grwDfblFnValsCombine cmb (GenericAgent (RWDiffable fpcs))+                         (GenericAgent (RWDiffable gpcs)) +    = GenericAgent . RWDiffable $+        \d₀ -> let (rc', fmay) = fpcs d₀+                   (rc'',gmay) = gpcs d₀+               in (unsafePreRegionIntersect rc' rc'',) $+                    case (fmay,gmay) of+                      (Option(Just(Differentiable f)), Option(Just(Differentiable g))) ->+                        pure . Differentiable $ \d+                         -> let (c', f', devf) = f d+                                (c'',g', devg) = g d+                                (c, h', devh) = cmb c' c''+                                h'l = h' *.* lcofst; h'r = h' *.* lcosnd+                            in ( c+                               , h' *.* linear (lapply f' &&& lapply g')+                               , \εc -> let εc' = transformMetric h'l εc+                                            εc'' = transformMetric h'r εc+                                            (δc',δc'') = devh εc +                                        in devf εc' ^+^ devg εc''+                                             ^+^ transformMetric f' δc'+                                             ^+^ transformMetric g' δc''+                               )+                      _ -> notDefinedHere+ where lcofst = linear(,zeroV)+       lcosnd = linear(zeroV,) ++++instance (LinearManifold s v, LocallyScalable s a, RealDimension s)+    => AdditiveGroup (RWDfblFuncValue s a v) where+  zeroV = point zeroV+  (^+^) = grwDfblFnValsCombine $ \a b -> (a^+^b, lPlus, const zeroV)+      where lPlus = linear $ uncurry (^+^)+  negateV = grwDfblFnValsFunc $ \a -> (negateV a, lNegate, const zeroV)+      where lNegate = linear negateV++instance (RealDimension n, LocallyScalable n a)+            => Num (RWDfblFuncValue n a n) where+  fromInteger i = point $ fromInteger i+  (+) = grwDfblFnValsCombine $ \a b -> (a+b, lPlus, const zeroV)+      where lPlus = linear $ uncurry (+)+  (*) = grwDfblFnValsCombine $+          \a b -> ( a*b+                  , linear $ \(da,db) -> a*db + b*da+                  , \d -> let d¹₂ = sqrt d in (d¹₂,d¹₂)+                  )+  negate = grwDfblFnValsFunc $ \a -> (negate a, lNegate, const zeroV)+      where lNegate = linear negate+  abs = (RWDiffable absPW $~)+   where absPW a₀+          | a₀<0       = (negativePreRegion, pure desc)+          | otherwise  = (positivePreRegion, pure asc)+         desc = actuallyLinear $ linear negate+         asc = actuallyLinear idL+  signum = (RWDiffable sgnPW $~)+   where sgnPW a₀+          | a₀<0       = (negativePreRegion, pure (const 1))+          | otherwise  = (positivePreRegion, pure (const $ -1))++instance (RealDimension n, LocallyScalable n a)+            => Fractional (RWDfblFuncValue n a n) where+  fromRational i = point $ fromRational i+  recip = (RWDiffable rcipPW $~)+   where rcipPW a₀+          | a₀<0       = (negativePreRegion, pure (Differentiable negp))+          | otherwise  = (positivePreRegion, pure (Differentiable posp))+         negp x = (x'¹, (- x'¹^2) *^ idL, dev_ε_δ δ)+                 -- ε = 1/x − δ/x² − 1/(x+δ)+                 -- ε·x + ε·δ = 1 + δ/x − δ/x − δ²/x² − 1+                 --           = -δ²/x²+                 -- 0 = δ² + ε·x²·δ + ε·x³+                 -- δ = let mph = -ε·x²/2 in mph + sqrt (mph² − ε·x³)+          where δ ε = let mph = -ε*x^2/2 in mph + sqrt (mph^2 - ε*x^3)+                x'¹ = recip x+         posp x = (x'¹, (- x'¹^2) *^ idL, dev_ε_δ δ)+          where δ ε = let mph = -ε*x^2/2 in mph + sqrt (mph^2 + ε*x^3)+                x'¹ = recip x++++++-- Helper for checking ε-estimations in GHCi with dynamic-plot:+-- epsEst (f,f') εsgn δf (ViewXCenter xc) (ViewHeight h)+--    = let δfxc = δf xc+--      in tracePlot $ reverse [ (xc - δ, f xc - δ * f' xc + εsgn*ε) |+--                               ε <- [0, h/500 .. h], let δ = δfxc ε]+--                          ++ [ (xc + δ, f xc + δ * f' xc + εsgn*ε) |+--                               ε <- [0, h/500 .. h], let δ = δfxc ε] +-- Golfed version:+-- epsEst(f,d)s φ(ViewXCenter ξ)(ViewHeight h)=let ζ=φ ξ in tracePlot$[(ξ-δ,f ξ-δ*d ξ+s*abs ε)|ε<-[-h,-0.998*h..h],let δ=ζ(abs ε)*signum ε]++instance (RealDimension n, LocallyScalable n a)+            => Floating (RWDfblFuncValue n a n) where+  pi = point pi+  +  exp = grwDfblFnValsFunc+    $ \x -> let ex = exp x+            in ( ex, ex *^ idL, dev_ε_δ $ \ε -> acosh(ε/(2*ex) + 1) )+                 -- ε = e^(x+δ) − eˣ − eˣ·δ +                 --   = eˣ·(e^δ − 1 − δ) +                 --   ≤ eˣ · (e^δ − 1 + e^(-δ) − 1)+                 --   = eˣ · 2·(cosh(δ) − 1)+                 -- cosh(δ) ≥ ε/(2·eˣ) + 1+                 -- δ ≥ acosh(ε/(2·eˣ) + 1)+  log = (RWDiffable lnRW $~)+   where lnRW x | x > 0      = (positivePreRegion, pure (Differentiable lnPosR))+                | otherwise  = (negativePreRegion, notDefinedHere)+         lnPosR x = ( log x, recip x *^ idL, dev_ε_δ $ \ε -> x * sqrt(1 - exp(-ε)) )+                 -- ε = ln x + (-δ)/x − ln(x−δ)+                 --   = ln (x / ((x−δ) · exp(δ/x)))+                 -- x/e^ε = (x−δ) · exp(δ/x)+                 -- let γ = δ/x ∈ [0,1[+                 -- exp(-ε) = (1−γ) · e^γ+                 --         ≥ (1−γ) · (1+γ)+                 --         = 1 − γ²+                 -- γ ≥ sqrt(1 − exp(-ε)) +                 -- δ ≥ x · sqrt(1 − exp(-ε)) +                    +  sqrt = (RWDiffable sqrtRW $~)+   where sqrtRW x | x > 0      = (positivePreRegion, pure (Differentiable sqrtPosR))+                  | otherwise  = (negativePreRegion, notDefinedHere)+         sqrtPosR x = ( sx, idL ^/ (2*sx), dev_ε_δ $+                          \ε -> 2 * (s2 * sqrt sx^3 * sqrt ε + signum (ε*2-sx) * sx * ε) )+          where sx = sqrt x; s2 = sqrt 2+                 -- Exact inverse of O(δ²) remainder.+  +  sin = grwDfblFnValsFunc sinDfb+   where sinDfb x = ( sx, cx *^ idL, dev_ε_δ δ )+          where sx = sin x; cx = cos x+                δ ε = let δ₀ = sqrt $ 2 * ε / (abs sx + abs cx/3)+                      in if δ₀ < 1 -- TODO: confirm selection of δ-definition range.+                          then δ₀+                          else max 1 $ (ε - abs sx - 1) / cos x+                 -- When sin x ≥ 0, cos x ≥ 0, δ ∈ [0,1[+                 -- ε = sin x + δ · cos x − sin(x+δ)+                 --   = sin x + δ · cos x − sin x · cos δ − cos x · sin δ+                 --   ≤ sin x + δ · cos x − sin x · (1−δ²/2) − cos x · (δ − δ³/6)+                 --   = sin x · δ²/2 + cos x · δ³/6+                 --   ≤ δ² · (sin x / 2 + cos x / 6)+                 -- δ ≥ sqrt(2 · ε / (sin x + cos x / 3))+                 -- For general δ≥0,+                 -- ε ≤ δ · cos x + sin x + 1+                 -- δ ≥ (ε − sin x − 1) / cos x+  cos = sin . (globalDiffable' (actuallyAffine (pi/2) idL) $~)+  +  sinh x = (exp x - exp (-x))/2+    {- = grwDfblFnValsFunc sinhDfb+   where sinhDfb x = ( sx, cx *^ idL, dev_ε_δ δ )+          where sx = sinh x; cx = cosh x+                δ ε = undefined -}+                 -- ε = sinh x + δ · cosh x − sinh(x+δ)+                 --   = ½ · ( eˣ − e⁻ˣ + δ · (eˣ + e⁻ˣ) − exp(x+δ) + exp(-x−δ) )+                 --                  = ½·e⁻ˣ · ( e²ˣ − 1 + δ · (e²ˣ + 1) − e²ˣ·e^δ + e^-δ )+                 --   = ½ · ( eˣ − e⁻ˣ + δ · (eˣ + e⁻ˣ) − exp(x+δ) + exp(-x−δ) )+  cosh x = (exp x + exp (-x))/2+  tanh x = (exp x - exp (-x)) / (exp x + exp (-x))++  atan = grwDfblFnValsFunc atanDfb+   where atanDfb x = ( atnx, idL ^/ (1+x^2), dev_ε_δ δ )+          where atnx = atan x+                c = (atnx*2/pi)^2+                p = 1 + abs x/(2*pi)+                δ ε = p * (sqrt ε + ε * c)+                 -- Semi-empirically obtained: with the epsEst helper,+                 -- it is observed that this function is (for xc≥0) a lower bound+                 -- to the arctangent. The growth of the p coefficient makes sense+                 -- and holds for arbitrarily large xc, because those move us linearly+                 -- away from the only place where the function is not virtually constant+                 -- (around 0).+   +  asin = (RWDiffable asinRW $~)+   where asinRW x | x < (-1)   = (preRegionFromMinInfTo (-1), notDefinedHere)  +                  | x > 1      = (preRegionToInfFrom 1, notDefinedHere)+                  | otherwise  = (intervalPreRegion (-1,1), pure (Differentiable asinDefdR))+         asinDefdR x = ( asinx, asin'x *^ idL, dev_ε_δ δ )+          where asinx = asin x; asin'x = recip (sqrt $ 1 - x^2)+                c = 1 - x^2 +                δ ε = sqrt ε * c+                 -- Empirical, with epsEst upper bound.++  acos = (RWDiffable acosRW $~)+   where acosRW x | x < (-1)   = (preRegionFromMinInfTo (-1), notDefinedHere)  +                  | x > 1      = (preRegionToInfFrom 1, notDefinedHere)+                  | otherwise  = (intervalPreRegion (-1,1), pure (Differentiable acosDefdR))+         acosDefdR x = ( acosx, acos'x *^ idL, dev_ε_δ δ )+          where acosx = acos x; acos'x = - recip (sqrt $ 1 - x^2)+                c = 1 - x^2+                δ ε = sqrt ε * c -- Like for asin – it's just a translation/reflection.++  asinh = grwDfblFnValsFunc asinhDfb+   where asinhDfb x = ( asinhx, idL ^/ sqrt(1+x^2), dev_ε_δ δ )+          where asinhx = asinh x+                δ ε = abs x * sqrt((1 - exp(-ε))*0.8 + ε^2/(3*abs x)) + sqrt(ε/(abs x+0.5))+                 -- Empirical, modified from log function (the area hyperbolic sine+                 -- resembles two logarithmic lobes), with epsEst-checked lower bound.+  +  acosh = (RWDiffable acoshRW $~)+   where acoshRW x | x > 0      = (positivePreRegion, pure (Differentiable acoshDfb))+                  | otherwise  = (negativePreRegion, notDefinedHere)+         acoshDfb x = ( acosh x, idL ^/ sqrt(x^2 - 2), dev_ε_δ δ )+          where δ ε = (2 - 1/sqrt x) * (s2 * sqrt sx^3 * sqrt(ε/s2) + signum (ε*s2-sx) * sx * ε/s2) +                sx = sqrt(x-1)+                s2 = sqrt 2+                 -- Empirical, modified from sqrt function – the area hyperbolic cosine+                 -- strongly resembles \x -> sqrt(2 · (x-1)).+                    +  atanh = (RWDiffable atnhRW $~)+   where atnhRW x | x < (-1)   = (preRegionFromMinInfTo (-1), notDefinedHere)  +                  | x > 1      = (preRegionToInfFrom 1, notDefinedHere)+                  | otherwise  = (intervalPreRegion (-1,1), pure (Differentiable atnhDefdR))+         atnhDefdR x = ( atanh x, recip(1-x^2) *^ idL, dev_ε_δ $ \ε -> sqrt(tanh ε)*(1-abs x) )+                 -- Empirical, with epsEst upper bound.+  +  +  +
+ Data/Manifold/Types.hs view
@@ -0,0 +1,140 @@+-- |+-- Module      : Data.Manifold.Types+-- Copyright   : (c) Justus Sagemüller 2015+-- License     : GPL v3+-- +-- Maintainer  : (@) sagemueller $ geo.uni-koeln.de+-- Stability   : experimental+-- Portability : portable+-- +++{-# LANGUAGE FlexibleInstances        #-}+{-# LANGUAGE UndecidableInstances     #-}+-- {-# LANGUAGE OverlappingInstances     #-}+{-# LANGUAGE TypeFamilies             #-}+{-# LANGUAGE FunctionalDependencies   #-}+{-# LANGUAGE FlexibleContexts         #-}+{-# LANGUAGE GADTs                    #-}+{-# LANGUAGE RankNTypes               #-}+{-# LANGUAGE TupleSections            #-}+{-# LANGUAGE ConstraintKinds          #-}+{-# LANGUAGE PatternGuards            #-}+{-# LANGUAGE TypeOperators            #-}+{-# LANGUAGE ScopedTypeVariables      #-}+{-# LANGUAGE RecordWildCards          #-}+++module Data.Manifold.Types where+++import Data.VectorSpace+import Data.AffineSpace+import Data.Basis+import Data.Complex hiding (magnitude)+import Data.Void+import Data.Monoid++import qualified Prelude++import Control.Category.Constrained.Prelude hiding ((^))+import Control.Arrow.Constrained+import Control.Monad.Constrained+import Data.Foldable.Constrained+++++++type EuclidSpace v = (HasBasis v, EqFloating(Scalar v), Eq v)+type EqFloating f = (Eq f, Ord f, Floating f)++++data GraphWindowSpec = GraphWindowSpec {+    lBound, rBound, bBound, tBound :: Double+  , xResolution, yResolution :: Int+  }+++++data ZeroDim k = Origin deriving(Eq, Show)+instance Monoid (ZeroDim k) where+  mempty = Origin+  mappend Origin Origin = Origin+instance AdditiveGroup (ZeroDim k) where+  zeroV = Origin+  Origin ^+^ Origin = Origin+  negateV Origin = Origin+instance VectorSpace (ZeroDim k) where+  type Scalar (ZeroDim k) = k+  _ *^ Origin = Origin+instance HasBasis (ZeroDim k) where+  type Basis (ZeroDim k) = Void+  basisValue = absurd+  decompose Origin = []+  decompose' Origin = absurd++data S⁰ = PositiveHalfSphere | NegativeHalfSphere deriving(Eq, Show)+newtype S¹ = S¹ { φParamS¹ :: Double -- [-π, π[+                } deriving (Show)+data S² = S² { ϑParamS² :: !Double -- [0, π[+             , φParamS² :: !Double -- [-π, π[+             } deriving (Show)+++class NaturallyEmbedded m v where+  embed :: m -> v+  coEmbed :: v -> m+  ++instance (VectorSpace y) => NaturallyEmbedded x (x,y) where+  embed x = (x, zeroV)+  coEmbed (x,_) = x+instance (VectorSpace y, VectorSpace z) => NaturallyEmbedded x ((x,y),z) where+  embed x = (embed x, zeroV)+  coEmbed (x,_) = coEmbed x++instance NaturallyEmbedded S⁰ ℝ where+  embed PositiveHalfSphere = 1+  embed NegativeHalfSphere = -1+  coEmbed x | x>=0       = PositiveHalfSphere+            | otherwise  = NegativeHalfSphere+instance NaturallyEmbedded S¹ ℝ² where+  embed (S¹ φ) = (cos φ, sin φ)+  coEmbed (x,y) = S¹ $ atan2 y x+instance NaturallyEmbedded S² ℝ³ where+  embed (S² ϑ φ) = ((cos φ * sin ϑ, sin φ * sin ϑ), cos ϑ)+  coEmbed ((x,y),z) = S² (acos $ z/r) (atan2 y x)+   where r = sqrt $ x^2 + y^2 + z^2+ +++++type Endomorphism a = a->a+++type ℝ = Double+type ℝ² = (ℝ,ℝ)+type ℝ³ = (ℝ²,ℝ)++instance VectorSpace () where+  type Scalar () = ℝ+  _ *^ () = ()++instance HasBasis () where+  type Basis () = Void+  basisValue = absurd+  decompose () = []+  decompose' () = absurd+instance InnerSpace () where+  () <.> () = 0++++(^) :: Num a => a -> Int -> a+(^) = (Prelude.^)+
manifolds.cabal view
@@ -1,5 +1,5 @@ Name:                manifolds-Version:             0.1.0.0+Version:             0.1.0.2 Category:            Math Synopsis:            Working with manifolds in a direct, embedding-free way. Description:         Manifolds, a generalisation of the notion of \"smooth curves\" or sufaces,@@ -33,6 +33,7 @@   Build-Depends:     base>=4.5 && < 6                      , transformers                      , vector-space>=0.8+                     , MemoTrie                      , vector                      , vector-algorithms                      , containers@@ -41,7 +42,8 @@                      , comonad                      , semigroups                      , void-                     , constrained-categories+                     , tagged+                     , constrained-categories >= 0.2 && < 0.3   other-extensions:  FlexibleInstances                      , TypeFamilies                      , FlexibleContexts@@ -54,8 +56,11 @@                      , TupleSections   ghc-options:       -O2   Exposed-modules:   Data.Manifold+                     Data.Manifold.PseudoAffine+                     Data.LinearMap.HerMetric                      -- Data.Manifold.Visualisation.R3.GLUT-  Other-modules:   Data.List.FastNub+  Other-modules:   Data.Manifold.Types+                   Data.List.FastNub                    Util.Associate                    Util.LtdShow   default-language: Haskell2010