packages feed

cayley-dickson 0.2.0.0 → 0.2.1.0

raw patch · 3 files changed

+111/−59 lines, 3 filesdep ~basedep ~randomPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependency ranges changed: base, random

API changes (from Hackage documentation)

- Math.CayleyDickson: instance GHC.Float.RealFloat a => Math.CayleyDickson.Conjugable (Data.Complex.Complex a)
+ Math.CayleyDickson: instance (Math.CayleyDickson.Conjugable a, GHC.Float.RealFloat a) => Math.CayleyDickson.Conjugable (Data.Complex.Complex a)
+ Math.CayleyDickson: scalarPart' :: Conjugable a => a -> a
- Math.CayleyDickson: class Num a => Conjugable a
+ Math.CayleyDickson: class Num a => Conjugable a where conj = id scalarPart' = id

Files

cayley-dickson.cabal view
@@ -1,5 +1,5 @@ name:                cayley-dickson-version:             0.2.0.0+version:             0.2.1.0 synopsis:            Complex numbers, quaternions, octonions, sedenions, etc. description:         Cayley-Dickson constructions (complex numbers, quaternions,                      octonions, sedenions, etc.) over general scalars without@@ -23,7 +23,7 @@ library   exposed-modules:   Math.CayleyDickson   hs-source-dirs:    src-  build-depends:     base >= 4.8 && < 5+  build-depends:     base >= 4.7 && < 5   default-language:  Haskell2010   ghc-options:       -Wall -O2 @@ -31,6 +31,6 @@   type:              exitcode-stdio-1.0   hs-source-dirs:    test, src   main-is:           test.hs-  build-depends:     base >= 4.8 && < 5, random >= 1+  build-depends:     base >= 4.7 && < 5, random == 1.*   default-language:  Haskell2010   ghc-options:       -Wall
src/Math/CayleyDickson.hs view
@@ -66,7 +66,7 @@     basisElement,      -- * Classes-    Conjugable(conj),+    Conjugable(..),      -- ** Tags     Tag(tagVal),@@ -129,16 +129,19 @@ purePart (Scalar _) = Scalar 0 purePart (x :@ y) = purePart x :@ y --- | Dot product (actually the Hermitian inner product, a--- generalization of the dot product).+-- | Dot product. @(1 \`dot\`)@ is equivalent to @'scalarPart'@. dot :: Conjugable a => Nion n a -> Nion n a -> a-Scalar x `dot` Scalar y = conj x * y -- also defined as x * conj y+-- (y * conj x + x * conj y) / 2+Scalar x `dot` Scalar y = scalarPart' $ y * conj x x@(Scalar _) `dot` (y1 :@ _) = x `dot` y1 (x1 :@ _) `dot` y@(Scalar _) = x1 `dot` y (x1 :@ x2) `dot` (y1 :@ y2) = (x1 `dot` y1) + (x2 `dot` y2) --- | Cross product.+-- | Cross product. @(1 \`cross\`)@ is equivalent to @'purePart'@. The+-- cross product of two pures yields an element that is orthogonal to+-- both operands. cross :: Conjugable a => Nion n a -> Nion n a -> Nion n a+-- (y * conj x - x * conj y) / 2 x `cross` y = y * conj x -. x `dot` y  -- | Squared norm: the dot product of an element with itself.@@ -343,9 +346,10 @@  coord' :: (Tag n, Num a, Integral b, Bits b) => Proxy n -> Nion n a -> b -> a coord' _ (Scalar x) 0 = x-coord' _ (Scalar _) _ = 0 coord' n elt index-  | validIndex n index = f elt $ fromInteger $ tagVal n - 1+  | validIndex n index = case elt of+                           Scalar _ -> 0+                           _ -> f elt $ fromInteger $ tagVal n - 1   | otherwise = error "coord: out of range"   where     f (Scalar x) _ = x@@ -430,9 +434,8 @@  instance (Conjugable a, Fractional a) => Fractional (Nion n a) where   Scalar x / Scalar y = Scalar $ x / y-  x@(Scalar _) / y@(_ :@ _) = x * recip y   x@(_ :@ _) / Scalar y = smap (/ y) x-  x@(_ :@ _) / y@(_ :@ _) = (x * conj y) /. sqnorm y+  x / y = (x * conj y) /. sqnorm y    recip x = conj x /. sqnorm x   fromRational = fromScalar . fromRational@@ -512,31 +515,41 @@  -- | The /conjugate/ of an element is obtained by negating the pure -- part and conjugating the scalar part. The conjugate of a real--- number (which has no pure part) is the identity ('id').+-- number is the identity ('id'), which is the default implementation. class Num a => Conjugable a where+  -- | Conjugate.   conj :: a -> a+  conj = id +  -- | Equivalent to @(x + conj x) / 2@.+  scalarPart' :: a -> a+  scalarPart' = id+ instance Conjugable a => Conjugable (Nion n a) where   conj (Scalar x) = Scalar $ conj x   conj (x :@ y) = conj x :@ negate y -instance RealFloat a => Conjugable (C.Complex a) where+  scalarPart' (Scalar x) = Scalar $ scalarPart' x+  scalarPart' (x :@ _) = scalarPart' x++instance (Conjugable a, RealFloat a) => Conjugable (C.Complex a) where   conj = C.conjugate+  scalarPart' (x C.:+ _) = scalarPart' x C.:+ 0 -instance Conjugable Int where conj = id-instance Conjugable Integer where conj = id-instance Conjugable Float where conj = id-instance Conjugable Double where conj = id-instance Conjugable Z.Int8 where conj = id-instance Conjugable Z.Int16 where conj = id-instance Conjugable Z.Int32 where conj = id-instance Conjugable Z.Int64 where conj = id-instance Conjugable W.Word8 where conj = id-instance Conjugable W.Word16 where conj = id-instance Conjugable W.Word32 where conj = id-instance Conjugable W.Word64 where conj = id-instance Integral a => Conjugable (Q.Ratio a) where conj = id-instance F.HasResolution a => Conjugable (F.Fixed a) where conj = id+instance Conjugable Int+instance Conjugable Integer+instance Conjugable Float+instance Conjugable Double+instance Conjugable Z.Int8+instance Conjugable Z.Int16+instance Conjugable Z.Int32+instance Conjugable Z.Int64+instance Conjugable W.Word8+instance Conjugable W.Word16+instance Conjugable W.Word32+instance Conjugable W.Word64+instance Integral a => Conjugable (Q.Ratio a)+instance F.HasResolution a => Conjugable (F.Fixed a)  ----------------------------------------------------------------------------- -- doNotUse
test/test.hs view
@@ -3,11 +3,12 @@ import Data.Ratio (Ratio, (%)) import Control.Monad (replicateM, replicateM_, forM_, liftM) import System.Random (Random, randomRIO)+import System.IO (hFlush, stdout)  ---------------------------------------------------------- -- alternate formulas -pureDir :: (Tag n, Conjugable a, Floating a) => Nion n a -> Nion n a+pureDir :: (Conjugable a, Floating a) => Nion n a -> Nion n a pureDir x = p /. (norm p) where p = purePart x  cos' :: (Tag n, Conjugable a, RealFloat a) => Nion n a -> Nion n a@@ -22,11 +23,10 @@ sinh' :: (Tag n, Conjugable a, RealFloat a) => Nion n a -> Nion n a sinh' x = (exp x - exp (- x)) / 2 -dot' :: (Tag n, Conjugable a, Fractional a) => Nion n a -> Nion n a -> a+dot' :: (Conjugable a, Fractional a) => Nion n a -> Nion n a -> a dot' x y = scalarPart $ (y * conj x + x * conj y) / 2 -cross' :: (Tag n, Conjugable a, Fractional a) =>-          Nion n a -> Nion n a -> Nion n a+cross' :: (Conjugable a, Fractional a) => Nion n a -> Nion n a -> Nion n a cross' x y = (y * conj x - x * conj y) / 2  qmul :: Num a => a -> a -> a -> a ->@@ -43,16 +43,18 @@ epsilon = 1e-7  assert :: Bool -> IO ()-assert True = putChar '.'+assert True = do+  putChar '.'+  hFlush stdout assert False = error "assertion failed" -close :: Tag n => Nion n Double -> Nion n Double -> Bool+close :: Nion n Double -> Nion n Double -> Bool close x y = norm (x - y) < epsilon  closeReal :: Double -> Double -> Bool closeReal x y = abs (x - y) < epsilon -assertClose :: Tag n => Nion n Double -> Nion n Double -> IO ()+assertClose :: Nion n Double -> Nion n Double -> IO () assertClose x y = assert $ close x y  assertCloseReal :: Double -> Double -> IO ()@@ -79,13 +81,7 @@ randomEltI = randomElt boundsI  randomEltI' :: (Tag n1, Tag n2) => Integer -> IO (Nion n1 (Nion n2 Integer))-randomEltI' n = liftM nion $ replicateM (fromIntegral n) randomEltI--randomEltI2 :: Tag n => IO (Complex (Nion n Integer))-randomEltI2 = randomEltI' 2--randomEltI4 :: Tag n => IO (Quaternion (Nion n Integer))-randomEltI4 = randomEltI' 4+randomEltI' n = liftM nion $ replicateM (2^n) $ randomEltI  ---------------------------------------------------------- -- checks@@ -117,17 +113,16 @@ checkFloating1 :: Tag n => Nion n Double -> IO () checkFloating1 = checkFloating1' Proxy -checkFloating2' :: Tag n => Proxy n -> Nion n Double -> Nion n Double -> IO ()-checkFloating2' _ x y = do+checkFloating2 :: Nion n Double -> Nion n Double -> IO ()+checkFloating2 x y = do   assertCloseReal (x `dot` y) (x `dot'` y)   assertCloseReal (5 `dot` y) (5 `dot'` y)   assertCloseReal (x `dot` 5) (x `dot'` 5)+  assertCloseReal (3 `dot` 5) (3 `dot'` 5)   assertClose (x `cross` y) (x `cross'` y)   assertClose (5 `cross` y) (5 `cross'` y)   assertClose (x `cross` 5) (x `cross'` 5)--checkFloating2 :: Tag n => Nion n Double -> Nion n Double -> IO ()-checkFloating2 = checkFloating2' Proxy+  assertClose (3 `cross` 5) (3 `cross'` 5)  checkFloating3 :: Tag n => Nion n Double -> IO () checkFloating3 x' = do@@ -295,6 +290,7 @@   let y = quaternion 1 2 3 4 :: Quaternion (Ratio Integer)   assert $ y / 2 == quaternion (1 % 2) 1 (3 % 2) 2   assert $ recip y == quaternion (1 % 30) (-1 % 15) (-1 % 10) (-2 % 15)+  assert $ 3 / y == quaternion (1 % 10) (-1 % 5) (-3 % 10) (-2 % 5)   assert $ y * recip y == 1  checkPower :: IO ()@@ -315,12 +311,12 @@   assert $ y ^^. (-1 :: Integer) == recip y   assert $ y ^^. (-2 :: Integer) == recip (y * y) -checkZeroAndOne :: (Show a, Eq a, Conjugable a) => Nion n1 (Nion n2 a) -> IO ()+checkZeroAndOne :: (Conjugable a, Eq a) => Nion n1 (Nion n2 a) -> IO () checkZeroAndOne x = do   assert $ 0 + x == x   assert $ 1 * x == x -checkDistributive :: (Show a, Eq a, Conjugable a) =>+checkDistributive :: (Conjugable a, Eq a) =>                      Nion n1 (Nion n2 a) -> Nion n1 (Nion n2 a) ->                      Nion n2 a -> Nion n2 a ->                      IO ()@@ -328,7 +324,7 @@   assert $ (r + s) .* x == r .* x + s .* x   assert $ r .* (x + y) == r .* x + r .* y -checkModule :: (Show a, Eq a, Conjugable a) =>+checkModule :: (Conjugable a, Eq a) =>                Nion n1 (Nion n2 a) -> Nion n1 (Nion n2 a) ->                Nion n2 a -> Nion n2 a -> IO () checkModule x y r s = do@@ -336,7 +332,18 @@   checkZeroAndOne x   assert $ (r * s) .* x == r .* (s .* x) -checkIsomorphism :: (Conjugable a, Show a, Eq a) =>+checkDotCross :: (Conjugable a, Eq a) =>+                 Nion n1 (Nion n2 a) -> Nion n1 (Nion n2 a) -> IO ()+checkDotCross x' y' = do+  let x = purePart x'+      y = purePart y'+      x_cross_y = x `cross` y+  assert $ 2 * fromScalar (x `dot` y) == y * conj x + x * conj y+  assert $ 2 * x_cross_y == y * conj x - x * conj y+  assert $ x `dot` x_cross_y == 0+  assert $ y `dot` x_cross_y == 0++checkIsomorphism :: (Conjugable a, Eq a) =>                     ((Nion n1 (Nion n2 a)) -> Nion n3 a) ->                     (Nion n1 (Nion n2 a)) -> (Nion n1 (Nion n2 a)) ->                     IO ()@@ -349,6 +356,8 @@   assert $ f (x - y) == f x - f y   assert $ f (x * y) == f x * f y   assert $ scalarPart (sqnorm x) == sqnorm (f x)+  assert $ scalarPart (x `dot` y) == f x `dot` f y+  assert $ f (x `cross` y) == f x `cross` f y  phi :: (Tag n1, Tag n2, Tag n3, Conjugable a) =>        (Nion n1 (Nion n2 a)) -> Nion n3 a@@ -359,42 +368,70 @@   let f = phi :: Complex (Complex Integer) -> Quaternion Integer   r <- randomEltI :: IO (Complex Integer)   s <- randomEltI :: IO (Complex Integer)-  x <- randomEltI2 :: IO (Complex (Complex Integer))-  y <- randomEltI2 :: IO (Complex (Complex Integer))+  x <- randomEltI' 1 :: IO (Complex (Complex Integer))+  y <- randomEltI' 1 :: IO (Complex (Complex Integer))   checkIsomorphism f x y   checkModule x y r s+  checkDotCross x y  checkProperties2 :: IO () checkProperties2 = do   let f = phi :: Complex (Quaternion Integer) -> Octonion Integer   r <- randomEltI :: IO (Quaternion Integer)   s <- randomEltI :: IO (Quaternion Integer)-  x <- randomEltI2 :: IO (Complex (Quaternion Integer))-  y <- randomEltI2 :: IO (Complex (Quaternion Integer))+  x <- randomEltI' 1 :: IO (Complex (Quaternion Integer))+  y <- randomEltI' 1 :: IO (Complex (Quaternion Integer))   checkIsomorphism f x y   checkModule x y r s+  checkDotCross x y  checkProperties3 :: IO () checkProperties3 = do   let f = phi :: Complex (Octonion Integer) -> Sedenion Integer   r <- randomEltI :: IO (Octonion Integer)   s <- randomEltI :: IO (Octonion Integer)-  x <- randomEltI2 :: IO (Complex (Octonion Integer))-  y <- randomEltI2 :: IO (Complex (Octonion Integer))+  x <- randomEltI' 1 :: IO (Complex (Octonion Integer))+  y <- randomEltI' 1 :: IO (Complex (Octonion Integer))   checkIsomorphism f x y   checkDistributive x y r s   checkZeroAndOne x+  checkDotCross x y  checkProperties4 :: IO () checkProperties4 = do   let f = phi :: Quaternion (Complex Integer) -> Octonion Integer   r <- randomEltI :: IO (Complex Integer)   s <- randomEltI :: IO (Complex Integer)-  x <- randomEltI4 :: IO (Quaternion (Complex Integer))-  y <- randomEltI4 :: IO (Quaternion (Complex Integer))+  x <- randomEltI' 2 :: IO (Quaternion (Complex Integer))+  y <- randomEltI' 2 :: IO (Quaternion (Complex Integer))   checkIsomorphism f x y   checkModule x y r s+  checkDotCross x y +checkProperties5 :: IO ()+checkProperties5 = do+  let f = phi :: Octonion (Sedenion Integer) -> Nion Tag7 Integer+  r <- randomEltI :: IO (Sedenion Integer)+  s <- randomEltI :: IO (Sedenion Integer)+  x <- randomEltI' 3 :: IO (Octonion (Sedenion Integer))+  y <- randomEltI' 3 :: IO (Octonion (Sedenion Integer))+  checkIsomorphism f x y+  checkZeroAndOne x+  checkDistributive x y r s+  checkDotCross x y++checkProperties6 :: IO ()+checkProperties6 = do+  let f = phi :: Sedenion (Nion Tag5 Integer) -> Nion Tag9 Integer+  r <- randomEltI :: IO (Nion Tag5 Integer)+  s <- randomEltI :: IO (Nion Tag5 Integer)+  x <- randomEltI' 4 :: IO (Sedenion (Nion Tag5 Integer))+  y <- randomEltI' 4 :: IO (Sedenion (Nion Tag5 Integer))+  checkIsomorphism f x y+  checkZeroAndOne x+  checkDistributive x y r s+  checkDotCross x y+ main :: IO () main = do   checkBasic@@ -413,4 +450,6 @@     checkProperties2     checkProperties3     checkProperties4+  checkProperties5+  checkProperties6   putStrLn "\nAll tests passed."