Copyright | (c) Henning Thielemann 2007 |
---|---|
Maintainer | numericprelude@henning-thielemann.de |
Stability | provisional |
Portability | portable |
Safe Haskell | None |
Language | Haskell98 |
Implementation of partial fractions. Useful e.g. for fractions of integers and fractions of polynomials.
For the considered ring the prime factorization must be unique.
Synopsis
- data T a = Cons a (Map (ToOrd a) [a])
- fromFractionSum :: C a => a -> [(a, [a])] -> T a
- toFractionSum :: C a => T a -> (a, [(a, [a])])
- appPrec :: Int
- toFraction :: C a => T a -> T a
- toFactoredFraction :: C a => T a -> ([a], a)
- multiToFraction :: C a => a -> [a] -> T a
- hornerRev :: C a => a -> [a] -> a
- fromFactoredFraction :: (C a, C a) => [a] -> a -> T a
- fromFactoredFractionAlt :: (C a, C a) => [a] -> a -> T a
- multiFromFraction :: C a => [a] -> a -> (a, [a])
- fromValue :: a -> T a
- reduceHeads :: C a => T a -> T a
- carryRipple :: C a => a -> [a] -> (a, [a])
- normalizeModulo :: C a => T a -> T a
- removeZeros :: (C a, C a) => T a -> T a
- zipWith :: C a => (a -> a -> a) -> ([a] -> [a] -> [a]) -> T a -> T a -> T a
- mulFrac :: C a => T a -> T a -> (a, a)
- mulFrac' :: C a => T a -> T a -> (T a, T a)
- mulFracStupid :: C a => T a -> T a -> ((T a, T a), T a)
- mulFracOverlap :: C a => T a -> T a -> ((T a, T a), T a)
- scaleFrac :: (C a, C a) => T a -> T a -> T a
- scaleInt :: (C a, C a) => a -> T a -> T a
- mul :: (C a, C a) => T a -> T a -> T a
- mulFast :: (C a, C a) => T a -> T a -> T a
- indexMapMapWithKey :: (a -> b -> c) -> Map (ToOrd a) b -> Map (ToOrd a) c
- indexMapToList :: Map (ToOrd a) b -> [(a, b)]
- indexMapFromList :: C a => [(a, b)] -> Map (ToOrd a) b
- mapApplySplit :: Ord a => a -> (c -> c -> c) -> (b -> c) -> (Map a b -> Map a c) -> Map a b -> Map a c
Documentation
>>>
import qualified MathObj.PartialFraction as PartialFraction
>>>
import qualified MathObj.Polynomial.Core as PolyCore
>>>
import qualified MathObj.Polynomial as Poly
>>>
import qualified Algebra.PrincipalIdealDomain as PID
>>>
import qualified Algebra.Indexable as Indexable
>>>
import qualified Algebra.Laws as Laws
>>>
import qualified Number.Ratio as Ratio
>>>
import Test.NumericPrelude.Utility ((/\))
>>>
import qualified Test.QuickCheck as QC
>>>
import NumericPrelude.Numeric as NP
>>>
import NumericPrelude.Base as P
>>>
import Prelude ()
>>>
>>>
import Control.Applicative (liftA2)
>>>
>>>
--
>>>
genSmallPrime :: QC.Gen Integer
>>>
genSmallPrime =
>>>
let primes = [2,3,5,7,11,13]
>>>
in QC.elements (primes ++ map negate primes)
>>>
>>>
genPartialFractionInt :: QC.Gen (PartialFraction.T Integer)
>>>
genPartialFractionInt =
>>>
liftA2 PartialFraction.fromFactoredFraction
>>>
(QC.listOf genSmallPrime) QC.arbitrary
>>>
>>>
>>>
genIrreduciblePolynomial :: QC.Gen (Poly.T Rational)
>>>
genIrreduciblePolynomial = do
>>>
QC.NonZero unit <- QC.arbitrary
>>>
fmap (Poly.fromCoeffs . map (unit*)) $
>>>
QC.elements [[2,3],[2,0,1],[3,0,1],[1,-3,0,1]]
>>>
>>>
genPartialFractionPoly :: QC.Gen (PartialFraction.T (Poly.T Rational))
>>>
genPartialFractionPoly =
>>>
liftA2 PartialFraction.fromFactoredFraction
>>>
(fmap (take 3) $ QC.listOf genIrreduciblePolynomial)
>>>
(fmap (Poly.fromCoeffs . PolyCore.normalize . take 5) QC.arbitrary)
>>>
>>>
>>>
fractionConv :: (PID.C a, Indexable.C a) => [a] -> a -> Bool
>>>
fractionConv xs y =
>>>
PartialFraction.toFraction (PartialFraction.fromFactoredFraction xs y) ==
>>>
y % product xs
>>>
>>>
fractionConvAlt :: (PID.C a, Indexable.C a) => [a] -> a -> Bool
>>>
fractionConvAlt xs y =
>>>
PartialFraction.fromFactoredFraction xs y ==
>>>
PartialFraction.fromFactoredFractionAlt xs y
>>>
>>>
scaleInt :: (PID.C a, Indexable.C a) => a -> PartialFraction.T a -> Bool
>>>
scaleInt k a =
>>>
PartialFraction.toFraction (PartialFraction.scaleInt k a) ==
>>>
Ratio.scale k (PartialFraction.toFraction a)
>>>
>>>
add, sub, mul ::
>>>
(PID.C a, Indexable.C a) =>
>>>
PartialFraction.T a -> PartialFraction.T a -> Bool
>>>
add = Laws.homomorphism PartialFraction.toFraction (+) (+)
>>>
sub = Laws.homomorphism PartialFraction.toFraction (-) (-)
>>>
mul = Laws.homomorphism PartialFraction.toFraction (*) (*)
Cons z (indexMapFromList [(x0,[y00,y01]), (x1,[y10]), (x2,[y20,y21,y22])])
represents the partial fraction
z + y00x0 + y01x0^2 + y10x1 + y20x2 + y21x2^2 + y22x2^3
The denominators x0, x1, x2, ...
must be irreducible,
but we can't check this in general.
It is also not enough to have relatively prime denominators,
because when adding two partial fraction representations
there might concur denominators that have non-trivial common divisors.
Instances
Eq a => Eq (T a) Source # | |
Show a => Show (T a) Source # | |
(C a, C a, C a) => C (T a) Source # | genPartialFractionInt /\ \x -> genPartialFractionInt /\ \y -> add x y genPartialFractionInt /\ \x -> genPartialFractionInt /\ \y -> sub x y genPartialFractionPoly /\ \x -> genPartialFractionPoly /\ \y -> add x y genPartialFractionPoly /\ \x -> genPartialFractionPoly /\ \y -> sub x y |
(C a, C a) => C (T a) Source # | |
fromFractionSum :: C a => a -> [(a, [a])] -> T a Source #
Unchecked construction.
toFractionSum :: C a => T a -> (a, [(a, [a])]) Source #
toFactoredFraction :: C a => T a -> ([a], a) Source #
C
is not really necessary here and
only due to invokation of toFraction
.
multiToFraction :: C a => a -> [a] -> T a Source #
fromFactoredFraction :: (C a, C a) => [a] -> a -> T a Source #
fromFactoredFraction x y
computes the partial fraction representation of y % product x
,
where the elements of x
must be irreducible.
The function transforms the factors into their standard form
with respect to unit factors.
There are more direct methods for special cases like polynomials over rational numbers where the denominators are linear factors.
QC.listOf genSmallPrime /\ fractionConv
fmap (take 3) (QC.listOf genIrreduciblePolynomial) /\ fractionConv
fromFactoredFractionAlt :: (C a, C a) => [a] -> a -> T a Source #
QC.listOf genSmallPrime /\ fractionConvAlt
fmap (take 3) (QC.listOf genIrreduciblePolynomial) /\ fractionConvAlt
multiFromFraction :: C a => [a] -> a -> (a, [a]) Source #
The list of denominators must contain equal elements. Sorry for this hack.
reduceHeads :: C a => T a -> T a Source #
A normalization step which separates the integer part from the leading fraction of each sub-list.
carryRipple :: C a => a -> [a] -> (a, [a]) Source #
Cf. Number.Positional
normalizeModulo :: C a => T a -> T a Source #
A normalization step which reduces all elements in sub-lists
modulo their denominators.
Zeros might be the result, that must be remove with removeZeros
.
removeZeros :: (C a, C a) => T a -> T a Source #
Remove trailing zeros in sub-lists
because if lists are converted to fractions by multiToFraction
we must be sure that the denominator of the (cancelled) fraction
is indeed the stored power of the irreducible denominator.
Otherwise mulFrac
leads to wrong results.
mulFrac :: C a => T a -> T a -> (a, a) Source #
Transforms a product of two partial fractions
into a sum of two fractions.
The denominators must be at least relatively prime.
Since T
requires irreducible denominators,
these are also relatively prime.
Example: mulFrac (1%6) (1%4)
fails because of the common divisor 2
.
mulFracStupid :: C a => T a -> T a -> ((T a, T a), T a) Source #
Works always but simply puts the product into the last fraction.
mulFracOverlap :: C a => T a -> T a -> ((T a, T a), T a) Source #
Also works if the operands share a non-trivial divisor. However the results are quite arbitrary.
scaleFrac :: (C a, C a) => T a -> T a -> T a Source #
Expects an irreducible denominator as associate in standard form.
scaleInt :: (C a, C a) => a -> T a -> T a Source #
genPartialFractionInt /\ \x k -> scaleInt k x
genPartialFractionPoly /\ \x k -> scaleInt k x
mulFast :: (C a, C a) => T a -> T a -> T a Source #
genPartialFractionInt /\ \x -> genPartialFractionInt /\ \y -> mul x y
genPartialFractionPoly /\ \x -> genPartialFractionPoly /\ \y -> mul x y
Helper functions for work with Maps with Indexable keys
indexMapToList :: Map (ToOrd a) b -> [(a, b)] Source #