packages feed

converge (empty) → 0.1

raw patch · 3 files changed

+100/−0 lines, 3 filesdep +basesetup-changed

Dependencies added: base

Files

+ Setup.lhs view
@@ -0,0 +1,5 @@+#!/usr/bin/env runhaskell++> import Distribution.Simple+> main = defaultMain+
+ converge.cabal view
@@ -0,0 +1,29 @@+name:                   converge+version:                0.1+stability:              provisional++cabal-version:          >= 1.6+build-type:             Simple++author:                 James Cook <mokus@deepbondi.net>+maintainer:             James Cook <mokus@deepbondi.net>+license:                PublicDomain+homepage:               /dev/null++category:               Math, Numerical+synopsis:               Limit operations for converging sequences+description:            Limit operations for converging sequences.  This is+                        fairly simple right now.++tested-with:            GHC == 6.8.3,+                        GHC == 6.10.4,+                        GHC == 6.12.1, GHC == 6.12.3++source-repository head+  type: darcs+  location: http://code.haskell.org/~mokus/converge++Library+  hs-source-dirs:       src+  exposed-modules:      Math.Sequence.Converge+  build-depends:        base >= 3 && <5
+ src/Math/Sequence/Converge.hs view
@@ -0,0 +1,66 @@+module Math.Sequence.Converge where++import Data.List+import Data.Maybe+import Data.Monoid++-- |Take items from the list until two successive items are equal and +-- return the second of them (or an item is not equal to itself, to handle+-- NaN without a 'RealFloat' context.  In this case, the first item of the +-- pair is returned) .  If the list ends before a match is found, +-- returns the last element of the list.+converge :: Eq a => [a] -> a+converge = fromMaybe empty . convergeBy eq Just+    where+        empty = error "converge: empty list"+        +        eq (a:b:_)+            | a == b        = Just b+            | b /= b        = Just a+        eq _ = Nothing++-- |@convergeTo absEps relEps xs@ takes items from @xs@ until two successive+-- items @x@ and @y@ are within either @absEps@ or @relEps * max (abs x) (abs+-- y)@ of each other, in which case the second of the pair is returned, or +-- until an item is found that does not equal itself (which would typically +-- be a NaN), in which case the preceding item is returned.  If the list ends+-- before a match is found, the last element of the list is returned.+--+-- For example, approximating the golden mean by applying Newton's method to +-- find a root of @x^2 - x - 1@:+-- +-- > phi :: Rational+-- > phi = convergeTo 1e-100 0 (iterate (\x -> (x*x + 1) / (2*x-1)) 1)+convergeTo :: (Fractional a, Ord a) => a -> a -> [a] -> a+convergeTo absEps relEps = fromMaybe empty . convergeBy eq Just+    where+        empty = error "convergeTo: empty list"+        eq (a:b:_)+            | b /= b                            = Just a+            | absDiff <= abs absEps             = Just b+            | absDiff <= abs relEps * relScale  = Just b+            where+                absDiff = abs (a-b)+                relScale = max (abs a) (abs b)+        eq _ = Nothing++-- |@convergeBy f end xs@ looks through @xs@ for the first segment for which+-- @f@ returns a value, and returns that value.  Typically @f@ would be +-- something like:+-- +-- > f (a:b:_)+-- >    | abs(a-b) <= eps+-- >    = Just (0.5 * (a + b))+-- > f _ = Nothing+-- +-- If no such segment is found, applies @end@ to the last item in the list+-- and returns the result.  If the list was empty, returns 'Nothing'.+-- +convergeBy :: ([a] -> Maybe b) -> (a -> Maybe b) -> [a] -> Maybe b+convergeBy f end = listToMaybe . catMaybes . map f' . tails+    where +        f' xs = case f xs of+            Nothing -> end' xs+            other   -> other+        end' [x] = end x+        end'  _  = Nothing