packages feed

poly (empty) → 0.1.0.0

raw patch · 8 files changed

+267/−0 lines, 8 filesdep +QuickCheckdep +basedep +polysetup-changed

Dependencies added: QuickCheck, base, poly, quickcheck-classes, semirings, tasty, tasty-quickcheck, vector

Files

+ LICENSE view
@@ -0,0 +1,30 @@+Copyright Andrew Lelechenko (c) 2019++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++    * Redistributions of source code must retain the above copyright+      notice, this list of conditions and the following disclaimer.++    * Redistributions in binary form must reproduce the above+      copyright notice, this list of conditions and the following+      disclaimer in the documentation and/or other materials provided+      with the distribution.++    * Neither the name of Andrew Lelechenko nor the names of other+      contributors may be used to endorse or promote products derived+      from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ README.md view
@@ -0,0 +1,3 @@+# poly++A type to represent polynomials with Num and Semiring instances.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ changelog.md view
@@ -0,0 +1,3 @@+# 0.1.0.0++* Initial release.
+ poly.cabal view
@@ -0,0 +1,51 @@+name: poly+version: 0.1.0.0+synopsis: Polynomials+description:+  A type to represent polynomials with Num and Semiring instances.+homepage: https://github.com/Bodigrim/poly#readme+license: BSD3+license-file: LICENSE+author: Andrew Lelechenko+maintainer: andrew.lelechenko@gmail.com+copyright: 2019 Andrew Lelechenko+category: Math, Numerical+build-type: Simple+extra-source-files: README.md+cabal-version: >=1.10+tested-with: GHC ==7.10.3 GHC ==8.0.2 GHC ==8.2.2 GHC ==8.4.4 GHC ==8.6.4+extra-source-files:+  changelog.md++source-repository head+  type: git+  location: https://github.com/Bodigrim/poly++library+  hs-source-dirs: src+  exposed-modules:+    Data.Poly+  other-modules:+    Data.Poly.Uni.Dense+  build-depends:+    base >= 4.8 && < 5,+    semirings,+    vector+  default-language: Haskell2010+  ghc-options: -Wall++test-suite poly-tests+  type: exitcode-stdio-1.0+  main-is: Main.hs+  build-depends:+    base >=4.8 && <5,+    poly,+    QuickCheck >=2.10,+    quickcheck-classes >=0.6.1,+    semirings,+    tasty,+    tasty-quickcheck,+    vector+  default-language: Haskell2010+  hs-source-dirs: test+  ghc-options: -Wall
+ src/Data/Poly.hs view
@@ -0,0 +1,14 @@+-- |+-- Module:      Data.Poly+-- Copyright:   (c) 2019 Andrew Lelechenko+-- Licence:     BSD3+-- Maintainer:  Andrew Lelechenko <andrew.lelechenko@gmail.com>+--+-- Polynomials.+--++module Data.Poly+  ( module Data.Poly.Uni.Dense+  ) where++import Data.Poly.Uni.Dense
+ src/Data/Poly/Uni/Dense.hs view
@@ -0,0 +1,130 @@+-- |+-- Module:      Data.Poly.Uni.Dense+-- Copyright:   (c) 2019 Andrew Lelechenko+-- Licence:     BSD3+-- Maintainer:  Andrew Lelechenko <andrew.lelechenko@gmail.com>+--+-- Dense polynomials of one variable.+--++{-# LANGUAGE ScopedTypeVariables #-}++module Data.Poly.Uni.Dense+  ( Poly+  , unPoly+  , toPoly+  , toPoly'+  ) where++import Prelude hiding (negate)+import Control.Monad+import Control.Monad.ST+import Data.List (foldl')+import Data.Semiring (Semiring(..), Ring(..))+import Data.Vector (Vector)+import qualified Data.Vector as V+import qualified Data.Vector.Mutable as MV++-- | Polynomials of one variable.+--+-- >>> :set -XOverloadedLists+-- >>> -- (1 + x) * (-1 + x) = (-1 + x^2)+-- >>> toPoly [1,1] * toPoly [-1,1]+-- Poly {unPoly = [-1,0,1]}+--+-- >>> :set -XOverloadedLists+-- >>> -- (1 + x) + (1 - x) = 2+-- >>> toPoly [1,1] + toPoly [1,-1]+-- Poly {unPoly = [2]}+newtype Poly a = Poly+  { unPoly :: Vector a+  -- ^ Convert 'Poly' to a vector of coefficients+  -- (first element corresponds to a constant term).+  }+  deriving (Eq, Ord, Show)++-- | Make 'Poly' from a list of coefficients+-- (first element corresponds to a constant term).+--+-- >>> :set -XOverloadedLists+-- >>> toPoly [1,2,3]+-- Poly {unPoly = [1,2,3]}+--+-- >>> :set -XOverloadedLists+-- >>> toPoly [0,0,0]+-- Poly {unPoly = []}+toPoly :: (Eq a, Num a) => Vector a -> Poly a+toPoly = Poly . dropWhileEnd (== 0)++-- | Make 'Poly' from a vector of coefficients+-- (first element corresponds to a constant term).+--+-- >>> :set -XOverloadedLists+-- >>> toPoly' [1,2,3]+-- Poly {unPoly = [1,2,3]}+--+-- >>> :set -XOverloadedLists+-- >>> toPoly' [0,0,0]+-- Poly {unPoly = []}+toPoly' :: (Eq a, Semiring a) => Vector a -> Poly a+toPoly' = Poly . dropWhileEnd (== zero)++instance (Eq a, Num a) => Num (Poly a) where+  Poly xs + Poly ys = toPoly $ zipOrCopy (+) xs ys+  Poly xs - Poly ys = toPoly $ zipOrCopy (-) xs ys+  abs = id+  signum = const 1+  fromInteger n = case fromInteger n of+    0 -> Poly $ V.empty+    m -> Poly $ V.singleton m+  Poly xs * Poly ys = toPoly $ convolution 0 (+) (*) xs ys++instance (Eq a, Semiring a) => Semiring (Poly a) where+  zero = Poly V.empty+  one+    | (one :: a) == zero = zero+    | otherwise = Poly $ V.singleton one+  plus (Poly xs) (Poly ys) = toPoly' $ zipOrCopy plus xs ys+  times (Poly xs) (Poly ys) = toPoly' $ convolution zero plus times xs ys++instance (Eq a, Ring a) => Ring (Poly a) where+  negate (Poly xs) = Poly $ V.map negate xs++dropWhileEnd :: (a -> Bool) -> Vector a -> Vector a+dropWhileEnd p xs = V.slice 0 (go (V.length xs)) xs+  where+    go 0 = 0+    go n = if p (xs V.! (n - 1)) then go (n - 1) else n++zipOrCopy :: (a -> a -> a) -> Vector a -> Vector a -> Vector a+zipOrCopy f xs ys = runST $ do+  zs <- MV.new lenZs+  forM_ [0 .. lenZs - 1] $ \i ->+    MV.write zs i (f (xs V.! i) (ys V.! i))+  when (lenXs < lenYs) $+    forM_ [lenXs .. lenYs - 1] $ \i ->+      MV.write zs i (ys V.! i)+  when (lenYs < lenXs) $+    forM_ [lenYs .. lenXs - 1] $ \i ->+      MV.write zs i (xs V.! i)+  V.unsafeFreeze zs+  where+    lenXs = V.length xs+    lenYs = V.length ys+    lenZs = lenXs `max` lenYs++convolution :: a -> (a -> a -> a) -> (a -> a -> a) -> Vector a -> Vector a -> Vector a+convolution zer add mul xs ys+  | V.null xs || V.null ys = V.empty+  | otherwise = runST $ do+    zs <- MV.new lenZs+    forM_ [0 .. lenZs - 1] $ \k -> do+      let is = [max (k - lenYs + 1) 0 .. min k (lenXs - 1)]+          -- js = reverse [max (k - lenXs) 0 .. min k lenYs]+      let acc = foldl' add zer $ flip map is $ \i -> mul (xs V.! i) (ys V.! (k - i))+      MV.write zs k acc+    V.unsafeFreeze zs+  where+    lenXs = V.length xs+    lenYs = V.length ys+    lenZs = lenXs + lenYs - 1
+ test/Main.hs view
@@ -0,0 +1,34 @@+{-# OPTIONS_GHC -fno-warn-orphans #-}++module Main where++import Data.Int+import Data.Poly+import Data.Proxy+import Data.Semiring+import qualified Data.Vector as V+import Test.Tasty+import Test.Tasty.QuickCheck+import Test.QuickCheck.Classes++main :: IO ()+main = defaultMain $ testGroup "All"+    [ semiringTests+    ]++semiringTests :: TestTree+semiringTests+  = testGroup "Semiring"+  $ map (uncurry testProperty)+  $ concatMap lawsProperties+  [ semiringLaws (Proxy :: Proxy (Poly ()))+  ,     ringLaws (Proxy :: Proxy (Poly ()))+  , semiringLaws (Proxy :: Proxy (Poly Int8))+  ,     ringLaws (Proxy :: Proxy (Poly Int8))+  , semiringLaws (Proxy :: Proxy (Poly Integer))+  ,     ringLaws (Proxy :: Proxy (Poly Integer))+  ]++instance (Eq a, Semiring a, Arbitrary a) => Arbitrary (Poly a) where+  arbitrary = toPoly' . V.fromList <$> arbitrary+  shrink = fmap (toPoly' . V.fromList) . shrink . V.toList . unPoly