packages feed

cyclotomic 0.1 → 0.2

raw patch · 2 files changed

+106/−49 lines, 2 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- Data.Complex.Cyclotomic: isGaussianRational :: Cyclotomic -> Bool
- Data.Complex.Cyclotomic: isRational :: Cyclotomic -> Bool
+ Data.Complex.Cyclotomic: gaussianRat :: Rational -> Rational -> Cyclotomic
+ Data.Complex.Cyclotomic: isGaussianRat :: Cyclotomic -> Bool
+ Data.Complex.Cyclotomic: isRat :: Cyclotomic -> Bool
+ Data.Complex.Cyclotomic: polarRat :: Rational -> Rational -> Cyclotomic
+ Data.Complex.Cyclotomic: toReal :: Cyclotomic -> Maybe Double

Files

cyclotomic.cabal view
@@ -1,5 +1,5 @@ Name:                cyclotomic-Version:             0.1+Version:             0.2 Synopsis:            A subfield of the complex numbers for exact calculation Description:         The cyclotomic numbers are a subset of the                      complex numbers with a number of nice properties.
src/Data/Complex/Cyclotomic.hs view
@@ -1,32 +1,61 @@ {-# OPTIONS_GHC -Wall #-} --- | The cyclotomic numbers are a subset of the complex numbers with---   the following properties:------   1.  The cyclotomic numbers are represented exactly, enabling exact---   computations and equality comparisons.------   2.  The cyclotomic numbers contain the Gaussian rationals---   (complex numbers of the form 'p' + 'q' 'i' with 'p' and 'q' rational).---   As a consequence, the cyclotomic numbers are a dense subset of the---   complex numbers.------   3.  The cyclotomic numbers contain the square roots of all rational numbers.------   4.  The cyclotomic numbers form a field:  they are closed under addition, subtraction,---   multiplication, and division.------   5.  The cyclotomic numbers contain the sine and cosine of all rational---   multiples of pi.------   6.  The cyclotomic numbers can be thought of as the rational field extended---   with 'n'th roots of unity for arbitrarily large integers 'n'.------   This algorithm for cyclotomic numbers is adapted from code by---   Martin Schoenert and Thomas Breuer in the GAP project <http://www.gap-system.org/> .---   See in particular source files gap4r4\/src\/cyclotom.c and---   gap4r4\/lib\/cyclotom.gi .+-- Module      :  Data.Complex.Cyclotomic+-- Copyright   :  (c) Scott N. Walck 2012+-- License     :  GPL-3 (see LICENSE)+-- Maintainer  :  Scott N. Walck <walck@lvc.edu> +{- | The cyclotomic numbers are a subset of the complex numbers with+     the following properties:+    +     1.  The cyclotomic numbers are represented exactly, enabling exact+     computations and equality comparisons.+    +     2.  The cyclotomic numbers contain the Gaussian rationals+     (complex numbers of the form 'p' + 'q' 'i' with 'p' and 'q' rational).+     As a consequence, the cyclotomic numbers are a dense subset of the+     complex numbers.+    +     3.  The cyclotomic numbers contain the square roots of all rational numbers.+    +     4.  The cyclotomic numbers form a field:  they are closed under addition, subtraction,+     multiplication, and division.+    +     5.  The cyclotomic numbers contain the sine and cosine of all rational+     multiples of pi.+    +     6.  The cyclotomic numbers can be thought of as the rational field extended+     with 'n'th roots of unity for arbitrarily large integers 'n'.++     Floating point numbers do not do well with equality comparison:++>(sqrt 2 + sqrt 3)^2 == 5 + 2 * sqrt 6+> -> False++     "Data.Complex.Cyclotomic" represents these numbers exactly, allowing equality comparison:++>(sqrtRat 2 + sqrtRat 3)^2 == 5 + 2 * sqrtRat 6+> -> True++     'Cyclotomic's can be exported as inexact complex numbers using the 'toComplex' function:++>e 6+> -> -e(3)^2+>real $ e 6+> -> 1/2+>imag $ e 6+> -> -1/2*e(12)^7 + 1/2*e(12)^11+>imag (e 6) == sqrtRat 3 / 2+> -> True+>toComplex $ e 6+> -> 0.5000000000000003 :+ 0.8660254037844384++     The algorithms for cyclotomic numbers are adapted from code by+     Martin Schoenert and Thomas Breuer in the GAP project <http://www.gap-system.org/>+     (in particular source files gap4r4\/src\/cyclotom.c and+     gap4r4\/lib\/cyclotom.gi).+-}+ module Data.Complex.Cyclotomic     (Cyclotomic     ,i@@ -35,14 +64,17 @@     ,sqrtRat     ,sinDeg     ,cosDeg+    ,gaussianRat+    ,polarRat     ,conj     ,real     ,imag     ,modSq-    ,toComplex     ,isReal-    ,isRational-    ,isGaussianRational+    ,isRat+    ,isGaussianRat+    ,toComplex+    ,toReal     ,toRat     )     where@@ -58,22 +90,26 @@                              , coeffs :: M.Map Integer Rational                              } deriving (Eq) +-- | @signum c@ is the complex number with magnitude 1 that has the same argument as c;+--   @signum c = c / abs c@. instance Num Cyclotomic where     (+) = sumCyc     (*) = prodCyc     (-) c1 c2 = sumCyc c1 (aInvCyc c2)     negate = aInvCyc     abs = sqrtRat . modSq-    signum = error "signum not defined for cyclotomic numbers"+    signum 0 = zeroCyc+    signum c = c / abs c     fromInteger 0 = zeroCyc     fromInteger n = Cyclotomic 1 (M.singleton 0 (fromIntegral n))  instance Fractional Cyclotomic where     recip = invCyc+    fromRational 0 = zeroCyc     fromRational r = Cyclotomic 1 (M.singleton 0 r) --- | The primitive 'n'th root of unity.---   For example, 'e'(4) = 'i' is the primitive 4th root of unity,+-- | The primitive @n@th root of unity.+--   For example, @'e'(4) = 'i'@ is the primitive 4th root of unity, --   and 'e'(5) = exp(2*pi*i/5) is the primitive 5th root of unity. --   In general, 'e' 'n' = exp(2*pi*i/'n'). e :: Integer -> Cyclotomic@@ -164,6 +200,19 @@ i :: Cyclotomic i = e 4 +-- | Make a Gaussian rational; @gaussianRat p q@ is the same as @p + q * i@.+gaussianRat :: Rational -> Rational -> Cyclotomic+gaussianRat p q = fromRational p + fromRational q * i++-- | A complex number in polar form, with rational magnitude @r@ and rational angle @s@+--   of the form @r * exp(2*pi*i*s)@; @polarRat r s@ is the same as @r * e q ^ p@,+--   where @s = p/q@.+polarRat :: Rational -> Rational -> Cyclotomic+polarRat r s = fromRational r * e q ^ p+    where+      p = numerator s+      q = denominator s+ -- | Complex conjugate. conj :: Cyclotomic -> Cyclotomic conj (Cyclotomic n mp)@@ -183,12 +232,6 @@             Just msq -> msq             Nothing  -> error $ "modSq:  tried z = " ++ show z --- | Export as an inexact complex number.-toComplex :: Cyclotomic -> Complex Double-toComplex c = sum [fromRational r * en^p | (p,r) <- M.toList (coeffs c)]-    where en = exp (0 :+ 2*pi/n)-          n = fromIntegral (order c)- convertToBase :: Integer -> M.Map Integer Rational -> M.Map Integer Rational convertToBase n mp = foldr (\(p,r) m -> replace n p r m) mp (extraneousPowers n) @@ -304,10 +347,12 @@  -- | Product of two cyclotomic numbers. prodCyc :: Cyclotomic -> Cyclotomic -> Cyclotomic-prodCyc (Cyclotomic o1 m1) (Cyclotomic o2 m2)-    = mkCyclotomic ord $ M.fromListWith (+)-      [((o2*e1+o1*e2) `mod` ord,c1*c2) | (e1,c1) <- M.toList m1, (e2,c2) <- M.toList m2]-      where ord = o1 * o2+prodCyc (Cyclotomic o1 map1) (Cyclotomic o2 map2)+    = let ord = lcm o1 o2+          m1 = ord `div` o1+          m2 = ord `div` o2+      in mkCyclotomic ord $ M.fromListWith (+)+             [((m1*e1+m2*e2) `mod` ord,c1*c2) | (e1,c1) <- M.toList map1, (e2,c2) <- M.toList map2]  -- | Product of a rational number and a cyclotomic number. prodRatCyc :: Rational -> Cyclotomic -> Cyclotomic@@ -331,15 +376,27 @@ isReal c = c == conj c  -- | Is the cyclotomic a rational?-isRational :: Cyclotomic -> Bool-isRational (Cyclotomic 1 _) = True-isRational _                = False+isRat :: Cyclotomic -> Bool+isRat (Cyclotomic 1 _) = True+isRat _                = False  -- | Is the cyclotomic a Gaussian rational?-isGaussianRational :: Cyclotomic -> Bool-isGaussianRational c = isRational (real c) && isRational (imag c)+isGaussianRat :: Cyclotomic -> Bool+isGaussianRat c = isRat (real c) && isRat (imag c) --- | Return Just rational if the cyclotomic is rational, Nothing otherwise.+-- | Export as an inexact complex number.+toComplex :: Cyclotomic -> Complex Double+toComplex c = sum [fromRational r * en^p | (p,r) <- M.toList (coeffs c)]+    where en = exp (0 :+ 2*pi/n)+          n = fromIntegral (order c)++-- | Export as an inexact real number if possible.+toReal :: Cyclotomic -> Maybe Double+toReal c+    | isReal c   = Just $ realPart (toComplex c)+    | otherwise  = Nothing++-- | Return an exact rational number if possible. toRat :: Cyclotomic -> Maybe Rational toRat (Cyclotomic 1 mp)     | mp == M.empty  = Just 0