quadratic-irrational-0.0.2: An implementation of quadratic irrationals

Copyright© 2014 Johan Kiviniemi
LicenseMIT
MaintainerJohan Kiviniemi <devel@johan.kiviniemi.name>
Stabilityprovisional
PortabilityViewPatterns
Safe HaskellNone
LanguageHaskell2010

Numeric.QuadraticIrrational

Contents

Description

An implementation of quadratic irrationals with support for conversion from and to periodic continued fractions.

Synopsis

Constructors and deconstructors

data QI Source

(a + b √c) / d

Instances

qi Source

Arguments

:: Integer

a

-> Integer

b

-> Integer

c

-> Integer

d

-> QI 

Given a, b, c and d such that n = (a + b √c)/d, constuct a QI corresponding to n.

>>> qi 3 4 5 6
qi 3 4 5 6

The fractions are reduced:

>>> qi 30 40 5 60
qi 3 4 5 6

If b = 0 then c is zeroed and vice versa:

>>> qi 3 0 42 1
qi 3 0 0 1
>>> qi 3 42 0 1
qi 3 0 0 1

The b √c term is simplified:

>>> qi 0 1 (5*5*6) 1
qi 0 5 6 1

If c = 1 (after simplification) then b is moved to a:

>>> qi 1 5 (2*2) 1
qi 11 0 0 1

qi' Source

Arguments

:: Rational

a

-> Rational

b

-> Integer

c

-> QI 

Given a, b and c such that n = a + b √c, constuct a QI corresponding to n.

>>> qi' 0.5 0.7 2
qi 5 7 2 10

runQI :: QI -> (Integer -> Integer -> Integer -> Integer -> a) -> a Source

Given n and f such that n = (a + b √c)/d, run f a b c d.

>>> runQI (qi 3 4 5 6) (\a b c d -> (a,b,c,d))
(3,4,5,6)

runQI' :: QI -> (Rational -> Rational -> Integer -> a) -> a Source

Given n and f such that n = a + b √c, run f a b c.

>>> runQI' (qi' 0.5 0.7 2) (\a b c -> (a, b, c))
(1 % 2,7 % 10,2)

unQI :: QI -> (Integer, Integer, Integer, Integer) Source

Given n such that n = (a + b √c)/d, return (a, b, c, d).

>>> unQI (qi 3 4 5 6)
(3,4,5,6)

unQI' :: QI -> (Rational, Rational, Integer) Source

Given n such that n = a + b √c, return (a, b, c).

>>> unQI' (qi' 0.5 0.7 2)
(1 % 2,7 % 10,2)

Lenses

_qi :: Lens' QI (Integer, Integer, Integer, Integer) Source

Given a QI corresponding to n = (a + b √c)/d, access (a, b, c, d).

>>> view _qi (qi 3 4 5 6)
(3,4,5,6)
>>> over _qi (\(a,b,c,d) -> (a+10, b+10, c+10, d+10)) (qi 3 4 5 6)
qi 13 14 15 16

_qi' :: Lens' QI (Rational, Rational, Integer) Source

Given a QI corresponding to n = a + b √c, access (a, b, c).

>>> view _qi' (qi' 0.5 0.7 2)
(1 % 2,7 % 10,2)
>>> over _qi' (\(a,b,c) -> (a/5, b/6, c*3)) (qi 3 4 5 6)
qi 9 10 15 90

_qiABD :: Lens' QI (Integer, Integer, Integer) Source

Given a QI corresponding to n = (a + b √c)/d, access (a, b, d). Avoids having to simplify b √c upon reconstruction.

>>> view _qiABD (qi 3 4 5 6)
(3,4,6)
>>> over _qiABD (\(a,b,d) -> (a+10, b+10, d+10)) (qi 3 4 5 6)
qi 13 14 5 16

_qiA :: Lens' QI Integer Source

Given a QI corresponding to n = (a + b √c)/d, access a. It is more efficient to use _qi or _qiABD when modifying multiple terms at once.

>>> view _qiA (qi 3 4 5 6)
3
>>> over _qiA (+ 10) (qi 3 4 5 6)
qi 13 4 5 6

_qiB :: Lens' QI Integer Source

Given a QI corresponding to n = (a + b √c)/d, access b. It is more efficient to use _qi or _qiABD when modifying multiple terms at once.

>>> view _qiB (qi 3 4 5 6)
4
>>> over _qiB (+ 10) (qi 3 4 5 6)
qi 3 14 5 6

_qiC :: Lens' QI Integer Source

Given a QI corresponding to n = (a + b √c)/d, access c. It is more efficient to use _qi or _qiABD when modifying multiple terms at once.

>>> view _qiC (qi 3 4 5 6)
5
>>> over _qiC (+ 10) (qi 3 4 5 6)
qi 3 4 15 6

_qiD :: Lens' QI Integer Source

Given a QI corresponding to n = (a + b √c)/d, access d. It is more efficient to use _qi or _qiABD when modifying multiple terms at once.

>>> view _qiD (qi 3 4 5 6)
6
>>> over _qiD (+ 10) (qi 3 4 5 6)
qi 3 4 5 16

Numerical operations

qiZero :: QI Source

The constant zero.

>>> qiZero
qi 0 0 0 1

qiOne :: QI Source

The constant one.

>>> qiOne
qi 1 0 0 1

qiIsZero :: QI -> Bool Source

Check if the value is zero.

>>> map qiIsZero [qiZero, qiOne, qiSubR (qi 7 0 0 2) 3.5]
[True,False,True]

qiToFloat :: Floating a => QI -> a Source

Convert a QI number into a Floating one.

>>> qiToFloat (qi 3 4 5 6) == ((3 + 4 * sqrt 5)/6 :: Double)
True

qiAddI :: QI -> Integer -> QI Source

Add an Integer to a QI.

>>> qi 3 4 5 6 `qiAddI` 1
qi 9 4 5 6

qiSubI :: QI -> Integer -> QI Source

Subtract an Integer from a QI.

>>> qi 3 4 5 6 `qiSubI` 1
qi (-3) 4 5 6

qiMulI :: QI -> Integer -> QI Source

Multiply a QI by an Integer.

>>> qi 3 4 5 6 `qiMulI` 2
qi 3 4 5 3

qiDivI :: QI -> Integer -> QI Source

Divice a QI by an Integer.

>>> qi 3 4 5 6 `qiDivI` 2
qi 3 4 5 12

qiAddR :: QI -> Rational -> QI Source

Add a Rational to a QI.

>>> qi 3 4 5 6 `qiAddR` 1.2
qi 51 20 5 30

qiSubR :: QI -> Rational -> QI Source

Subtract a Rational from a QI.

>>> qi 3 4 5 6 `qiSubR` 1.2
qi (-21) 20 5 30

qiMulR :: QI -> Rational -> QI Source

Multiply a QI by a Rational.

>>> qi 3 4 5 6 `qiMulR` 0.5
qi 3 4 5 12

qiDivR :: QI -> Rational -> QI Source

Divice a QI by a Rational.

>>> qi 3 4 5 6 `qiDivR` 0.5
qi 3 4 5 3

qiNegate :: QI -> QI Source

Negate a QI.

>>> qiNegate (qi 3 4 5 6)
qi (-3) (-4) 5 6

qiRecip :: QI -> Maybe QI Source

Compute the reciprocal of a QI.

>>> qiRecip (qi 5 0 0 2)
Just (qi 2 0 0 5)
>>> qiRecip (qi 0 1 5 2)
Just (qi 0 2 5 5)
>>> qiRecip qiZero
Nothing

qiAdd :: QI -> QI -> Maybe QI Source

Add two QIs if the square root terms are the same or zeros.

>>> qi 3 4 5 6 `qiAdd` qiOne
Just (qi 9 4 5 6)
>>> qi 3 4 5 6 `qiAdd` qi 3 4 5 6
Just (qi 3 4 5 3)
>>> qi 0 1 5 1 `qiAdd` qi 0 1 6 1
Nothing

qiSub :: QI -> QI -> Maybe QI Source

Subtract two QIs if the square root terms are the same or zeros.

>>> qi 3 4 5 6 `qiSub` qiOne
Just (qi (-3) 4 5 6)
>>> qi 3 4 5 6 `qiSub` qi 3 4 5 6
Just (qi 0 0 0 1)
>>> qi 0 1 5 1 `qiSub` qi 0 1 6 1
Nothing

qiMul :: QI -> QI -> Maybe QI Source

Multiply two QIs if the square root terms are the same or zeros.

>>> qi 3 4 5 6 `qiMul` qiZero
Just (qi 0 0 0 1)
>>> qi 3 4 5 6 `qiMul` qiOne
Just (qi 3 4 5 6)
>>> qi 3 4 5 6 `qiMul` qi 3 4 5 6
Just (qi 89 24 5 36)
>>> qi 0 1 5 1 `qiMul` qi 0 1 6 1
Nothing

qiDiv :: QI -> QI -> Maybe QI Source

Divide two QIs if the square root terms are the same or zeros.

>>> qi 3 4 5 6 `qiDiv` qiZero
Nothing
>>> qi 3 4 5 6 `qiDiv` qiOne
Just (qi 3 4 5 6)
>>> qi 3 4 5 6 `qiDiv` qi 3 4 5 6
Just (qi 1 0 0 1)
>>> qi 3 4 5 6 `qiDiv` qi 0 1 5 1
Just (qi 20 3 5 30)
>>> qi 0 1 5 1 `qiDiv` qi 0 1 6 1
Nothing

qiPow :: QI -> Integer -> QI Source

Exponentiate a QI to an Integer power.

>>> qi 3 4 5 6 `qiPow` 0
qi 1 0 0 1
>>> qi 3 4 5 6 `qiPow` 1
qi 3 4 5 6
>>> qi 3 4 5 6 `qiPow` 2
qi 89 24 5 36

qiFloor :: QI -> Integer Source

Compute the floor of a QI.

>>> qiFloor (qi 10 0 0 2)
5
>>> qiFloor (qi 10 2 2 2)
6
>>> qiFloor (qi 10 2 5 2)
7

Continued fractions

continuedFractionToQI :: (Integer, CycList Integer) -> QI Source

Convert a (possibly periodic) continued fraction to a QI.

[2; 2] = 2 + 1/2 = 5/2.

>>> continuedFractionToQI (2,NonCyc [2])
qi 5 0 0 2

[2; 1, 1, 1, 4, 1, 1, 1, 4, …] = √7.

>>> continuedFractionToQI (2,Cyc [] 1 [1,1,4])
qi 0 1 7 1
>>> continuedFractionToQI (0,Cyc [83,78,65,75,69] 32 [66,65,68,71,69,82])
qi 987601513930253257378987883 1 14116473325908285531353005 81983584717737887813195873886

qiToContinuedFraction :: QI -> (Integer, CycList Integer) Source

Convert a QI into a (possibly periodic) continued fraction.

5/2 = 2 + 1/2 = [2; 2].

>>> qiToContinuedFraction (qi 5 0 0 2)
(2,NonCyc [2])

√7 = [2; 1, 1, 1, 4, 1, 1, 1, 4, …].

>>> qiToContinuedFraction (qi 0 1 7 1)
(2,Cyc [] 1 [1,1,4])
>>> qiToContinuedFraction (qi 987601513930253257378987883 1 14116473325908285531353005 81983584717737887813195873886)
(0,Cyc [83,78,65,75,69] 32 [66,65,68,71,69,82])