packages feed

numeric-prelude-0.4.4: gaussian/MathObj/Gaussian/ExponentTuple.hs

{-# LANGUAGE RebindableSyntax #-}
module MathObj.Gaussian.ExponentTuple where

import qualified Test.QuickCheck as QC

import Control.Applicative (liftA2, liftA3)

import Data.Function.HT (compose2)

import NumericPrelude.Base as P
import NumericPrelude.Numeric as NP


{- $setup
>>> import MathObj.Gaussian.ExponentTuple (HoelderConjugates(HoelderConjugates))
>>> import MathObj.Gaussian.ExponentTuple (YoungConjugates(YoungConjugates))
>>> import NumericPrelude.Base as P
>>> import NumericPrelude.Numeric as NP
>>> import Prelude ()
-}


{- |
For @(HoelderConjugates p q)@ it holds

prop> \(HoelderConjugates p q)  ->  p>=1 && q>=1 && 1/p + 1/q == 1
-}
data HoelderConjugates = HoelderConjugates Rational Rational
   deriving Show

instance QC.Arbitrary HoelderConjugates where
   arbitrary = genHoelderConjugates0

genHoelderConjugates0 :: QC.Gen HoelderConjugates
genHoelderConjugates0 =
   liftA2
      (\(QC.Positive p) (QC.Positive q) ->
         let s = p + q in HoelderConjugates (s % p) (s % q))
      QC.arbitrary QC.arbitrary

genHoelderConjugates1 :: QC.Gen HoelderConjugates
genHoelderConjugates1 =
   liftA2
      (\(QC.Positive p) (QC.Positive q) ->
         let s = 1%p + 1%q
         in HoelderConjugates (fromInteger p * s) (fromInteger q * s))
      QC.arbitrary QC.arbitrary


{- |
For @(YoungConjugates p q r)@ it holds

prop> \(YoungConjugates p q r)  ->  p>=1 && q>=1 && r>=1 && 1/p + 1/q == 1/r + 1
-}
data YoungConjugates = YoungConjugates Rational Rational Rational
   deriving Show

instance QC.Arbitrary YoungConjugates where
   arbitrary = genYoungConjugates0

{-
Find positive natural numbers @a, b, c, d@ with

> a + b = c + d

and

> d >= a, d >= b, d >= c

then set

> p=d/a, q=d/b, r=d/c


a+b<=c
b+c<=a
->  2b <= 0
-}
genYoungConjugates0 :: QC.Gen YoungConjugates
genYoungConjugates0 =
   liftA3
      (\(QC.Positive a0) (QC.Positive b0) (QC.Positive c0) ->
         let guardSwap cond (x,y) =
                if cond x y then (x,y) else (y,x)
             {-
             If a+b<=c, then from b>0 it follows a<c and thus c+b>a.
             Swapping a and c is enough and we have not to consider more cases.
             -}
             (a1,c1) = guardSwap (\a c -> a+b0>c) (a0,c0)
             b1 = b0
             d1 = a1+b1-c1
             ((a2,b2),(c2,d2)) =
                guardSwap (compose2 (<=) snd)
                   (guardSwap (<=) (a1,b1),
                    guardSwap (<=) (c1,d1))
         in  YoungConjugates (d2%a2) (d2%b2) (d2%c2))
      QC.arbitrary QC.arbitrary QC.arbitrary

{- |
This one is simpler, but may yield exponents smaller than 1.
-}
genYoungConjugates1 :: QC.Gen YoungConjugates
genYoungConjugates1 =
   liftA3
      (\(QC.Positive a0) (QC.Positive b0) (QC.Positive c0) ->
         let {-
             If a+b<=c, then from b>0 it follows a<c and thus c+b>a.
             Swapping a and c is enough and we have not to consider more cases.
             -}
             (a1,c1) = if a0+b0<=c0 then (c0,a0) else (a0,c0)
             b1 = b0
             d1 = a1+b1-c1
         in  YoungConjugates (d1%a1) (d1%b1) (d1%c1))
      QC.arbitrary QC.arbitrary QC.arbitrary