diff --git a/Eigensystem.hs b/Eigensystem.hs
--- a/Eigensystem.hs
+++ b/Eigensystem.hs
@@ -1,11 +1,10 @@
-
 ------------------------------------------------------------------------------
--- Haskell module:	Eigensystem
--- Date:		initialized 2001-03-25, last modified 2001-03-25
--- Author:		Jan Skibinski, Numeric Quest Inc.
--- Location:		http://www.numeric-quest.com/haskell/Eigensystem.hs
--- See also:		http://www.numeric-quest.com/haskell/QuantumVector.html
--- See also:		http://www.numeric-quest.com/haskell/Orthogonals.html
+-- Haskell module:      Eigensystem
+-- Date:                initialized 2001-03-25, last modified 2001-03-25
+-- Author:              Jan Skibinski, Numeric Quest Inc.
+-- Location:            http://www.numeric-quest.com/haskell/Eigensystem.hs
+-- See also:            http://www.numeric-quest.com/haskell/QuantumVector.html
+-- See also:            http://www.numeric-quest.com/haskell/Orthogonals.html
 --
 -- Description:
 --
@@ -30,7 +29,7 @@
 --   manipulation on operators is too difficult, while it is trivial
 --   to obtain the corresponding results via matrices. One example is a
 --   computation of a Hermitian conjugate of A:
---	< ei | A' | ej > = conjugate < ej | A | ej >
+--      < ei | A' | ej > = conjugate < ej | A | ej >
 --     (Here ' stands for a dagger)
 --   If however the operator A is made from a product or a sum of simpler
 --   operators, whose Hermitian conjugates are known to us, then the
@@ -54,57 +53,57 @@
 import Complex
 import QuantumVector
 import LinearAlgorithms (triangular, tridiagonal, triangular2)
-import List (findIndex)	
+import List (findIndex)
 
 ----------------------------------------------------------------------------
 -- Category: Eigensystem for QuantumVector
 ----------------------------------------------------------------------------
 
-eigenvalues :: Ord a => Bool -> Int -> [Ket a] -> (Ket a -> Ket a) -> [Scalar]	
+eigenvalues :: Ord a => Bool -> Int -> [Ket a] -> (Ket a -> Ket a) -> [Scalar]
 eigenvalues doTri n es a
-    --	A list of eigenvalues of operator 'a'
-    --	obtained after 'n' triangularizations
-    --	of a matrix corresponding to operator 'a'
-    --	where
-    --	    'es' is a list of base vectors
-    --	    'doTri' declares whether or not we
-    --	      want the initial tridiagonalization
-    --	      (applies to Hermitian operators only)
-    | doTri == True	=  f b1
-    | otherwise		=  f b
+    --  A list of eigenvalues of operator 'a'
+    --  obtained after 'n' triangularizations
+    --  of a matrix corresponding to operator 'a'
+    --  where
+    --      'es' is a list of base vectors
+    --      'doTri' declares whether or not we
+    --        want the initial tridiagonalization
+    --        (applies to Hermitian operators only)
+    | doTri == True     =  f b1
+    | otherwise         =  f b
     where
-	f c		= diagonals  $ operator es $ triangular n c
-	diagonals us	= [toBra e <> us e | e <- es]
-	b 		= matrix es a
-	b1		= tridiagonal b		
-	
-	
+        f c             = diagonals  $ operator es $ triangular n c
+        diagonals us    = [toBra e <> us e | e <- es]
+        b               = matrix es a
+        b1              = tridiagonal b
+
+
 eigenpairs :: Ord a => Int -> [Ket a] -> (Ket a -> Ket a) -> ([Scalar], [Ket a])
 eigenpairs n es a
-    --	A pair of lists (eigenvalues, eigenvectors) of hermitian
-    --	operator 'a' obtained after 'n' triangularizations of 'a'
-    --	where
-    --	    'es' is a list of base vectors
-    --	Note: For a moment this applies only to Hermitian operators
-    --	until we decide what would be the best way to compute eigenvectors
-    --	of a triangular matrix: the method from module Orthogonal, power
-    --	iteration, etc.
+    --  A pair of lists (eigenvalues, eigenvectors) of hermitian
+    --  operator 'a' obtained after 'n' triangularizations of 'a'
+    --  where
+    --      'es' is a list of base vectors
+    --  Note: For a moment this applies only to Hermitian operators
+    --  until we decide what would be the best way to compute eigenvectors
+    --  of a triangular matrix: the method from module Orthogonal, power
+    --  iteration, etc.
     = (ls, xs)
     where
-        (t, q)	= triangular2 n b
-	b	= matrix es a
-	ls	= [ tk!!k | (tk, k) <- zip t [0..length t - 1] ]
-	xs	= [compose qk es | qk <- q]
+        (t, q)  = triangular2 n b
+        b       = matrix es a
+        ls      = [ tk!!k | (tk, k) <- zip t [0..length t - 1] ]
+        xs      = [compose qk es | qk <- q]
 
 adjoint :: Ord a => [Ket a] -> (Ket a -> Ket a) -> (Ket a -> Ket a)
 adjoint es a
-    --	A Hermitian conjugate of operator a,
-    --	(or a-dagger, or adjoint to a)
-    --	where 'es' is a list of base vectors
-    =	operator es ms
+    --  A Hermitian conjugate of operator a,
+    --  (or a-dagger, or adjoint to a)
+    --  where 'es' is a list of base vectors
+    =   operator es ms
     where
-	ms = [[ conjugate (toBra ei <> vj) | vj <- v] | ei <- es]
-	v = [a ej | ej <- es]
+        ms = [[ conjugate (toBra ei <> vj) | vj <- v] | ei <- es]
+        v = [a ej | ej <- es]
 
 
 ----------------------------------------------------------------------------
@@ -112,28 +111,28 @@
 ----------------------------------------------------------------------------
 
 operator :: Ord a => [Ket a] -> [[Scalar]] -> Ket a -> Ket a
-operator basis ms x
-    --	Definition of an operator corresponding
-    --	to a matrix 'ms' given as a list of scalar
-    --	columns
-    --	where
-    --	    'basis' is a complete list of base vectors
-    --	    'x' is any ket vector from this space
-    =	a >< x
+operator bss ms x
+    --  Definition of an operator corresponding
+    --  to a matrix 'ms' given as a list of scalar
+    --  columns
+    --  where
+    --      'bss' (basis) is a complete list of base vectors
+    --      'x' is any ket vector from this space
+    =   a >< x
     where
-	a u = case (findIndex (u == ) basis) of
-		Just k  -> compose (ms !! k) basis
-		Nothing -> error "Out of bounds"
+        a u = case (findIndex (u == ) bss) of
+                Just k  -> compose (ms !! k) bss
+                Nothing -> error "Out of bounds"
 
 
 matrix :: Ord a => [Ket a] -> (Ket a -> Ket a) -> [[Scalar]]
-matrix basis a
-    --	List of scalar columns representing
-    --	the operator 'a' in a given 'basis'
+matrix bss a
+    --  List of scalar columns representing
+    --  the operator 'a' in a given 'basis'
     = [[ei' <> vj | ei' <- e'] | vj <- v]
     where
-        v = [a ej | ej <- basis]
-	e' = [toBra ei | ei <- basis]
+        v = [a ej | ej <- bss]
+        e' = [toBra ei | ei <- bss]
 
 ----------------------------------------------------------------------------
 -- Category: Test data
@@ -142,32 +141,34 @@
 
 matrixA :: [[Scalar]]
 matrixA
-    --	Test matrix A represented as list of scalar columns.
-    =	[
-		[1, 2, 4, 1, 5]
-	,	[2, 3, 2, 6, 4]
-	,	[4, 2, 5, 2, 3]
-	,	[1, 6, 2, 7, 2]
-	,	[5, 4, 3, 2, 9]
-	]
+    --  Test matrix A represented as list of scalar columns.
+    =   [
+                [1, 2, 4, 1, 5]
+        ,       [2, 3, 2, 6, 4]
+        ,       [4, 2, 5, 2, 3]
+        ,       [1, 6, 2, 7, 2]
+        ,       [5, 4, 3, 2, 9]
+        ]
 
-opA	= operator basisA matrixA
+opA :: Ket Int -> Ket Int
+opA     = operator basisA matrixA
 
-basisA	= map Ket [1..5::Int] -- or: map Ket "abcde", etc.
-			
+basisA :: [Ket Int]
+basisA  = map Ket [1..5::Int] -- or: map Ket "abcde", etc.
+
 ---------------------------------------------------------------------------
 -- Copyright:
 --
---	(C) 2001 Numeric Quest, All rights reserved
+--      (C) 2001 Numeric Quest, All rights reserved
 --
 --      Email: jans@numeric-quest.com
 --
---      http://www.numeric-quest.com	
+--      http://www.numeric-quest.com
 --
 -- License:
 --
---	GNU General Public License, GPL
+--      GNU General Public License, GPL
 --
 ---------------------------------------------------------------------------
 
-		 	
+
diff --git a/Fraction.hs b/Fraction.hs
--- a/Fraction.hs
+++ b/Fraction.hs
@@ -1,69 +1,69 @@
 -- Module:
 --
---	Fraction.hs
+--      Fraction.hs
 --
 -- Language:
 --
---	Haskell
+--      Haskell
 --
 -- Description: Rational with transcendental functionalities
 --
 --
---	This is a generalized Rational in disguise. Rational, as a type
---	synonim, could not be directly made an instance of any new class
---	at all.
---	But we would like it to be an instance of Transcendental, where
---	trigonometry, hyperbolics, logarithms, etc. are defined.
---	So here we are tiptoe-ing around, re-defining everything from
---	scratch, before designing the transcendental functions -- which
---	is the main motivation for this module.
+--      This is a generalized Rational in disguise. Rational, as a type
+--      synonim, could not be directly made an instance of any new class
+--      at all.
+--      But we would like it to be an instance of Transcendental, where
+--      trigonometry, hyperbolics, logarithms, etc. are defined.
+--      So here we are tiptoe-ing around, re-defining everything from
+--      scratch, before designing the transcendental functions -- which
+--      is the main motivation for this module.
 --
---	Aside from its ability to compute transcendentals, Fraction
---	allows for denominators zero. Unlike Rational, Fraction does
---	not produce run-time errors for zero denominators, but use such
---	entities as indicators of invalid results -- plus or minus
---	infinities. Operations on fractions never fail in principle.
+--      Aside from its ability to compute transcendentals, Fraction
+--      allows for denominators zero. Unlike Rational, Fraction does
+--      not produce run-time errors for zero denominators, but use such
+--      entities as indicators of invalid results -- plus or minus
+--      infinities. Operations on fractions never fail in principle.
 --
 --      However, some function may compute slowly when both numerators
---	and denominators of their arguments are chosen to be huge.
---	For example, periodicity relations are utilized with large
---	arguments in trigonometric functions to reduce the arguments
---	to smaller values and thus improve on the convergence
---	of continued fractions. Yet, if pi number is chosen to
---	be extremely accurate then the reduced argument would
---	become a fraction with huge numerator and denominator
---	-- thus slowing down the entire computation of a trigonometric
---	function.
+--      and denominators of their arguments are chosen to be huge.
+--      For example, periodicity relations are utilized with large
+--      arguments in trigonometric functions to reduce the arguments
+--      to smaller values and thus improve on the convergence
+--      of continued fractions. Yet, if pi number is chosen to
+--      be extremely accurate then the reduced argument would
+--      become a fraction with huge numerator and denominator
+--      -- thus slowing down the entire computation of a trigonometric
+--      function.
 --
 -- Usage:
 --
---	When computation speed is not an issue and accuracy is important
---	this module replaces some of the functionalities typically handled
---	by the floating point numbers: trigonometry, hyperbolics, roots
---	and some special functions. All computations, including definitions
---	of the basic constants pi and e, can be carried with any desired
---	accuracy. One suggested usage is for mathematical servers, where
---	safety might be more important than speed. See also the module
---	Numerus, which supports mixed arithmetic between Integer,
---	Fraction and Cofra (Complex fraction), and returns complex
---	legal answers in some cases where Fraction would produce
---	infinities: log (-5), sqrt (-1), etc.  
+--      When computation speed is not an issue and accuracy is important
+--      this module replaces some of the functionalities typically handled
+--      by the floating point numbers: trigonometry, hyperbolics, roots
+--      and some special functions. All computations, including definitions
+--      of the basic constants pi and e, can be carried with any desired
+--      accuracy. One suggested usage is for mathematical servers, where
+--      safety might be more important than speed. See also the module
+--      Numerus, which supports mixed arithmetic between Integer,
+--      Fraction and Cofra (Complex fraction), and returns complex
+--      legal answers in some cases where Fraction would produce
+--      infinities: log (-5), sqrt (-1), etc.
 --
---	
+--
 -- Required:
 --
---	Haskell Prelude 
--- 
+--      Haskell Prelude
+--
 -- Author:
 --
--- 	Jan Skibinski, Numeric Quest Inc.
+--      Jan Skibinski, Numeric Quest Inc.
 --
 -- Date:
 --
---	1998.08.16, last modified 2000.05.31
---	
+--      1998.08.16, last modified 2000.05.31
+--
 -- See also bottom of the page for description of the format used
--- for continued fractions, references, etc. 
+-- for continued fractions, references, etc.
 -------------------------------------------------------------------
 
 module Fraction where
@@ -73,57 +73,57 @@
 infix 7  :-:
 
 -------------------------------------------------------------------
---		Category: Basics
+--              Category: Basics
 -------------------------------------------------------------------
- 
+
 data Fraction = Integer :-: Integer
-	deriving (Eq)
+        deriving (Eq)
 
 num, den :: Fraction -> Integer
-num (x:-:y) = x
-den (x:-:y) = y
- 
-reduce	:: Fraction -> Fraction
+num (x:-:_) = x
+den (_:-:y) = y
+
+reduce  :: Fraction -> Fraction
 reduce (x:-:0)
-	| x < 0 = (-1):-:0
-	| otherwise = 1:-:0
+        | x < 0 = (-1):-:0
+        | otherwise = 1:-:0
 reduce (x:-:y) =
-	(u `quot` d) :-: (v `quot` d)
+        (u `quot` d) :-: (v `quot` d)
         where
             d = gcd u v
             (u,v)
                 | y < 0     = (-x,-y)
-                | otherwise = (x,y) 
-             
+                | otherwise = (x,y)
+
 (//)   :: Integer -> Integer -> Fraction
 x // y = reduce (x:-:y)
 
 approx      :: Fraction -> Fraction -> Fraction
-approx eps (x:-:0) = x//0
+approx _ (x:-:0) = x//0
 approx eps x =
     simplest (x-eps) (x+eps)
-    where 
-        simplest x y 
-            | y < x     = simplest y x
-            | x == y    = x
-            | x > 0     = simplest' (num x) (den x) (num y) (den y)
-            | y < 0     = - simplest' (-(num y)) (den y) (-(num x)) (den x)
+    where
+        simplest y z
+            | z < y     = simplest z y
+            | y == z    = y
+            | y > 0     = simplest' (num y) (den y) (num z) (den z)
+            | z < 0     = - simplest' (-(num z)) (den z) (-(num y)) (den y)
             | otherwise = 0 :-: 1
         simplest' n d n' d'        -- assumes 0 < n//d < n'//d'
             | r == 0    = q :-: 1
             | q /= q'   = (q+1) :-: 1
             | otherwise = (q*n''+d'') :-: n''
-            where 
+            where
                 (q,r)       = quotRem n d
                 (q',r')     = quotRem n' d'
                 (n'':-:d'') = simplest' d' r' d r
 
 -------------------------------------------------------------------
---		Category: Instantiation of some Prelude classes
+--              Category: Instantiation of some Prelude classes
 -------------------------------------------------------------------
-             
+
 instance Read Fraction where
-    readsPrec p = 
+    readsPrec p =
         readParen (p > 7) (\r -> [(x//y,u) | (x,s)   <- reads r,
                                               ("//",t) <- lex s,
                                               (y,u)   <- reads t ])
@@ -142,13 +142,13 @@
     (x:-:y) * (x':-:y')  = reduce ((x*x') :-: (y*y'))
     negate (x:-:y)       = negate x :-: y
     abs (x:-:y)          = abs x :-: y
-    signum (x:-:y)       = signum x :-: 1
+    signum (x:-:_)       = signum x :-: 1
     fromInteger n        = fromInteger n :-: 1
-    
+
 instance Fractional Fraction where
     (x:-:0) / (x':-:0)   = ((signum x * signum x'):-:0)
-    (x:-:y) / (x':-:0)   = (0:-:1)
-    (x:-:0) / (x':-:y')  = (x:-:0)   
+    (_:-:_) / (_:-:0)   = (0:-:1)
+    (x:-:0) / (_:-:_)  = (x:-:0)
     (x:-:y) / (x':-:y')  = reduce ((x*y') :-: (y*x'))
     recip (x:-:y)        = if x < 0 then (-y) :-: (-x) else y :-: x
     fromRational a       = x :-: y
@@ -156,10 +156,10 @@
                                x = numerator a
                                y = denominator a
 
-                   
+
 instance Real Fraction where
-    toRational (x :-: 0) = toRational (0%1) 
-    	-- or shoud we return some huge number instead?
+    toRational (_ :-: 0) = toRational ((0::Int)%(1::Int))
+        -- or shoud we return some huge number instead?
     toRational (x :-: y) = toRational (x % y)
 
 
@@ -189,426 +189,426 @@
 numericEnumFromTo n m        = takeWhile (<= m) (numericEnumFrom n)
 numericEnumFromThenTo n n' m = takeWhile p (numericEnumFromThen n n')
                                where p | n' >= n   = (<= m)
-				       | otherwise = (>= m)
+                                       | otherwise = (>= m)
 
 ------------------------------------------------------------------
---		Category: Conversion
---	from continued fraction to fraction and vice versa,
---	from Taylor series to continued fraction.
+--              Category: Conversion
+--      from continued fraction to fraction and vice versa,
+--      from Taylor series to continued fraction.
 -------------------------------------------------------------------
-type CF	= [(Fraction, Fraction)]
+type CF = [(Fraction, Fraction)]
 
 fromCF :: CF -> Fraction
 fromCF x =
-	--
-	-- Convert finite continued fraction to fraction
-	-- evaluating from right to left. This is used
-	-- mainly for testing in conjunction with "toCF".
-	--
-	foldr g (1//1) x
-	where
-	    g	:: (Fraction, Fraction) -> Fraction -> Fraction
-	    g u v = (fst u) + (snd u)/v
+        --
+        -- Convert finite continued fraction to fraction
+        -- evaluating from right to left. This is used
+        -- mainly for testing in conjunction with "toCF".
+        --
+        foldr g (1//1) x
+        where
+            g   :: (Fraction, Fraction) -> Fraction -> Fraction
+            g u v = (fst u) + (snd u)/v
 
-toCF	:: Fraction -> CF
+toCF    :: Fraction -> CF
 toCF (u:-:0) = [(u//0,0//1)]
 toCF x =
-	--
-	-- Convert fraction to finite continued fraction
-	--
-	toCF' x []
-	where
-	    toCF' u lst =
+        --
+        -- Convert fraction to finite continued fraction
+        --
+        toCF' x []
+        where
+            toCF' u lst =
                 case r of
                 0 -> reverse (((q//1),(0//1)):lst)
-                _ -> toCF' (b//r) (((q//1),(1//1)):lst) 
-	        where
-	            a = num u
-	            b = den u 
-	            (q,r) = quotRem a b 
+                _ -> toCF' (b//r) (((q//1),(1//1)):lst)
+                where
+                    a = num u
+                    b = den u
+                    (q,r) = quotRem a b
 
 
 approxCF :: Fraction -> CF -> Fraction
-approxCF eps [] = 0//1
-approxCF eps x 
-	--
-	-- Approximate infinite continued fraction x by fraction,
-	-- evaluating from left to right, and stopping when
-	-- accuracy eps is achieved, or when a partial numerator
-	-- is zero -- as it indicates the end of CF.
-	--
-	-- This recursive function relates continued fraction
-	-- to rational approximation.
-	--
-	| den h == 0 = h 
-	| otherwise = approxCF' eps x 0 1 1 q' p' 1
-	    where
-	        h = fst (x!!0)
-	        (q', p') = x!!0
-	        approxCF' eps x v2 v1 u2 u1 a' n 
-	            | abs (1 - f1/f) < eps = approx eps f
-	            | a == 0    = approx eps f 
-	            | otherwise = approxCF' eps x v1 v u1 u a (n+1)
-	            where
-	                (b, a) = x!!n
-	                u  = b*u1 + a'*u2
-	                v  = b*v1 + a'*v2
-	                f  = u/v
-	                f1 = u1/v1
-	    	           
+approxCF _ [] = 0//1
+approxCF eps x
+        --
+        -- Approximate infinite continued fraction x by fraction,
+        -- evaluating from left to right, and stopping when
+        -- accuracy eps is achieved, or when a partial numerator
+        -- is zero -- as it indicates the end of CF.
+        --
+        -- This recursive function relates continued fraction
+        -- to rational approximation.
+        --
+        | den h == 0 = h
+        | otherwise = approxCF' eps x 0 1 1 q' p' 1
+            where
+                h = fst (x!!0)
+                (q', p') = x!!0
+                approxCF' ept y v2 v1 u2 u1 a' n
+                    | abs (1 - f1/f) < ept = approx ept f
+                    | a == 0    = approx ept f
+                    | otherwise = approxCF' ept y v1 v u1 u a (n+1)
+                    where
+                        (b, a) = y!!n
+                        u  = b*u1 + a'*u2
+                        v  = b*v1 + a'*v2
+                        f  = u/v
+                        f1 = u1/v1
 
+fromTaylorToCF :: (Fractional a) => [a] -> a -> [(a, a)]
 fromTaylorToCF s x =
-	--
-	-- Convert infinite number of terms of Taylor expansion of 
-	-- a function f(x) to an infinite continued fraction,
-	-- where s = [s0,s1,s2,s3....] is a list of Taylor
-	-- series coefficients, such that f(x)=s0 + s1*x + s2*x^2.... 
-	--
-	-- Require: No Taylor coefficient is zero
-	--
-	zero:one:[higher m | m <- [2..]]
-	where
-	    zero      = (s!!0, s!!1 * x) 
-	    one       = (1, -s!!2/s!!1 * x)
-	    higher m  = (1 + s!!m/s!!(m-1) * x, -s!!(m+1)/s!!m * x)
-	    
+        --
+        -- Convert infinite number of terms of Taylor expansion of
+        -- a function f(x) to an infinite continued fraction,
+        -- where s = [s0,s1,s2,s3....] is a list of Taylor
+        -- series coefficients, such that f(x)=s0 + s1*x + s2*x^2....
+        --
+        -- Require: No Taylor coefficient is zero
+        --
+        zero:one:[higher m | m <- [2..]]
+        where
+            zero      = (s!!0, s!!1 * x)
+            one       = (1, -s!!2/s!!1 * x)
+            higher m  = (1 + s!!m/s!!(m-1) * x, -s!!(m+1)/s!!m * x)
 
+
 fromFraction :: Fraction -> Double
 fromFraction = fromRational . toRational
-	
+
 ------------------------------------------------------------------
---		Category: Auxiliaries
+--              Category: Auxiliaries
 ------------------------------------------------------------------
 
-fac	:: Integer -> Integer	    
+fac     :: Integer -> Integer
 fac = product . enumFromTo 1
 
 integerRoot2 :: Integer -> Integer
 integerRoot2 1 = 1
 integerRoot2 x =
         --
-	-- Biggest integer m, such that x - m^2 >= 0,
-	-- where x is a positive integer
+        -- Biggest integer m, such that x - m^2 >= 0,
+        -- where x is a positive integer
         --
         integerRoot2' 0 x (x `div` 2) x
         where
-            integerRoot2' lo hi r y 
-	        | c > y      = integerRoot2' lo r ((r + lo) `div` 2) y
-	        | c == y     = r
-	        | otherwise  = 
-	            if (r+1)^2 > y then
-	                r
-	            else
-	                integerRoot2' r hi ((r + hi) `div` 2) y
-	            where c = r^2
+            integerRoot2' lo hi r y
+                | c > y      = integerRoot2' lo r ((r + lo) `div` 2) y
+                | c == y     = r
+                | otherwise  =
+                    if (r+1)^(2::Int) > y then
+                        r
+                    else
+                        integerRoot2' r hi ((r + hi) `div` 2) y
+                    where c = r^(2::Int)
 
 ------------------------------------------------------------------
---		Category: Class Transcendental
+--              Category: Class Transcendental
 --
---	This class declares functions for three data types:
---	Fraction, Cofraction (complex fraction) and Numerus
---	- a generalization of Integer, Fraction and Cofraction.
+--      This class declares functions for three data types:
+--      Fraction, Cofraction (complex fraction) and Numerus
+--      - a generalization of Integer, Fraction and Cofraction.
 ------------------------------------------------------------------
 class Transcendental a where
-    pi'		:: Fraction -> a
-    tan'	:: Fraction -> a -> a
-    sin'	:: Fraction -> a -> a
-    cos'	:: Fraction -> a -> a
-    atan'	:: Fraction -> a -> a
-    asin'	:: Fraction -> a -> a
-    acos'	:: Fraction -> a -> a
+    pi'         :: Fraction -> a
+    tan'        :: Fraction -> a -> a
+    sin'        :: Fraction -> a -> a
+    cos'        :: Fraction -> a -> a
+    atan'       :: Fraction -> a -> a
+    asin'       :: Fraction -> a -> a
+    acos'       :: Fraction -> a -> a
     sqrt'       :: Fraction -> a -> a
-    root'	:: Fraction -> a-> Integer -> a
-    power'	:: Fraction -> a -> a -> a
-    exp'	:: Fraction -> a -> a
-    tanh'	:: Fraction -> a -> a
-    sinh'	:: Fraction -> a -> a
-    cosh'	:: Fraction -> a -> a
-    atanh'	:: Fraction -> a -> a
-    asinh'	:: Fraction -> a -> a
-    acosh'	:: Fraction -> a -> a
-    log'	:: Fraction -> a -> a
-    decimal	:: Integer -> a -> IO ()
+    root'       :: Fraction -> a-> Integer -> a
+    power'      :: Fraction -> a -> a -> a
+    exp'        :: Fraction -> a -> a
+    tanh'       :: Fraction -> a -> a
+    sinh'       :: Fraction -> a -> a
+    cosh'       :: Fraction -> a -> a
+    atanh'      :: Fraction -> a -> a
+    asinh'      :: Fraction -> a -> a
+    acosh'      :: Fraction -> a -> a
+    log'        :: Fraction -> a -> a
+    decimal     :: Integer -> a -> IO ()
 
 -------------------------------------------------------------------
 -- Everything below is the instantiation of class Transcendental
 -- for type Fraction. See also modules Cofra and Numerus.
 --
---		Category: Constants 
+--              Category: Constants
 -------------------------------------------------------------------
 
 instance Transcendental Fraction where
-  	    
+
     pi' eps =
-    	--
-	-- pi with accuracy eps
-	--
-	-- Based on Ramanujan formula, as described in Ref. 3
-	-- Accuracy: extremely good, 10^-19 for one term of continued
-	-- fraction
-	--
-	(sqrt' eps d) / (approxCF eps (fromTaylorToCF s x))
-	where
-	    x = 1//(640320^3)::Fraction
-	    s = [((-1)^k*(fac (6*k))//((fac k)^3*(fac (3*k))))*((a*k+b)//c) | k<-[0..]]
+        --
+        -- pi with accuracy eps
+        --
+        -- Based on Ramanujan formula, as described in Ref. 3
+        -- Accuracy: extremely good, 10^-19 for one term of continued
+        -- fraction
+        --
+        (sqrt' eps d) / (approxCF eps (fromTaylorToCF s x))
+        where
+            x = 1//(640320^(3::Int))::Fraction
+            s = [((-1)^k*(fac (6*k))//((fac k)^(3::Int)*(fac (3*k))))*((a*k+b)//c) | k<-[0..]]
             a = 545140134
-	    b = 13591409
-	    c = 426880
-	    d = 10005
-	    
+            b = 13591409
+            c = 426880
+            d = 10005
+
 ---------------------------------------------------------------------
---		Category: Trigonometry
+--              Category: Trigonometry
 ---------------------------------------------------------------------
-	 
-    tan' eps 0  = 0
-    tan' eps (u:-:0) = 1//0
+
+    tan' _ 0  = 0
+    tan' _ (_:-:0) = 1//0
     tan' eps x
-    	--
-	-- Tangent x computed with accuracy of eps.
-	-- 
-	-- Trigonometric identities are used first to reduce
-	-- the value of x to a value from within the range of [-pi/2,pi/2]
-	--
-	| x >= half_pi'  = tan' eps (x - ((1+m)//1)*pi)
-	| x <= -half_pi' = tan' eps (x + ((1+m)//1)*pi)
-	--- | absx > 1       = 2 * t/(1 - t^2)
-	| otherwise      = approxCF eps (cf x) 	    
-	where
-	    absx    = abs x 
-	    t       = tan' eps (x/2)
-	    m       = floor ((absx - half_pi)/ pi)
-	    pi      = pi' eps
-	    half_pi'= 158//100
-	    half_pi = pi * (1//2)
-	    cf u    = ((0//1,1//1):[((2*r + 1)/u, -1) | r <- [0..]])
-                       
-    sin' eps 0      = 0
-    sin' eps (u:-:0)= 1//0
+        --
+        -- Tangent x computed with accuracy of eps.
+        --
+        -- Trigonometric identities are used first to reduce
+        -- the value of x to a value from within the range of [-pi/2,pi/2]
+        --
+        | x >= half_pi'  = tan' eps (x - ((1+m)//1)*p)
+        | x <= -half_pi' = tan' eps (x + ((1+m)//1)*p)
+        --- | absx > 1       = 2 * t/(1 - t^2)
+        | otherwise      = approxCF eps (cf x)
+        where
+            absx    = abs x
+            _       = tan' eps (x/2)
+            m       = floor ((absx - half_pi)/ p)
+            p      = pi' eps
+            half_pi'= 158//100
+            half_pi = p * (1//2)
+            cf u    = ((0//1,1//1):[((2*r + 1)/u, -1) | r <- [0..]])
+
+    sin' _ 0      = 0
+    sin' _ (_:-:0)= 1//0
     sin' eps x      = 2*t/(1 + t*t)
         where
             t = tan' eps (x/2)
 
-    cos' eps 0      = 1
-    cos' eps (u:-:0)= 1//0
+    cos' _ 0      = 1
+    cos' _ (_:-:0)= 1//0
     cos' eps x      = (1 - p)/(1 + p)
         where
-            t = tan' eps (x/2) 
+            t = tan' eps (x/2)
             p = t*t
-        
+
     atan' eps x
-	--
-	-- Inverse tangent of x with approximation eps
-	--
-	| x == 1//0    = (pi' eps)/2
-	| x == (-1//0) = -(pi' eps)/2
-	| x == 0       = 0
-	| x > 1    = (pi' eps)/2 - atan' eps (1/x)
-	| x < -1   = -(pi' eps)/2 - atan' eps (1/x)
-	| otherwise    = approxCF eps ((0,x):[((2*m - 1),(m*x)^2) | m<- [1..]])
-	
-   
-    asin' eps x 
-	--
-	-- Inverse sine of x with approximation eps
-	--
-	| x == 0    = 0//1
-	| abs x > 1 = 1//0
-	| x == 1    = (pi' eps) *(1//2)
-	| x == -1   = (pi' eps) * ((-1)//2)
-	| otherwise = atan' eps (x / (sqrt' eps (1 - x^2)))
+        --
+        -- Inverse tangent of x with approximation eps
+        --
+        | x == 1//0    = (pi' eps)/2
+        | x == (-1//0) = -(pi' eps)/2
+        | x == 0       = 0
+        | x > 1    = (pi' eps)/2 - atan' eps (1/x)
+        | x < -1   = -(pi' eps)/2 - atan' eps (1/x)
+        | otherwise    = approxCF eps ((0,x):[((2*m - 1),(m*x)^(2::Int)) | m<- [1..]])
 
- 	
-    acos' eps x 
-	--
-	-- Inverse cosine of x with approximation eps
-	--
-	| x == 0    = (pi' eps)*(1//2)
-	| abs x > 1 = 1//0
-	| x == 1    = 0//1
-	| x == -1   = pi' eps
-	| otherwise = atan' eps ((sqrt' eps (1 - x^2)) / x)
-	 
+
+    asin' eps x
+        --
+        -- Inverse sine of x with approximation eps
+        --
+        | x == 0    = 0//1
+        | abs x > 1 = 1//0
+        | x == 1    = (pi' eps) *(1//2)
+        | x == -1   = (pi' eps) * ((-1)//2)
+        | otherwise = atan' eps (x / (sqrt' eps (1 - x^(2::Int))))
+
+
+    acos' eps x
+        --
+        -- Inverse cosine of x with approximation eps
+        --
+        | x == 0    = (pi' eps)*(1//2)
+        | abs x > 1 = 1//0
+        | x == 1    = 0//1
+        | x == -1   = pi' eps
+        | otherwise = atan' eps ((sqrt' eps (1 - x^(2::Int))) / x)
+
 ---------------------------------------------------------------------
---		Category: Roots
+--              Category: Roots
 ---------------------------------------------------------------------
-  
+
     sqrt' eps x
         --
-	-- Square root of x with approximation eps
-	--
-	-- The CF pattern is: [(m,x-m^2),(2m,x-m^2),(2m,x-m^2)....]
-	-- where m is the biggest integer such that x-m^2 >= 0
-	--
-	| x == 1//0    = 1//0
-	| x < 0        = 1//0
-	| x == 0       = 0
-	| x < 1        = 1/(sqrt' eps (1/x))
-	| otherwise    = approxCF eps ((m,x-m^2):[(2*m,x-m^2) | r<-[0..]]) 
-	where
-	    m = (integerRoot2 (floor x))//1
-	  
-    root' eps x k 
-	--
-	-- k-th root of positive number x with approximation eps
-	--
-	| x == (1//0)  = 1//0
-	| x < 0        = 1//0
-	| x == 0       = 0
-	| k == 0       = 1//0
-	| otherwise    = exp' eps ((log' eps x) * (1//k))
-	 
+        -- Square root of x with approximation eps
+        --
+        -- The CF pattern is: [(m,x-m^2),(2m,x-m^2),(2m,x-m^2)....]
+        -- where m is the biggest integer such that x-m^2 >= 0
+        --
+        | x == 1//0    = 1//0
+        | x < 0        = 1//0
+        | x == 0       = 0
+        | x < 1        = 1/(sqrt' eps (1/x))
+        | otherwise    = approxCF eps ((m,x-m^(2::Int)):[(2*m,x-m^(2::Int)) | _<-[(0::Integer)..]])
+        where
+            m = (integerRoot2 (floor x))//1
 
+    root' eps x k
+        --
+        -- k-th root of positive number x with approximation eps
+        --
+        | x == (1//0)  = 1//0
+        | x < 0        = 1//0
+        | x == 0       = 0
+        | k == 0       = 1//0
+        | otherwise    = exp' eps ((log' eps x) * (1//k))
+
+
 ---------------------------------------------------------------------
---		Category: Powers
+--              Category: Powers
 ---------------------------------------------------------------------
 
-    power' eps x y 
-	--
-	-- x to power of y with approximation eps
-	--
-	| x == (1//0) = 1//0
-	| x < 0       = 1//0
-	| x == 0      = 0
-	| y == 0      = 1
-	| y == (1//0) = 1//0
-	| y == (-1//0) = 0
-	| otherwise   = exp' eps (y * (log' eps x))
-			
+    power' eps x y
+        --
+        -- x to power of y with approximation eps
+        --
+        | x == (1//0) = 1//0
+        | x < 0       = 1//0
+        | x == 0      = 0
+        | y == 0      = 1
+        | y == (1//0) = 1//0
+        | y == (-1//0) = 0
+        | otherwise   = exp' eps (y * (log' eps x))
+
 ---------------------------------------------------------------------
---		Category: Exponentials and hyperbolics
+--              Category: Exponentials and hyperbolics
 ---------------------------------------------------------------------
 
-    exp' eps x 
-	--
-	-- Exponent of x with approximation eps
-	--
-	-- Based on Jacobi type continued fraction for exponential,
-	-- with fractional terms:
-	--     n == 0 ==> (1,x) 
-	--     n == 1 ==> (1 -x/2, x^2/12) 
-	--     n >= 2 ==> (1, x^2/(16*n^2 - 4))
-	-- For x outside [-1,1] apply identity exp(x) = (exp(x/2))^2
-	--
-	| x == 1//0    = 1//0
-	| x == (-1//0) = 0
-	| x == 0       = 1
-	| x > 1        = (approxCF eps (f (x*(1//p))))^p
-	| x < (-1)     = (approxCF eps (f (x*(1//q))))^q
-	| otherwise    = approxCF eps (f x)
-	where
-	    p = ceiling x
-	    q = -(floor x)
-	    f y = (1,y):(1-y/2,y^2/12):[(1,y^2/(16*n^2-4)) | n<-[2..]]
-	    	       
-	        
+    exp' eps x
+        --
+        -- Exponent of x with approximation eps
+        --
+        -- Based on Jacobi type continued fraction for exponential,
+        -- with fractional terms:
+        --     n == 0 ==> (1,x)
+        --     n == 1 ==> (1 -x/2, x^2/12)
+        --     n >= 2 ==> (1, x^2/(16*n^2 - 4))
+        -- For x outside [-1,1] apply identity exp(x) = (exp(x/2))^2
+        --
+        | x == 1//0    = 1//0
+        | x == (-1//0) = 0
+        | x == 0       = 1
+        | x > 1        = (approxCF eps (f (x*(1//p))))^p
+        | x < (-1)     = (approxCF eps (f (x*(1//q))))^q
+        | otherwise    = approxCF eps (f x)
+        where
+            p = ceiling x
+            q = -(floor x)
+            f y = (1,y):(1-y/2,y^(2::Int)/12):[(1,y^(2::Int)/(16*n^(2::Int)-4)) | n<-[2..]]
+
+
     cosh' eps x =
-	--
-	-- Hyperbolic cosine with approximation eps
-	--
-	(a + b)*(1//2)
-	where
-	    a = exp' eps x
-	    b = 1/a
+        --
+        -- Hyperbolic cosine with approximation eps
+        --
+        (a + b)*(1//2)
+        where
+            a = exp' eps x
+            b = 1/a
 
     sinh' eps x =
-	--
-	-- Hyperbolic sine with approximation eps
-	--
-	(a - b)*(1//2)
-	where
-	    a = exp' eps x
-	    b = 1/a
+        --
+        -- Hyperbolic sine with approximation eps
+        --
+        (a - b)*(1//2)
+        where
+            a = exp' eps x
+            b = 1/a
 
     tanh' eps x =
-	--
-	-- Hyperbolic tangent with approximation eps
-	--
-	(a - b)/ (a + b)
-	where
-	    a = exp' eps x
-	    b = 1/a
+        --
+        -- Hyperbolic tangent with approximation eps
+        --
+        (a - b)/ (a + b)
+        where
+            a = exp' eps x
+            b = 1/a
 
-    atanh' eps x 
-	--
-	-- Inverse hyperbolic tangent with approximation eps
-	--
-	
-	| x >= 1     = 1//0
-	| x <= -1    = -1//0
-	| otherwise  = (1//2) * (log' eps ((1 + x) / (1 - x)))
-	
-    asinh' eps x 
-	--
-	-- Inverse hyperbolic sine
-	--
-	| x == 1//0  =  1//0
-	| x == -1//0 = -1//0
-	| otherwise  = log' eps (x + (sqrt' eps (x^2 + 1)))
-	
+    atanh' eps x
+        --
+        -- Inverse hyperbolic tangent with approximation eps
+        --
+
+        | x >= 1     = 1//0
+        | x <= -1    = -1//0
+        | otherwise  = (1//2) * (log' eps ((1 + x) / (1 - x)))
+
+    asinh' eps x
+        --
+        -- Inverse hyperbolic sine
+        --
+        | x == 1//0  =  1//0
+        | x == -1//0 = -1//0
+        | otherwise  = log' eps (x + (sqrt' eps (x^(2::Int) + 1)))
+
     acosh' eps x
-	--
-	-- Inverse hyperbolic cosine
-	--
-	| x == 1//0 = 1//0
-	| x < 1     = 1//0
-	| otherwise = log' eps (x + (sqrt' eps (x^2 - 1)))
-		    		      
+        --
+        -- Inverse hyperbolic cosine
+        --
+        | x == 1//0 = 1//0
+        | x < 1     = 1//0
+        | otherwise = log' eps (x + (sqrt' eps (x^(2::Int) - 1)))
+
 ---------------------------------------------------------------------
---		Category: Logarithms
+--              Category: Logarithms
 ---------------------------------------------------------------------
 
     log' eps x
-    	-- 
-	-- Natural logarithm of strictly positive x 
-	--
-	-- Based on Stieltjes type continued fraction for log (1+y)
-	--     (0,y):(1,y/2):[(1,my/(4m+2)),(1,(m+1)y/(4m+2)),....
-	--     (m >= 1, two elements per m)
-	-- Efficient only for x close to one. For larger x we recursively
-	-- apply the identity log(x) = log(x/2) + log(2)
-	--
-	| x == 1//0 =  1//0
-	| x <= 0    = -1//0
-	| x <  1    = -log' eps (1/x)
-	| x == 1    =  0
-	| otherwise =
-	    case (scaled (x,0)) of
-	    (1,s) -> (s//1) * approxCF eps (series 1)
-	    (y,0) -> approxCF eps (series (y-1)) 
-	    (y,s) -> approxCF eps (series (y-1)) + (s//1)*approxCF eps (series 1)
-	where      
+        --
+        -- Natural logarithm of strictly positive x
+        --
+        -- Based on Stieltjes type continued fraction for log (1+y)
+        --     (0,y):(1,y/2):[(1,my/(4m+2)),(1,(m+1)y/(4m+2)),....
+        --     (m >= 1, two elements per m)
+        -- Efficient only for x close to one. For larger x we recursively
+        -- apply the identity log(x) = log(x/2) + log(2)
+        --
+        | x == 1//0 =  1//0
+        | x <= 0    = -1//0
+        | x <  1    = -log' eps (1/x)
+        | x == 1    =  0
+        | otherwise =
+            case (scaled (x,0)) of
+            (1,s) -> (s//1) * approxCF eps (series 1)
+            (y,0) -> approxCF eps (series (y-1))
+            (y,s) -> approxCF eps (series (y-1)) + (s//1)*approxCF eps (series 1)
+        where
             series :: Fraction -> CF
             series u = (0,u):(1,u/2):[(1,u*((m+n)//(4*m + 2)))|m<-[1..],n<-[0,1]]
-	    scaled :: (Fraction,Integer) -> (Fraction, Integer)
-            scaled (x, n)
-	        | x == 2 = (1,n+1)
-	        | x < 2 = (x, n)
-	        | otherwise = scaled (x*(1//2), n+1)
+            scaled :: (Fraction,Integer) -> (Fraction, Integer)
+            scaled (y, n)
+                | y == 2 = (1,n+1)
+                | y < 2 = (y, n)
+                | otherwise = scaled (y*(1//2), n+1)
 
-	 
+
 ---------------------------------------------------------------------
---		Category: IO
+--              Category: IO
 ---------------------------------------------------------------------
-    decimal n (u:-:0) = putStr (show u++"//0")
+    decimal _ (u:-:0) = putStr (show u++"//0")
     decimal n x
-	--
-	-- Print Fraction with an accuracy to n decimal places,
-	-- or symbols +/- 1//0 for infinities.
-	| n <= 0    = decimal 1 x
-	| x < 0     = putStr (g (-v*10) (den x) n ("-"++show (-u) ++"."))
-	| otherwise = putStr (g (v*10) (den x) n (show u++"."))
-	where
-	    (u, v) = quotRem (num x) (den x)
-	    g x y 0 str = str
-	    g x y n str =
-	        case (p, q) of
-	        (_,0) -> str ++ show p 
-	        (_,_) -> g (q*10) y (n-1) (str ++ show p) 
-	        where 
-	            (p, q) = quotRem x y
-	            
-	              
-  
+        --
+        -- Print Fraction with an accuracy to n decimal places,
+        -- or symbols +/- 1//0 for infinities.
+        | n <= 0    = decimal 1 x
+        | x < 0     = putStr (g (-v*10) (den x) n ("-"++show (-u) ++"."))
+        | otherwise = putStr (g (v*10) (den x) n (show u++"."))
+        where
+            (u, v) = quotRem (num x) (den x)
+            g _ _ 0 str = str
+            g y z m str =
+                case (p, q) of
+                (_,0) -> str ++ show p
+                (_,_) -> g (q*10) z (m-1) (str ++ show p)
+                where
+                    (p, q) = quotRem y z
+
+
+
 ---------------------------------------------------------------------------
 -- References:
 --
@@ -618,46 +618,46 @@
 --      http://www.mathsoft.com/asolve/constant/cntfrc/cntfrc.html
 -- 3. "Efficient on-line computation of real functions using exact floating
 --     point", by Peter John Potts, Imperial College
---	http://theory.doc.ic.ac.uk/~pjp/ieee.html
+--      http://theory.doc.ic.ac.uk/~pjp/ieee.html
 --------------------------------------------------------------------------
 
 --------------------------------------------------------------------------
 
---	The following representation of continued fractions is used:
+--      The following representation of continued fractions is used:
 --
---	Continued fraction:	     CF representation:
---	==================           ====================
---	b0 + a0
+--      Continued fraction:          CF representation:
+--      ==================           ====================
+--      b0 + a0
 --           -------        ==>      [(b0, a0), (b1, a1), (b2, a2).....]
 --           b1 + a1
 --                -------
 --                b2 + ...
 --
---	where "a's" and "b's" are Fractions.
--- 
---	Many continued fractions could be represented by much simpler form
---	[b1,b2,b3,b4..], where all coefficients "a" would have the same value 1
---	and would not need to be explicitely listed; and the coefficients "b"
---	could be chosen as integers.
---	However, there are some useful continued fractions that are
---	given with fraction coefficients: "a", "b" or both.
---	A fractional form can always be converted to an integer form, but
---	a conversion process is not always simple and such an effort is not
---	always worth of the achieved savings in the storage space or the
---	computational efficiency. 
+--      where "a's" and "b's" are Fractions.
 --
+--      Many continued fractions could be represented by much simpler form
+--      [b1,b2,b3,b4..], where all coefficients "a" would have the same value 1
+--      and would not need to be explicitely listed; and the coefficients "b"
+--      could be chosen as integers.
+--      However, there are some useful continued fractions that are
+--      given with fraction coefficients: "a", "b" or both.
+--      A fractional form can always be converted to an integer form, but
+--      a conversion process is not always simple and such an effort is not
+--      always worth of the achieved savings in the storage space or the
+--      computational efficiency.
+--
 ----------------------------------------------------------------------------
 --
 -- Copyright:
 --
---	(C) 1998 Numeric Quest, All rights reserved
+--      (C) 1998 Numeric Quest, All rights reserved
 --
 --      <jans@numeric-quest.com>
 --
---      http://www.numeric-quest.com	
+--      http://www.numeric-quest.com
 --
 -- License:
 --
---	GNU General Public License, GPL
--- 
+--      GNU General Public License, GPL
+--
 -----------------------------------------------------------------------------
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,674 @@
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+  The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works.  By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users.  We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors.  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+  To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights.  Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received.  You must make sure that they, too, receive
+or can get the source code.  And you must show them these terms so they
+know their rights.
+
+  Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+  For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software.  For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+  Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so.  This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software.  The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable.  Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products.  If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+  Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary.  To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                       TERMS AND CONDITIONS
+
+  0. Definitions.
+
+  "This License" refers to version 3 of the GNU General Public License.
+
+  "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+  "The Program" refers to any copyrightable work licensed under this
+License.  Each licensee is addressed as "you".  "Licensees" and
+"recipients" may be individuals or organizations.
+
+  To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy.  The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+  A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+  To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy.  Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+  To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies.  Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+  An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License.  If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+  1. Source Code.
+
+  The "source code" for a work means the preferred form of the work
+for making modifications to it.  "Object code" means any non-source
+form of a work.
+
+  A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+  The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form.  A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+  The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities.  However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work.  For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+  The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+  The Corresponding Source for a work in source code form is that
+same work.
+
+  2. Basic Permissions.
+
+  All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met.  This License explicitly affirms your unlimited
+permission to run the unmodified Program.  The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work.  This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+  You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force.  You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright.  Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+  Conveying under any other circumstances is permitted solely under
+the conditions stated below.  Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+  No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+  When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+  4. Conveying Verbatim Copies.
+
+  You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+  You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+  5. Conveying Modified Source Versions.
+
+  You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+    a) The work must carry prominent notices stating that you modified
+    it, and giving a relevant date.
+
+    b) The work must carry prominent notices stating that it is
+    released under this License and any conditions added under section
+    7.  This requirement modifies the requirement in section 4 to
+    "keep intact all notices".
+
+    c) You must license the entire work, as a whole, under this
+    License to anyone who comes into possession of a copy.  This
+    License will therefore apply, along with any applicable section 7
+    additional terms, to the whole of the work, and all its parts,
+    regardless of how they are packaged.  This License gives no
+    permission to license the work in any other way, but it does not
+    invalidate such permission if you have separately received it.
+
+    d) If the work has interactive user interfaces, each must display
+    Appropriate Legal Notices; however, if the Program has interactive
+    interfaces that do not display Appropriate Legal Notices, your
+    work need not make them do so.
+
+  A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit.  Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+  6. Conveying Non-Source Forms.
+
+  You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+    a) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by the
+    Corresponding Source fixed on a durable physical medium
+    customarily used for software interchange.
+
+    b) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by a
+    written offer, valid for at least three years and valid for as
+    long as you offer spare parts or customer support for that product
+    model, to give anyone who possesses the object code either (1) a
+    copy of the Corresponding Source for all the software in the
+    product that is covered by this License, on a durable physical
+    medium customarily used for software interchange, for a price no
+    more than your reasonable cost of physically performing this
+    conveying of source, or (2) access to copy the
+    Corresponding Source from a network server at no charge.
+
+    c) Convey individual copies of the object code with a copy of the
+    written offer to provide the Corresponding Source.  This
+    alternative is allowed only occasionally and noncommercially, and
+    only if you received the object code with such an offer, in accord
+    with subsection 6b.
+
+    d) Convey the object code by offering access from a designated
+    place (gratis or for a charge), and offer equivalent access to the
+    Corresponding Source in the same way through the same place at no
+    further charge.  You need not require recipients to copy the
+    Corresponding Source along with the object code.  If the place to
+    copy the object code is a network server, the Corresponding Source
+    may be on a different server (operated by you or a third party)
+    that supports equivalent copying facilities, provided you maintain
+    clear directions next to the object code saying where to find the
+    Corresponding Source.  Regardless of what server hosts the
+    Corresponding Source, you remain obligated to ensure that it is
+    available for as long as needed to satisfy these requirements.
+
+    e) Convey the object code using peer-to-peer transmission, provided
+    you inform other peers where the object code and Corresponding
+    Source of the work are being offered to the general public at no
+    charge under subsection 6d.
+
+  A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+  A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling.  In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage.  For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product.  A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+  "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source.  The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+  If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information.  But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+  The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed.  Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+  Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+  7. Additional Terms.
+
+  "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law.  If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+  When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it.  (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.)  You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+  Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+    a) Disclaiming warranty or limiting liability differently from the
+    terms of sections 15 and 16 of this License; or
+
+    b) Requiring preservation of specified reasonable legal notices or
+    author attributions in that material or in the Appropriate Legal
+    Notices displayed by works containing it; or
+
+    c) Prohibiting misrepresentation of the origin of that material, or
+    requiring that modified versions of such material be marked in
+    reasonable ways as different from the original version; or
+
+    d) Limiting the use for publicity purposes of names of licensors or
+    authors of the material; or
+
+    e) Declining to grant rights under trademark law for use of some
+    trade names, trademarks, or service marks; or
+
+    f) Requiring indemnification of licensors and authors of that
+    material by anyone who conveys the material (or modified versions of
+    it) with contractual assumptions of liability to the recipient, for
+    any liability that these contractual assumptions directly impose on
+    those licensors and authors.
+
+  All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10.  If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term.  If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+  If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+  Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+  8. Termination.
+
+  You may not propagate or modify a covered work except as expressly
+provided under this License.  Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+  However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+  Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+  Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License.  If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+  9. Acceptance Not Required for Having Copies.
+
+  You are not required to accept this License in order to receive or
+run a copy of the Program.  Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance.  However,
+nothing other than this License grants you permission to propagate or
+modify any covered work.  These actions infringe copyright if you do
+not accept this License.  Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+  10. Automatic Licensing of Downstream Recipients.
+
+  Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License.  You are not responsible
+for enforcing compliance by third parties with this License.
+
+  An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations.  If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+  You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License.  For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+  11. Patents.
+
+  A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based.  The
+work thus licensed is called the contributor's "contributor version".
+
+  A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version.  For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+  Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+  In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement).  To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+  If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients.  "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+  If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+  A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License.  You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+  Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+  12. No Surrender of Others' Freedom.
+
+  If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all.  For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+  13. Use with the GNU Affero General Public License.
+
+  Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work.  The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+  14. Revised Versions of this License.
+
+  The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+  Each version is given a distinguishing version number.  If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation.  If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+  If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+  Later license versions may give you additional or different
+permissions.  However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+  15. Disclaimer of Warranty.
+
+  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. Limitation of Liability.
+
+  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+  17. Interpretation of Sections 15 and 16.
+
+  If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+  If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+    <program>  Copyright (C) <year>  <name of author>
+    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+  You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+  The GNU General Public License does not permit incorporating your program
+into proprietary programs.  If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.  But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/LinearAlgorithms.hs b/LinearAlgorithms.hs
--- a/LinearAlgorithms.hs
+++ b/LinearAlgorithms.hs
@@ -1,10 +1,9 @@
-
 ------------------------------------------------------------------------------
--- Haskell module:	LinearAlgorithms
--- Date:		initialized 2001-03-25, last modified 2001-04-01
--- Author:		Jan Skibinski, Numeric Quest Inc.
--- Location:		http://www.numeric-quest.com/haskell/LinearAlgorithms.hs
--- See also:		http://www.numeric-quest.com/haskell/Orthogonals.html
+-- Haskell module:      LinearAlgorithms
+-- Date:                initialized 2001-03-25, last modified 2001-04-01
+-- Author:              Jan Skibinski, Numeric Quest Inc.
+-- Location:            http://www.numeric-quest.com/haskell/LinearAlgorithms.hs
+-- See also:            http://www.numeric-quest.com/haskell/Orthogonals.html
 --
 -- Description:
 -- This module provides several _selected_ linear algebra algorithms,
@@ -15,14 +14,14 @@
 
 -- Here is a list of implemented algorithms:
 --
--- + triangular		A => R		where R is upper triangular
--- + triangular2	A => (R, Q)	such that R = Q' A Q
+-- + triangular         A => R          where R is upper triangular
+-- + triangular2        A => (R, Q)     such that R = Q' A Q
 --
--- + tridiagonal	H => T		where H is Hermitian and T is
--- + tridiagonal2	H => (T, Q)	tridiagonal, such that T = Q' H Q
+-- + tridiagonal        H => T          where H is Hermitian and T is
+-- + tridiagonal2       H => (T, Q)     tridiagonal, such that T = Q' H Q
 --
--- + subsAnnihilator	A => Q	such that Q A has zeroed subdiagonals
--- + reflection		x => y	where y is a complex reflection of x
+-- + subsAnnihilator    A => Q  such that Q A has zeroed subdiagonals
+-- + reflection         x => y  where y is a complex reflection of x
 --
 -- Other algoritms, such as solution of linear equations are, at this time,
 -- imported from module Orthogonals. The latter also deals with triangulization,
@@ -36,10 +35,10 @@
 ----------------------------------------------------------------------------
 
 module LinearAlgorithms (
-	triangular,
-	triangular2,
-	tridiagonal,
-	tridiagonal2,
+        triangular,
+        triangular2,
+        tridiagonal,
+        tridiagonal2,
         Scalar,) where
 
 import Complex
@@ -50,198 +49,198 @@
 ----------------------------------------------------------------------------
 -- Category: Iterative triangularization
 --
---   triangular		A => R		where R is upper triangular
---   triangular2	A => (R, Q)	such that R = Q' A Q
+--   triangular         A => R          where R is upper triangular
+--   triangular2        A => (R, Q)     such that R = Q' A Q
 ----------------------------------------------------------------------------
 
 mult :: [[Scalar]] -> [[Scalar]] -> [[Scalar]]
 a `mult` b
-    --	A matrix-product of matrices 'a' and 'b'
-    --		C = A B
-    --	where all matrices are represented as lists
-    --	of scalar columns	
-	= matrix_matrix' (transposed a) b
+    --  A matrix-product of matrices 'a' and 'b'
+    --          C = A B
+    --  where all matrices are represented as lists
+    --  of scalar columns
+        = matrix_matrix' (transposed a) b
 
 triangular :: Int -> [[Scalar]] -> [[Scalar]]
 triangular n a
-    --	A (hopefully) triangular matrix R = Q' A Q obtained by
-    --	'n' similarity transformations S(k) of matrix A:
-    --		Q = S1 S2 S3 ....
+    --  A (hopefully) triangular matrix R = Q' A Q obtained by
+    --  'n' similarity transformations S(k) of matrix A:
+    --          Q = S1 S2 S3 ....
     --
     -- If matrix A is Hermitian then the result is close
     -- to a diagonal matrix for sufficiently large n.
-    | n == 0	= a
+    | n == 0    = a
     | otherwise = triangular (n - 1) a1
     where
-	a1  = (q' `mult` a ) `mult` q
-	q'  = subsAnnihilator 0 a
-	q   = adjoint q'
-	
+        a1  = (q' `mult` a ) `mult` q
+        q'  = subsAnnihilator 0 a
+        q   = adjoint q'
 
+
 triangular2 :: Int -> [[Scalar]] -> ([[Scalar]], [[Scalar]])
 triangular2 n a
-    --	A pair of matrices (R, Q) obtained by 'n'
-    --	similarity transformations, where R = Q' A Q
-    --	is a (hopefully) triangular matrix, or diagonal
-    --	if A is Hermitian. The transformation matrix Q
-    --	is required for computation of eigenvectors
-    --	of A.
+    --  A pair of matrices (R, Q) obtained by 'n'
+    --  similarity transformations, where R = Q' A Q
+    --  is a (hopefully) triangular matrix, or diagonal
+    --  if A is Hermitian. The transformation matrix Q
+    --  is required for computation of eigenvectors
+    --  of A.
     = triangular2' n a (unit_matrix n)
     where
-	triangular2' n a p
-	    | n == 0	= (a, p)
-	    | otherwise = triangular2' (n - 1) a1 p1
-	    where
-		a1 = (q' `mult` a ) `mult` q
-		p1 = p `mult` q
-		q' = subsAnnihilator 0 a
-		q  = adjoint q'
-		
+        triangular2' o b p
+            | o == 0    = (b, p)
+            | otherwise = triangular2' (o - 1) b1 p1
+            where
+                b1 = (q' `mult` b ) `mult` q
+                p1 = p `mult` q
+                q' = subsAnnihilator 0 b
+                q  = adjoint q'
 
+
 ----------------------------------------------------------------------------
 -- Category: Tridiagonalization of a Hermitian matrix
 --
--- + tridiagonal	H -> T	where H is Hermitian and T is tridiagonal
--- + tridiagonal2	H -> (T, Q)	such that T = Q' H Q
+-- + tridiagonal        H -> T  where H is Hermitian and T is tridiagonal
+-- + tridiagonal2       H -> (T, Q)     such that T = Q' H Q
 ----------------------------------------------------------------------------
 
 
 tridiagonal :: [[Scalar]] -> [[Scalar]]
 tridiagonal h
-    --	A tridiagonal matrix T = Q' H Q, obtained from Hermitian
-    --	matrix H by a finite number of elementary similarity
-    --	transformations (Householder reductions).
-    | n < 3		= h	
-    | otherwise 	= f (tail es) h 1
+    --  A tridiagonal matrix T = Q' H Q, obtained from Hermitian
+    --  matrix H by a finite number of elementary similarity
+    --  transformations (Householder reductions).
+    | n < 3             = h
+    | otherwise         = f (tail es) h 1
     where
-	n	= length h
-	es	= unit_matrix n
-	
-	f bs a k
-	    | length bs == 1	= a
-	    | otherwise		= f (tail bs)  a1 (k+1)
-	    where
-		a1	= (q' `mult` a) `mult` q
-		q'	= [r e | e <- es]
-		q	= adjoint q'
-		r 	= reflection u (head bs)
-		u	= replicate k 0 ++ drop k (a!!(k-1))
+        n       = length h
+        es      = unit_matrix n
 
+        f bs a k
+            | length bs == 1    = a
+            | otherwise         = f (tail bs)  a1 (k+1)
+            where
+                a1      = (q' `mult` a) `mult` q
+                q'      = [r e | e <- es]
+                q       = adjoint q'
+                r       = reflection u (head bs)
+                u       = replicate k 0 ++ drop k (a!!(k-1))
 
+
 tridiagonal2 :: [[Scalar]] -> ([[Scalar]], [[Scalar]])
 tridiagonal2 h
-    --	A pair (T, Q) of matrices, obtained from
-    --	similarity transformation of Hermitian matrix H
-    --	where T = Q' H Q is a tridiagonal matrix and Q is unitary
-    --	transformation made of a finite product of
-    --	elementary Householder reductions.
-    | n < 3		= (h, es)	
-    | otherwise 	= f (tail es) h es 1
+    --  A pair (T, Q) of matrices, obtained from
+    --  similarity transformation of Hermitian matrix H
+    --  where T = Q' H Q is a tridiagonal matrix and Q is unitary
+    --  transformation made of a finite product of
+    --  elementary Householder reductions.
+    | n < 3             = (h, es)
+    | otherwise         = f (tail es) h es 1
     where
-	n	= length h
-	es	= unit_matrix n
-	
-	f bs a p k
-	    | length bs == 1	= (a, p)
-	    | otherwise		= f (tail bs) a1 p1 (k+1)
-	    where
-		a1	= (q' `mult` a) `mult` q
-		q'	= [r e | e <- es]
-		q	= adjoint q'
-		p1	= p `mult` q
-		r 	= reflection u (head bs)
-		u	= replicate k 0 ++ drop k (a!!(k-1))
+        n       = length h
+        es      = unit_matrix n
 
+        f bs a p k
+            | length bs == 1    = (a, p)
+            | otherwise         = f (tail bs) a1 p1 (k+1)
+            where
+                a1      = (q' `mult` a) `mult` q
+                q'      = [r e | e <- es]
+                q       = adjoint q'
+                p1      = p `mult` q
+                r       = reflection u (head bs)
+                u       = replicate k 0 ++ drop k (a!!(k-1))
 
+
 ----------------------------------------------------------------------------
 -- Category: Elementary unitary transformations
 --
--- + subsAnnihilator	A => Q	such that Q A has zeroed subdiagonals
--- + reflection		x => y	where y is a complex reflection of x
+-- + subsAnnihilator    A => Q  such that Q A has zeroed subdiagonals
+-- + reflection         x => y  where y is a complex reflection of x
 ----------------------------------------------------------------------------
 
 subsAnnihilator :: Int -> [[Scalar]] -> [[Scalar]]
 subsAnnihilator k a
-    --	A unitary matrix Q' transforming any n x n
-    --	matrix A to an upper matrix B, which has
-    --	zero values below its 'k'-th subdiagonal
-    --	(annihilates all subdiagonals below k-th)
-    --		B = Q' A
-    --	where
-    --	    'a' is a list of columns of matrix A
+    --  A unitary matrix Q' transforming any n x n
+    --  matrix A to an upper matrix B, which has
+    --  zero values below its 'k'-th subdiagonal
+    --  (annihilates all subdiagonals below k-th)
+    --          B = Q' A
+    --  where
+    --      'a' is a list of columns of matrix A
     --
-    --	If k=0 then B is an upper triangular matrix,
-    --	if k=1 then B is an upper Hessenberg matrix.
-    --	The transformation Q is built from n - k - 1
-    --	elementary Householder transformations of
-    --	the first n-k-1 columns of iteratively transformed
-    --	matrix A.
-    | n < 2 + k		= es	
-    | otherwise 	= f (drop k es) a1 es k
+    --  If k=0 then B is an upper triangular matrix,
+    --  if k=1 then B is an upper Hessenberg matrix.
+    --  The transformation Q is built from n - k - 1
+    --  elementary Householder transformations of
+    --  the first n-k-1 columns of iteratively transformed
+    --  matrix A.
+    | n < 2 + k         = es
+    | otherwise         = f (drop k es) a1 es k
     where
-	n	= length a
-	es	= unit_matrix n
-	a1	= take (n - 1 - k) a
+        n       = length a
+        es      = unit_matrix n
+        a1      = take (n - 1 - k) a
 
-	f bs a p k
-	    | length bs == 1	= p
-	    | otherwise		= f (tail bs)  a1 p1 (k+1)
-	    where
-		a1	= [r v |v <- tail a]
-		p1	= q' `mult` p
-		q'	= [r e | e <- es]	
-		r 	= reflection u (head bs)
-		u	= replicate k 0 ++ drop k (head a)
+        f bs b p l
+            | length bs == 1    = p
+            | otherwise         = f (tail bs)  b1 p1 (l+1)
+            where
+                b1      = [r v |v <- tail b]
+                p1      = q' `mult` p
+                q'      = [r e | e <- es]
+                r       = reflection u (head bs)
+                u       = replicate k 0 ++ drop l (head b)
 
 
 reflection :: [Scalar] -> [Scalar] -> [Scalar] -> [Scalar]
 reflection a e x
-    --	A vector resulting from unitary complex
-    --	Householder-like transformation of vector 'x'.
+    --  A vector resulting from unitary complex
+    --  Householder-like transformation of vector 'x'.
     --
-    --	The operator of such transformation is defined
-    --	by mapping vector 'a' to a multiple 'p' of vector 'e'
-    --		U |a > = p | e >
-    --	where scalar 'p' is chosen to guarantee unitarity
-    --		< a | a > = < p e | p e>.
+    --  The operator of such transformation is defined
+    --  by mapping vector 'a' to a multiple 'p' of vector 'e'
+    --          U |a > = p | e >
+    --  where scalar 'p' is chosen to guarantee unitarity
+    --          < a | a > = < p e | p e>.
     --
-    --	This transformation is not generally Hermitian, because
-    --	the scalar 'p' might become complex - unless
-    --		< a | e > = < e | a >,
-    --	which is the case when both vectors are real, and
-    --	when this transformation becomes a simple Hermitian
-    --	reflection operation.
-    --	See reference [1] for details.
+    --  This transformation is not generally Hermitian, because
+    --  the scalar 'p' might become complex - unless
+    --          < a | e > = < e | a >,
+    --  which is the case when both vectors are real, and
+    --  when this transformation becomes a simple Hermitian
+    --  reflection operation.
+    --  See reference [1] for details.
     --
     | d == 0    = x
     | otherwise = [xk - z * yk |(xk, yk) <- zip x y]
     where
-	z = s * bra_ket y x
-	s = 2/h :+ (-2 * g)/h
-	h = 1 + g^2
-	g = imagPart a_b / d
-	d = a_a - realPart a_b
-	y = normalized [ak - bk |(ak, bk) <- zip a b]
-	p = a_a / (realPart (bra_ket e e))
-	b = map ((sqrt p :+ 0) * ) e
-	a_a = realPart (bra_ket a a)
-	a_b = bra_ket a b
+        z = s * bra_ket y x
+        s = 2/h :+ (-2 * g)/h
+        h = 1 + g^(2::Int)
+        g = imagPart a_b / d
+        d = a_a - realPart a_b
+        y = normalized [ak - bk |(ak, bk) <- zip a b]
+        p = a_a / (realPart (bra_ket e e))
+        b = map ((sqrt p :+ 0) * ) e
+        a_a = realPart (bra_ket a a)
+        a_b = bra_ket a b
 
 ----------------------------------------------------------------------------
 -- Category: Test data
 --
 ----------------------------------------------------------------------------
 
-matrixA :: [[Scalar]]
-matrixA
-    --	Test matrix A represented as list of scalar columns.
-    =	[
-		[1, 2, 4, 1, 5]
-	,	[2, 3, 2, 6, 4]
-	,	[4, 2, 5, 2, 3]
-	,	[1, 6, 2, 7, 2]
-	,	[5, 4, 3, 2, 9]
-	]
+-- matrixA :: [[Scalar]]
+-- matrixA
+--     --  Test matrix A represented as list of scalar columns.
+--     =   [
+--                 [1, 2, 4, 1, 5]
+--         ,       [2, 3, 2, 6, 4]
+--         ,       [4, 2, 5, 2, 3]
+--         ,       [1, 6, 2, 7, 2]
+--         ,       [5, 4, 3, 2, 9]
+--         ]
 
 ----------------------------------------------------------------------------
 -- Module documentation
@@ -267,7 +266,7 @@
 -- The Schur theorem states that there exists a unitary matrix Q such
 -- that any nonsingular matrix A can be transformed to an upper triangular
 -- matrix R via similarity transformation
---	R = Q' A Q
+--      R = Q' A Q
 -- which preserves the eigenvalues. Here Q' stands for a Hermitian
 -- conjugate of Q (adjoint, or Q-dagger).
 
@@ -275,7 +274,7 @@
 -- elements, finding such transformation solves the first part of
 -- the eigenproblem. The second part, finding the eigenvectors of A,
 -- is trivial since they can be computed from eigenvectors of R:
---	| x(A) > = Q | x(R) >
+--      | x(A) > = Q | x(R) >
 --
 -- In particular, when matrix A is Hermitian, then the matrix R
 -- becomes diagonal, and the eigenvectors of R are its normalized
@@ -291,7 +290,7 @@
 -- The methods known in literature as QR factorization (decomposition)
 -- methods iteratively compose such unitary matrix Q from a series of
 -- elementary unitary transformations, Q(1), Q(2)..:
---	Q = Q(1) Q(2) Q(3) ...
+--      Q = Q(1) Q(2) Q(3) ...
 -- The most popular method of finding those elementary unitary
 -- transformations relies on a reflection transformation, so selected as
 -- to zero out all components of the matrix below its main diagonal. Our
@@ -312,8 +311,8 @@
 -- if you are interested in eigenvalues only. But when you need
 -- the eigenvectors as well, then use the function 'triangular2',
 -- which also delivers the transformation Q, as shown below:
---   triangular		A => R	where R is upper triangular
---   triangular2	A => (R, Q)	such that R = Q' A Q
+--   triangular         A => R  where R is upper triangular
+--   triangular2        A => (R, Q)     such that R = Q' A Q
 --
 -- Tridiagonalization of Hermitian matrices:
 -- -----------------------------------------
@@ -339,8 +338,8 @@
 --
 -- Again, we are offering here two versions of the tridiagonalization:
 --
--- + tridiagonal	H -> T	where H is Hermitian and T is tridiagonal
--- + tridiagonal2	H -> (T, Q)	such that T = Q' H Q
+-- + tridiagonal        H -> T  where H is Hermitian and T is tridiagonal
+-- + tridiagonal2       H -> (T, Q)     such that T = Q' H Q
 --
 -- Elementary transformations:
 -- ---------------------------
@@ -353,27 +352,27 @@
 -- all matrix components below its first subdiagonal - leading to a so-called
 -- upper Hessenberg matrix.
 --
--- + subsAnnihilator	A => Q	such that Q A has zeroed subdiagonals
--- + reflection		x => y	where y is a complex reflection of x
+-- + subsAnnihilator    A => Q  such that Q A has zeroed subdiagonals
+-- + reflection         x => y  where y is a complex reflection of x
 --
 ----------------------------------------------------------------------------
 -- References:
--- [1]	Xiaobai Sun, On Elementary Unitary and Phi-unitary transformations,
---	Duke University, Department Of Computer Science, 1995,
---	http://citeseer.nj.nec.com/340881.html	 	
+-- [1]  Xiaobai Sun, On Elementary Unitary and Phi-unitary transformations,
+--      Duke University, Department Of Computer Science, 1995,
+--      http://citeseer.nj.nec.com/340881.html
 ---------------------------------------------------------------------------
 --
 -- Copyright:
 --
---	(C) 2001 Numeric Quest, All rights reserved
+--      (C) 2001 Numeric Quest, All rights reserved
 --
 --      Email: jans@numeric-quest.com
 --
---      http://www.numeric-quest.com	
+--      http://www.numeric-quest.com
 --
 -- License:
 --
---	GNU General Public License, GPL
+--      GNU General Public License, GPL
 --
 ---------------------------------------------------------------------------
 
diff --git a/Orthogonals.lhs b/Orthogonals.lhs
--- a/Orthogonals.lhs
+++ b/Orthogonals.lhs
@@ -3,1857 +3,1864 @@
 <BASE HREF="http://www.numeric-quest.com/haskell/Orthogonals.html">
 
 <title>
-	Indexless linear algebra algorithms
-</title>
-</head>
-<body>
-<ul>
-<center>
-<h1>
-			***
-</h1>
-<h1>
-	Indexless linear algebra algorithms
-</h1>
-<b>
-<br>
-	Orthogonalization, linear equations, eigenvalues and eigenvectors
-<br>
-	Literate Haskell module <i>Orthogonals.lhs</i>
-</b>
-<p>
-	Jan Skibinski, <a href="http://www.numeric-quest.com/news/">
-	Numeric Quest Inc.</a>, Huntsville, Ontario, Canada
-<p>
-	1998.09.19, last modified 1998.12.28
-</center>
-<hr>
-<p>
-	It has been argued that the functional paradigm offers more
-	support for scientific computing than the traditional imperative
-	programming, such as greater similarity of functional implementation
-	to mathematical specification of a problem. However, efficiency
-	of scientific algorithms implemented in Haskell is very low compared
-	to efficiencies of C or Fortran implementations - notwithstanding
-	the exceptional descriptive power of Haskell.
-<dd>
-	It has been also argued that tradition and inertia are partially
-	responsible for this sore state and that many functional algorithms
-	are direct translations of their imperative counterparts.
-<dd>
-	Arrays - with their indexing schemes and destructive updating
-	are basic tools of imperative programming. But pure functional
-	languages, which prohibit variable reassignments, cannot compete
-	with imperative languages by using the same tools and following
-	similar reasoning and patterns - unless the functional arrays
-	themselves are designed with performance in mind. This is
-	a case with Clean, where efficiency of one kind of their arrays
-	-- strict unboxed array, approaches efficiency of C.
-<dd>
-	But this has not been done for Haskell arrays yet. They are
-	lazy, boxed and use auxilliary association lists (index, value)
-	for initialization -- the latter being mostly responsible for
-	low efficiency of those algorithms that create many interim
-	arrays.
-<dd>
-	It appears, that -- as long as indexing scheme is not used
-	for lookups and updates -- Haskell lists are more efficient
-	than arrays -- at least at the currents state of Haskell.
-<p>
-	With this in mind, we are attempting to demonstrate here
-	that the indexing traps can be successfully avoided.
-	This module implements afresh several typical problems from linear
-	algebra. Standard Haskell lists are employed instead of arrays
-	and not a single algorithm ever uses indices for lookups
-	or updates.
-<dd>
-	We do not claim high efficiency of these algorithms; consider
-	them exploratory. However, we do claim that the clarity of
-	these algorithms is significantly better than of those functionally
-	similar algorithms that employ indexing schemes.
-<p>
-	Two major algorithms have been invented and implemented in Haskell:
-	one for solving systems of linear equations and one for finding
-	eigenvalues and eigenvectors of almost any type of a square matrix.
-	This includes symmetric, hermitian, general complex or nonsymmetric
-	matrices with real eigenvalues.
-<dd>
-	Amazingly, both methods are based on the same factorization, akin
-	to QR method, but not exactly the same as the standard QR one.
-	A simple trick allows to extend this method to nonsymmetric real
-	matrices with complex eigenvalues and thus one method applies to
-	all types of matrices.
-	It follows that the eigenvalue/eigenvector problem can be consistently
-	treated all across the board. In addition, no administrative
-	(housekeeping) boring trivia is required here and that helps to
-	clearly explain the mechanisms employed.
-
-</i>
-<p>
-<hr>
-<p>
-<b>
-	Contents
-</b>
-<p>
-<ul>
-<p><li>
-	Notation
-<p><li>
-	Scalar products and vector normalization
-<ul>
-<li><b>
-	    bra_ket</b>, scalar product
-<li><b>
-	    sum_product</b>, a cousin of bra_ket
-<li><b>
-	    norm</b>, vector norm
-<li><b>
-	    normalized</b>, vector normalized to one
-</ul>
-<p><li>
-	Transposition and adjoining of matrices
-<ul>
-<li><b>
-	    transposed</b>, transposed matrix
-<li><b>
-	    adjoint</b>, transposed and conjugated matrix
-</ul>
-<p><li>
-	Products involving matrices
-<ul>
-<li><b>
-	    matrix_matrix</b>, product of two matrices as list of rows
-<li><b>
-	    matrix_matrix'</b>, product of two matrices as list of columns
-<li><b>
-	    triangle_matrix'</b>, upper triangular matrix times square matrix
-<li><b>
-	    matrix_ket</b>, matrix times ket vector
-<li><b>
-	    bra_matrix</b>, bra vector times matrix
-<li><b>
-	    bra_matrix_ket</b>, matrix multiplied on both sides by vectors
-<li><b>
-	    scalar_matrix</b>, scalar times matrix
-</ul>
-<p><li>
-	Orthogonalization process
-<ul>
-<li><b>
-	    orthogonals</b>, set of orthogonal vectors
-<li><b>
-	    gram_schmidt</b>, vector perpendicular to a hyperplane
-</ul>
-
-<p><li>
-	Solutions of linear equations by orthogonalization
-<ul>
-<li><b>
-	    one_ket_triangle</b>, triangularization of one vector equation
-<li><b>
-	    one_ket_solution</b>, solution for one unknown vector
-<li><b>
-	    many_kets_triangle</b>, triangularization of several vector equations
-<li><b>
-	    many_kets_solution</b>, solution for several unknown vectors
-</ul>
-<p><li>
-	Matrix inversion
-<ul>
-<li><b>
-	    inverse</b>, inverse of a matrix
-</ul>
-<p><li>
-	QR factorization of matrices provided by "many_kets_triangle"
-<ul>
-<li><b>
-	    factors_QR</b>, QR alike factorization of matrices
-<li><b>
-	    determinant</b>, computation of the determinant based on the QR factorization
-</ul>
-<p><li>
-	Similarity transformations and eigenvalues
-<ul>
-<li><b>
-	    similar_to</b>, matrix obtained by similarity transformation
-<li><b>
-	    iterated_eigenvalues</b>, list of approximations of eigenvalues
-<li><b>
-	    eigenvalues</b>, final approximation of eigenvalues
-</ul>
-<p><li>
-	Preconditioning of real nonsymmetric matrices
-<ul>
-<li><b>
-	    add_to_diagonal</b>, simple preconditioning method
-</ul>
-<p><li>
-	Examples of iterated eigenvalues
-<ul>
-<li>
-	    Symmetric real matrix
-<li>
-	    Hermitian complex matrix
-<li>
-	    General complex matrix
-<li>
-	    Nonsymmetric real matrix with real eigenvalues
-<li>
-	    Nonsymmetric real matrix with complex eigenvalues
-</ul>
-<p><li>
-	Eigenvectors for distinct eigenvalues
-<ul>
-<li><b>
-		eigenkets</b>, eigenvectors for distinct eigenvalues
-</ul>
-<p><li>
-	Eigenvectors for degenerated eigenvalues
-<ul>
-<li><b>
-		eigenket'</b>, eigenvector based on a trial vector
-</ul>
-
-<p><li>
-	Auxiliary functions
-<ul>
-<li><b>
-	unit_matrix</b>, a unit matrix with 1's on a diagonal
-<li><b>
-	unit_vector</b>, a vector with one non-zero componenet
-<li><b>
-	diagonals</b>, vector made of a matrix diagonal
-</ul>
-</ul>
-
-<p>
-<hr>
-<p>
-<b>
-	Notation
-</b>
-<p>
-	What follows is written in Dirac's notation, as used
-	in Quantum Mechanics. Matrices are represented by capital
-	letters, while vectors come in two varieties:
-<ul>
-<p><li>
-	Bra vector x, written &lt; x |, is represented by one-row matrix
-<p><li> Ket vector y, written | y &gt;, is represented by one-column matrix
-</ul>
-<p>
-	Bra vectors can be obtained from ket vectors by transposition
-	and conjugation of their components. Conjugation is only
-	important for complex vectors.
-<p>
-	Scalar product of two vectors | x &gt; and | y &gt; is written
-	as
-<pre>
-	< x | y >
-</pre>
-	which looks like a bracket and is sometimes called a "bra_ket".
-	This justifies "bra" and "ket" names introduced by Dirac. There
-	is a good reason for conjugating the components of "bra-vector":
-	the scalar product of
-<pre>
-	< x | x >
-</pre>
-	should be a square of the norm of the vector "x", and that
-	means that it should be represented by a real number, or complex
-	number but with its imaginary part equal to zero.
-<p>
-<hr>
-<p>
-<pre>
-
-> module Orthogonals where
-> import Complex
-> import Ratio
-> import qualified List
-
-</pre>
-<b>
-	Scalar product and vector normalization
-</b>
-<p>
-	The scalar product "bra_ket" is a basis of many algorithms
-	presented here.
-
-
-<pre>
-
-> bra_ket :: (Scalar a, Num a) => [a] -> [a] -> a
-> bra_ket u v =
->       --
->       -- Scalar product of two vectors u and v,
->       -- or < u | v > in Dirac's notation.
->       -- This is equally valid for both: real and complex vectors.
->       --
->       sum_product u (map coupled v)
-
-</pre>
-
-	Notice the call to function "coupled" in the above implementation
-	of scalar product. This function conjugates its argument
-	if it is complex, otherwise does not change it. It is defined
-	in the class Scalar - specifically designed for this purpose
-	mainly.
-<dd>
-	This class also defines a norm of a vector that might be used
-	by some algorithms. So far we have been able to avoid this.
-<pre>
-
-> class Scalar a where
->     coupled    :: a->a
->     norm       :: [a] -> a
->     almostZero :: a -> Bool
->     scaled     :: [a] -> [a]
-
-> instance Scalar Double where
->     coupled x    = x
->     norm u       = sqrt (bra_ket u u)
->     almostZero x = (abs x) < 1.0e-8
->     scaled       = scaled'
-
-> instance Scalar Float where
->    coupled x    = x
->    norm u       = sqrt (bra_ket u u)
->    almostZero x = (abs x) < 1.0e-8
->    scaled       = scaled'
-
-> instance (Integral a) => Scalar (Ratio a) where
->     coupled x    = x
->     -- norm u    = fromDouble ((sqrt (bra_ket u u))::Double)
->     -- Intended hack to silently convert to and from Double.
->     -- But I do not know how to declare it properly.
->     --
->     -- Our type Fraction, when used instead of Ratio a, has its own
->     -- definition of sqrt. No hack would be needed here.
->     almostZero x = abs x < 1e-8
->     scaled       = scaled'
-
-> instance (RealFloat a) => Scalar (Complex a) where
->     coupled (x:+y) = x:+(-y)
->     norm u         = sqrt (realPart (bra_ket u u)) :+ 0
->     almostZero z   = (realPart (abs z)) < 1.0e-8
->     scaled u       = [(x/m):+(y/m) | x:+y <- u]
->        where m = maximum [max (abs x) (abs y) | x:+y <- u]
-
-> norm1 :: (Num a) => [a] -> a
-> norm1 = sum . map abs
-
-> norminf :: (Num a, Ord a) => [a] -> a
-> norminf = maximum . map abs
-
-> matnorm1 :: (Num a, Ord a) => [[a]] -> a
-> matnorm1 = matnorminf . transposed
-
-> matnorminf :: (Num a, Ord a) => [[a]] -> a
-> matnorminf = maximum . map norm1
-
-
-</pre>
-
-	But we also need a slightly different definition of
-	scalar product that will appear in multiplication of matrices
-	by vectors (or vice versa): a straightforward accumulated product
-	of two lists, where no complex conjugation takes place.
-	We will call it a 'sum_product".
-<pre>
-
-> sum_product :: Num a => [a] -> [a] -> a
-> sum_product u v =
->       --
->       -- Similar to scalar product but without
->       -- conjugations of | u > components
->       -- Used in matrix-vector or vector-matrix products
->       --
->       sum (zipWith (*) u v)
-
-</pre>
-	Some algorithms might need vectors normalized to one, although
-	we'll try to avoid the normalizations due to its high cost
-	or its inapplicability to rational numbers. Instead, we wiil
-	scale vectors by their maximal components.
-<pre>
-
-> normalized :: (Scalar a, Fractional a) => [a] -> [a]
-> normalized u =
->       [uk/n | uk <- u]
->       where
->           n = norm u
-
-> scaled' u =
->       [uk/um | uk <- u]
->       where
->           um = maximum [abs uk| uk <- u]
-
-</pre>
-<hr>
-<p>
-<b>
-	Transposition and adjoining of matrices
-</b>
-<p>
-	Matrices are represented here by lists of lists.
-	Function "transposed" converts from row-wise to column-wise
-	representation, or vice versa.
-<dd>
-	When transposition is combined with complex conjugation
-	the resulting matrix is called "adjoint".
-<p>
-	A square matrix is called symmetric if it is equal to its transpose
-<pre>
-	A = A<sup>T</sup>
-</pre>
-	It is called Hermitian, or self-adjoint, if it equals to
-	its adjoint
-<pre>
-	A = A<sup>+</sup>
-
-> transposed :: [[a]] -> [[a]]
-> transposed a
->     | null (head a) = []
->     | otherwise = ([head mi| mi <- a])
->                   :transposed ([tail mi| mi <- a])
-
-> adjoint :: Scalar a => [[a]] -> [[a]]
-> adjoint a
->     | null (head a) = []
->     | otherwise = ([coupled (head mi)| mi <- a])
->                   :adjoint ([tail mi| mi <- a])
-
-</pre>
-<p>
-<hr>
-<p>
-<b>
-	Linear combination and sum of two matrices
-</b>
-<p>
-	One can form a linear combination of two matrices, such
-	as
-<pre>
-	C = alpha A + beta B
-	where
-	    alpha and beta are scalars
-</pre>
-	The most generic form of any combination, not necessary
-	linear, of components of two matrices is given by "matrix_zipWith"
-	function below, which accepts a function "f" describing such
-	combination. For the linear combination with two scalars
-	the function "f" could be defined as:
-<pre>
-	f alpha beta a b = alpha*a + beta*b
-</pre>
-	For a straightforward addition of two matrices this auxiliary
-	function is simply "(+)".
-<pre>
-
-> matrix_zipWith f a b =
->     --
->     -- Matrix made of a combination
->     -- of matrices a and b - as specified by f
->     --
->     [zipWith f ak bk | (ak,bk) <- zip a b]
-
-> add_matrices a b = matrix_zipWith (+)
-
-</pre>
-
-<p>
-<hr>
-<p>
-<b>
-	Products involving matrices
-</b>
-<p>
-	Variety of products involving matrices can be defined.
-	Our Haskell implementation is based on lists of lists
-	and therefore is open to interpretation: sublists
-	can either represent the rows or the columns of a matrix.
-<dd>
-	The following definitions are somehow arbitrary, since
-	one can choose alternative interpretations of lists
-	representing matrices.
-<p>
-<b>
-	C = A B
-</b>
-<p>
-	Inner product of two matrices A B can be expressed quite simply,
-	providing that matrix A is represented by a list of rows
-	and B - by a list of columns. Function "matrix_matrix"
-	answers list of rows, while "matrix_matrix'" - list
-	of columns.
-<dd>
-	Major algorithms of this module make use of "triangle_matrix'",
-	which calculates a product of upper triangular matrix
-	with square matrix and returns a rectangular list of columns.
-
-<pre>
-
-> matrix_matrix :: Num a => [[a]] -> [[a]] -> [[a]]
-> matrix_matrix a b
-> --
-> -- A matrix being an inner product
-> -- of matrices A and B, where
-> --     A is represented by a list of rows a
-> --     B is represented by a list of columns b
-> --     result is represented by list of rows
-> -- Require: length of a is equal of length of b
-> -- Require: all sublists are of equal length
->
->       | null a = []
->       | otherwise = ([sum_product (head a) bi | bi <- b])
->                  : matrix_matrix (tail a) b
-
-> matrix_matrix' a b
->       --
->       -- Similar to "matrix_matrix"
->       -- but the result is represented by
->       -- a list of columns
->       --
->       | null b = []
->       | otherwise = ([sum_product ai (head b) | ai <- a])
->                    : matrix_matrix' a (tail b)
-
-
-> triangle_matrix' :: Num a => [[a]] -> [[a]] -> [[a]]
-> triangle_matrix' r q =
->       --
->       -- List of columns of of a product of
->       -- upper triangular matrix R and square
->       -- matrix Q
->       -- where
->       --     r is a list of rows of R
->       --     q is a list of columns of A
->       --
->       [f r qk | qk <- q]
->       where
->           f t u
->               | null t = []
->               | otherwise = (sum_product (head t) u)
->                             : (f (tail t) (tail u))
-
-
-
-</pre>
-<b>
-	| u &gt; = A | v &gt;
-</b>
-<p>
-	Product of a matrix and a ket-vector is another
-	ket vector. The following implementation assumes
-	that list "a" represents rows of matrix A.
-<pre>
-
-> matrix_ket :: Num a => [[a]] -> [a] -> [a]
-> matrix_ket a v = [sum_product ai v| ai <- a]
-
-</pre>
-<b>
-	&lt; u | = &lt; v | A
-</b>
-<p>
-	Bra-vector multiplied by a matrix produces
-	another bra-vector. The implementation below
-	assumes that list "a" represents columns
-	of matrix A. It is also assumed that vector
-	"v" is given in its standard "ket" representation,
-	therefore the definition below uses "bra_ket"
-	instead of "sum_product".
-<pre>
-
-> bra_matrix :: (Scalar a, Num a) => [a] -> [[a]] -> [a]
-> bra_matrix v a = [bra_ket v ai | ai <- a]
-
-</pre>
-<b>
-	alpha = &lt; u | A | v &gt;
-</b>
-<p>
-	This kind of product results in a scalar and is often
-	used to define elements of a new matrix, such as
-<pre>
-	B[i,j] = < ei | A | ej >
-</pre>
-	The implementation below assumes that list "a" represents
-	rows of matrix A.
-<pre>
-
-> bra_matrix_ket :: (Scalar a, Num a) => [a] -> [[a]] -> [a] -> a
-> bra_matrix_ket u a v =
->     bra_ket u (matrix_ket a v)
-
-</pre>
-<b>
-	B = alpha A
-</b>
-<p>
-	Below is a function which multiplies matrix by a scalar:
-<pre>
-
-> scalar_matrix :: Num a => a -> [[a]] -> [[a]]
-> scalar_matrix alpha a =
->       [[alpha*aij| aij <- ai] | ai<-a]
-
-</pre>
-<p>
-<hr>
-<p>
-<b>
-	Orthogonalization process
-</b>
-<p>
-
-	Gram-Schmidt orthogonalization procedure is used here
-	for calculation of sets of mutually orthogonal vectors.
-<dd>
-	Function "orthogonals" computes a set of mutually orthogonal
-	vectors - all orthogonal to a given vector. Such set plus
-	the input vector form a basis of the vector space. Another
-	words, they are the base vectors, although we cannot call them
-	unit vectors since we do not normalize them for two reasons:
-<ul>
-<li>
-	None of the algorithms presented here needs this -- quite
-	costly -- normalization.
-<li>
-	Some algorithms can be used either with doubles or with
-	rationals. The neat output of the latter is sometimes desirable
-	for pedagogical or accuracy reasons. But normalization requires "sqrt"
-	function, which is not defined for rational numbers. We could
-	use our module Fraction instead, where "sqrt" is defined,
-	but we'll leave it for a future revision of this module.
-</ul>
-<p>
-	Function "gram_schmidt" computes one vector - orthogonal
-	to an incomplete set of orthogonal vectors, which form a hyperplane
-	in the vector space. Another words, "gram_schmidt" vector is
-	perpendicular to such a hyperlane.
-
-
-<pre>
-
-> orthogonals :: (Scalar a, Fractional a) => [a] -> [[a]]
-> orthogonals x =
->       --
->       -- List of (n-1) linearly independent vectors,
->       -- (mutually orthogonal) and orthogonal to the
->       -- vector x, but not normalized,
->       -- where
->       --     n is a length of x.
->       --
->       orth [x] size (next (-1))
->       where
->           orth a n m
->               | n == 1        = drop 1 (reverse a)
->               | otherwise     = orth ((gram_schmidt a u ):a) (n-1) (next m)
->               where
->                   u = unit_vector m size
->           size = length x
->           next i = if (i+1) == k then (i+2) else (i+1)
->           k = length (takeWhile (== 0) x) -- first non-zero component of x
-
-> gram_schmidt :: (Scalar a, Fractional a) => [[a]] -> [a] -> [a]
-> gram_schmidt a u =
->       --
->       -- Projection of vector | u > on some direction
->       -- orthogonal to the hyperplane spanned by the list 'a'
->       -- of mutually orthogonal (linearly independent)
->       -- vectors.
->       --
->       gram_schmidt' a u u
->       where
->           gram_schmidt' a u v
->               | null a       = v
->               | all (== 0) e = gram_schmidt' (tail a) u v
->               | otherwise    = gram_schmidt' (tail a) u v'
->               where
->                   v' = vectorCombination v (-(bra_ket e u)/(bra_ket e e)) e
->                   e  = head a
->           vectorCombination x c y
->               | null x = []
->               | null y = []
->               | otherwise = (head x + c * (head y))
->                             : (vectorCombination (tail x) c (tail y))
-
-</pre>
-<p>
-<hr>
-<p>
-<b>
-	Solutions of linear equations by orthogonalization
-</b>
-<p>
-	A matrix equation for unknown vector | x &gt;
-<pre>
-	A | x > = | b >
-</pre>
-	can be rewritten as
-<pre>
-	x1 | 1 > + x2 | 2 > + x3 | 3 > + ... + xn | n > = | b >     (7.1)
-	where
-		| 1 >, | 2 >... represent columns of the matrix A
-</pre>
-	For any n-dimensional vector, such as "1", there exist
-	n-1 linearly independent vectors "ck" that are orthogonal to "1";
-	that is, each satisfies the relation:
-<pre>
-	< ck | 1 > = 0, for k = 1...m, where m = n - 1
-</pre>
-	If we could find all such vectors, then we could multiply
-	the equation (7.1) by each of them, and end up with m = n-1
-	following equations
-<pre>
-	< c1 | 2 > x2 + < c1 | 3 > x3 + ... < c1 | n > xn = < c1 | b >
-	< c2 | 2 > x2 + < c2 | 3 > x3 + ... < c2 | n > xn = < c2 | b >
-	.......
-	< cm | 2 > x2 + < cm | 3 > x3 + ... < cm | n > xn = < cm | b >
-</pre>
-	But the above is nothing more than a new matrix equation
-<pre>
-	A' | x' > = | b' >
-	or
-
-	x2 | 2'> + x3 | 3'> .... + xn | n'> = | b'>
-	where
-	    primed vectors | 2' >, etc. are the columns of the new
-	    matrix A'.
-</pre>
-	with the problem dimension reduced by one.
-
-<dd>
-	Taking as an example a four-dimensional problem and writing
-	down the successive transformations of the original equation
-	we will end up with the following triangular pattern made of
-	four vector equations:
-
-<pre>
-	x1 | 1 > + x2 | 2 > + x3 | 3 >  + x4 | 4 >   = | b >
-		   x2 | 2'> + x3 | 3'>  + x4 | 4'>   = | b'>
-			      x3 | 3''> + x4 | 4''>  = | b''>
-					  x4 | 4'''> = | b'''>
-</pre>
-	But if we premultiply each vector equation by a non-zero vector
-	of our choice, say &lt; 1 | , &lt; 2' |, &lt; 3'' |, and &lt; 4''' | - chosen
-	correspondingly for equations 1, 2, 3 and 4, then the above
-	system of vector equations will be converted to much simpler
-	system of scalar equations. The result is
-	shown below in matrix representation:
-
-<pre>
-	| p11  p12   p13   p14 | | x1 | = | q1 |
-	| 0    p22   p23   p24 | | x2 | = | q2 |
-	| 0    0     p33   p34 | | x3 | = | q3 |
-	| 0    0     0     p44 | | x4 | = | q4 |
-</pre>
-	In effect, we have triangularized our original matrix A.
-	Below is a function that does that for any problem size:
-<pre>
-
-> one_ket_triangle :: (Scalar a, Fractional a) => [[a]] -> [a] -> [([a],a)]
-> one_ket_triangle a b
->     --
->     -- List of pairs: (p, q) representing
->     -- rows of triangular matrix P and of vector | q >
->     -- in the equation P | x > = | q >, which
->     -- has been obtained by linear transformation
->     -- of the original equation A | x > = | b >
->     --
->     | null a = []
->     | otherwise = (p,q):(one_ket_triangle a' b')
->     where
->         p    = [bra_ket u ak | ak <- a]
->         q    = bra_ket u b
->         a'   = [[bra_ket ck ai | ck <- orth] | ai <- v]
->         b'   = [ bra_ket ck b  | ck <- orth]
->         orth = orthogonals u
->         u    = head a
->         v    = tail a
-
-</pre>
-	The triangular system of equations can be easily solved by
-	successive substitutions - starting with the last equation.
-
-<pre>
-
-> one_ket_solution :: (Fractional a, Scalar a) => [[a]] -> [a] -> [a]
-> one_ket_solution a b =
->     --
->     -- List representing vector |x>, which is
->     -- a solution of the matrix equation
->     --     A |x> = |b>
->     -- where
->     --     a is a list of columns of matrix A
->     --     b is a list representing vector |b>
->     --
->     solve' (unzip (reverse (one_ket_triangle a b))) []
->     where
->         solve' (a, b) xs
->             | null a  = xs
->             | otherwise = solve' ((tail a), (tail b)) (x:xs)
->             where
->                 x = (head b - (sum_product (tail u) xs))/(head u)
->                 u = head a
-
-</pre>
-	The triangularization procedure can be easily extended
-	to a list of several ket-vectors | b &gt; on the right hand
-	side of the original equation A | x &gt; = | b &gt; -- instead
-	of just one:
-<pre>
-
-> many_kets_triangle :: (Scalar a, Fractional a) => [[a]] -> [[a]] -> [([a],[a])]
-> many_kets_triangle a b
->     --
->     -- List of pairs: (p, q) representing
->     -- rows of triangular matrix P and of rectangular matrix Q
->     -- in the equation P X = Q, which
->     -- has been obtained by linear transformation
->     -- of the original equation A X = B
->     -- where
->     --     a is a list of columns of matrix A
->     --     b is a list of columns of matrix B
->     --
->     | null a = []
->     | otherwise = (p,q):(many_kets_triangle a' b')
->     where
->         p    = [bra_ket u ak   | ak <- a]
->         q    = [bra_ket u bk   | bk <- b]
->         a'   = [[bra_ket ck ai | ck <- orth] | ai <- v]
->         b'   = [[bra_ket ck bi | ck <- orth] | bi <- b]
->         orth = orthogonals u
->         u    = head a
->         v    = tail a
-
-</pre>
-	Similarly, function 'one_ket_solution' can be generalized
-	to function 'many_kets_solution' that handles cases with
-	several ket-vectors on the right hand side.
-<pre>
-
-> many_kets_solution a b =
->     --
->     -- List of columns of matrix X, which is
->     -- a solution of the matrix equation
->     --     A X = B
->     -- where
->     --     a is a list of columns of matrix A
->     --     b is a list of columns of matrix B
->     --
->     solve' p q emptyLists
->     where
->         (p, q) = unzip (reverse (many_kets_triangle a b))
->         emptyLists = [[] | k <- [1..(length (head q))]]
->         solve' a' b' x
->             | null a'  = x
->             | otherwise = solve' (tail a') (tail b')
->                                 [(f vk xk):xk  | (xk, vk) <- (zip x v)]
->             where
->                 f vk xk = (vk - (sum_product (tail u) xk))/(head u)
->                 u = head a'
->                 v = head b'
-
-
-</pre>
-<p>
-<hr>
-<p>
-<b>
-	Matrix inversion
-</b>
-<p>
-	Function 'many_kets_solution' can be used to compute
-	inverse of matrix A by specializing matrix B to a unit
-	matrix I:
-<pre>
-
-	A X = I
-</pre>
-	It follows that matrix X is an inverse of A; that is X = A<sup>-1</sup>.
-<pre>
-
-> inverse :: (Scalar a, Fractional a) => [[a]] -> [[a]]
-> inverse a = many_kets_solution a (unit_matrix (length a))
->       --
->       -- List of columns of inverse of matrix A
->       -- where
->       --     a is list of columns of A
-
-</pre>
-<p>
-<hr>
-<p>
-<b>
-	QR factorization of matrices
-</b>
-<p>
-	The process described above and implemented by
-	'many_kets_triangle' function transforms the equation
-<pre>
-	A X = B
-</pre>
-	into another equation for the same matrix X
-<pre>
-	R X = S
-</pre>
-	where R is an upper triangular matrix. All operations
-	performed on matrices A and B during this process are linear,
-	and therefore we should be able to find a square matrix Q
-	that describes the entire process in one step. Indeed, assuming
-	that matrix A can be decomposed as a product of unknown matrix Q
-	and triangular matrix R and that Q<sup>-1</sup> is an inverse of matrix Q
-	we can reach the last equation by following these steps:
-<pre>
-	A X       = B
-	(Q R) X   = B
-	Q<sup>-1</sup> Q R X = Q<sup>-1</sup> B
-	R X       = S
-</pre>
-	It follows that during this process a given matrix B
-	transforms to matrix S, as delivered by 'many_kets_triangle':
-<pre>
-	S = Q<sup>-1</sup> B
-</pre>
-	from which the inverse of Q can be found:
-<pre>
-	Q<sup>-1</sup> = S B<sup>-1</sup>
-</pre>
-	Having a freedom of choice of the right hand side matrix B
-	we can choose the unit matrix I in place of B, and therefore
-	simplify the definition of Q<sup>-1</sup>:
-<pre>
-	Q<sup>-1</sup> = S,  if B is unit matrix
-</pre>
-	It follows that any non-singular matrix A can be decomposed
-	as a product of a matrix Q and a triangular matrix R
-
-<pre>
-	A = Q R
-</pre>
-	where matrices Q<sup>-1</sup> and R are delivered by "many_kets_triangle"
-	as a result of triangularization process of equation:
-<pre>
-	A X = I
-</pre>
-	The function below extracts a pair of matrices Q and R
-	from the answer provided by "many_kets_triangle".
-	During this process it inverts matrix Q<sup>-1</sup> to Q.
-	This factorization will be used by a sequence of similarity
-	transformations to be defined in the next section.
-
-<pre>
-
-> factors_QR :: (Fractional a, Scalar a) => [[a]] -> ([[a]],[[a]])
-> factors_QR a =
->       --
->       -- A pair of matrices (Q, R), such that
->       -- A = Q R
->       -- where
->       --     R is upper triangular matrix in row representation
->       --     (without redundant zeros)
->       --     Q is a transformation matrix in column representation
->       --     A is square matrix given as columns
->       --
->       (inverse (transposed q1),r)
->       where
->           (r, q1) = unzip (many_kets_triangle a (unit_matrix (length a)))
-
-</pre>
-
-<p>
-<hr>
-<p>
-<b>
-	Computation of the determinant
-</b>
-
-<!-- added by Henning Thielemann -->
-
-<pre>
-
-> determinant :: (Fractional a, Scalar a) => [[a]] -> a
-> determinant a =
->    let (q,r) = factors_QR a
->    -- matrix Q is not normed so we have to respect the norms of its rows
->    in  product (map norm q) * product (map head r)
-
-</pre>
-
-Naive division-free computation of the determinant by expanding the first column.
-It consumes n! multiplications.
-
-<pre>
-
-> determinantNaive :: (Num a) => [[a]] -> a
-> determinantNaive [] = 1
-> determinantNaive m  =
->    sum (alternate
->       (zipWith (*) (map head m)
->           (map determinantNaive (removeEach (map tail m)))))
-
-</pre>
-
-Compute the determinant with about n^4 multiplications
-without division according to the clow decomposition algorithm
-of Mahajan and Vinay, and Berkowitz
-as presented by Günter Rote:
-<a href="http://page.inf.fu-berlin.de/~rote/Papers/pdf/Division-free+algorithms.pdf">
-Division-Free Algorithms for the Determinant and the Pfaffian:
-Algebraic and Combinatorial Approaches</a>.
-
-<pre>
-
-> determinantClow :: (Num a) => [[a]] -> a
-> determinantClow [] = 1
-> determinantClow m =
->    let lm = length m
->    in  parityFlip lm (last (newClow m
->           (nest (lm-1) (longerClow m)
->               (take lm (iterate (0:) [1])))))
-
-</pre>
-
-Compute the weights of all clow sequences
-where the last clow is closed and a new one is started.
-
-<pre>
-
-> newClow :: (Num a) => [[a]] -> [[a]] -> [a]
-> newClow a c =
->    scanl (-) 0
->          (sumVec (zipWith (zipWith (*)) (List.transpose a) c))
-
-</pre>
-
-Compute the weights of all clow sequences
-where the last (open) clow is extended by a new arc.
-
-<pre>
-
-> extendClow :: (Num a) => [[a]] -> [[a]] -> [[a]]
-> extendClow a c =
->    map (\ai -> sumVec (zipWith scaleVec ai c)) a
-
-</pre>
-
-Given the matrix of all weights of clows of length l
-compute the weight matrix for all clows of length (l+1).
-Take the result of 'newClow' as diagonal
-and the result of 'extendClow' as lower triangle
-of the weight matrix.
-
-<pre>
-
-> longerClow :: (Num a) => [[a]] -> [[a]] -> [[a]]
-> longerClow a c =
->    let diagonal = newClow a c
->        triangle = extendClow a c
->    in  zipWith3 (\i t d -> take i t ++ [d]) [0 ..] triangle diagonal
-
-</pre>
-
-Auxiliary functions for the clow determinant.
-
-<pre>
-
-> {- | Compositional power of a function,
->      i.e. apply the function n times to a value. -}
-> nest :: Int -> (a -> a) -> a -> a
-> nest 0 _ x = x
-> nest n f x = f (nest (n-1) f x)
->
-> {- successively select elements from xs and remove one in each result list -}
-> removeEach :: [a] -> [[a]]
-> removeEach xs =
->    zipWith (++) (List.inits xs) (tail (List.tails xs))
->
-> alternate :: (Num a) => [a] -> [a]
-> alternate = zipWith id (cycle [id, negate])
->
-> parityFlip :: Num a => Int -> a -> a
-> parityFlip n x = if even n then x else -x
->
-> {-| Weight a list of numbers by a scalar. -}
-> scaleVec :: (Num a) => a -> [a] -> [a]
-> scaleVec k = map (k*)
->
-> {-| Add corresponding numbers of two lists. -}
-> {- don't use zipWith because it clips to the shorter list -}
-> addVec :: (Num a) => [a] -> [a] -> [a]
-> addVec x [] = x
-> addVec [] y = y
-> addVec (x:xs) (y:ys) = x+y : addVec xs ys
->
-> {-| Add some lists. -}
-> sumVec :: (Num a) => [[a]] -> [a]
-> sumVec = foldl addVec []
-
-</pre>
-
-
-
-<p>
-<hr>
-<p>
-<b>
-	Similarity transformations and eigenvalues
-</b>
-<p>
-	Two n-square matrices A and B are called similar if there
-	exists a non-singular matrix S such that:
-<pre>
-	B = S<sup>-1</sup> A S
-</pre>
-
-	It can be proven that:
-<ul>
-<li>
-	Any two similar matrices have the same eigenvalues
-<li>
-	Every n-square matrix A is similar to a triangular matrix
-	whose diagonal elements are the eigenvalues of A.
-</ul>
-<p>
-	If matrix A can be transformed to a triangular or a diagonal
-	matrix Ak by a sequence of similarity transformations then
-	the eigenvalues of matrix A are the diagonal elements of Ak.
-
-<p>
-
-	Let's construct the sequence of matrices similar to A
-<pre>
-	A, A1, A2, A3...
-</pre>
-	by the following iterations - each of which factorizes a matrix
-	by applying the function 'factors_QR' and then forms a product
-	of the factors taken in the reverse order:
-<pre>
-	A = Q R          = Q (R Q) Q<sup>-1</sup>    = Q A1 Q<sup>-1</sup>        =
-	  = Q (Q1 R1) Q<sup>-1</sup> = Q Q1 (R1 Q1) Q1<sup>-1</sup> Q<sup>-1</sup> = Q Q1 A2 Q1<sup>-1</sup> Q<sup>-1</sup> =
-	  = Q Q1 (Q2 R2) Q1<sup>-1</sup> Q<sup>-1</sup> = ...
-
-</pre>
-	We are hoping that after some number of iterations some matrix
-	Ak would become triangular and therefore its diagonal
-	elements could serve as eigenvalues of matrix A. As long as
-	a matrix has real eigenvalues only, this method should work well.
-	This applies to symmetric and hermitian matrices. It appears
-	that general complex matrices -- hermitian or not -- can also
-	be handled this way. Even more, this method also works for some
-	nonsymmetric real matrices, which have real eigenvalues only.
-<dd>
-	The only type of matrices that cannot be treated by this algorithm
-	are real nonsymmetric matrices, whose some eigenvalues are complex.
-	There is no operation in the process that converts real elements
-	to complex ones, which could find their way into diagonal
-	positions of a triangular matrix. But a simple preconditioning
-	of a matrix -- described in the next section -- replaces
-	a real matrix by a complex one, whose eigenvalues are related
-	to the eigenvalues of the matrix being replaced. And this allows
-	us to apply the same method all across the board.
-<dd>
-	It is worth noting that a process known in literature as QR
-	factorization is not uniquely defined and different algorithms
-	are employed for this. The algorithms using QR factorization
-	apply only to symmetric or hermitian matrices, and Q matrix
-	must be either orthogonal or unitary.
-<dd>
-	But our transformation matrix Q is not orthogonal nor unitary,
-	although its first row is orthogonal to all other rows. In fact,
-	this factorization is only similar to QR factorization. We just
-	keep the same name to help identify a category of the methods
-	to which it belongs.
-<dd>
-	The same factorization is used for tackling two major problems:
-	solving the systems of linear equations and finding the eigenvalues
-	of matrices.
-<dd>
-	Below is the function 'similar_to', which makes a new matrix that is
-	similar to a given matrix by applying our similarity transformation.
-<dd>
-	Function 'iterated_eigenvalues' applies this transformation n
-	times - storing diagonals of each new matrix as approximations of
-	eigenvalues.
-<dd>
-	Function 'eigenvalues' follows the same process but reports the last
-	approximation only.
-<pre>
-
-
-> similar_to :: (Fractional a, Scalar a) => [[a]] -> [[a]]
-> similar_to a =
->       --
->       -- List of columns of matrix A1 similar to A
->       -- obtained by factoring A as Q R and then
->       -- forming the product A1 = R Q = (inverse Q) A Q
->       -- where
->       --     a is list of columns of A
->       --
->       triangle_matrix' r q
->       where
->           (q,r) = factors_QR a
-
-> iterated_eigenvalues a n
->       --
->       -- List of vectors representing
->       -- successive approximations of
->       -- eigenvalues of matrix A
->       -- where
->       --     a is a list of columns of A
->       --     n is a number of requested iterations
->       --
->       | n == 0 = []
->       | otherwise = (diagonals a)
->                     : iterated_eigenvalues (similar_to a) (n-1)
-
-> eigenvalues a n
->       --
->       -- Eigenvalues of matrix A
->       -- obtained by n similarity iterations
->       -- where
->       --     a are the columns of A
->       --
->       | n == 0    = diagonals a
->       | otherwise = eigenvalues (similar_to a) (n-1)
-
-</pre>
-<p>
-<hr>
-<p>
-<b>
-	Preconditioning of real nonsymmetric matrices
-</b>
-<p>
-	As mentioned above, our QR-like factorization method works
-	well with almost all kind of matrices, but with the exception
-	of a class of real nonsymmetric matrices that have
-	complex eigenvalues.
-<dd>
-	There is no mechanism in that method that would be able to
-	produce complex eigenvalues out of the real components of
-	this type of nonsymmetric matrices. Simple trivial replacement
-	of real components of a matrix by its complex counterparts
-	does not work because zero-valued imaginary components do
-	not contribute in any way to production of nontrivial
-	imaginary components during the factorization process.
-<dd>
-	What we need is a trick that replaces real nonsymmetric matrix
-	by a nontrivial complex matrix in such a way that the results
-	of such replacements could be undone when the series of
-	similarity transformations finally produced the expected
-	effect in a form of a triangular matrix.
-<dd>
-	The practical solution is surprisingly simple:
-	it's suffice to add any complex number, such as "i", to the
-	main diagonal of a matrix, and when triangularization is done
-	-- subtract it back from computed eigenvalues.
-	The explanation follows.
-<p>
-	Consider the eigenproblem for real and nonsymmetric matrix A.
-<pre>
-	A | x > = a | x >
-</pre>
-	Let us now define a new complex matrix B, such that:
-<pre>
-	B = A + alpha I
-	where
-	    I is a unit matrix and alpha is a complex scalar
-</pre>
-	It is obvious that matrices A and B commute; that is:
-<pre>
-	A B = B A
-</pre>
-	It can be proven that if two matrices commute then they
-	have the same eigenvectors. Therefore we can use vector
-	| x &gt; of matrix A as an eigenvector of B:
-<pre>
-	B | x > = b | x >
-	B | x > = A | x > + alpha I | x >
-		= a | x > + alpha | x >
-		= (a + alpha) | x >
-</pre>
-	It follows that eigenvalues of B are related to the eigenvalues
-	of A by:
-<pre>
-	b = a + alpha
-</pre>
-	After eigenvalues of complex matrix B have been succesfully
-	computed, all what remains is to subtract "alpha" from them
-	all to obtain eigenvalues of A. And nothing has to be done
-	to eigenvectors of B - they are the same for A as well.
-	Simple and elegant!
-<p>
-	Below is an auxiliary function that adds a scalar to the
-	diagonal of a matrix:
-
-<pre>
-
-> add_to_diagonal :: Num a => a -> [[a]] -> [[a]]
-> add_to_diagonal alpha a =
->       --
->       -- Add constant alpha to diagonal of matrix A
->       --
->       [f ai ni | (ai,ni) <- zip a [0..(length a -1)]]
->       where
->           f b k = p++[head q + alpha]++(tail q)
->               where
->                   (p,q) = splitAt k b
->
-
-
-</pre>
-<p>
-<hr>
-<p>
-<b>
-	Examples of iterated eigenvalues
-</b>
-<p>
-
-
-	Here is an example of a symmetric real matrix with results
-	of application of function 'iterated_eigenvalues'.
-<pre>
-	| 7  -2  1 |
-	|-2  10 -2 |
-	| 1  -2  7 |
-
-	 [[7.0,     10.0,    7.0],
-	  [8.66667, 9.05752, 6.27582],
-	  [10.7928, 7.11006, 6.09718],
-	  [11.5513, 6.40499, 6.04367],
-	  [11.7889, 6.18968, 6.02142],
-	  [11.8943, 6.09506, 6.01068],
-	  [11.9468, 6.04788, 6.00534],
-	  [11.9733, 6.02405, 6.00267],
-	  [11.9866, 6.01206, 6.00134],
-	  [11.9933, 6.00604, 6.00067],
-	  [11.9966, 6.00302, 6.00034],
-	  [11.9983, 6.00151, 6.00017],
-	  [11.9992, 6.00076, 6.00008],
-	  [11.9996, 6.00038, 6.00004],
-	  [11.9998, 6.00019, 6.00002],
-	  [11.9999, 6.00010, 6.00001],
-	  [11.9999, 6.00005, 6.00001]]
-
-	  The true eigenvalues are:
-	  12, 6, 6
-
-</pre>
-	Here is an example of a hermitian matrix. (Eigenvalues of hermitian
-	matrices are real.) The algorithm works well and converges fast.
-<pre>
-	| 2   0     i|
-	[ 0   1   0  |
-	[ -i  0   2  |
-
-	[[2.8     :+ 0.0, 1.0 :+ 0.0, 1.2     :+ 0.0],
-	 [2.93979 :+ 0.0, 1.0 :+ 0.0, 1.06021 :+ 0.0],
-	 [2.97972 :+ 0.0, 1.0 :+ 0.0, 1.02028 :+ 0.0],
-	 [2.9932  :+ 0.0, 1.0 :+ 0.0, 1.0068  :+ 0.0],
-	 [2.99773 :+ 0.0, 1.0 :+ 0.0, 1.00227 :+ 0.0],
-	 [2.99924 :+ 0.0, 1.0 :+ 0.0, 1.00076 :+ 0.0],
-	 [2.99975 :+ 0.0, 1.0 :+ 0.0, 1.00025 :+ 0.0],
-	 [2.99992 :+ 0.0, 1.0 :+ 0.0, 1.00008 :+ 0.0],
-	 [2.99997 :+ 0.0, 1.0 :+ 0.0, 1.00003 :+ 0.0],
-	 [2.99999 :+ 0.0, 1.0 :+ 0.0, 1.00001 :+ 0.0],
-	 [3.0     :+ 0.0, 1.0 :+ 0.0, 1.0     :+ 0.0],
-	 [3.0     :+ 0.0, 1.0 :+ 0.0, 1.0     :+ 0.0],
-	 [3.0     :+ 0.0, 1.0 :+ 0.0, 1.0     :+ 0.0]]
-
-</pre>
-	Here is another example: this is a complex matrix and it is not
-	even hermitian. Yet, the algorithm still works, although its
-	fluctuates around true values.
-<pre>
-	| 2-i   0      i |
-	| 0     1+i  0   |
-	|   i   0    2-i |
-
-	[[2.0     :+ (-1.33333), 1.0 :+ 1.0, 2.0     :+ (-0.666667)],
-	 [1.89245 :+ (-1.57849), 1.0 :+ 1.0, 2.10755 :+ (-0.421509)],
-	 [1.81892 :+ (-1.80271), 1.0 :+ 1.0, 2.18108 :+ (-0.197289)],
-	 [1.84565 :+ (-1.99036), 1.0 :+ 1.0, 2.15435 :+ (-0.00964242)],
-	 [1.93958 :+ (-2.07773), 1.0 :+ 1.0, 2.06042 :+ 0.0777281],
-	 [2.0173  :+ (-2.06818), 1.0 :+ 1.0, 1.9827  :+ 0.0681793],
-	 [2.04357 :+ (-2.02437), 1.0 :+ 1.0, 1.95643 :+ 0.0243654],
-	 [2.03375 :+ (-1.99072), 1.0 :+ 1.0, 1.96625 :+ (-0.00928429)],
-	 [2.01245 :+ (-1.97875), 1.0 :+ 1.0, 1.98755 :+ (-0.0212528)],
-	 [1.99575 :+ (-1.98307), 1.0 :+ 1.0, 2.00425 :+ (-0.0169263)],
-	 [1.98938 :+ (-1.99359), 1.0 :+ 1.0, 2.01062 :+ (-0.00640583)],
-	 [1.99145 :+ (-2.00213), 1.0 :+ 1.0, 2.00855 :+ 0.00212504],
-	 [1.9968  :+ (-2.00535), 1.0 :+ 1.0, 2.0032  :+ 0.00535265],
-	 [2.00108 :+ (-2.00427), 1.0 :+ 1.0, 1.99892 :+ 0.0042723],
-	 [2.00268 :+ (-2.00159), 1.0 :+ 1.0, 1.99732 :+ 0.00158978],
-	 [2.00213 :+ (-1.99946), 1.0 :+ 1.0, 1.99787 :+ (-0.000541867)],
-	 [2.00079 :+ (-1.99866), 1.0 :+ 1.0, 1.9992  :+ (-0.00133514)],
-	 [1.99973 :+ (-1.99893), 1.0 :+ 1.0, 2.00027 :+ (-0.00106525)],
-	 [1.99933 :+ (-1.9996) , 1.0 :+ 1.0, 2.00067 :+ (-0.000397997)],
-	 [1.99947 :+ (-2.00013), 1.0 :+ 1.0, 2.00053 :+ 0.000134972]]
-
-	 The true eigenvalues are
-	 2 - 2i, 1 + i, 2
-</pre>
-	Some nonsymmetric real matrices have all real eigenvalues and
-	our algorithm still works for such cases. Here is one
-	such an example, which traditionally would have to be treated
-	by one of the Lanczos-like algorithms, specifically designed
-	for nonsymmetric real matrices. Evaluation of
-<br>
-<i>
-	iterated_eigenvalues [[2,1,1],[-2,1,3],[3,1,-1::Double]] 20
-</i>
-<br>
-	gives the following results
-<pre>
-	[[3.0,     -0.70818,-0.291815],
-	 [3.06743, -3.41538, 2.34795],
-	 [3.02238, -1.60013, 0.577753],
-	 [3.00746, -2.25793, 1.25047],
-	 [3.00248, -1.88764, 0.885154],
-	 [3.00083, -2.06025, 1.05943],
-	 [3.00028, -1.97098, 0.970702],
-	 [3.00009, -2.0148,  1.01471],
-	 [3.00003, -1.99268, 0.992648],
-	 [3.00001, -2.00368, 1.00367],
-	 [3.0,     -1.99817, 0.998161],
-	 [3.0,     -2.00092, 1.00092],
-	 [3.0,     -1.99954, 0.99954],
-	 [3.0,     -2.00023, 1.00023],
-	 [3.0,     -1.99989, 0.999885],
-	 [3.0,     -2.00006, 1.00006],
-	 [3.0,     -1.99997, 0.999971],
-	 [3.0,     -2.00001, 1.00001],
-	 [3.0,     -1.99999, 0.999993],
-	 [3.0,     -2.0,     1.0]]
-
-	 The true eigenvalues are:
-	 3, -2, 1
-</pre>
-	Finally, here is a case of a nonsymmetric real matrix with
-	complex eigenvalues:
-<pre>
-	| 2 -3 |
-	| 1  0 |
-</pre>
-	The direct application of "iterated_eigenvalues" would
-	fail to produce expected eigenvalues:
-<pre>
-	1 + i sqrt(2) and 1 - i sqrt (2)
-</pre>
-	But if we first precondition the matrix by adding "i" to its diagonal:
-<pre>
-	| 2+i  -3|
-	| 1     i|
-</pre>
-	and then compute its iterated eigenvalues:
-<br>
-<i>
-	iterated_eigenvalues [[2:+1,1],[-3,0:+1]] 20
-</i>
-<br>
-	then the method will succeed. Here are the results:
-<pre>
-
-	[[1.0     :+ 1.66667, 1.0     :+   0.333333 ],
-	[0.600936 :+ 2.34977, 1.39906 :+ (-0.349766)],
-	[0.998528 :+ 2.59355, 1.00147 :+ (-0.593555)],
-	[1.06991  :+ 2.413,   0.93009 :+ (-0.412998)],
-	[1.00021  :+ 2.38554, 0.99979 :+ (-0.385543)],
-	[0.988004 :+ 2.41407, 1.012   :+ (-0.414074)],
-	[0.999963 :+ 2.41919, 1.00004 :+ (-0.419191)],
-	[1.00206  :+ 2.41423, 0.99794 :+ (-0.414227)],
-	[1.00001  :+ 2.41336, 0.99999 :+ (-0.413361)],
-	[0.999647 :+ 2.41421, 1.00035 :+ (-0.414211)],
-	[0.999999 :+ 2.41436, 1.0     :+ (-0.41436) ],
-	[1.00006  :+ 2.41421, 0.99993 :+ (-0.414214)],
-	[1.0      :+ 2.41419, 1.0     :+ (-0.414188)],
-	[0.99999  :+ 2.41421, 1.00001 :+ (-0.414213)],
-	[1.0      :+ 2.41422, 1.0     :+ (-0.414218)],
-	[1.0      :+ 2.41421, 0.99999 :+ (-0.414213)],
-	[1.0      :+ 2.41421, 1.0     :+ (-0.414212)],
-	[1.0      :+ 2.41421, 1.0     :+ (-0.414213)],
-	[1.0      :+ 2.41421, 1.0     :+ (-0.414213)],
-	[1.0      :+ 2.41421, 1.0     :+ (-0.414213)]]
-</pre>
-	After subtracting "i" from the last result, we will get
-	what is expected.
-
-<p>
-<hr>
-<p>
-<b>
-	Eigenvectors for distinct eigenvalues
-</b>
-<p>
-	Assuming that eigenvalues of matrix A are already found
-	we may now attempt to find the corresponding aigenvectors
-	by solving the following homogeneous equation
-<pre>
-	(A - a I) | x > = 0
-</pre>
-	for each eigenvalue "a". The matrix
-<pre>
-	B = A - a I
-</pre>
-	is by definition singular, but in most cases it can be
-	triangularized by the familiar "factors_QR" procedure.
-<pre>
-	B | x > = Q R | x > = 0
-</pre>
-	It follows that the unknown eigenvector | x &gt; is one of
-	the solutions of the homogeneous equation:
-
-<pre>
-	R | x > = 0
-</pre>
-	where R is a singular, upper triangular matrix with at least one
-	zero on its diagonal.
-<dd>
-	If | x &gt; is a solution we seek, so is its scaled version
-	alpha | x &gt;. Therefore we have some freedom of scaling choice.
-	Since this is a homogeneous equation, one of the components
-	of | x &gt; can be freely chosen, while the remaining components
-	will depend on that choice.
-</pre>
-	To solve the above, we will be working from the bottom up of
-	the matrix equation, as illustrated in the example below:
-<pre>
-	| 0     1     1     3     | | x1 |
-	| 0     1     1     2     | | x2 |      /\
-	| 0     0     2     4     | | x3 | = 0  ||
-	| 0     0     0     0     | | x4 |      ||
-</pre>
-	Recall that the diagonal elements of any triangular matrix
-	are its eigenvalues.
-	Our example matrix has three distinct eigenvalues:
-	0, 1, 2. The eigenvalue 0 has degree of degeneration two.
-	Presence of degenerated eigenvalues complicates
-	the solution process. The complication arises when we have to
-	make our decision about how to solve the trivial scalar equations
-	with zero coefficients, such as
-<pre>
-	0 * x4 = 0
-</pre>
-	resulting from multiplication of the bottom row by vector | x &gt;.
-	Here we have two choices: "x4" could be set to 0, or to any
-	nonzero number 1, say. By always choosing the "0" option
-	we might end up with the all-zero trivial vector --  which is
-	obviously not what we want. Persistent choice of the "1" option,
-	might lead to a conflict between some of the equations, such as
-	the equations one and four in our example.
-<p>
-	So the strategy is as follows.
-<p>
-	If there is at least one zero on the diagonal, find the topmost
-	row with zero on the diagonal and choose for it the solution "1".
-	Diagonal zeros in other rows would force the solution "0".
-	If the diagonal element is not zero than simply solve
-	an arithmetic equation that arises from the substitutions of
-	previously computed components of the eigenvector. Since certain
-	inaccuracies acumulate during QR factorization, set to zero all
-	very small elements of matrix R.
-<p>
-	By applying this strategy to our example we'll end up with the
-	eigenvector
-<pre>
-	< x | = [1, 0, 0, 0]
-</pre>
-
-<p>
-	If the degree of degeneration of an eigenvalue of A is 1 then the
-	corresponding eigenvector is unique -- subject to scaling.
-	Otherwise an eigenvector found by this method is one of many
-	possible solutions, and any linear combination of such solutions
-	is also an eigenvector. This method is not able to find more than one
-	solution for degenerated eigenvalues. An alternative method, which
-	handles degenerated cases, will be described in the next section.
-<p>
-	The function below calculates eigenvectors corresponding to
-	distinct selected eigenvalues of any square matrix A, provided
-	that the singular matrix B = A - a I can still be factorized as Q R,
-	where R is an upper triangular matrix.
-
-<pre>
-
-> eigenkets a u
->       --
->       -- List of eigenkets of a square matrix A
->       -- where
->       --     a is a list of columns of A
->       --     u is a list of eigenvalues of A
->       --     (This list does not need to be complete)
->       --
->       | null u        = []
->       | not (null x') = x':(eigenkets a (tail u))
->       | otherwise     = (eigenket_UT (reverse b) d []):(eigenkets a (tail u))
->       where
->           a'  = add_to_diagonal (-(head u)) a
->           x'  = unit_ket a' 0 (length a')
->           b   = snd (factors_QR a')
->           d   = discriminant [head bk | bk <- b] 1
->           discriminant u n
->               | null u    = []
->               | otherwise = x : (discriminant (tail u) m)
->               where
->                   (x, m)
->                       | (head u) == 0     = (n, 0)
->                       | otherwise         = (n, n)
->           eigenket_UT b d xs
->               | null b   = xs
->               | otherwise = eigenket_UT (tail b) (tail d) (x:xs)
->               where
->                   x = solve_row (head b) (head d) xs
->
->           solve_row u n x
->               | almostZero p = n
->               | otherwise    = q/p
->               where
->                   p = head u
->                   q
->                       | null x = 0
->                       | otherwise = -(sum_product (tail u) x)
->
->           unit_ket a' m n
->               | null a'              = []
->               | all (== 0) (head a') = unit_vector m n
->               | otherwise            = unit_ket (tail a') (m+1) n
-
-</pre>
-<p>
-<hr>
-<p>
-<b>
-	Eigenvectors for degenerated eigenvalues
-</b>
-<p>
-	Few facts:
-<ul>
-<li>
-	Eigenvectors of a general matrix A, which does not have any
-	special symmetry, are not generally orthogonal. However, they
-	are orthogonal, or can be made orthogonal, to another set of
-	vectors that are eigenvectors of adjoint matrix A<sup>+</sup>;
-	that is the matrix obtained by complex conjugation and transposition
-	of matrix A.
-<li>
-	Eigenvectors corresponding to nondegenerated eigenvalues of
-	hermitian or symmetric matrix are orthogonal.
-<li>
-	Eigenvectors corresponding to degenerated eigenvalues are - in
-	general - neither orthogonal among themselves, nor orthogonal
-	to the remaining eigenvectors corresponding to other
-	eigenvalues. But since any linear combination of such degenerated
-	eigenvectors is also an eigenvector, we can orthogonalize
-	them by Gram-Schmidt orthogonalization procedure.
-</ul>
-	Many practical applications deal solely with hermitian
-	or symmetric matrices, and for such cases the orthogonalization
-	is not only possible, but also desired for variety of reasons.
-<dd>
-	But the method presented in the previous section is not able
-	to find more than one eigenvector corresponding to a degenerated
-	eigenvalue. For example, the symmetric matrix
-<pre>
-	    |  7  -2   1 |
-	A = | -2  10  -2 |
-	    |  1  -2   7 |
-</pre>
-	has two distinct eigenvalues: 12 and 6 -- the latter
-	being degenerated with degree of two. Two corresponding
-	eigenvectors are:
-<pre>
-	< x1 | = [1, -2, 1] -- for 12
-	< x2 | = [1,  1, 1] -- for 6
-</pre>
-	It happens that those vectors are orthogonal, but this is
-	just an accidental result. However, we are missing a third
-	distinct eigenvector. To find it we need another method.
-	One possibility is presented below and the explanation
-	follows.
-<pre>
-
-> eigenket' a alpha eps x' =
->       --
->       -- Eigenket of matrix A corresponding to eigenvalue alpha
->       -- where
->       --     a is a list of columns of matrix A
->       --     eps is a trial inaccuracy factor
->       --         artificially introduced to cope
->       --         with singularities of A - alpha I.
->       --         One might try eps = 0, 0.00001, 0.001, etc.
->       --     x' is a trial eigenvector
->       --
->       scaled [xk' - dk | (xk', dk) <- zip x' d]
->       where
->           b = add_to_diagonal (-alpha*(1+eps)) a
->           d = one_ket_solution b y
->           y = matrix_ket (transposed b) x'
-
-</pre>
-	Let us assume a trial vector | x' &gt;, such that
-<pre>
-	| x' > = | x > + | d >
-	where
-	    | x > is an eigenvector we seek
-	    | d > is an error of our estimation of | x >
-</pre>
-	We first form a matrix B, such that:
-<pre>
-	B = A - alpha I
-</pre>
-	and multiply it by the trial vector | x' &gt;, which
-	results in a vector | y &gt;
-<pre>
-	B | x' > = |y >
-</pre>
-	On another hand:
-<pre>
-	B | x' > = B | x > + B | d > = B | d >
-	because
-	    B | x > = A | x > - alpha | x > = 0
-</pre>
-	Comparing both equations we end up with:
-<pre>
-	B | d > = | y >
-</pre>
-	that is: with the system of linear equations for unknown error | d &gt;.
-	Finally, we subtract error | d &gt; from our trial vector | x' &gt;
-	to obtain the true eigenvector | x &gt;.
-<p>
-	But there is some problem with this approach: matrix B is
-	by definition singular, and as such, it might be difficult
-	to handle. One of the two processes might fail, and their failures
-	relate to division by zero that might happen during either the
-	QR factorization, or the solution of the triangular system of equations.
-<p>
-	But if we do not insist that matrix B should be exactly singular,
-	but almost singular:
-<pre>
-	B = A - alpha (1 + eps) I
-</pre>
-	then this method might succeed. However, the resulting eigenvector
-	will be the approximation only, and we would have to experiment
-	a bit with different values of "eps" to extrapolate the true
-	eigenvector.
-<p>
-	The trial vector | x' &gt; can be chosen randomly, although some
-	choices would still lead to singularity problems. Aside from
-	this, this method is quite versatile, because:
-<ul>
-<li>
-	Any random vector | x' &gt; leads to the same eigenvector
-	for nondegenerated eigenvalues,
-<li>
-	Different random vectors | x' &gt;, chosen for degenerated
-	eigenvalues, produce -- in most cases -- distinct eigenvectors.
-	And this is what we want. If we need it, we can the always
-	orthogonalize those eigenvectors either internally (always
-	possible) or externally as well (possible only for hermitian
-	or symmetric matrices).
-</ul>
-	It might be instructive to compute the eigenvectors for
-	the examples used in demonstration of computation of eigenvalues.
-	We'll leave to the reader, since this module is already too obese.
-<p>
-<hr>
-<p>
-<b>
-	Auxiliary functions
-</b>
-<p>
-	The functions below are used in the main algorithms of
-	this module. But they can be also used for testing. For example,
-	the easiest way to test the usage of resources is to use easily
-	definable unit matrices and unit vectors, as in:
-
-<pre>
-	one_ket_solution (unit_matrix n::[[Double]])
-			 (unit_vector 0 n::[Double])
-	where n = 20, etc.
-
-
-> unit_matrix :: Num a => Int -> [[a]]
-> unit_matrix m =
->       --
->       -- Unit square matrix of with dimensions m x m
->       --
->       [g 0 k | k <- [0..(m-1)]]
->       where
->       g i k
->           | i == m    = []
->           | i == k    = 1:(g (i+1) k)
->           | otherwise = 0:(g (i+1) k)
->
-
-> unit_vector :: Num a => Int -> Int -> [a]
-> unit_vector i m =
->       --
->       -- Unit vector of length m
->       -- with 1 at position i, zero otherwise
->       [g i k| k <- [0..(m-1)]]
->       where
->           g i k
->               | i == k    = 1
->               | otherwise = 0
-
-> diagonals :: [[a]] -> [a]
-> diagonals a =
->       --
->       -- Vector made of diagonal components
->       -- of square matrix a
->       --
->       diagonals' a 0
->       where
->           diagonals' a n
->               | null a = []
->               | otherwise = (head (drop n (head a)))
->                             :(diagonals' (tail a) (n+1))
-
-
-</pre>
-
-<pre>
------------------------------------------------------------------------------
---
--- Copyright:
---
---      (C) 1998 Numeric Quest Inc., All rights reserved
---
--- Email:
---
---      jans@numeric-quest.com
---
--- License:
---
---      GNU General Public License, GPL
---
------------------------------------------------------------------------------
-</pre>
-</ul>
-</body>
-
-<SCRIPT language="Javascript">
-<!--
-
-// FILE ARCHIVED ON 20010628005806 AND RETRIEVED FROM THE
-// INTERNET ARCHIVE ON 20030626101500.
-// JAVASCRIPT APPENDED BY WAYBACK MACHINE, COPYRIGHT INTERNET ARCHIVE.
-// ALL OTHER CONTENT MAY ALSO BE PROTECTED BY COPYRIGHT (17 U.S.C.
-// SECTION 108(a)(3)).
-
-   var sWayBackCGI = "http://web.archive.org/web/20010628005806/";
-
-   function xLateUrl(aCollection, sProp) {
-      var i = 0;
-      for(i = 0; i < aCollection.length; i++)
-	 if (aCollection[i][sProp].indexOf("mailto:") == -1 &&
-	     aCollection[i][sProp].indexOf("javascript:") == -1)
-	    aCollection[i][sProp] = sWayBackCGI + aCollection[i][sProp];
+        Indexless linear algebra algorithms
+</title>
+</head>
+<body>
+<ul>
+<center>
+<h1>
+                        ***
+</h1>
+<h1>
+        Indexless linear algebra algorithms
+</h1>
+<b>
+<br>
+        Orthogonalization, linear equations, eigenvalues and eigenvectors
+<br>
+        Literate Haskell module <i>Orthogonals.lhs</i>
+</b>
+<p>
+        Jan Skibinski, <a href="http://www.numeric-quest.com/news/">
+        Numeric Quest Inc.</a>, Huntsville, Ontario, Canada
+<p>
+        1998.09.19, last modified 1998.12.28
+</center>
+<hr>
+<p>
+        It has been argued that the functional paradigm offers more
+        support for scientific computing than the traditional imperative
+        programming, such as greater similarity of functional implementation
+        to mathematical specification of a problem. However, efficiency
+        of scientific algorithms implemented in Haskell is very low compared
+        to efficiencies of C or Fortran implementations - notwithstanding
+        the exceptional descriptive power of Haskell.
+<dd>
+        It has been also argued that tradition and inertia are partially
+        responsible for this sore state and that many functional algorithms
+        are direct translations of their imperative counterparts.
+<dd>
+        Arrays - with their indexing schemes and destructive updating
+        are basic tools of imperative programming. But pure functional
+        languages, which prohibit variable reassignments, cannot compete
+        with imperative languages by using the same tools and following
+        similar reasoning and patterns - unless the functional arrays
+        themselves are designed with performance in mind. This is
+        a case with Clean, where efficiency of one kind of their arrays
+        -- strict unboxed array, approaches efficiency of C.
+<dd>
+        But this has not been done for Haskell arrays yet. They are
+        lazy, boxed and use auxiliary association lists (index, value)
+        for initialization -- the latter being mostly responsible for
+        low efficiency of those algorithms that create many interim
+        arrays.
+<dd>
+        It appears, that -- as long as indexing scheme is not used
+        for lookups and updates -- Haskell lists are more efficient
+        than arrays -- at least at the currents state of Haskell.
+<p>
+        With this in mind, we are attempting to demonstrate here
+        that the indexing traps can be successfully avoided.
+        This module implements afresh several typical problems from linear
+        algebra. Standard Haskell lists are employed instead of arrays
+        and not a single algorithm ever uses indices for lookups
+        or updates.
+<dd>
+        We do not claim high efficiency of these algorithms; consider
+        them exploratory. However, we do claim that the clarity of
+        these algorithms is significantly better than of those functionally
+        similar algorithms that employ indexing schemes.
+<p>
+        Two major algorithms have been invented and implemented in Haskell:
+        one for solving systems of linear equations and one for finding
+        eigenvalues and eigenvectors of almost any type of a square matrix.
+        This includes symmetric, hermitian, general complex or nonsymmetric
+        matrices with real eigenvalues.
+<dd>
+        Amazingly, both methods are based on the same factorization, akin
+        to QR method, but not exactly the same as the standard QR one.
+        A simple trick allows to extend this method to nonsymmetric real
+        matrices with complex eigenvalues and thus one method applies to
+        all types of matrices.
+        It follows that the eigenvalue/eigenvector problem can be consistently
+        treated all across the board. In addition, no administrative
+        (housekeeping) boring trivia is required here and that helps to
+        clearly explain the mechanisms employed.
+
+</i>
+<p>
+<hr>
+<p>
+<b>
+        Contents
+</b>
+<p>
+<ul>
+<p><li>
+        Notation
+<p><li>
+        Scalar products and vector normalization
+<ul>
+<li><b>
+            bra_ket</b>, scalar product
+<li><b>
+            sum_product</b>, a cousin of bra_ket
+<li><b>
+            norm</b>, vector norm
+<li><b>
+            normalized</b>, vector normalized to one
+</ul>
+<p><li>
+        Transposition and adjoining of matrices
+<ul>
+<li><b>
+            transposed</b>, transposed matrix
+<li><b>
+            adjoint</b>, transposed and conjugated matrix
+</ul>
+<p><li>
+        Products involving matrices
+<ul>
+<li><b>
+            matrix_matrix</b>, product of two matrices as list of rows
+<li><b>
+            matrix_matrix'</b>, product of two matrices as list of columns
+<li><b>
+            triangle_matrix'</b>, upper triangular matrix times square matrix
+<li><b>
+            matrix_ket</b>, matrix times ket vector
+<li><b>
+            bra_matrix</b>, bra vector times matrix
+<li><b>
+            bra_matrix_ket</b>, matrix multiplied on both sides by vectors
+<li><b>
+            scalar_matrix</b>, scalar times matrix
+</ul>
+<p><li>
+        Orthogonalization process
+<ul>
+<li><b>
+            orthogonals</b>, set of orthogonal vectors
+<li><b>
+            gram_schmidt</b>, vector perpendicular to a hyperplane
+</ul>
+
+<p><li>
+        Solutions of linear equations by orthogonalization
+<ul>
+<li><b>
+            one_ket_triangle</b>, triangularization of one vector equation
+<li><b>
+            one_ket_solution</b>, solution for one unknown vector
+<li><b>
+            many_kets_triangle</b>, triangularization of several vector equations
+<li><b>
+            many_kets_solution</b>, solution for several unknown vectors
+</ul>
+<p><li>
+        Matrix inversion
+<ul>
+<li><b>
+            inverse</b>, inverse of a matrix
+</ul>
+<p><li>
+        QR factorization of matrices provided by "many_kets_triangle"
+<ul>
+<li><b>
+            factors_QR</b>, QR alike factorization of matrices
+<li><b>
+            determinant</b>, computation of the determinant based on the QR factorization
+</ul>
+<p><li>
+        Similarity transformations and eigenvalues
+<ul>
+<li><b>
+            similar_to</b>, matrix obtained by similarity transformation
+<li><b>
+            iterated_eigenvalues</b>, list of approximations of eigenvalues
+<li><b>
+            eigenvalues</b>, final approximation of eigenvalues
+</ul>
+<p><li>
+        Preconditioning of real nonsymmetric matrices
+<ul>
+<li><b>
+            add_to_diagonal</b>, simple preconditioning method
+</ul>
+<p><li>
+        Examples of iterated eigenvalues
+<ul>
+<li>
+            Symmetric real matrix
+<li>
+            Hermitian complex matrix
+<li>
+            General complex matrix
+<li>
+            Nonsymmetric real matrix with real eigenvalues
+<li>
+            Nonsymmetric real matrix with complex eigenvalues
+</ul>
+<p><li>
+        Eigenvectors for distinct eigenvalues
+<ul>
+<li><b>
+                eigenkets</b>, eigenvectors for distinct eigenvalues
+</ul>
+<p><li>
+        Eigenvectors for degenerated eigenvalues
+<ul>
+<li><b>
+                eigenket'</b>, eigenvector based on a trial vector
+</ul>
+
+<p><li>
+        Auxiliary functions
+<ul>
+<li><b>
+        unit_matrix</b>, a unit matrix with 1's on a diagonal
+<li><b>
+        unit_vector</b>, a vector with one non-zero component
+<li><b>
+        diagonals</b>, vector made of a matrix diagonal
+</ul>
+</ul>
+
+<p>
+<hr>
+<p>
+<b>
+        Notation
+</b>
+<p>
+        What follows is written in Dirac's notation, as used
+        in Quantum Mechanics. Matrices are represented by capital
+        letters, while vectors come in two varieties:
+<ul>
+<p><li>
+        Bra vector x, written &lt; x |, is represented by one-row matrix
+<p><li> Ket vector y, written | y &gt;, is represented by one-column matrix
+</ul>
+<p>
+        Bra vectors can be obtained from ket vectors by transposition
+        and conjugation of their components. Conjugation is only
+        important for complex vectors.
+<p>
+        Scalar product of two vectors | x &gt; and | y &gt; is written
+        as
+<pre>
+        < x | y >
+</pre>
+        which looks like a bracket and is sometimes called a "bra_ket".
+        This justifies "bra" and "ket" names introduced by Dirac. There
+        is a good reason for conjugating the components of "bra-vector":
+        the scalar product of
+<pre>
+        < x | x >
+</pre>
+        should be a square of the norm of the vector "x", and that
+        means that it should be represented by a real number, or complex
+        number but with its imaginary part equal to zero.
+<p>
+<hr>
+<p>
+<pre>
+
+> module Orthogonals where
+> import Complex
+> import Ratio
+> import qualified List
+
+</pre>
+<b>
+        Scalar product and vector normalization
+</b>
+<p>
+        The scalar product "bra_ket" is a basis of many algorithms
+        presented here.
+
+
+<pre>
+
+> bra_ket :: (Scalar a, Num a) => [a] -> [a] -> a
+> bra_ket u v =
+>       --
+>       -- Scalar product of two vectors u and v,
+>       -- or < u | v > in Dirac's notation.
+>       -- This is equally valid for both: real and complex vectors.
+>       --
+>       sum_product u (map coupled v)
+
+</pre>
+
+        Notice the call to function "coupled" in the above implementation
+        of scalar product. This function conjugates its argument
+        if it is complex, otherwise does not change it. It is defined
+        in the class Scalar - specifically designed for this purpose
+        mainly.
+<dd>
+        This class also defines a norm of a vector that might be used
+        by some algorithms. So far we have been able to avoid this.
+<pre>
+
+> class Scalar a where
+>     coupled    :: a->a
+>     norm       :: [a] -> a
+>     almostZero :: a -> Bool
+>     scaled     :: [a] -> [a]
+
+> instance Scalar Double where
+>     coupled x    = x
+>     norm u       = sqrt (bra_ket u u)
+>     almostZero x = (abs x) < 1.0e-8
+>     scaled       = scaled'
+
+> instance Scalar Float where
+>    coupled x    = x
+>    norm u       = sqrt (bra_ket u u)
+>    almostZero x = (abs x) < 1.0e-8
+>    scaled       = scaled'
+
+> instance (Integral a) => Scalar (Ratio a) where
+>     coupled x    = x
+>     -- norm u    = fromDouble ((sqrt (bra_ket u u))::Double)
+>     -- Intended hack to silently convert to and from Double.
+>     -- But I do not know how to declare it properly.
+>     --
+>     -- Our type Fraction, when used instead of Ratio a, has its own
+>     -- definition of sqrt. No hack would be needed here.
+>     almostZero x = abs x < 1e-8
+>     scaled       = scaled'
+
+> instance (RealFloat a) => Scalar (Complex a) where
+>     coupled (x:+y) = x:+(-y)
+>     norm u         = sqrt (realPart (bra_ket u u)) :+ 0
+>     almostZero z   = (realPart (abs z)) < 1.0e-8
+>     scaled u       = [(x/m):+(y/m) | x:+y <- u]
+>        where m = maximum [max (abs x) (abs y) | x:+y <- u]
+
+> norm1 :: (Num a) => [a] -> a
+> norm1 = sum . map abs
+
+> norminf :: (Num a, Ord a) => [a] -> a
+> norminf = maximum . map abs
+
+> matnorm1 :: (Num a, Ord a) => [[a]] -> a
+> matnorm1 = matnorminf . transposed
+
+> matnorminf :: (Num a, Ord a) => [[a]] -> a
+> matnorminf = maximum . map norm1
+
+
+</pre>
+
+        But we also need a slightly different definition of
+        scalar product that will appear in multiplication of matrices
+        by vectors (or vice versa): a straightforward accumulated product
+        of two lists, where no complex conjugation takes place.
+        We will call it a 'sum_product".
+<pre>
+
+> sum_product :: Num a => [a] -> [a] -> a
+> sum_product u v =
+>       --
+>       -- Similar to scalar product but without
+>       -- conjugations of | u > components
+>       -- Used in matrix-vector or vector-matrix products
+>       --
+>       sum (zipWith (*) u v)
+
+</pre>
+        Some algorithms might need vectors normalized to one, although
+        we'll try to avoid the normalizations due to its high cost
+        or its inapplicability to rational numbers. Instead, we wiil
+        scale vectors by their maximal components.
+<pre>
+
+> normalized :: (Scalar a, Fractional a) => [a] -> [a]
+> normalized u =
+>       [uk/n | uk <- u]
+>       where
+>           n = norm u
+
+> scaled' :: (Fractional t, Ord t) => [t] -> [t]
+> scaled' u =
+>       [uk/um | uk <- u]
+>       where
+>           um = maximum [abs uk| uk <- u]
+
+</pre>
+<hr>
+<p>
+<b>
+        Transposition and adjoining of matrices
+</b>
+<p>
+        Matrices are represented here by lists of lists.
+        Function "transposed" converts from row-wise to column-wise
+        representation, or vice versa.
+<dd>
+        When transposition is combined with complex conjugation
+        the resulting matrix is called "adjoint".
+<p>
+        A square matrix is called symmetric if it is equal to its transpose
+<pre>
+        A = A<sup>T</sup>
+</pre>
+        It is called Hermitian, or self-adjoint, if it equals to
+        its adjoint
+<pre>
+        A = A<sup>+</sup>
+
+> transposed :: [[a]] -> [[a]]
+> transposed a
+>     | null (head a) = []
+>     | otherwise = ([head mi| mi <- a])
+>                   :transposed ([tail mi| mi <- a])
+
+> adjoint :: Scalar a => [[a]] -> [[a]]
+> adjoint a
+>     | null (head a) = []
+>     | otherwise = ([coupled (head mi)| mi <- a])
+>                   :adjoint ([tail mi| mi <- a])
+
+</pre>
+<p>
+<hr>
+<p>
+<b>
+        Linear combination and sum of two matrices
+</b>
+<p>
+        One can form a linear combination of two matrices, such
+        as
+<pre>
+        C = alpha A + beta B
+        where
+            alpha and beta are scalars
+</pre>
+        The most generic form of any combination, not necessary
+        linear, of components of two matrices is given by "matrix_zipWith"
+        function below, which accepts a function "f" describing such
+        combination. For the linear combination with two scalars
+        the function "f" could be defined as:
+<pre>
+        f alpha beta a b = alpha*a + beta*b
+</pre>
+        For a straightforward addition of two matrices this auxiliary
+        function is simply "(+)".
+<pre>
+
+> matrix_zipWith :: (a -> b -> c) -> [[a]] -> [[b]] -> [[c]]
+> matrix_zipWith f a b =
+>     --
+>     -- Matrix made of a combination
+>     -- of matrices a and b - as specified by f
+>     --
+>     [zipWith f ak bk | (ak,bk) <- zip a b]
+
+> add_matrices :: (Num a) => t -> t1 -> [[a]] -> [[a]] -> [[a]]
+> add_matrices _ _ = matrix_zipWith (+)
+
+</pre>
+
+<p>
+<hr>
+<p>
+<b>
+        Products involving matrices
+</b>
+<p>
+        Variety of products involving matrices can be defined.
+        Our Haskell implementation is based on lists of lists
+        and therefore is open to interpretation: sublists
+        can either represent the rows or the columns of a matrix.
+<dd>
+        The following definitions are somehow arbitrary, since
+        one can choose alternative interpretations of lists
+        representing matrices.
+<p>
+<b>
+        C = A B
+</b>
+<p>
+        Inner product of two matrices A B can be expressed quite simply,
+        providing that matrix A is represented by a list of rows
+        and B - by a list of columns. Function "matrix_matrix"
+        answers list of rows, while "matrix_matrix'" - list
+        of columns.
+<dd>
+        Major algorithms of this module make use of "triangle_matrix'",
+        which calculates a product of upper triangular matrix
+        with square matrix and returns a rectangular list of columns.
+
+<pre>
+
+> matrix_matrix :: Num a => [[a]] -> [[a]] -> [[a]]
+> matrix_matrix a b
+> --
+> -- A matrix being an inner product
+> -- of matrices A and B, where
+> --     A is represented by a list of rows a
+> --     B is represented by a list of columns b
+> --     result is represented by list of rows
+> -- Require: length of a is equal of length of b
+> -- Require: all sublists are of equal length
+>
+>       | null a = []
+>       | otherwise = ([sum_product (head a) bi | bi <- b])
+>                  : matrix_matrix (tail a) b
+
+> matrix_matrix' :: (Num a) => [[a]] -> [[a]] -> [[a]]
+> matrix_matrix' a b
+>       --
+>       -- Similar to "matrix_matrix"
+>       -- but the result is represented by
+>       -- a list of columns
+>       --
+>       | null b = []
+>       | otherwise = ([sum_product ai (head b) | ai <- a])
+>                    : matrix_matrix' a (tail b)
+
+
+> triangle_matrix' :: Num a => [[a]] -> [[a]] -> [[a]]
+> triangle_matrix' r q =
+>       --
+>       -- List of columns of of a product of
+>       -- upper triangular matrix R and square
+>       -- matrix Q
+>       -- where
+>       --     r is a list of rows of R
+>       --     q is a list of columns of A
+>       --
+>       [f r qk | qk <- q]
+>       where
+>           f t u
+>               | null t = []
+>               | otherwise = (sum_product (head t) u)
+>                             : (f (tail t) (tail u))
+
+
+
+</pre>
+<b>
+        | u &gt; = A | v &gt;
+</b>
+<p>
+        Product of a matrix and a ket-vector is another
+        ket vector. The following implementation assumes
+        that list "a" represents rows of matrix A.
+<pre>
+
+> matrix_ket :: Num a => [[a]] -> [a] -> [a]
+> matrix_ket a v = [sum_product ai v| ai <- a]
+
+</pre>
+<b>
+        &lt; u | = &lt; v | A
+</b>
+<p>
+        Bra-vector multiplied by a matrix produces
+        another bra-vector. The implementation below
+        assumes that list "a" represents columns
+        of matrix A. It is also assumed that vector
+        "v" is given in its standard "ket" representation,
+        therefore the definition below uses "bra_ket"
+        instead of "sum_product".
+<pre>
+
+> bra_matrix :: (Scalar a, Num a) => [a] -> [[a]] -> [a]
+> bra_matrix v a = [bra_ket v ai | ai <- a]
+
+</pre>
+<b>
+        alpha = &lt; u | A | v &gt;
+</b>
+<p>
+        This kind of product results in a scalar and is often
+        used to define elements of a new matrix, such as
+<pre>
+        B[i,j] = < ei | A | ej >
+</pre>
+        The implementation below assumes that list "a" represents
+        rows of matrix A.
+<pre>
+
+> bra_matrix_ket :: (Scalar a, Num a) => [a] -> [[a]] -> [a] -> a
+> bra_matrix_ket u a v =
+>     bra_ket u (matrix_ket a v)
+
+</pre>
+<b>
+        B = alpha A
+</b>
+<p>
+        Below is a function which multiplies matrix by a scalar:
+<pre>
+
+> scalar_matrix :: Num a => a -> [[a]] -> [[a]]
+> scalar_matrix alpha a =
+>       [[alpha*aij| aij <- ai] | ai<-a]
+
+</pre>
+<p>
+<hr>
+<p>
+<b>
+        Orthogonalization process
+</b>
+<p>
+
+        Gram-Schmidt orthogonalization procedure is used here
+        for calculation of sets of mutually orthogonal vectors.
+<dd>
+        Function "orthogonals" computes a set of mutually orthogonal
+        vectors - all orthogonal to a given vector. Such set plus
+        the input vector form a basis of the vector space. Another
+        words, they are the base vectors, although we cannot call them
+        unit vectors since we do not normalize them for two reasons:
+<ul>
+<li>
+        None of the algorithms presented here needs this -- quite
+        costly -- normalization.
+<li>
+        Some algorithms can be used either with doubles or with
+        rationals. The neat output of the latter is sometimes desirable
+        for pedagogical or accuracy reasons. But normalization requires "sqrt"
+        function, which is not defined for rational numbers. We could
+        use our module Fraction instead, where "sqrt" is defined,
+        but we'll leave it for a future revision of this module.
+</ul>
+<p>
+        Function "gram_schmidt" computes one vector - orthogonal
+        to an incomplete set of orthogonal vectors, which form a hyperplane
+        in the vector space. Another words, "gram_schmidt" vector is
+        perpendicular to such a hyperlane.
+
+
+<pre>
+
+> orthogonals :: (Scalar a, Fractional a) => [a] -> [[a]]
+> orthogonals x =
+>       --
+>       -- List of (n-1) linearly independent vectors,
+>       -- (mutually orthogonal) and orthogonal to the
+>       -- vector x, but not normalized,
+>       -- where
+>       --     n is a length of x.
+>       --
+>       orth [x] size (next (-1))
+>       where
+>           orth a n m
+>               | n == 1        = drop 1 (reverse a)
+>               | otherwise     = orth ((gram_schmidt a u ):a) (n-1) (next m)
+>               where
+>                   u = unit_vector m size
+>           size = length x
+>           next i = if (i+1) == k then (i+2) else (i+1)
+>           k = length (takeWhile (== 0) x) -- first non-zero component of x
+
+> gram_schmidt :: (Scalar a, Fractional a) => [[a]] -> [a] -> [a]
+> gram_schmidt a u =
+>       --
+>       -- Projection of vector | u > on some direction
+>       -- orthogonal to the hyperplane spanned by the list 'a'
+>       -- of mutually orthogonal (linearly independent)
+>       -- vectors.
+>       --
+>       gram_schmidt' a u u
+>       where
+>           gram_schmidt' [] _ w = w
+>           gram_schmidt' (b:bs) v w
+>               | all (== 0) b = gram_schmidt' bs v w
+>               | otherwise    = gram_schmidt' bs v w'
+>               where
+>                   w' = vectorCombination w (-(bra_ket b v)/(bra_ket b b)) b
+>           vectorCombination x c y
+>               | null x = []
+>               | null y = []
+>               | otherwise = (head x + c * (head y))
+>                             : (vectorCombination (tail x) c (tail y))
+
+</pre>
+<p>
+<hr>
+<p>
+<b>
+        Solutions of linear equations by orthogonalization
+</b>
+<p>
+        A matrix equation for unknown vector | x &gt;
+<pre>
+        A | x > = | b >
+</pre>
+        can be rewritten as
+<pre>
+        x1 | 1 > + x2 | 2 > + x3 | 3 > + ... + xn | n > = | b >     (7.1)
+        where
+                | 1 >, | 2 >... represent columns of the matrix A
+</pre>
+        For any n-dimensional vector, such as "1", there exist
+        n-1 linearly independent vectors "ck" that are orthogonal to "1";
+        that is, each satisfies the relation:
+<pre>
+        < ck | 1 > = 0, for k = 1...m, where m = n - 1
+</pre>
+        If we could find all such vectors, then we could multiply
+        the equation (7.1) by each of them, and end up with m = n-1
+        following equations
+<pre>
+        < c1 | 2 > x2 + < c1 | 3 > x3 + ... < c1 | n > xn = < c1 | b >
+        < c2 | 2 > x2 + < c2 | 3 > x3 + ... < c2 | n > xn = < c2 | b >
+        .......
+        < cm | 2 > x2 + < cm | 3 > x3 + ... < cm | n > xn = < cm | b >
+</pre>
+        But the above is nothing more than a new matrix equation
+<pre>
+        A' | x' > = | b' >
+        or
+
+        x2 | 2'> + x3 | 3'> .... + xn | n'> = | b'>
+        where
+            primed vectors | 2' >, etc. are the columns of the new
+            matrix A'.
+</pre>
+        with the problem dimension reduced by one.
+
+<dd>
+        Taking as an example a four-dimensional problem and writing
+        down the successive transformations of the original equation
+        we will end up with the following triangular pattern made of
+        four vector equations:
+
+<pre>
+        x1 | 1 > + x2 | 2 > + x3 | 3 >  + x4 | 4 >   = | b >
+                   x2 | 2'> + x3 | 3'>  + x4 | 4'>   = | b'>
+                              x3 | 3''> + x4 | 4''>  = | b''>
+                                          x4 | 4'''> = | b'''>
+</pre>
+        But if we premultiply each vector equation by a non-zero vector
+        of our choice, say &lt; 1 | , &lt; 2' |, &lt; 3'' |, and &lt; 4''' | - chosen
+        correspondingly for equations 1, 2, 3 and 4, then the above
+        system of vector equations will be converted to much simpler
+        system of scalar equations. The result is
+        shown below in matrix representation:
+
+<pre>
+        | p11  p12   p13   p14 | | x1 | = | q1 |
+        | 0    p22   p23   p24 | | x2 | = | q2 |
+        | 0    0     p33   p34 | | x3 | = | q3 |
+        | 0    0     0     p44 | | x4 | = | q4 |
+</pre>
+        In effect, we have triangularized our original matrix A.
+        Below is a function that does that for any problem size:
+<pre>
+
+> one_ket_triangle :: (Scalar a, Fractional a) => [[a]] -> [a] -> [([a],a)]
+> one_ket_triangle a b
+>     --
+>     -- List of pairs: (p, q) representing
+>     -- rows of triangular matrix P and of vector | q >
+>     -- in the equation P | x > = | q >, which
+>     -- has been obtained by linear transformation
+>     -- of the original equation A | x > = | b >
+>     --
+>     | null a = []
+>     | otherwise = (p,q):(one_ket_triangle a' b')
+>     where
+>         p    = [bra_ket u ak | ak <- a]
+>         q    = bra_ket u b
+>         a'   = [[bra_ket ck ai | ck <- orth] | ai <- v]
+>         b'   = [ bra_ket ck b  | ck <- orth]
+>         orth = orthogonals u
+>         u    = head a
+>         v    = tail a
+
+</pre>
+        The triangular system of equations can be easily solved by
+        successive substitutions - starting with the last equation.
+
+<pre>
+
+> one_ket_solution :: (Fractional a, Scalar a) => [[a]] -> [a] -> [a]
+> one_ket_solution a b =
+>     --
+>     -- List representing vector |x>, which is
+>     -- a solution of the matrix equation
+>     --     A |x> = |b>
+>     -- where
+>     --     a is a list of columns of matrix A
+>     --     b is a list representing vector |b>
+>     --
+>     solve' (unzip (reverse (one_ket_triangle a b))) []
+>     where
+>         solve' (d, c) xs
+>             | null d  = xs
+>             | otherwise = solve' ((tail d), (tail c)) (x:xs)
+>             where
+>                 x = (head c - (sum_product (tail u) xs))/(head u)
+>                 u = head d
+
+</pre>
+        The triangularization procedure can be easily extended
+        to a list of several ket-vectors | b &gt; on the right hand
+        side of the original equation A | x &gt; = | b &gt; -- instead
+        of just one:
+<pre>
+
+> many_kets_triangle :: (Scalar a, Fractional a) => [[a]] -> [[a]] -> [([a],[a])]
+> many_kets_triangle a b
+>     --
+>     -- List of pairs: (p, q) representing
+>     -- rows of triangular matrix P and of rectangular matrix Q
+>     -- in the equation P X = Q, which
+>     -- has been obtained by linear transformation
+>     -- of the original equation A X = B
+>     -- where
+>     --     a is a list of columns of matrix A
+>     --     b is a list of columns of matrix B
+>     --
+>     | null a = []
+>     | otherwise = (p,q):(many_kets_triangle a' b')
+>     where
+>         p    = [bra_ket u ak   | ak <- a]
+>         q    = [bra_ket u bk   | bk <- b]
+>         a'   = [[bra_ket ck ai | ck <- orth] | ai <- v]
+>         b'   = [[bra_ket ck bi | ck <- orth] | bi <- b]
+>         orth = orthogonals u
+>         u    = head a
+>         v    = tail a
+
+</pre>
+        Similarly, function 'one_ket_solution' can be generalized
+        to function 'many_kets_solution' that handles cases with
+        several ket-vectors on the right hand side.
+<pre>
+
+> many_kets_solution :: (Scalar a, Fractional a) => [[a]] -> [[a]] -> [[a]]
+> many_kets_solution a b =
+>     --
+>     -- List of columns of matrix X, which is
+>     -- a solution of the matrix equation
+>     --     A X = B
+>     -- where
+>     --     a is a list of columns of matrix A
+>     --     b is a list of columns of matrix B
+>     --
+>     solve' p q emptyLists
+>     where
+>         (p, q) = unzip (reverse (many_kets_triangle a b))
+>         emptyLists = [[] | _ <- [1..(length (head q))]]
+>         solve' a' b' x
+>             | null a'  = x
+>             | otherwise = solve' (tail a') (tail b')
+>                                 [(f vk xk):xk  | (xk, vk) <- (zip x v)]
+>             where
+>                 f vk xk = (vk - (sum_product (tail u) xk))/(head u)
+>                 u = head a'
+>                 v = head b'
+
+
+</pre>
+<p>
+<hr>
+<p>
+<b>
+        Matrix inversion
+</b>
+<p>
+        Function 'many_kets_solution' can be used to compute
+        inverse of matrix A by specializing matrix B to a unit
+        matrix I:
+<pre>
+
+        A X = I
+</pre>
+        It follows that matrix X is an inverse of A; that is X = A<sup>-1</sup>.
+<pre>
+
+> inverse :: (Scalar a, Fractional a) => [[a]] -> [[a]]
+> inverse a = many_kets_solution a (unit_matrix (length a))
+>       --
+>       -- List of columns of inverse of matrix A
+>       -- where
+>       --     a is list of columns of A
+
+</pre>
+<p>
+<hr>
+<p>
+<b>
+        QR factorization of matrices
+</b>
+<p>
+        The process described above and implemented by
+        'many_kets_triangle' function transforms the equation
+<pre>
+        A X = B
+</pre>
+        into another equation for the same matrix X
+<pre>
+        R X = S
+</pre>
+        where R is an upper triangular matrix. All operations
+        performed on matrices A and B during this process are linear,
+        and therefore we should be able to find a square matrix Q
+        that describes the entire process in one step. Indeed, assuming
+        that matrix A can be decomposed as a product of unknown matrix Q
+        and triangular matrix R and that Q<sup>-1</sup> is an inverse of matrix Q
+        we can reach the last equation by following these steps:
+<pre>
+        A X       = B
+        (Q R) X   = B
+        Q<sup>-1</sup> Q R X = Q<sup>-1</sup> B
+        R X       = S
+</pre>
+        It follows that during this process a given matrix B
+        transforms to matrix S, as delivered by 'many_kets_triangle':
+<pre>
+        S = Q<sup>-1</sup> B
+</pre>
+        from which the inverse of Q can be found:
+<pre>
+        Q<sup>-1</sup> = S B<sup>-1</sup>
+</pre>
+        Having a freedom of choice of the right hand side matrix B
+        we can choose the unit matrix I in place of B, and therefore
+        simplify the definition of Q<sup>-1</sup>:
+<pre>
+        Q<sup>-1</sup> = S,  if B is unit matrix
+</pre>
+        It follows that any non-singular matrix A can be decomposed
+        as a product of a matrix Q and a triangular matrix R
+
+<pre>
+        A = Q R
+</pre>
+        where matrices Q<sup>-1</sup> and R are delivered by "many_kets_triangle"
+        as a result of triangularization process of equation:
+<pre>
+        A X = I
+</pre>
+        The function below extracts a pair of matrices Q and R
+        from the answer provided by "many_kets_triangle".
+        During this process it inverts matrix Q<sup>-1</sup> to Q.
+        This factorization will be used by a sequence of similarity
+        transformations to be defined in the next section.
+
+<pre>
+
+> factors_QR :: (Fractional a, Scalar a) => [[a]] -> ([[a]],[[a]])
+> factors_QR a =
+>       --
+>       -- A pair of matrices (Q, R), such that
+>       -- A = Q R
+>       -- where
+>       --     R is upper triangular matrix in row representation
+>       --     (without redundant zeros)
+>       --     Q is a transformation matrix in column representation
+>       --     A is square matrix given as columns
+>       --
+>       (inverse (transposed q1),r)
+>       where
+>           (r, q1) = unzip (many_kets_triangle a (unit_matrix (length a)))
+
+</pre>
+
+<p>
+<hr>
+<p>
+<b>
+        Computation of the determinant
+</b>
+
+<!-- added by Henning Thielemann -->
+
+<pre>
+
+> determinant :: (Fractional a, Scalar a) => [[a]] -> a
+> determinant a =
+>    let (q,r) = factors_QR a
+>    -- matrix Q is not normed so we have to respect the norms of its rows
+>    in  product (map norm q) * product (map head r)
+
+</pre>
+
+Naive division-free computation of the determinant by expanding the first column.
+It consumes n! multiplications.
+
+<pre>
+
+> determinantNaive :: (Num a) => [[a]] -> a
+> determinantNaive [] = 1
+> determinantNaive m  =
+>    sum (alternate
+>       (zipWith (*) (map head m)
+>           (map determinantNaive (removeEach (map tail m)))))
+
+</pre>
+
+Compute the determinant with about n^4 multiplications
+without division according to the clow decomposition algorithm
+of Mahajan and Vinay, and Berkowitz
+as presented by Günter Rote:
+<a href="http://page.inf.fu-berlin.de/~rote/Papers/pdf/Division-free+algorithms.pdf">
+Division-Free Algorithms for the Determinant and the Pfaffian:
+Algebraic and Combinatorial Approaches</a>.
+
+<pre>
+
+> determinantClow :: (Num a) => [[a]] -> a
+> determinantClow [] = 1
+> determinantClow m =
+>    let lm = length m
+>    in  parityFlip lm (last (newClow m
+>           (nest (lm-1) (longerClow m)
+>               (take lm (iterate (0:) [1])))))
+
+</pre>
+
+Compute the weights of all clow sequences
+where the last clow is closed and a new one is started.
+
+<pre>
+
+> newClow :: (Num a) => [[a]] -> [[a]] -> [a]
+> newClow a c =
+>    scanl (-) 0
+>          (sumVec (zipWith (zipWith (*)) (List.transpose a) c))
+
+</pre>
+
+Compute the weights of all clow sequences
+where the last (open) clow is extended by a new arc.
+
+<pre>
+
+> extendClow :: (Num a) => [[a]] -> [[a]] -> [[a]]
+> extendClow a c =
+>    map (\ai -> sumVec (zipWith scaleVec ai c)) a
+
+</pre>
+
+Given the matrix of all weights of clows of length l
+compute the weight matrix for all clows of length (l+1).
+Take the result of 'newClow' as diagonal
+and the result of 'extendClow' as lower triangle
+of the weight matrix.
+
+<pre>
+
+> longerClow :: (Num a) => [[a]] -> [[a]] -> [[a]]
+> longerClow a c =
+>    let diagonal = newClow a c
+>        triangle = extendClow a c
+>    in  zipWith3 (\i t d -> take i t ++ [d]) [0 ..] triangle diagonal
+
+</pre>
+
+Auxiliary functions for the clow determinant.
+
+<pre>
+
+> {- | Compositional power of a function,
+>      i.e. apply the function n times to a value. -}
+> nest :: Int -> (a -> a) -> a -> a
+> nest 0 _ x = x
+> nest n f x = f (nest (n-1) f x)
+>
+> {- successively select elements from xs and remove one in each result list -}
+> removeEach :: [a] -> [[a]]
+> removeEach xs =
+>    zipWith (++) (List.inits xs) (tail (List.tails xs))
+>
+> alternate :: (Num a) => [a] -> [a]
+> alternate = zipWith id (cycle [id, negate])
+>
+> parityFlip :: Num a => Int -> a -> a
+> parityFlip n x = if even n then x else -x
+>
+> {-| Weight a list of numbers by a scalar. -}
+> scaleVec :: (Num a) => a -> [a] -> [a]
+> scaleVec k = map (k*)
+>
+> {-| Add corresponding numbers of two lists. -}
+> {- don't use zipWith because it clips to the shorter list -}
+> addVec :: (Num a) => [a] -> [a] -> [a]
+> addVec x [] = x
+> addVec [] y = y
+> addVec (x:xs) (y:ys) = x+y : addVec xs ys
+>
+> {-| Add some lists. -}
+> sumVec :: (Num a) => [[a]] -> [a]
+> sumVec = foldl addVec []
+
+</pre>
+
+
+
+<p>
+<hr>
+<p>
+<b>
+        Similarity transformations and eigenvalues
+</b>
+<p>
+        Two n-square matrices A and B are called similar if there
+        exists a non-singular matrix S such that:
+<pre>
+        B = S<sup>-1</sup> A S
+</pre>
+
+        It can be proven that:
+<ul>
+<li>
+        Any two similar matrices have the same eigenvalues
+<li>
+        Every n-square matrix A is similar to a triangular matrix
+        whose diagonal elements are the eigenvalues of A.
+</ul>
+<p>
+        If matrix A can be transformed to a triangular or a diagonal
+        matrix Ak by a sequence of similarity transformations then
+        the eigenvalues of matrix A are the diagonal elements of Ak.
+
+<p>
+
+        Let's construct the sequence of matrices similar to A
+<pre>
+        A, A1, A2, A3...
+</pre>
+        by the following iterations - each of which factorizes a matrix
+        by applying the function 'factors_QR' and then forms a product
+        of the factors taken in the reverse order:
+<pre>
+        A = Q R          = Q (R Q) Q<sup>-1</sup>    = Q A1 Q<sup>-1</sup>        =
+          = Q (Q1 R1) Q<sup>-1</sup> = Q Q1 (R1 Q1) Q1<sup>-1</sup> Q<sup>-1</sup> = Q Q1 A2 Q1<sup>-1</sup> Q<sup>-1</sup> =
+          = Q Q1 (Q2 R2) Q1<sup>-1</sup> Q<sup>-1</sup> = ...
+
+</pre>
+        We are hoping that after some number of iterations some matrix
+        Ak would become triangular and therefore its diagonal
+        elements could serve as eigenvalues of matrix A. As long as
+        a matrix has real eigenvalues only, this method should work well.
+        This applies to symmetric and hermitian matrices. It appears
+        that general complex matrices -- hermitian or not -- can also
+        be handled this way. Even more, this method also works for some
+        nonsymmetric real matrices, which have real eigenvalues only.
+<dd>
+        The only type of matrices that cannot be treated by this algorithm
+        are real nonsymmetric matrices, whose some eigenvalues are complex.
+        There is no operation in the process that converts real elements
+        to complex ones, which could find their way into diagonal
+        positions of a triangular matrix. But a simple preconditioning
+        of a matrix -- described in the next section -- replaces
+        a real matrix by a complex one, whose eigenvalues are related
+        to the eigenvalues of the matrix being replaced. And this allows
+        us to apply the same method all across the board.
+<dd>
+        It is worth noting that a process known in literature as QR
+        factorization is not uniquely defined and different algorithms
+        are employed for this. The algorithms using QR factorization
+        apply only to symmetric or hermitian matrices, and Q matrix
+        must be either orthogonal or unitary.
+<dd>
+        But our transformation matrix Q is not orthogonal nor unitary,
+        although its first row is orthogonal to all other rows. In fact,
+        this factorization is only similar to QR factorization. We just
+        keep the same name to help identify a category of the methods
+        to which it belongs.
+<dd>
+        The same factorization is used for tackling two major problems:
+        solving the systems of linear equations and finding the eigenvalues
+        of matrices.
+<dd>
+        Below is the function 'similar_to', which makes a new matrix that is
+        similar to a given matrix by applying our similarity transformation.
+<dd>
+        Function 'iterated_eigenvalues' applies this transformation n
+        times - storing diagonals of each new matrix as approximations of
+        eigenvalues.
+<dd>
+        Function 'eigenvalues' follows the same process but reports the last
+        approximation only.
+<pre>
+
+
+> similar_to :: (Fractional a, Scalar a) => [[a]] -> [[a]]
+> similar_to a =
+>       --
+>       -- List of columns of matrix A1 similar to A
+>       -- obtained by factoring A as Q R and then
+>       -- forming the product A1 = R Q = (inverse Q) A Q
+>       -- where
+>       --     a is list of columns of A
+>       --
+>       triangle_matrix' r q
+>       where
+>           (q,r) = factors_QR a
+
+> iterated_eigenvalues :: (Scalar a1, Fractional a1, Num a) => [[a1]] -> a -> [[a1]]
+> iterated_eigenvalues a n
+>       --
+>       -- List of vectors representing
+>       -- successive approximations of
+>       -- eigenvalues of matrix A
+>       -- where
+>       --     a is a list of columns of A
+>       --     n is a number of requested iterations
+>       --
+>       | n == 0 = []
+>       | otherwise = (diagonals a)
+>                     : iterated_eigenvalues (similar_to a) (n-1)
+
+> eigenvalues :: (Scalar a1, Fractional a1, Num a) => [[a1]] -> a -> [a1]
+> eigenvalues a n
+>       --
+>       -- Eigenvalues of matrix A
+>       -- obtained by n similarity iterations
+>       -- where
+>       --     a are the columns of A
+>       --
+>       | n == 0    = diagonals a
+>       | otherwise = eigenvalues (similar_to a) (n-1)
+
+</pre>
+<p>
+<hr>
+<p>
+<b>
+        Preconditioning of real nonsymmetric matrices
+</b>
+<p>
+        As mentioned above, our QR-like factorization method works
+        well with almost all kind of matrices, but with the exception
+        of a class of real nonsymmetric matrices that have
+        complex eigenvalues.
+<dd>
+        There is no mechanism in that method that would be able to
+        produce complex eigenvalues out of the real components of
+        this type of nonsymmetric matrices. Simple trivial replacement
+        of real components of a matrix by its complex counterparts
+        does not work because zero-valued imaginary components do
+        not contribute in any way to production of nontrivial
+        imaginary components during the factorization process.
+<dd>
+        What we need is a trick that replaces real nonsymmetric matrix
+        by a nontrivial complex matrix in such a way that the results
+        of such replacements could be undone when the series of
+        similarity transformations finally produced the expected
+        effect in a form of a triangular matrix.
+<dd>
+        The practical solution is surprisingly simple:
+        it's suffice to add any complex number, such as "i", to the
+        main diagonal of a matrix, and when triangularization is done
+        -- subtract it back from computed eigenvalues.
+        The explanation follows.
+<p>
+        Consider the eigenproblem for real and nonsymmetric matrix A.
+<pre>
+        A | x > = a | x >
+</pre>
+        Let us now define a new complex matrix B, such that:
+<pre>
+        B = A + alpha I
+        where
+            I is a unit matrix and alpha is a complex scalar
+</pre>
+        It is obvious that matrices A and B commute; that is:
+<pre>
+        A B = B A
+</pre>
+        It can be proven that if two matrices commute then they
+        have the same eigenvectors. Therefore we can use vector
+        | x &gt; of matrix A as an eigenvector of B:
+<pre>
+        B | x > = b | x >
+        B | x > = A | x > + alpha I | x >
+                = a | x > + alpha | x >
+                = (a + alpha) | x >
+</pre>
+        It follows that eigenvalues of B are related to the eigenvalues
+        of A by:
+<pre>
+        b = a + alpha
+</pre>
+        After eigenvalues of complex matrix B have been succesfully
+        computed, all what remains is to subtract "alpha" from them
+        all to obtain eigenvalues of A. And nothing has to be done
+        to eigenvectors of B - they are the same for A as well.
+        Simple and elegant!
+<p>
+        Below is an auxiliary function that adds a scalar to the
+        diagonal of a matrix:
+
+<pre>
+
+> add_to_diagonal :: Num a => a -> [[a]] -> [[a]]
+> add_to_diagonal alpha a =
+>       --
+>       -- Add constant alpha to diagonal of matrix A
+>       --
+>       [f ai ni | (ai,ni) <- zip a [0..(length a -1)]]
+>       where
+>           f b k = p++[head q + alpha]++(tail q)
+>               where
+>                   (p,q) = splitAt k b
+>
+
+
+</pre>
+<p>
+<hr>
+<p>
+<b>
+        Examples of iterated eigenvalues
+</b>
+<p>
+
+
+        Here is an example of a symmetric real matrix with results
+        of application of function 'iterated_eigenvalues'.
+<pre>
+        | 7  -2  1 |
+        |-2  10 -2 |
+        | 1  -2  7 |
+
+         [[7.0,     10.0,    7.0],
+          [8.66667, 9.05752, 6.27582],
+          [10.7928, 7.11006, 6.09718],
+          [11.5513, 6.40499, 6.04367],
+          [11.7889, 6.18968, 6.02142],
+          [11.8943, 6.09506, 6.01068],
+          [11.9468, 6.04788, 6.00534],
+          [11.9733, 6.02405, 6.00267],
+          [11.9866, 6.01206, 6.00134],
+          [11.9933, 6.00604, 6.00067],
+          [11.9966, 6.00302, 6.00034],
+          [11.9983, 6.00151, 6.00017],
+          [11.9992, 6.00076, 6.00008],
+          [11.9996, 6.00038, 6.00004],
+          [11.9998, 6.00019, 6.00002],
+          [11.9999, 6.00010, 6.00001],
+          [11.9999, 6.00005, 6.00001]]
+
+          The true eigenvalues are:
+          12, 6, 6
+
+</pre>
+        Here is an example of a hermitian matrix. (Eigenvalues of hermitian
+        matrices are real.) The algorithm works well and converges fast.
+<pre>
+        | 2   0     i|
+        [ 0   1   0  |
+        [ -i  0   2  |
+
+        [[2.8     :+ 0.0, 1.0 :+ 0.0, 1.2     :+ 0.0],
+         [2.93979 :+ 0.0, 1.0 :+ 0.0, 1.06021 :+ 0.0],
+         [2.97972 :+ 0.0, 1.0 :+ 0.0, 1.02028 :+ 0.0],
+         [2.9932  :+ 0.0, 1.0 :+ 0.0, 1.0068  :+ 0.0],
+         [2.99773 :+ 0.0, 1.0 :+ 0.0, 1.00227 :+ 0.0],
+         [2.99924 :+ 0.0, 1.0 :+ 0.0, 1.00076 :+ 0.0],
+         [2.99975 :+ 0.0, 1.0 :+ 0.0, 1.00025 :+ 0.0],
+         [2.99992 :+ 0.0, 1.0 :+ 0.0, 1.00008 :+ 0.0],
+         [2.99997 :+ 0.0, 1.0 :+ 0.0, 1.00003 :+ 0.0],
+         [2.99999 :+ 0.0, 1.0 :+ 0.0, 1.00001 :+ 0.0],
+         [3.0     :+ 0.0, 1.0 :+ 0.0, 1.0     :+ 0.0],
+         [3.0     :+ 0.0, 1.0 :+ 0.0, 1.0     :+ 0.0],
+         [3.0     :+ 0.0, 1.0 :+ 0.0, 1.0     :+ 0.0]]
+
+</pre>
+        Here is another example: this is a complex matrix and it is not
+        even hermitian. Yet, the algorithm still works, although its
+        fluctuates around true values.
+<pre>
+        | 2-i   0      i |
+        | 0     1+i  0   |
+        |   i   0    2-i |
+
+        [[2.0     :+ (-1.33333), 1.0 :+ 1.0, 2.0     :+ (-0.666667)],
+         [1.89245 :+ (-1.57849), 1.0 :+ 1.0, 2.10755 :+ (-0.421509)],
+         [1.81892 :+ (-1.80271), 1.0 :+ 1.0, 2.18108 :+ (-0.197289)],
+         [1.84565 :+ (-1.99036), 1.0 :+ 1.0, 2.15435 :+ (-0.00964242)],
+         [1.93958 :+ (-2.07773), 1.0 :+ 1.0, 2.06042 :+ 0.0777281],
+         [2.0173  :+ (-2.06818), 1.0 :+ 1.0, 1.9827  :+ 0.0681793],
+         [2.04357 :+ (-2.02437), 1.0 :+ 1.0, 1.95643 :+ 0.0243654],
+         [2.03375 :+ (-1.99072), 1.0 :+ 1.0, 1.96625 :+ (-0.00928429)],
+         [2.01245 :+ (-1.97875), 1.0 :+ 1.0, 1.98755 :+ (-0.0212528)],
+         [1.99575 :+ (-1.98307), 1.0 :+ 1.0, 2.00425 :+ (-0.0169263)],
+         [1.98938 :+ (-1.99359), 1.0 :+ 1.0, 2.01062 :+ (-0.00640583)],
+         [1.99145 :+ (-2.00213), 1.0 :+ 1.0, 2.00855 :+ 0.00212504],
+         [1.9968  :+ (-2.00535), 1.0 :+ 1.0, 2.0032  :+ 0.00535265],
+         [2.00108 :+ (-2.00427), 1.0 :+ 1.0, 1.99892 :+ 0.0042723],
+         [2.00268 :+ (-2.00159), 1.0 :+ 1.0, 1.99732 :+ 0.00158978],
+         [2.00213 :+ (-1.99946), 1.0 :+ 1.0, 1.99787 :+ (-0.000541867)],
+         [2.00079 :+ (-1.99866), 1.0 :+ 1.0, 1.9992  :+ (-0.00133514)],
+         [1.99973 :+ (-1.99893), 1.0 :+ 1.0, 2.00027 :+ (-0.00106525)],
+         [1.99933 :+ (-1.9996) , 1.0 :+ 1.0, 2.00067 :+ (-0.000397997)],
+         [1.99947 :+ (-2.00013), 1.0 :+ 1.0, 2.00053 :+ 0.000134972]]
+
+         The true eigenvalues are
+         2 - 2i, 1 + i, 2
+</pre>
+        Some nonsymmetric real matrices have all real eigenvalues and
+        our algorithm still works for such cases. Here is one
+        such an example, which traditionally would have to be treated
+        by one of the Lanczos-like algorithms, specifically designed
+        for nonsymmetric real matrices. Evaluation of
+<br>
+<i>
+        iterated_eigenvalues [[2,1,1],[-2,1,3],[3,1,-1::Double]] 20
+</i>
+<br>
+        gives the following results
+<pre>
+        [[3.0,     -0.70818,-0.291815],
+         [3.06743, -3.41538, 2.34795],
+         [3.02238, -1.60013, 0.577753],
+         [3.00746, -2.25793, 1.25047],
+         [3.00248, -1.88764, 0.885154],
+         [3.00083, -2.06025, 1.05943],
+         [3.00028, -1.97098, 0.970702],
+         [3.00009, -2.0148,  1.01471],
+         [3.00003, -1.99268, 0.992648],
+         [3.00001, -2.00368, 1.00367],
+         [3.0,     -1.99817, 0.998161],
+         [3.0,     -2.00092, 1.00092],
+         [3.0,     -1.99954, 0.99954],
+         [3.0,     -2.00023, 1.00023],
+         [3.0,     -1.99989, 0.999885],
+         [3.0,     -2.00006, 1.00006],
+         [3.0,     -1.99997, 0.999971],
+         [3.0,     -2.00001, 1.00001],
+         [3.0,     -1.99999, 0.999993],
+         [3.0,     -2.0,     1.0]]
+
+         The true eigenvalues are:
+         3, -2, 1
+</pre>
+        Finally, here is a case of a nonsymmetric real matrix with
+        complex eigenvalues:
+<pre>
+        | 2 -3 |
+        | 1  0 |
+</pre>
+        The direct application of "iterated_eigenvalues" would
+        fail to produce expected eigenvalues:
+<pre>
+        1 + i sqrt(2) and 1 - i sqrt (2)
+</pre>
+        But if we first precondition the matrix by adding "i" to its diagonal:
+<pre>
+        | 2+i  -3|
+        | 1     i|
+</pre>
+        and then compute its iterated eigenvalues:
+<br>
+<i>
+        iterated_eigenvalues [[2:+1,1],[-3,0:+1]] 20
+</i>
+<br>
+        then the method will succeed. Here are the results:
+<pre>
+
+        [[1.0     :+ 1.66667, 1.0     :+   0.333333 ],
+        [0.600936 :+ 2.34977, 1.39906 :+ (-0.349766)],
+        [0.998528 :+ 2.59355, 1.00147 :+ (-0.593555)],
+        [1.06991  :+ 2.413,   0.93009 :+ (-0.412998)],
+        [1.00021  :+ 2.38554, 0.99979 :+ (-0.385543)],
+        [0.988004 :+ 2.41407, 1.012   :+ (-0.414074)],
+        [0.999963 :+ 2.41919, 1.00004 :+ (-0.419191)],
+        [1.00206  :+ 2.41423, 0.99794 :+ (-0.414227)],
+        [1.00001  :+ 2.41336, 0.99999 :+ (-0.413361)],
+        [0.999647 :+ 2.41421, 1.00035 :+ (-0.414211)],
+        [0.999999 :+ 2.41436, 1.0     :+ (-0.41436) ],
+        [1.00006  :+ 2.41421, 0.99993 :+ (-0.414214)],
+        [1.0      :+ 2.41419, 1.0     :+ (-0.414188)],
+        [0.99999  :+ 2.41421, 1.00001 :+ (-0.414213)],
+        [1.0      :+ 2.41422, 1.0     :+ (-0.414218)],
+        [1.0      :+ 2.41421, 0.99999 :+ (-0.414213)],
+        [1.0      :+ 2.41421, 1.0     :+ (-0.414212)],
+        [1.0      :+ 2.41421, 1.0     :+ (-0.414213)],
+        [1.0      :+ 2.41421, 1.0     :+ (-0.414213)],
+        [1.0      :+ 2.41421, 1.0     :+ (-0.414213)]]
+</pre>
+        After subtracting "i" from the last result, we will get
+        what is expected.
+
+<p>
+<hr>
+<p>
+<b>
+        Eigenvectors for distinct eigenvalues
+</b>
+<p>
+        Assuming that eigenvalues of matrix A are already found
+        we may now attempt to find the corresponding aigenvectors
+        by solving the following homogeneous equation
+<pre>
+        (A - a I) | x > = 0
+</pre>
+        for each eigenvalue "a". The matrix
+<pre>
+        B = A - a I
+</pre>
+        is by definition singular, but in most cases it can be
+        triangularized by the familiar "factors_QR" procedure.
+<pre>
+        B | x > = Q R | x > = 0
+</pre>
+        It follows that the unknown eigenvector | x &gt; is one of
+        the solutions of the homogeneous equation:
+
+<pre>
+        R | x > = 0
+</pre>
+        where R is a singular, upper triangular matrix with at least one
+        zero on its diagonal.
+<dd>
+        If | x &gt; is a solution we seek, so is its scaled version
+        alpha | x &gt;. Therefore we have some freedom of scaling choice.
+        Since this is a homogeneous equation, one of the components
+        of | x &gt; can be freely chosen, while the remaining components
+        will depend on that choice.
+</pre>
+        To solve the above, we will be working from the bottom up of
+        the matrix equation, as illustrated in the example below:
+<pre>
+        | 0     1     1     3     | | x1 |
+        | 0     1     1     2     | | x2 |      /\
+        | 0     0     2     4     | | x3 | = 0  ||
+        | 0     0     0     0     | | x4 |      ||
+</pre>
+        Recall that the diagonal elements of any triangular matrix
+        are its eigenvalues.
+        Our example matrix has three distinct eigenvalues:
+        0, 1, 2. The eigenvalue 0 has degree of degeneration two.
+        Presence of degenerated eigenvalues complicates
+        the solution process. The complication arises when we have to
+        make our decision about how to solve the trivial scalar equations
+        with zero coefficients, such as
+<pre>
+        0 * x4 = 0
+</pre>
+        resulting from multiplication of the bottom row by vector | x &gt;.
+        Here we have two choices: "x4" could be set to 0, or to any
+        nonzero number 1, say. By always choosing the "0" option
+        we might end up with the all-zero trivial vector --  which is
+        obviously not what we want. Persistent choice of the "1" option,
+        might lead to a conflict between some of the equations, such as
+        the equations one and four in our example.
+<p>
+        So the strategy is as follows.
+<p>
+        If there is at least one zero on the diagonal, find the topmost
+        row with zero on the diagonal and choose for it the solution "1".
+        Diagonal zeros in other rows would force the solution "0".
+        If the diagonal element is not zero than simply solve
+        an arithmetic equation that arises from the substitutions of
+        previously computed components of the eigenvector. Since certain
+        inaccuracies acumulate during QR factorization, set to zero all
+        very small elements of matrix R.
+<p>
+        By applying this strategy to our example we'll end up with the
+        eigenvector
+<pre>
+        < x | = [1, 0, 0, 0]
+</pre>
+
+<p>
+        If the degree of degeneration of an eigenvalue of A is 1 then the
+        corresponding eigenvector is unique -- subject to scaling.
+        Otherwise an eigenvector found by this method is one of many
+        possible solutions, and any linear combination of such solutions
+        is also an eigenvector. This method is not able to find more than one
+        solution for degenerated eigenvalues. An alternative method, which
+        handles degenerated cases, will be described in the next section.
+<p>
+        The function below calculates eigenvectors corresponding to
+        distinct selected eigenvalues of any square matrix A, provided
+        that the singular matrix B = A - a I can still be factorized as Q R,
+        where R is an upper triangular matrix.
+
+<pre>
+
+> eigenkets :: (Scalar a, Fractional a) => [[a]] -> [a] -> [[a]]
+> eigenkets a u
+>       --
+>       -- List of eigenkets of a square matrix A
+>       -- where
+>       --     a is a list of columns of A
+>       --     u is a list of eigenvalues of A
+>       --     (This list does not need to be complete)
+>       --
+>       | null u        = []
+>       | not (null x') = x':(eigenkets a (tail u))
+>       | otherwise     = (eigenket_UT (reverse b) d []):(eigenkets a (tail u))
+>       where
+>           a'  = add_to_diagonal (-(head u)) a
+>           x'  = unit_ket a' 0 (length a')
+>           b   = snd (factors_QR a')
+>           d   = discriminant [head bk | bk <- b] 1
+>           discriminant v n
+>               | null v    = []
+>               | otherwise = x : (discriminant (tail v) m)
+>               where
+>                   (x, m)
+>                       | (head u) == 0     = (n, 0)
+>                       | otherwise         = (n, n)
+>           eigenket_UT c e xs
+>               | null c    = xs
+>               | otherwise = eigenket_UT (tail c) (tail e) (x:xs)
+>               where
+>                   x = solve_row (head c) (head e) xs
+>
+>           solve_row (v:vs) n x
+>               | almostZero v = n
+>               | otherwise    = q/v
+>               where
+>                   q
+>                       | null x = 0
+>                       | otherwise = -(sum_product vs x)
+>
+>           unit_ket b' m n
+>               | null b'              = []
+>               | all (== 0) (head b') = unit_vector m n
+>               | otherwise            = unit_ket (tail b') (m+1) n
+
+</pre>
+<p>
+<hr>
+<p>
+<b>
+        Eigenvectors for degenerated eigenvalues
+</b>
+<p>
+        Few facts:
+<ul>
+<li>
+        Eigenvectors of a general matrix A, which does not have any
+        special symmetry, are not generally orthogonal. However, they
+        are orthogonal, or can be made orthogonal, to another set of
+        vectors that are eigenvectors of adjoint matrix A<sup>+</sup>;
+        that is the matrix obtained by complex conjugation and transposition
+        of matrix A.
+<li>
+        Eigenvectors corresponding to nondegenerated eigenvalues of
+        hermitian or symmetric matrix are orthogonal.
+<li>
+        Eigenvectors corresponding to degenerated eigenvalues are - in
+        general - neither orthogonal among themselves, nor orthogonal
+        to the remaining eigenvectors corresponding to other
+        eigenvalues. But since any linear combination of such degenerated
+        eigenvectors is also an eigenvector, we can orthogonalize
+        them by Gram-Schmidt orthogonalization procedure.
+</ul>
+        Many practical applications deal solely with hermitian
+        or symmetric matrices, and for such cases the orthogonalization
+        is not only possible, but also desired for variety of reasons.
+<dd>
+        But the method presented in the previous section is not able
+        to find more than one eigenvector corresponding to a degenerated
+        eigenvalue. For example, the symmetric matrix
+<pre>
+            |  7  -2   1 |
+        A = | -2  10  -2 |
+            |  1  -2   7 |
+</pre>
+        has two distinct eigenvalues: 12 and 6 -- the latter
+        being degenerated with degree of two. Two corresponding
+        eigenvectors are:
+<pre>
+        < x1 | = [1, -2, 1] -- for 12
+        < x2 | = [1,  1, 1] -- for 6
+</pre>
+        It happens that those vectors are orthogonal, but this is
+        just an accidental result. However, we are missing a third
+        distinct eigenvector. To find it we need another method.
+        One possibility is presented below and the explanation
+        follows.
+<pre>
+
+> eigenket' :: (Scalar a, Fractional a) => [[a]] -> a -> a -> [a] -> [a]
+> eigenket' a alpha eps x' =
+>       --
+>       -- Eigenket of matrix A corresponding to eigenvalue alpha
+>       -- where
+>       --     a is a list of columns of matrix A
+>       --     eps is a trial inaccuracy factor
+>       --         artificially introduced to cope
+>       --         with singularities of A - alpha I.
+>       --         One might try eps = 0, 0.00001, 0.001, etc.
+>       --     x' is a trial eigenvector
+>       --
+>       scaled [xk' - dk | (xk', dk) <- zip x' d]
+>       where
+>           b = add_to_diagonal (-alpha*(1+eps)) a
+>           d = one_ket_solution b y
+>           y = matrix_ket (transposed b) x'
+
+</pre>
+        Let us assume a trial vector | x' &gt;, such that
+<pre>
+        | x' > = | x > + | d >
+        where
+            | x > is an eigenvector we seek
+            | d > is an error of our estimation of | x >
+</pre>
+        We first form a matrix B, such that:
+<pre>
+        B = A - alpha I
+</pre>
+        and multiply it by the trial vector | x' &gt;, which
+        results in a vector | y &gt;
+<pre>
+        B | x' > = |y >
+</pre>
+        On another hand:
+<pre>
+        B | x' > = B | x > + B | d > = B | d >
+        because
+            B | x > = A | x > - alpha | x > = 0
+</pre>
+        Comparing both equations we end up with:
+<pre>
+        B | d > = | y >
+</pre>
+        that is: with the system of linear equations for unknown error | d &gt;.
+        Finally, we subtract error | d &gt; from our trial vector | x' &gt;
+        to obtain the true eigenvector | x &gt;.
+<p>
+        But there is some problem with this approach: matrix B is
+        by definition singular, and as such, it might be difficult
+        to handle. One of the two processes might fail, and their failures
+        relate to division by zero that might happen during either the
+        QR factorization, or the solution of the triangular system of equations.
+<p>
+        But if we do not insist that matrix B should be exactly singular,
+        but almost singular:
+<pre>
+        B = A - alpha (1 + eps) I
+</pre>
+        then this method might succeed. However, the resulting eigenvector
+        will be the approximation only, and we would have to experiment
+        a bit with different values of "eps" to extrapolate the true
+        eigenvector.
+<p>
+        The trial vector | x' &gt; can be chosen randomly, although some
+        choices would still lead to singularity problems. Aside from
+        this, this method is quite versatile, because:
+<ul>
+<li>
+        Any random vector | x' &gt; leads to the same eigenvector
+        for nondegenerated eigenvalues,
+<li>
+        Different random vectors | x' &gt;, chosen for degenerated
+        eigenvalues, produce -- in most cases -- distinct eigenvectors.
+        And this is what we want. If we need it, we can the always
+        orthogonalize those eigenvectors either internally (always
+        possible) or externally as well (possible only for hermitian
+        or symmetric matrices).
+</ul>
+        It might be instructive to compute the eigenvectors for
+        the examples used in demonstration of computation of eigenvalues.
+        We'll leave to the reader, since this module is already too obese.
+<p>
+<hr>
+<p>
+<b>
+        Auxiliary functions
+</b>
+<p>
+        The functions below are used in the main algorithms of
+        this module. But they can be also used for testing. For example,
+        the easiest way to test the usage of resources is to use easily
+        definable unit matrices and unit vectors, as in:
+
+<pre>
+        one_ket_solution (unit_matrix n::[[Double]])
+                         (unit_vector 0 n::[Double])
+        where n = 20, etc.
+
+
+> unit_matrix :: Num a => Int -> [[a]]
+> unit_matrix m =
+>       --
+>       -- Unit square matrix of with dimensions m x m
+>       --
+>       [g 0 k | k <- [0..(m-1)]]
+>       where
+>       g i k
+>           | i == m    = []
+>           | i == k    = 1:(g (i+1) k)
+>           | otherwise = 0:(g (i+1) k)
+>
+
+> unit_vector :: Num a => Int -> Int -> [a]
+> unit_vector i m =
+>       --
+>       -- Unit vector of length m
+>       -- with 1 at position i, zero otherwise
+>       [g i k| k <- [0..(m-1)]]
+>       where
+>           g j k
+>               | j == k    = 1
+>               | otherwise = 0
+
+> diagonals :: [[a]] -> [a]
+> diagonals a =
+>       --
+>       -- Vector made of diagonal components
+>       -- of square matrix a
+>       --
+>       diagonals' a 0
+>       where
+>           diagonals' b n
+>               | null b = []
+>               | otherwise =
+>                   (head $ drop n $ head b) : (diagonals' (tail b) (n+1))
+
+
+</pre>
+
+<pre>
+-----------------------------------------------------------------------------
+--
+-- Copyright:
+--
+--      (C) 1998 Numeric Quest Inc., All rights reserved
+--
+-- Email:
+--
+--      jans@numeric-quest.com
+--
+-- License:
+--
+--      GNU General Public License, GPL
+--
+-----------------------------------------------------------------------------
+</pre>
+</ul>
+</body>
+
+<SCRIPT language="Javascript">
+<!--
+
+// FILE ARCHIVED ON 20010628005806 AND RETRIEVED FROM THE
+// INTERNET ARCHIVE ON 20030626101500.
+// JAVASCRIPT APPENDED BY WAYBACK MACHINE, COPYRIGHT INTERNET ARCHIVE.
+// ALL OTHER CONTENT MAY ALSO BE PROTECTED BY COPYRIGHT (17 U.S.C.
+// SECTION 108(a)(3)).
+
+   var sWayBackCGI = "http://web.archive.org/web/20010628005806/";
+
+   function xLateUrl(aCollection, sProp) {
+      var i = 0;
+      for(i = 0; i < aCollection.length; i++)
+         if (aCollection[i][sProp].indexOf("mailto:") == -1 &&
+             aCollection[i][sProp].indexOf("javascript:") == -1)
+            aCollection[i][sProp] = sWayBackCGI + aCollection[i][sProp];
    }
 
    if (document.links)  xLateUrl(document.links, "href");
diff --git a/QuantumVector.lhs b/QuantumVector.lhs
--- a/QuantumVector.lhs
+++ b/QuantumVector.lhs
@@ -3,1233 +3,1235 @@
 <BASE HREF="http://www.numeric-quest.com/haskell/QuantumVector.html">
 
 <title>
-	 Quantum vector
-</title>
-</head>
-<body>
-<center>
-<h1>
-	***
-</h1>
-<h1>
-	Quantum vector
-</h1>
-<p>
-<b>
-
-	Jan Skibinski, <a href=http://www.numeric-quest.com/news/>
-	Numeric Quest Inc.</a>, Huntsville, Ontario, Canada
-<br>
-	Literate Haskell module <em>QuantumVector.lhs</em>
-<p>
-	Initialized: 2000-05-31, last modified: 2000-06-10
-</b>
-</center>
-
-<blockquote>
-<em>
-<p>
-<hr>
-<p>
-	This is our attempt to model the abstract Dirac's formalism
-	of Quantum Mechanics in Haskell. Although we have been
-	developing quantum mechanical applications and examples for some time [2], the
-	machinery used there is tightly coupled to a concrete
-	representation of states and observables by complex vectors
-	and matrices. implemented mainly as Haskell lazy lists.
-<p>
-	However, the Dirac's formalism in Hilbert space is much more
-	abstract than that, and many problems of Quantum Mechanics can be
-	solved without referring to any
-	particular matrix representation, but using certain generic properties
-	of operators, such as their commutative relations instead.
-	Haskell seems to be well suited for such abstract tasks,
-	even in its current form that does not support any
-	of the abstract notions of computer algebra as yet.
-	This has been already recognized by Jerzy Karczmarczuk [1],
-	where he proposes a very interesting representation of Hilbert
-	space and illustrates it by several powerful examples.
-	But the task is not trivial and far from being complete.
-	Quantum Mechanics presents many challenges to any formalism
-	and only by careful examination of many of its facets
-	and alternative approaches, a consistent model of
-	Dirac's formalism can be developed for Haskell. Hoping to
-	help with solving this problem, we present here a computing
-	abstract, which is quite different from that of [1].
-<p>
-	We recognize a quantum state as an abstract vector | x &gt;,
-	which can be represented in one of many possible bases -- similar
-	to many alternative representations of a 3D vector in rotated systems
-	of coordinates. A choice of a particular basis is controlled
-	by a generic type variable, which can be any Haskell object
-	-- providing that it supports a notion of equality and ordering.
-	A state which is composed of many quantum subsystems, not
-	necessarily of the same type, can be represented in a vector
-	space considered to be a tensor product of the subspaces.
-
-<p>
-	With this abstract notion we proceed with Haskell definition of two
-	vector spaces: Ket and its dual Bra. We demonstrate
-	that both are properly defined according to the abstract
-	mathematical definition of vector spaces. We then introduce inner
-	product and show that our Bra and Ket can be indeed
-	considered the vector spaces with inner product. Multitude
-	of examples is attached in the description. To verify
-	the abstract machinery developed here we also provide the basic library
-	module <a href="http://www.numeric-quest.com/haskell/Momenta.html">
-	Momenta</a> -- a non-trivial example designed to compute Clebsch-Gordan coefficients
-	of a transformation from one basis of angular momenta to another.
-<p>
-	Section 6 is a rehash of known definitions of linear operators
-	with the emphasis on both Dirac and Haskell notations and on
-	Haskell examples. The formalism developed here centers around
-	two operations: a scalar product of two vectors, <b>x &lt;&gt; y</b>,
-	and a closure operation, <b>a &gt;&lt; x</b>, which can be considered
-	an application of a quantum operator <b>a</b> to a vector <b>x</b>.
-	At this stage our formalism applies only to discrete cases, but
-	we hope to generalize it on true Hilbert space as well.
-</em>
-<p>
-<hr>
-<p>
-<b>
-	Contents
-</b>
-<ul>
-<li>
-	1. Infix operators
-<li>
-	2. Vector space
-<li>
-	3. Ket vector space
-<li>
-	4. Bra vector space
-<li>
-	5. Bra and Ket spaces as inner product spaces
-<li>
-	6. Linear operators
-<ul>
-<li>            6.1. Operator notation
-<li>
-		6.2. Renaming the representation
-<li>
-		6.3. Closure formula, or identity operator
-<li>
-		6.4. Changing the representation
-<li>
-		6.5. Implementation of the operator equation A | x &gt; = | y &gt;
-<li>
-		6.6. Inverse operator
-<li>
-		6.7. Matrix representation of an operator
-<li>
-		6.8. Adjoint operator
-<li>
-		6.9. Unitary operator
-<li>
-		6.10. Hermitian operator
-</ul>
-<li>
-	7. Showing kets and bras
-<li>
-	8. Data Tuple for tensor products
-<li>
-	9. References
-<li>
-	10. Copyright and license
-
-</ul>
-
-<p>
-<hr>
-<p>
-<b>
-	1. Infix operators
-</b>
-<p>
-	Haskell requires that fixities of infix operators are defined
-	at the top of the module. So here they are. They are
-	to be explained later.
-
-</b>
-<pre>
-
-> module QuantumVector where
-> import Complex                  -- our Scalar is Complex Double
-> import Fraction hiding (reduce) -- to bypass enum bug in Ratio and for better pretty printing
-> import List (nub)
-
-> infixl 7 *>  -- tensor product of two kets
-> infixl 7 <*  -- tensor product of two bras
-
-> -- scalar-ket multiplication
-> infix 6 |>
-> -- scalar-bra multiplication
-> infix 6 <|
-
-
-> infixl 5 +>  -- sum of two kets
-> infixl 5 <+  -- sum of two bras
-
-
-> infix 4 <>  -- inner product
-> infix 5 ><  -- closure
-
-</pre>
-<p>
-<hr>
-<p>
-<b>
-	2. Vector space
-</b>
-<p>
-	Definition. A set V of elements x ,y ,z ,...is called a vector
-	(or linear) space over a complex field C if
-<ul>
-<li>
-	(a) vector addition  + is defined in V such that V is an
-	abelian group under addition, with identity element 0
-<pre>
-	1: <b>x</b> + <b>y</b>       = <b>y</b> + <b>x</b>
-	2: <b>x</b> + (<b>y</b> + <b>z</b>) = (<b>x</b> + <b>y</b>) + <b>z</b>
-	3: <b>0</b> + <b>x</b>       = <b>x</b> + <b>0</b>
-
-</pre>
-<p>
-<li>
-	(b) the set is close with respect to scalar multiplication
-	and vector addition
-<pre>
-	4: a (<b>x</b> + <b>y</b>)   = a <b>x</b> + a <b>y</b>
-	5: (a + b) <b>x</b>   = a <b>x</b> + b <b>x</b>
-	6: a (b <b>x</b>)     = (a b) <b>x</b>
-	7: 1 <b>x</b>         = <b>x</b>
-	8: 0 <b>x</b>         = <b>0</b>
-	    where
-		a, b, c are complex scalars
-</pre>
-</ul>
-	Definition. The maximum number of linearly independent vectors
-	in V or, what is the same thing, the minimum number of linearly
-	independent vectors required to span V is the dimension r of
-	vector space V.
-<p>
-	Definition. A set of r linearly independent vectors is called
-	a basis of the space. Each vector of the space is then a unique
-	linear combination of the vectors of this basis.
-<p>
-	Based on the above definitions we will define two vector
-	spaces: ket space and its dual -- bra space, which, in addition
-	to the above properties, will also support
-	several common operations -- grouped below in the class
-	DiracVector.
-<pre>
-
-> class DiracVector a where
->     add        :: a -> a -> a
->     scale      :: Scalar -> a -> a
->     reduce     :: a -> a
->     basis      :: a -> [a]
->     components :: a -> [Scalar]
->     compose    :: [Scalar] -> [a] -> a
->     dimension  :: a -> Int
->     norm       :: a -> Double
->     normalize  :: a -> a
-
->     dimension x   = length (basis x)
->
->     normalize x
->         | normx == 0 = x
->         | otherwise  = compose cs (basis x)
->          where
->             cs     = [a*v :+ b*v |a :+ b <- components x]
->             v      = 1 / normx
->             normx  = norm x
-
-</pre>
-<p>
-<hr>
-<p>
-<b>
-	3. Ket vector space
-</b>
-<p>
-	We submit that the following datatype and accompanying
-	operations define a complex vector space, which we will call
-	the ket vector space.
-<pre>
-
-> type Scalar = Complex Double
-
-> data Ket a  =
->            KetZero                     -- zero ket vector
->          | Ket a                       -- base ket vector
->          | Scalar  :|> Ket a           -- scaling ket vectors
->          | Ket a   :+> Ket a           -- spanning ket space
-
-</pre>
-
-	A tensor product of two ket spaces is also a ket space.
-<pre>
-
-> (*>) :: (Ord a, Ord b) => Ket a -> Ket b -> Ket (Tuple a b)
-> Ket a   *> Ket b    = Ket (a :* b)
-> x       *> KetZero  = KetZero
-> KetZero *> y        = KetZero
-> x       *> y        = foldl1 (:+>) [((Bra a <> x) * (Bra b <> y)) :|> Ket (a :* b)
->                                   | Ket a <- basis x, Ket b <- basis y]
-
-
-> (|>) :: Ord a => Scalar -> Ket a -> Ket a
->     --
->     -- Multiplication of ket by scalar
->     --
-> s |> (x :+> y)  = (s |> x) +> (s |> y)
-> s |> KetZero    = KetZero
-> 0 |> x          = KetZero
-> s |> (s2 :|> x) = (s * s2) |> x
-> s |> x          = s :|> x
-
-
-> (+>) :: Ord a => Ket a  -> Ket a  -> Ket a
->     --
->     -- Addition of two kets
->     --
-> x +> KetZero = x
-> KetZero +> x = x
-> x +> y       = reduce (x :+> y)
-
-
-> instance (Eq a, Ord a) => Eq (Ket a) where
->     --
->     -- Two ket vectors are equal if they have identical
->     -- components
->     --
->     x == y = and [c k x == c k y  | k <- basis x]
->         where
->             c k x = (toBra k) <> x
-
-
-</pre>
-	The data Ket is parametrized by type variable "a", which can be
-	anything that can be compared for equality and ordered: integer,
-	tuple, list of integers, etc. For example, the data
-	constructor <code>Ket (3::Int)</code> creates a base vector <code>|3></code>,
-	annotated by Int.
-	Similarly, <code>Ket (2::Int,1::Int)</code>, creates a base vector
-	<code>|(2,1)></code> annotated by a tuple of Ints. Those two
-	vectors belong to two different bases.
-<p>
-	The eight examples below illustrate the eight defining equations
-	of the vector space, given in section 1. All of them evaluate
-	to True.
-<pre>
-
-	1: Ket 2 +> Ket 3            == Ket 3 +> Ket 2
-	2: Ket 1 +> (Ket 2 +> Ket 3) == (Ket 1 +> Ket 2) +> Ket 3
-	3: Ket 1 +> KetZero          == KetZero +> Ket 1
-	4: 5 |> (Ket 2 +> Ket 3)     == 5 |> Ket 2 +> 5 |> Ket 3
-	5: (5 + 7) |> Ket 2          == 5 |> Ket 2 +> 7 |> Ket 2
-	6: 2 |> (4 |> Ket 2)         == 8 |> Ket 2
-	7: 1 |> Ket 2                == Ket 2
-	8: 0 |> Ket 2                == KetZero
-</pre>
-	The ket expressions can be pretty printed, as shown below.
-<pre>
-	Ket 2 +> Ket 3        ==> 1.0 |2> + 1.0 |3>
-	5 |> (Ket 2 +> Ket 3) ==> 5.0 |2> + 5.0 |3>
-	2 |> (4 |> Ket 2)     ==> 8.0 |2>
-</pre>
-	In order to support all those identities we also need several
-	additional functions for reducing the vector to its canonical form,
-	for composing the ket vector, and for extracting the ket
-	basis and the ket components -- as shown below.
-<pre>
-
-
-> reduceKet :: Ord a => Ket a -> Ket a
-> reduceKet x
->     --
->     -- Reduce vector `x' to its canonical form
->     --
->     = compose cs ks
->       where
->           ks = basis x
->           cs = [toBra k <> x | k <- ks]
-
-
-> ketBasis :: Ord a => Ket a -> [Ket a]
->     --
->     -- Sorted list of unique base vectors of the ket vector
->     --
-> ketBasis KetZero        = []
-> ketBasis (Ket k)        = [Ket k]
-> ketBasis (s :|> x)      = [x]
-> ketBasis (k1 :+> k2)    = nub (ketBasis k1 ++ ketBasis k2)
-
-
-> toBra :: Ord a => Ket a -> Bra a
->     --
->     -- Convert from ket to bra vector
->     --
-> toBra (Ket k)           = Bra k
-> toBra (x :+> y)         = toBra x :<+ toBra y
-> toBra (p :|> x)         = (conjugate p) :<| toBra x
-
-
-> instance Ord a => DiracVector (Ket a)  where
->     add           = (+>)
->     scale         = (|>)
->     reduce        = reduceKet
->     basis         = ketBasis
->     components x  = [toBra e <> x | e <- basis x]
->     compose xs ks = foldl1 (:+>) [fst z :|> snd z  | z <- zip xs ks]
->
->     norm KetZero  = 0
->     norm x        = sqrt $ realPart (toBra x <> x)
-
-
-</pre>
-	But those auxilliary functions refer to vectors from the
-	conjugated space bra, which we shall now define below.
-<p>
-<hr>
-<p>
-<b>
-	4. Bra vector space
-</b>
-<p>
-	Definition. Let V be the defining n-dimensional complex vector
-	space. Associate with the defining n-dimensional complex vector
-	space V a conjugate (or dual) n-dimensional vector space
-	obtained by complex conjugation of elements x in V.
-<p>
-	We will call this space the bra space, and the corresponding vectors
-	- the bra vectors. Further, we submit that the following datatype and the corresponding
-	operations define bra space in Haskell.
-<pre>
-
-> data Bra a =
->            BraZero                   -- zero bra vector
->          | Bra a                     -- base bra vector
->          | Scalar :<| Bra a          -- scaling bra vectors
->          | Bra a  :<+ Bra a          -- spanning bra space
-
-
-</pre>
-	A tensor product of two bra spaces is also a bra space.
-<pre>
-
-> (<*) :: (Ord a, Ord b) => Bra a -> Bra b -> Bra (Tuple a b)
-> Bra a   <* Bra b    = Bra (a :* b)
-> x       <* BraZero  = BraZero
-> BraZero <* y        = BraZero
-> x       <* y        = foldl1 (:<+) [((x <> Ket a) * (y <> Ket b)) :<| Bra (a :* b)
->                                   | Bra a <- basis x, Bra b <- basis y]
-
-> (<|) :: Ord a => Scalar -> Bra a -> Bra a
-> s <| (x :<+ y)  = (s <| x) <+ (s <| y)
-> s <| BraZero    = BraZero
-> 0 <| x          = BraZero
-> s <| (s2 :<| x) = (s * s2) <| x
-> s <| x          = s :<| x
-
-
-> (<+) :: Ord a => Bra a -> Bra a -> Bra a
->     --
->     -- Sum of two bra vectors
->     --
-> x <+ BraZero = x
-> BraZero <+ x  = x
-> x <+ y       = reduce (x :<+ y)
-
-
-> instance (Eq a, Ord a) => Eq (Bra a) where
->     --
->     -- Two bra vectors are equal if they have
->     -- identical components
->     --
->     --
->     x == y = and [c b x == c b y  | b <- basis x]
->         where
->             c b x = x <> toKet b
-
-</pre>
-
-	Similarly to what we have done for ket vectors, we also define several
-	additional functions for reducing the bra vector to its canonical form,
-	for composing the bra vector, and for extracting the bra
-	basis and the bra components -- as shown below.
-<pre>
-
-> reduceBra :: Ord a => Bra a -> Bra a
-> reduceBra x
->     --
->     -- Reduce bra vector `x' to its canonical form
->     --
->     = compose cs bs
->       where
->           bs = basis x
->           cs = [x <> toKet b | b <- bs]
-
-
-> braBasis :: Ord a => Bra a -> [Bra a]
->     --
->     -- List of unique basis of the bra vector
->     --
-> braBasis BraZero        = []
-> braBasis (Bra b)        = [Bra b]
-> braBasis (s :<| x)     = [x]
-> braBasis (b1 :<+ b2)   = nub (braBasis b1 ++ braBasis b2)
-
-
-> toKet :: Ord a => Bra a -> Ket a
->     --
->     -- Convert from bra to ket vector
->     --
-> toKet (Bra k)            = Ket k
-> toKet (x :<+ y)        = toKet x :+> toKet y
-> toKet (p :<| Bra k)    = (conjugate p) :|> Ket k
-
-
-> instance Ord a => DiracVector (Bra a)  where
->     add           = (<+)
->     scale         = (<|)
->     reduce        = reduceBra
->     basis         = braBasis
->     components x  = [x <> toKet e | e <- basis x]
->     compose xs ks = foldl1 (:<+) [fst z :<| snd z  | z <- zip xs ks]
->
->     norm BraZero  = 0
->     norm x        = sqrt $ realPart (x <> toKet x)
-
-
-</pre>
-<p>
-<hr>
-<p>
-<b>
-	5. Bra and Ket spaces as inner product spaces
-</b>
-<p>
-
-	Definition. A complex vector space V is an inner product space
-	if with every pair of elements x ,y  from V there is associated
-	a unique inner (or scalar) product < x | y > from C, such that
-<pre>
-	9:  < x | y >          = < y | x ><sup>*</sup>
-	10: < a x | b y >      = a<sup>*</sup> b < x | y >
-	11: < z | a x + b y >  = a < z | x > + b < z, y >
-	    where
-		a, b, c are the complex scalars
-</pre>
-	We submit that the dual ket and bra spaces are inner product
-	spaces, providing that the inner product is defined by the operator
-	<> given below:
-<pre>
-
-
-
-> (<>) :: Ord a => Bra a -> Ket a -> Scalar
->     --
->     -- Inner product, or the "bra-ket" product
->     --
-> BraZero       <> x              = 0
-> x             <> KetZero        = 0
-> Bra i         <> Ket j          = d i j
-> (p :<| x)     <> (q :|> y)      = p * q * (x <> y)
-> (p :<| x)     <> y              = p * (x <> y)
-> x             <> (q :|> y)      = q * (x <> y)
-> x             <> (y1 :+> y2)    = (x  <> y1) + (x <> y2)
-> (x1 :<+ x2)   <> y              = (x1 <> y)  + (x2 <> y)
-
-
-> d :: Eq a => a -> a -> Scalar
-> d i j
->     --
->     -- Classical Kronecker's delta
->     -- for instances of Eq class
->     --
->     | i == j    = 1
->     | otherwise = 0
->
-
-</pre>
-	The expressions below illustrate the definitions 9-11.
-	They are all true.
-<pre>
-9:  (toBra x <> y) == conjugate (toBra y <> x)
-10: (toBra (a |> x) <> (b |> y)) == (conjugate a)*b*(toBra x <> y)
-11: (toBra z <> (a |> x +> b |> y)) == a*(toBra z <> x) + b*(toBra z <> y)
-    where
-	x = (2 :+ 3) |> Ket 2
-	y = ((1:+2) |> Ket 3) +> Ket 2
-	z = Ket 2 +> Ket 3
-	a = 2:+1
-	b = 1
-</pre>
-<p>
-<hr>
-<p>
-<b>
-	6. Linear operators
-</b>
-<p>
-
-	Linear operators, or simply operators, are functions from vector
-	in representation a <em>a</em> to vector in representation <em>b</em>
-
-<pre>
-	a :: Ket a -> Ket b
-</pre>
-	although quite often the operations are performed
-	on the same representation. The linear operators A are defined by
-<pre>
-	A (c1 | x > + c2 | y > ) = c1 A | x > + c2 A | y >
-</pre>
-
-<p>
-	We will describe variety of special types
-	of operators, such as inverse, unitary, adjoint and hermitian.
-	This is not an accident that the names of those operators
-	resemble names from matrix calculus, since
-	Dirac vectors and operators can be viewed as matrices.
-<p>
-	With the exception of variety of examples, no significant
-	amount of Haskell code will be added here. This section
-	is devoted mainly to documentation; we feel that it is important
-	to provide clear definitions of the operators, as seen from
-	the Haskell perspective. Being a strongly typed language,
-	Haskell might not allow for certain relations often shown
-	in traditional matrix calculus, such as
-<pre>
-	A = B
-</pre>
-	since the two operators might have in fact two distinct signatures.
-	In matrix calculus one only compares tables of unnamed numbers,
-	while in our Haskell formalism we compare typed
-	entieties.
-	For this reason, we will be threading quite
-	slowly here, from one definition to another to assure that
-	they are correct from the perspective of
-	typing rules of Haskell.
-
-<p>
-<hr>
-<p>
-<b>
-	6.1. Operator notation
-</b>
-<p>
-	The notation
-<pre>
-	| y > = A | x >
-</pre>
-	is pretty obvious: operator A acting on vector | x &gt; produces
-	vector | y &gt;. It is not obvious though whether both vectors
-	use the same representation. The Haskell version of the above
-	clarifies this point, as in this example:
-<pre>
-	y = a >< x
-	   where
-		a :: Ket Int -> Ket (Int, Int)
-		a = ......
-</pre>
-	In this case it is seen the two vectors have distinct
-	representations. The operator &gt;&lt; will be explained soon
-	but for now treat is as an application of an operator
-	to a vector, or some kind of a product of the two.
-<p>
-	The above can be also written as
-<pre>
-	| y > = | A x >
-</pre>
-	where the right hand side is just a defining label saying that the
-	resulting vector has been produced by operator A acting on | x &gt;.
-<p>
-	Linear operators can also act on the bra vectors
-<pre>
-	< y | = < x | A
-		<---
-</pre>
-	providing that they have correct signatures. This postfix notation
-	though is a bit awkward, and not supported by Haskell. To avoid
-	confusion we will be using the following notation instead:
-<pre>
-	< y | = < A x |
-</pre>
-	which says that bra y is obtained from ket y,
-	where | y &gt; = | A x &gt;,  as before. In Haskell we will write
-	it as
-<pre>
-	y = toBra $ a >< x
-
-</pre>
-
-<p>
-<hr>
-<p>
-<b>
-	6.2. Renaming the representation
-</b>
-<p>
-	One simple example of an operator is <em>label "new"</em>
-	which renames a vector representation by adding extra label
-	<em>"new"</em> in the basis vectors <em>Ket a</em>. Silly
-	as it sounds, this and other similar re-labeling operations
-	can be actually quite useful; for example,
-	we might wish to distinguish between old and new bases, or
-	just to satisfy the Haskell typechecker.
-<pre>
-
-	label :: (Ord a, Ord b) => b -> Ket a -> Ket (b, a)
-	label i (Ket a) = Ket (i, a)
-	label i x       = (label i) >< x
-
-</pre>
-<p>
-<hr>
-<p>
-<b>
-	6.3. Closure formula, or identity operator
-</b>
-<p>
-	Although the general Dirac formalism often refers to
-	abstract vectors | x &gt;, our implementation must
-	be more concrete than that -- we always represent the
-	abstract vectors in some basis of our choice, as in:
-<pre>
-	| x > = c<sub>k</sub> | k >   (sum over k)
-</pre>
-	To recover the component c<sub>k</sub> we form
-	the inner product
-<pre>
-	    c<sub>k</sub> = < k | x >
-</pre>
-	Putting it back to the previous equation:
-<pre>
-	| x > = < k | x > | k >      (sum over k)
-	      = | k > < k | x >
-	      = Id | x >
-	where
-	    Id = | k > < k |        (sum over k)
-</pre>
-	we can see that the vector | x &gt; has been abstracted away. The formula
-	says that vector | x &gt; can be decomposed in any basis
-	by applying identity operator Id to it. This is also known
-	as a closure formula. Well, Haskell has the "id" function too,
-	and we could apply it to any ket, as in:
-<pre>
-	id (Ket 1 +> 10 |> Ket 2) ==> | 1 > + 10 | 2 >
-</pre>
-	but Haskell's "id" does not know anything about representations;
-	it just gives us back the same vector | x &gt; in our original
-	representation.
-<p>
-	We need something more accurately depicting the closure
-	formula | k &gt; &lt; k |, that would allow us to change
-	the representation if we wanted to, or leave it alone
-	otherwise. Here is the <em>closure</em> function and
-	coresponding operator (&gt;&lt;) that implement
-	the closure formula for a given <em>operator</em>.
-<pre>
-
-> closure :: (DiracVector a, DiracVector b) => (a -> b) -> a -> b
-> closure operator x =
->    compose' (components x) (map operator (basis x))
->      where
->         compose' xs ks = foldl1 add (zipWith scale xs ks)
-
-> operator >< x = closure operator x
-
-
-</pre>
-<p>
-<hr>
-<p>
-<b>
-	6.4. Changing the representation
-</b>
-<p>
-	The silly <em>label</em> function found in the comment of the
-	section 6.1 uses in fact the closure relation. But we could
-	define is simpler than that:
-<pre>
-
-> label i (Ket x) = Ket (i, x)
-
-</pre>
-	and then apply a closure to a vector x, as in:
-<pre>
-	closure (label 0) (Ket 2 +> 7 |> Ket 3)
-		==> 1.0 |(0,2)> + 7.0 |(0,3)>
-</pre>
-	Somewhat more realistic example involves "rotation" of
-	the old basis with simulaneous base renaming:
-<pre>
-
-> rot :: Ket Int -> Ket (Int, Int)
-> rot (Ket 1) = normalize $ Ket (1,1) +> Ket (1,2)
-> rot (Ket 2) = normalize $ Ket (1,1) +> (-1) |> Ket (1,2)
-> rot (Ket _) = error "exceeded space dimension"
-
-</pre>
-	The example function
-	<em>rot</em> assumes transformation from
-	two-dimensional basis [| 1 &gt;, | 2 &gt;] to another
-	two-dimensional basis [| (1,1) &gt;, | (1,2) &gt;] by
-	expressing the old basis by the new one. Given this
-	transformation we can apply the closure to any vector | x &gt;
-	represented in the old basis; as a result we will get
-	the same vector | x &gt; but represented in the new
-	basis.
-<pre>
-	rot >< (Ket 1 +> 7 |> Ket 2) ==>
-		5.65685 |(1,1)> + -4.24264 |(1,2)>
-</pre>
-
-<p>
-<hr>
-<p>
-<b>
-	6.5. Implementation of the operator equation A | x &gt; = | y &gt;
-</b>
-<p>
-	The Haskell implementation of the closure formula is not just
-	a useless simulation of the theoretical closure  - it is one of the
-	workhorses of the apparatus employed here.
-<p>
-	We will be using linear operators to evaluate equations
-	like this:
-<pre>
-	| y > = A | x >
-</pre>
-	The resulting vector | y &gt; can have either the same
-	representation as | x &gt; or different - depending on
-	the nature of operator A. The most general type of
-	A is
-<pre>
-	Ket a -> Ket b
-</pre>
-	but more often than not the basis will be the same as before.
-	But how we define the operator A itself? The best way is
-	to specify how it acts on the base vectors | k &gt;. If we can chose
-	as our basis the eigenvectors of A this would be even better,
-	because the definition of A would be then extremely simple.
-	After inserting the identity | k &gt;&lt; k | between the
-	operator A and vector | x &gt; in the above equation one gets
-<pre>
-	| y > = A | k > < k | x >            (sum over k)
-</pre>
-	This will be implemented in Haskell as:
-<pre>
-	y = a >< x
-</pre>
-	The closure formula will take care of the rest and it will
-	produce the result | y &gt; . The examples previously given
-	do just that. One caveat though: since operator A will
-	only be defined for the basis, but not for other vectors,
-	skipping the closure formula and coding directly
-<pre>
-	y = a' x
-</pre>
-	is not advisable.
-	This will certainly fail for vectors other than basis unless
-	one makes extra provisions for that. This is what we did
-	in module Momenta, before we had the closure support ready.
-	Using the closure is safe and this is the way to go!
-
-
-<p>
-<hr>
-<p>
-<b>
-	6.6. Inverse operator
-</b>
-<p>
-	An operator B = A<sup>-1</sup> that inverses the
-	equation
-<pre>
-	| y > = A | x >
-	  y   = a >< x -- where a :: Ket a -> Ket b
-</pre>
-	into
-<pre>
-	| x > = B | y >
-	  x   = b >< y -- where b :: Ket b -> Ket a
-</pre>
-	is called the inverse operator.
-<p>
-	For example, the inverse operator to the operator <em>label i</em>
-	is:
-<pre>
-
-> label' :: (Ord a, Ord b) => Ket (a, b) -> Ket b
-> label' (Ket (i, x)) = Ket x
-
-</pre>
-	It is easy to check that applying the operator A and its inverse
-	A<sup>-1</sup> in succession to any ket | x &gt; one should
-	obtain the same vector | x &gt; again, as in:
-
-<pre>
-	A<sup>-1</sup> A | x > = | x >
-
-	-- Haskell example
-	label' >< (label 0 >< x) == x
-	   where
-		x = Ket 1 +> 10 |> Ket 7
-	==> True
-</pre>
-	Once again, notice the omnipresent closure operator in Haskell
-	implementation. Tempting as it might be to implement the
-	above example as
-<pre>
-	-- Do not do it in Haskell!!!
-	(label' . label 0) >< x == x
-	    where
-	       x = Ket 1 +> 10 |> Ket 7
-	==> True
-</pre>
-	this is not a recommended way. Although this example would work,
-	but a similar example for <em>rotation</em> operations would
-	fail in a spectacular way. The correct way is to insert the
-	closure operator between two rotations:
-<pre>
-	rot' >< (rot >< x) == x
-	    where
-		x = Ket 1 +> 10 |> Ket 2
-	==> True
-</pre>
-	where the inverse operator <em>rot'</em> is defined below:
-
-<pre>
-
-> rot' :: Ket (Int, Int) -> Ket (Int)
-> rot' (Ket (1,1)) = normalize $ Ket 1 +> Ket 2
-> rot' (Ket (1,2)) = normalize $ Ket 1 +> (-1) |> Ket 2
-> rot' (Ket (_,_)) = error "exceeded space dimension"
-
-</pre>
-<p>
-<hr>
-<p>
-<b>
-	6.7. Matrix representation of an operator
-</b>
-<p>
-<p>
-	The scalar products
-<pre>
-	< k | A l' > = < k | A | l' >
-</pre>
-	such that | k &gt; and | l' &gt; are the base vectors
-	(in general belonging to two different bases), form a transformation
-	matrix Akl'.
-<p>
-	In Haskell this matrix is formed as
-<pre>
-	k <> a >< l'
-	    where
-	       k  = ... :: Bra b
-	       l' = ... :: Ket a
-	       a  = ... :: Ket a -> Ket b
-</pre>
-
-<p>
-<hr>
-<p>
-<b>
-	6.8. Adjoint operator
-</b>
-<font color="teal">
-<p>
-	Our definition of adjoint operator is different
-	than that in theory of determinants. Many books, not necessarily
-	quantum mechanical oriented, refer to the latter as <em>
-	classical adjoint operator</em>.
-</font>
-
-<p>
-	With every linear operator A we can associate an adjoint
-	operator B = A<sup>+</sup>, also known as Hermitian conjugate
-	operator, such that equality of the two scalar
-	products
-<pre>
-	< A<sup>+</sup> u | x > = < u | A x >
-</pre>
-	holds for every vector | u &gt; and | x &gt;.
-	In Haskell notation the above can be written as:
-<pre>
-	(toBra (b >< u) <> x) == toBra u <> a >< x
-	    where
-		 a = ... :: Ket a -> Ket b
-		 b = ... :: Ket b -> Ket a
-		 x = ... :: Ket a
-		 u = ... :: Ket b
-
-</pre>
-	For example, the operator <em>rot'</em> is adjoint
-	to operator <em>rot</em>
-<pre>
-	(toBra (rot' >< u) <> x) == (toBra u <> rot >< x)
-	    where
-		x = Ket 1 +> 10 |> Ket 2
-		u = Ket (1,1) +> 4 |> Ket (1,2)
-	==> True
-
-</pre>
-	It can be shown that
-<pre>
-	(A<sup>+</sup>)<sup>+</sup> = A
-</pre>
-	Matrix A<sup>+</sup> is conjugate transposed to A, as
-	proven below
-
-<pre>
-	= A<sup>+</sup>kl'
-	= < k | A<sup>+</sup> | l' >
-	= < k | A<sup>+</sup> l' >
-	= < A<sup>+</sup> l' | k ><sup>*</sup>
-	= < l' | A | k ><sup>*</sup>
-	= A<sup>*</sup>l'k
-</pre>
-
-
-<p>
-<hr>
-<p>
-<b>
-	6.9. Unitary operator
-</b>
-<p>
-	Unitary transformations preserve norms of vectors.
-	We say, that the norm of a vector is invariant under unitary
-	transformation.
-	Operators describing such transformations are called
-	unitary operators.
-<pre>
-	< A x | A x > = < x | x >
-
-</pre>
-	The example of this is rotation transformation, which indeed
-	preserves the norm of any vector x, as shown in this Haskell
-	example
-<pre>
-	(toBra u <> u) == (toBra x <> x)
-	    where
-		u = rot >< x
-		x = Ket 1 +> 10 |> Ket 2
-
-	==> True
-</pre>
-<p>
-	Inverse and adjoint operators of unitary operators are equal
-<pre>
-	A<sup>-1</sup> = A<sup>+</sup>
-</pre>
-	which indeed is true for our example operator <em>rot</em>.
-<p>
-	Computation of the adjont operators A<sup>+</sup> from A
-	is quite easy since the process is rather mechanical, as
-	described in the previous section. On the other hand, finding
-	inverse operators is not that easy, with the exception of
-	some simple cases, such as our example 2D rotation.
-	It is therefore important to know whether a given operator
-	is unitary, as this would allow us to replace inverse
-	operators by adjoint operators.
-
-
-<p>
-<hr>
-<p>
-<b>
-	6.10. Hermitian operator
-</b>
-<p>
-	A Hermitian operator is a self adjoint operator; that is
-<pre>
-	< A u | x > = < u | A x >
-</pre>
-	Another words: A<sup>+</sup> = A.
-<p>
-	Notice however, that this relation holds only for the
-	vectors in the same representation, since in general
-	the operators
-	A and A<sup>+</sup> have distinct signatures, unless
-	types a, b are the same:
-<pre>
-	a  :: Ket a -> Ket b -- operator A
-	a' :: Ket b -> Ket a -- operator A<sup>+</sup>
-</pre>
-	Elements of hermitian matrices must therefore satisfy:
-<pre>
-	 Aij = (Aji)<sup>*</sup>
-</pre>
-	In particular, their diagonal elements must be real.
-<p>
-	Our example operator <em>rot</em> is not hermitian,
-	since it describes transformation from one basis
-	to another.
-	But here is a simple example of a hermitian operator, which
-	multiplies any ket by scalar 4. It satisfies our definition:
-<pre>
-	(toBra (a >< u) <> x) == (toBra u <> a >< x)
-	where
-	    a v = 4 |> v
-
-	    x = Ket 1 +> Ket 2
-	    u = Ket 2
-
-	==> True
-</pre>
-	Here is a short quote from [3].
-<blockquote>
-	Why do we care whether an operator is Hermitian?
-	It's because of a few theorems:
-
-<ol>
-<li>
-	The eigenvalues of Hermitian operators are always real.
-<li>
-	The expectation values of Hermitian operators are always real.
-<li>
-	The eigenvectors of Hermitian operators span the Hilbert space.
-<li>
-	The eigenvectors of Hermitian operators belonging to distinct eigenvalues are orthogonal.
-</ol>
-	In quantum mechanics, these characteristics are essential if you
-	want to represent measurements with operators. Operators must be
-	Hermitian so that observables are real. And, you must be able to
-	expand in the eigenfunctions - the expansion coefficients
-	give you probabilities!
-</blockquote>
-<p>
-<hr>
-<p>
-<b>
-	7. Showing kets and bras
-</b>
-<p>
-	Lastly, here are show functions for pretty printing of Dirac
-	vectors.
-<pre>
-
-> instance (Show a, Eq a, Ord a) => Show (Ket a)  where
->     showsPrec n KetZero   = showString "| Zero >"
->     showsPrec n (Ket j)   = showString "|" . showsPrec n j . showString ">"
->     showsPrec n (x :|> k) = showsScalar n x . showsPrec n k
->     showsPrec n (j :+> k) = showsPrec n j . showString " + " . showsPrec n k
-
-> instance (Show a, Eq a, Ord a) => Show (Bra a)  where
->     showsPrec n BraZero   = showString "< Zero |"
->     showsPrec n (Bra j)   = showString "<" . showsPrec n j . showString "|"
->     showsPrec n (x :<| k) = showsScalar n x . showsPrec n k
->     showsPrec n (j :<+ k) = showsPrec n j . showString " + " . showsPrec n k
-
-
-> showsScalar n x@(a :+ b)
->     | b == 0    = showsPrec n a . showString " "
->     | otherwise = showString "(" .showsPrec n x . showString ") "
-
-</pre>
-<p>
-<hr>
-<p>
-<b>
-	8. Data Tuple for tensor products
-</b>
-<p>
-	A state vector of several subsystems is modelled as a ket parametrized
-	by a type variable Tuple, which is similar to ordinary () but is
-	shown differently. Tensor product of several simple states leads
-	to deeply entangled structure, with many parenthesis obstructing
-	readability. What we really want is a simple notation for easy
-	visualization of products of several states, as in:
-<pre>
-	Ket 1 *> Ket (2, 1) * Ket '+' ==> | 1; (2,1); '+' >
-</pre>
-	See module Momenta for practical example of tensor products
-	of vector spaces.
-<pre>
-
-> data Tuple a b =  a :* b
->     deriving (Eq, Ord)
-
-> instance (Show a, Show b) => Show (Tuple a b) where
->     showsPrec n (a :* b) = showsPrec n a . showString "; " . showsPrec n b
-
-</pre>
-<p>
-<hr>
-<p>
-<b>
-	9. References
-</b>
-<p>
-<ul>
-<p>
-<li>
-
-	[1] Jerzy Karczmarczuk, Scientific computation and functional
-	programming, Dept. of Computer Science, University of Caen, France,
-	Jan 20, 1999, <a href="http://www.info.unicaen.fr/~karczma/">
-	http://www.info.unicaen.fr/~karczma/</a>
-<p>
-<li>
-	[2] Jan Skibinski, Collection of Haskell modules,
-	Numeric Quest Inc., <a href="http://www.numeric-quest.com/haskell/">
-	http://www.numeric-quest.com/haskell/"</a>
-<p>
-<li>
-	[3] Steven Pollock, University of Colorado,
-	<a href="http://www.colorado.edu/physics/phys3220/3220_fa97/notes/notes_table.html">
-	Quantum Mechanics, Physics 3220 Fall 97, lecture notes</a>
-
-</ul>
-<p>
-<hr>
-<p>
-<b>
-	10. Copyright and license
-</b>
-
-<pre>
---
--- Copyright:
---
---      (C) 2000 Numeric Quest, All rights reserved
---
---      Email: jans@numeric-quest.com
---
---      http://www.numeric-quest.com
---
--- License:
---
---      GNU General Public License, GPL
---
-
-</pre>
-</blockquote>
-</body>
-
-<SCRIPT language="Javascript">
-<!--
-
-// FILE ARCHIVED ON 20010421035521 AND RETRIEVED FROM THE
-// INTERNET ARCHIVE ON 20030715011358.
-// JAVASCRIPT APPENDED BY WAYBACK MACHINE, COPYRIGHT INTERNET ARCHIVE.
-// ALL OTHER CONTENT MAY ALSO BE PROTECTED BY COPYRIGHT (17 U.S.C.
-// SECTION 108(a)(3)).
-
-   var sWayBackCGI = "http://web.archive.org/web/20010421035521/";
-
-   function xLateUrl(aCollection, sProp) {
-      var i = 0;
-      for(i = 0; i < aCollection.length; i++)
-	 if (aCollection[i][sProp].indexOf("mailto:") == -1 &&
-	     aCollection[i][sProp].indexOf("javascript:") == -1)
-	    aCollection[i][sProp] = sWayBackCGI + aCollection[i][sProp];
+         Quantum vector
+</title>
+</head>
+<body>
+<center>
+<h1>
+        ***
+</h1>
+<h1>
+        Quantum vector
+</h1>
+<p>
+<b>
+
+        Jan Skibinski, <a href=http://www.numeric-quest.com/news/>
+        Numeric Quest Inc.</a>, Huntsville, Ontario, Canada
+<br>
+        Literate Haskell module <em>QuantumVector.lhs</em>
+<p>
+        Initialized: 2000-05-31, last modified: 2000-06-10
+</b>
+</center>
+
+<blockquote>
+<em>
+<p>
+<hr>
+<p>
+        This is our attempt to model the abstract Dirac's formalism
+        of Quantum Mechanics in Haskell. Although we have been
+        developing quantum mechanical applications and examples for some time [2], the
+        machinery used there is tightly coupled to a concrete
+        representation of states and observables by complex vectors
+        and matrices. implemented mainly as Haskell lazy lists.
+<p>
+        However, the Dirac's formalism in Hilbert space is much more
+        abstract than that, and many problems of Quantum Mechanics can be
+        solved without referring to any
+        particular matrix representation, but using certain generic properties
+        of operators, such as their commutative relations instead.
+        Haskell seems to be well suited for such abstract tasks,
+        even in its current form that does not support any
+        of the abstract notions of computer algebra as yet.
+        This has been already recognized by Jerzy Karczmarczuk [1],
+        where he proposes a very interesting representation of Hilbert
+        space and illustrates it by several powerful examples.
+        But the task is not trivial and far from being complete.
+        Quantum Mechanics presents many challenges to any formalism
+        and only by careful examination of many of its facets
+        and alternative approaches, a consistent model of
+        Dirac's formalism can be developed for Haskell. Hoping to
+        help with solving this problem, we present here a computing
+        abstract, which is quite different from that of [1].
+<p>
+        We recognize a quantum state as an abstract vector | x &gt;,
+        which can be represented in one of many possible bases -- similar
+        to many alternative representations of a 3D vector in rotated systems
+        of coordinates. A choice of a particular basis is controlled
+        by a generic type variable, which can be any Haskell object
+        -- providing that it supports a notion of equality and ordering.
+        A state which is composed of many quantum subsystems, not
+        necessarily of the same type, can be represented in a vector
+        space considered to be a tensor product of the subspaces.
+
+<p>
+        With this abstract notion we proceed with Haskell definition of two
+        vector spaces: Ket and its dual Bra. We demonstrate
+        that both are properly defined according to the abstract
+        mathematical definition of vector spaces. We then introduce inner
+        product and show that our Bra and Ket can be indeed
+        considered the vector spaces with inner product. Multitude
+        of examples is attached in the description. To verify
+        the abstract machinery developed here we also provide the basic library
+        module <a href="http://www.numeric-quest.com/haskell/Momenta.html">
+        Momenta</a> -- a non-trivial example designed to compute Clebsch-Gordan coefficients
+        of a transformation from one basis of angular momenta to another.
+<p>
+        Section 6 is a rehash of known definitions of linear operators
+        with the emphasis on both Dirac and Haskell notations and on
+        Haskell examples. The formalism developed here centers around
+        two operations: a scalar product of two vectors, <b>x &lt;&gt; y</b>,
+        and a closure operation, <b>a &gt;&lt; x</b>, which can be considered
+        an application of a quantum operator <b>a</b> to a vector <b>x</b>.
+        At this stage our formalism applies only to discrete cases, but
+        we hope to generalize it on true Hilbert space as well.
+</em>
+<p>
+<hr>
+<p>
+<b>
+        Contents
+</b>
+<ul>
+<li>
+        1. Infix operators
+<li>
+        2. Vector space
+<li>
+        3. Ket vector space
+<li>
+        4. Bra vector space
+<li>
+        5. Bra and Ket spaces as inner product spaces
+<li>
+        6. Linear operators
+<ul>
+<li>            6.1. Operator notation
+<li>
+                6.2. Renaming the representation
+<li>
+                6.3. Closure formula, or identity operator
+<li>
+                6.4. Changing the representation
+<li>
+                6.5. Implementation of the operator equation A | x &gt; = | y &gt;
+<li>
+                6.6. Inverse operator
+<li>
+                6.7. Matrix representation of an operator
+<li>
+                6.8. Adjoint operator
+<li>
+                6.9. Unitary operator
+<li>
+                6.10. Hermitian operator
+</ul>
+<li>
+        7. Showing kets and bras
+<li>
+        8. Data Tuple for tensor products
+<li>
+        9. References
+<li>
+        10. Copyright and license
+
+</ul>
+
+<p>
+<hr>
+<p>
+<b>
+        1. Infix operators
+</b>
+<p>
+        Haskell requires that fixities of infix operators are defined
+        at the top of the module. So here they are. They are
+        to be explained later.
+
+</b>
+<pre>
+
+> module QuantumVector where
+> import Complex                  -- our Scalar is Complex Double
+> import List (nub)
+
+> infixl 7 *>  -- tensor product of two kets
+> infixl 7 <*  -- tensor product of two bras
+
+> -- scalar-ket multiplication
+> infix 6 |>
+> -- scalar-bra multiplication
+> infix 6 <|
+
+
+> infixl 5 +>  -- sum of two kets
+> infixl 5 <+  -- sum of two bras
+
+
+> infix 4 <>  -- inner product
+> infix 5 ><  -- closure
+
+</pre>
+<p>
+<hr>
+<p>
+<b>
+        2. Vector space
+</b>
+<p>
+        Definition. A set V of elements x ,y ,z ,...is called a vector
+        (or linear) space over a complex field C if
+<ul>
+<li>
+        (a) vector addition  + is defined in V such that V is an
+        abelian group under addition, with identity element 0
+<pre>
+        1: <b>x</b> + <b>y</b>       = <b>y</b> + <b>x</b>
+        2: <b>x</b> + (<b>y</b> + <b>z</b>) = (<b>x</b> + <b>y</b>) + <b>z</b>
+        3: <b>0</b> + <b>x</b>       = <b>x</b> + <b>0</b>
+
+</pre>
+<p>
+<li>
+        (b) the set is close with respect to scalar multiplication
+        and vector addition
+<pre>
+        4: a (<b>x</b> + <b>y</b>)   = a <b>x</b> + a <b>y</b>
+        5: (a + b) <b>x</b>   = a <b>x</b> + b <b>x</b>
+        6: a (b <b>x</b>)     = (a b) <b>x</b>
+        7: 1 <b>x</b>         = <b>x</b>
+        8: 0 <b>x</b>         = <b>0</b>
+            where
+                a, b, c are complex scalars
+</pre>
+</ul>
+        Definition. The maximum number of linearly independent vectors
+        in V or, what is the same thing, the minimum number of linearly
+        independent vectors required to span V is the dimension r of
+        vector space V.
+<p>
+        Definition. A set of r linearly independent vectors is called
+        a basis of the space. Each vector of the space is then a unique
+        linear combination of the vectors of this basis.
+<p>
+        Based on the above definitions we will define two vector
+        spaces: ket space and its dual -- bra space, which, in addition
+        to the above properties, will also support
+        several common operations -- grouped below in the class
+        DiracVector.
+<pre>
+
+> class DiracVector a where
+>     add        :: a -> a -> a
+>     scale      :: Scalar -> a -> a
+>     reduce     :: a -> a
+>     basis      :: a -> [a]
+>     components :: a -> [Scalar]
+>     compose    :: [Scalar] -> [a] -> a
+>     dimension  :: a -> Int
+>     norm       :: a -> Double
+>     normalize  :: a -> a
+
+>     dimension x   = length (basis x)
+>
+>     normalize x
+>         | normx == 0 = x
+>         | otherwise  = compose cs (basis x)
+>          where
+>             cs     = [a*v :+ b*v |a :+ b <- components x]
+>             v      = 1 / normx
+>             normx  = norm x
+
+</pre>
+<p>
+<hr>
+<p>
+<b>
+        3. Ket vector space
+</b>
+<p>
+        We submit that the following datatype and accompanying
+        operations define a complex vector space, which we will call
+        the ket vector space.
+<pre>
+
+> type Scalar = Complex Double
+
+> data Ket a  =
+>            KetZero                     -- zero ket vector
+>          | Ket a                       -- base ket vector
+>          | Scalar  :|> Ket a           -- scaling ket vectors
+>          | Ket a   :+> Ket a           -- spanning ket space
+
+</pre>
+
+        A tensor product of two ket spaces is also a ket space.
+<pre>
+
+> (*>) :: (Ord a, Ord b) => Ket a -> Ket b -> Ket (Tuple a b)
+> Ket a   *> Ket b    = Ket (a :* b)
+> _       *> KetZero  = KetZero
+> KetZero *> _        = KetZero
+> x       *> y        = foldl1 (:+>) [((Bra a <> x) * (Bra b <> y)) :|> Ket (a :* b)
+>                                   | Ket a <- basis x, Ket b <- basis y]
+
+
+> (|>) :: Ord a => Scalar -> Ket a -> Ket a
+>     --
+>     -- Multiplication of ket by scalar
+>     --
+> s |> (x :+> y)  = (s |> x) +> (s |> y)
+> _ |> KetZero    = KetZero
+> 0 |> _          = KetZero
+> s |> (s2 :|> x) = (s * s2) |> x
+> s |> x          = s :|> x
+
+
+> (+>) :: Ord a => Ket a  -> Ket a  -> Ket a
+>     --
+>     -- Addition of two kets
+>     --
+> x +> KetZero = x
+> KetZero +> x = x
+> x +> y       = reduce (x :+> y)
+
+
+> instance (Eq a, Ord a) => Eq (Ket a) where
+>     --
+>     -- Two ket vectors are equal if they have identical
+>     -- components
+>     --
+>     x == y = and [c k x == c k y  | k <- basis x]
+>         where
+>             c k z = (toBra k) <> z
+
+
+</pre>
+        The data Ket is parametrized by type variable "a", which can be
+        anything that can be compared for equality and ordered: integer,
+        tuple, list of integers, etc. For example, the data
+        constructor <code>Ket (3::Int)</code> creates a base vector <code>|3></code>,
+        annotated by Int.
+        Similarly, <code>Ket (2::Int,1::Int)</code>, creates a base vector
+        <code>|(2,1)></code> annotated by a tuple of Ints. Those two
+        vectors belong to two different bases.
+<p>
+        The eight examples below illustrate the eight defining equations
+        of the vector space, given in section 1. All of them evaluate
+        to True.
+<pre>
+
+        1: Ket 2 +> Ket 3            == Ket 3 +> Ket 2
+        2: Ket 1 +> (Ket 2 +> Ket 3) == (Ket 1 +> Ket 2) +> Ket 3
+        3: Ket 1 +> KetZero          == KetZero +> Ket 1
+        4: 5 |> (Ket 2 +> Ket 3)     == 5 |> Ket 2 +> 5 |> Ket 3
+        5: (5 + 7) |> Ket 2          == 5 |> Ket 2 +> 7 |> Ket 2
+        6: 2 |> (4 |> Ket 2)         == 8 |> Ket 2
+        7: 1 |> Ket 2                == Ket 2
+        8: 0 |> Ket 2                == KetZero
+</pre>
+        The ket expressions can be pretty printed, as shown below.
+<pre>
+        Ket 2 +> Ket 3        ==> 1.0 |2> + 1.0 |3>
+        5 |> (Ket 2 +> Ket 3) ==> 5.0 |2> + 5.0 |3>
+        2 |> (4 |> Ket 2)     ==> 8.0 |2>
+</pre>
+        In order to support all those identities we also need several
+        additional functions for reducing the vector to its canonical form,
+        for composing the ket vector, and for extracting the ket
+        basis and the ket components -- as shown below.
+<pre>
+
+
+> reduceKet :: Ord a => Ket a -> Ket a
+> reduceKet x
+>     --
+>     -- Reduce vector `x' to its canonical form
+>     --
+>     = compose cs ks
+>       where
+>           ks = basis x
+>           cs = [toBra k <> x | k <- ks]
+
+
+> ketBasis :: Ord a => Ket a -> [Ket a]
+>     --
+>     -- Sorted list of unique base vectors of the ket vector
+>     --
+> ketBasis KetZero        = []
+> ketBasis (Ket k)        = [Ket k]
+> ketBasis (_ :|> x)      = [x]
+> ketBasis (k1 :+> k2)    = nub (ketBasis k1 ++ ketBasis k2)
+
+
+> toBra :: Ord a => Ket a -> Bra a
+>     --
+>     -- Convert from ket to bra vector
+>     --
+> toBra (Ket k)           = Bra k
+> toBra (x :+> y)         = toBra x :<+ toBra y
+> toBra (p :|> x)         = (conjugate p) :<| toBra x
+
+
+> instance Ord a => DiracVector (Ket a)  where
+>     add           = (+>)
+>     scale         = (|>)
+>     reduce        = reduceKet
+>     basis         = ketBasis
+>     components x  = [toBra e <> x | e <- basis x]
+>     compose xs ks = foldl1 (:+>) [fst z :|> snd z  | z <- zip xs ks]
+>
+>     norm KetZero  = 0
+>     norm x        = sqrt $ realPart (toBra x <> x)
+
+
+</pre>
+        But those auxilliary functions refer to vectors from the
+        conjugated space bra, which we shall now define below.
+<p>
+<hr>
+<p>
+<b>
+        4. Bra vector space
+</b>
+<p>
+        Definition. Let V be the defining n-dimensional complex vector
+        space. Associate with the defining n-dimensional complex vector
+        space V a conjugate (or dual) n-dimensional vector space
+        obtained by complex conjugation of elements x in V.
+<p>
+        We will call this space the bra space, and the corresponding vectors
+        - the bra vectors. Further, we submit that the following datatype and the corresponding
+        operations define bra space in Haskell.
+<pre>
+
+> data Bra a =
+>            BraZero                   -- zero bra vector
+>          | Bra a                     -- base bra vector
+>          | Scalar :<| Bra a          -- scaling bra vectors
+>          | Bra a  :<+ Bra a          -- spanning bra space
+
+
+</pre>
+        A tensor product of two bra spaces is also a bra space.
+<pre>
+
+> (<*) :: (Ord a, Ord b) => Bra a -> Bra b -> Bra (Tuple a b)
+> Bra a   <* Bra b    = Bra (a :* b)
+> _       <* BraZero  = BraZero
+> BraZero <* _        = BraZero
+> x       <* y        = foldl1 (:<+) [((x <> Ket a) * (y <> Ket b)) :<| Bra (a :* b)
+>                                   | Bra a <- basis x, Bra b <- basis y]
+
+> (<|) :: Ord a => Scalar -> Bra a -> Bra a
+> s <| (x :<+ y)  = (s <| x) <+ (s <| y)
+> _ <| BraZero    = BraZero
+> 0 <| _          = BraZero
+> s <| (s2 :<| x) = (s * s2) <| x
+> s <| x          = s :<| x
+
+
+> (<+) :: Ord a => Bra a -> Bra a -> Bra a
+>     --
+>     -- Sum of two bra vectors
+>     --
+> x <+ BraZero = x
+> BraZero <+ x  = x
+> x <+ y       = reduce (x :<+ y)
+
+
+> instance (Eq a, Ord a) => Eq (Bra a) where
+>     --
+>     -- Two bra vectors are equal if they have
+>     -- identical components
+>     --
+>     --
+>     x == y = and [c b x == c b y  | b <- basis x]
+>         where
+>             c b z = z <> toKet b
+
+</pre>
+
+        Similarly to what we have done for ket vectors, we also define several
+        additional functions for reducing the bra vector to its canonical form,
+        for composing the bra vector, and for extracting the bra
+        basis and the bra components -- as shown below.
+<pre>
+
+> reduceBra :: Ord a => Bra a -> Bra a
+> reduceBra x
+>     --
+>     -- Reduce bra vector `x' to its canonical form
+>     --
+>     = compose cs bs
+>       where
+>           bs = basis x
+>           cs = [x <> toKet b | b <- bs]
+
+
+> braBasis :: Ord a => Bra a -> [Bra a]
+>     --
+>     -- List of unique basis of the bra vector
+>     --
+> braBasis BraZero        = []
+> braBasis (Bra b)        = [Bra b]
+> braBasis (_ :<| x)     = [x]
+> braBasis (b1 :<+ b2)   = nub (braBasis b1 ++ braBasis b2)
+
+
+> toKet :: Ord a => Bra a -> Ket a
+>     --
+>     -- Convert from bra to ket vector
+>     --
+> toKet (Bra k)            = Ket k
+> toKet (x :<+ y)        = toKet x :+> toKet y
+> toKet (p :<| Bra k)    = (conjugate p) :|> Ket k
+
+
+> instance Ord a => DiracVector (Bra a)  where
+>     add           = (<+)
+>     scale         = (<|)
+>     reduce        = reduceBra
+>     basis         = braBasis
+>     components x  = [x <> toKet e | e <- basis x]
+>     compose xs ks = foldl1 (:<+) [fst z :<| snd z  | z <- zip xs ks]
+>
+>     norm BraZero  = 0
+>     norm x        = sqrt $ realPart (x <> toKet x)
+
+
+</pre>
+<p>
+<hr>
+<p>
+<b>
+        5. Bra and Ket spaces as inner product spaces
+</b>
+<p>
+
+        Definition. A complex vector space V is an inner product space
+        if with every pair of elements x ,y  from V there is associated
+        a unique inner (or scalar) product < x | y > from C, such that
+<pre>
+        9:  < x | y >          = < y | x ><sup>*</sup>
+        10: < a x | b y >      = a<sup>*</sup> b < x | y >
+        11: < z | a x + b y >  = a < z | x > + b < z, y >
+            where
+                a, b, c are the complex scalars
+</pre>
+        We submit that the dual ket and bra spaces are inner product
+        spaces, providing that the inner product is defined by the operator
+        <> given below:
+<pre>
+
+
+
+> (<>) :: Ord a => Bra a -> Ket a -> Scalar
+>     --
+>     -- Inner product, or the "bra-ket" product
+>     --
+> BraZero       <> _              = 0
+> _             <> KetZero        = 0
+> Bra i         <> Ket j          = d i j
+> (p :<| x)     <> (q :|> y)      = p * q * (x <> y)
+> (p :<| x)     <> y              = p * (x <> y)
+> x             <> (q :|> y)      = q * (x <> y)
+> x             <> (y1 :+> y2)    = (x  <> y1) + (x <> y2)
+> (x1 :<+ x2)   <> y              = (x1 <> y)  + (x2 <> y)
+
+
+> d :: Eq a => a -> a -> Scalar
+> d i j
+>     --
+>     -- Classical Kronecker's delta
+>     -- for instances of Eq class
+>     --
+>     | i == j    = 1
+>     | otherwise = 0
+>
+
+</pre>
+        The expressions below illustrate the definitions 9-11.
+        They are all true.
+<pre>
+9:  (toBra x <> y) == conjugate (toBra y <> x)
+10: (toBra (a |> x) <> (b |> y)) == (conjugate a)*b*(toBra x <> y)
+11: (toBra z <> (a |> x +> b |> y)) == a*(toBra z <> x) + b*(toBra z <> y)
+    where
+        x = (2 :+ 3) |> Ket 2
+        y = ((1:+2) |> Ket 3) +> Ket 2
+        z = Ket 2 +> Ket 3
+        a = 2:+1
+        b = 1
+</pre>
+<p>
+<hr>
+<p>
+<b>
+        6. Linear operators
+</b>
+<p>
+
+        Linear operators, or simply operators, are functions from vector
+        in representation a <em>a</em> to vector in representation <em>b</em>
+
+<pre>
+        a :: Ket a -> Ket b
+</pre>
+        although quite often the operations are performed
+        on the same representation. The linear operators A are defined by
+<pre>
+        A (c1 | x > + c2 | y > ) = c1 A | x > + c2 A | y >
+</pre>
+
+<p>
+        We will describe variety of special types
+        of operators, such as inverse, unitary, adjoint and hermitian.
+        This is not an accident that the names of those operators
+        resemble names from matrix calculus, since
+        Dirac vectors and operators can be viewed as matrices.
+<p>
+        With the exception of variety of examples, no significant
+        amount of Haskell code will be added here. This section
+        is devoted mainly to documentation; we feel that it is important
+        to provide clear definitions of the operators, as seen from
+        the Haskell perspective. Being a strongly typed language,
+        Haskell might not allow for certain relations often shown
+        in traditional matrix calculus, such as
+<pre>
+        A = B
+</pre>
+        since the two operators might have in fact two distinct signatures.
+        In matrix calculus one only compares tables of unnamed numbers,
+        while in our Haskell formalism we compare typed
+        entieties.
+        For this reason, we will be threading quite
+        slowly here, from one definition to another to assure that
+        they are correct from the perspective of
+        typing rules of Haskell.
+
+<p>
+<hr>
+<p>
+<b>
+        6.1. Operator notation
+</b>
+<p>
+        The notation
+<pre>
+        | y > = A | x >
+</pre>
+        is pretty obvious: operator A acting on vector | x &gt; produces
+        vector | y &gt;. It is not obvious though whether both vectors
+        use the same representation. The Haskell version of the above
+        clarifies this point, as in this example:
+<pre>
+        y = a >< x
+           where
+                a :: Ket Int -> Ket (Int, Int)
+                a = ......
+</pre>
+        In this case it is seen the two vectors have distinct
+        representations. The operator &gt;&lt; will be explained soon
+        but for now treat is as an application of an operator
+        to a vector, or some kind of a product of the two.
+<p>
+        The above can be also written as
+<pre>
+        | y > = | A x >
+</pre>
+        where the right hand side is just a defining label saying that the
+        resulting vector has been produced by operator A acting on | x &gt;.
+<p>
+        Linear operators can also act on the bra vectors
+<pre>
+        < y | = < x | A
+                <---
+</pre>
+        providing that they have correct signatures. This postfix notation
+        though is a bit awkward, and not supported by Haskell. To avoid
+        confusion we will be using the following notation instead:
+<pre>
+        < y | = < A x |
+</pre>
+        which says that bra y is obtained from ket y,
+        where | y &gt; = | A x &gt;,  as before. In Haskell we will write
+        it as
+<pre>
+        y = toBra $ a >< x
+
+</pre>
+
+<p>
+<hr>
+<p>
+<b>
+        6.2. Renaming the representation
+</b>
+<p>
+        One simple example of an operator is <em>label "new"</em>
+        which renames a vector representation by adding extra label
+        <em>"new"</em> in the basis vectors <em>Ket a</em>. Silly
+        as it sounds, this and other similar re-labeling operations
+        can be actually quite useful; for example,
+        we might wish to distinguish between old and new bases, or
+        just to satisfy the Haskell typechecker.
+<pre>
+
+        label :: (Ord a, Ord b) => b -> Ket a -> Ket (b, a)
+        label i (Ket a) = Ket (i, a)
+        label i x       = (label i) >< x
+
+</pre>
+<p>
+<hr>
+<p>
+<b>
+        6.3. Closure formula, or identity operator
+</b>
+<p>
+        Although the general Dirac formalism often refers to
+        abstract vectors | x &gt;, our implementation must
+        be more concrete than that -- we always represent the
+        abstract vectors in some basis of our choice, as in:
+<pre>
+        | x > = c<sub>k</sub> | k >   (sum over k)
+</pre>
+        To recover the component c<sub>k</sub> we form
+        the inner product
+<pre>
+            c<sub>k</sub> = < k | x >
+</pre>
+        Putting it back to the previous equation:
+<pre>
+        | x > = < k | x > | k >      (sum over k)
+              = | k > < k | x >
+              = Id | x >
+        where
+            Id = | k > < k |        (sum over k)
+</pre>
+        we can see that the vector | x &gt; has been abstracted away. The formula
+        says that vector | x &gt; can be decomposed in any basis
+        by applying identity operator Id to it. This is also known
+        as a closure formula. Well, Haskell has the "id" function too,
+        and we could apply it to any ket, as in:
+<pre>
+        id (Ket 1 +> 10 |> Ket 2) ==> | 1 > + 10 | 2 >
+</pre>
+        but Haskell's "id" does not know anything about representations;
+        it just gives us back the same vector | x &gt; in our original
+        representation.
+<p>
+        We need something more accurately depicting the closure
+        formula | k &gt; &lt; k |, that would allow us to change
+        the representation if we wanted to, or leave it alone
+        otherwise. Here is the <em>closure</em> function and
+        coresponding operator (&gt;&lt;) that implement
+        the closure formula for a given <em>operator</em>.
+<pre>
+
+> closure :: (DiracVector a, DiracVector b) => (a -> b) -> a -> b
+> closure operator x =
+>    compose' (components x) (map operator (basis x))
+>      where
+>         compose' xs ks = foldl1 add (zipWith scale xs ks)
+
+> (><) :: (DiracVector b, DiracVector a) => (a -> b) -> a -> b
+> operator >< x = closure operator x
+
+
+</pre>
+<p>
+<hr>
+<p>
+<b>
+        6.4. Changing the representation
+</b>
+<p>
+        The silly <em>label</em> function found in the comment of the
+        section 6.1 uses in fact the closure relation. But we could
+        define is simpler than that:
+<pre>
+
+> label :: t -> Ket t1 -> Ket (t, t1)
+> label i (Ket x) = Ket (i, x)
+
+</pre>
+        and then apply a closure to a vector x, as in:
+<pre>
+        closure (label 0) (Ket 2 +> 7 |> Ket 3)
+                ==> 1.0 |(0,2)> + 7.0 |(0,3)>
+</pre>
+        Somewhat more realistic example involves "rotation" of
+        the old basis with simulaneous base renaming:
+<pre>
+
+> rot :: Ket Int -> Ket (Int, Int)
+> rot (Ket 1) = normalize $ Ket (1,1) +> Ket (1,2)
+> rot (Ket 2) = normalize $ Ket (1,1) +> (-1) |> Ket (1,2)
+> rot (Ket _) = error "exceeded space dimension"
+
+</pre>
+        The example function
+        <em>rot</em> assumes transformation from
+        two-dimensional basis [| 1 &gt;, | 2 &gt;] to another
+        two-dimensional basis [| (1,1) &gt;, | (1,2) &gt;] by
+        expressing the old basis by the new one. Given this
+        transformation we can apply the closure to any vector | x &gt;
+        represented in the old basis; as a result we will get
+        the same vector | x &gt; but represented in the new
+        basis.
+<pre>
+        rot >< (Ket 1 +> 7 |> Ket 2) ==>
+                5.65685 |(1,1)> + -4.24264 |(1,2)>
+</pre>
+
+<p>
+<hr>
+<p>
+<b>
+        6.5. Implementation of the operator equation A | x &gt; = | y &gt;
+</b>
+<p>
+        The Haskell implementation of the closure formula is not just
+        a useless simulation of the theoretical closure  - it is one of the
+        workhorses of the apparatus employed here.
+<p>
+        We will be using linear operators to evaluate equations
+        like this:
+<pre>
+        | y > = A | x >
+</pre>
+        The resulting vector | y &gt; can have either the same
+        representation as | x &gt; or different - depending on
+        the nature of operator A. The most general type of
+        A is
+<pre>
+        Ket a -> Ket b
+</pre>
+        but more often than not the basis will be the same as before.
+        But how we define the operator A itself? The best way is
+        to specify how it acts on the base vectors | k &gt;. If we can chose
+        as our basis the eigenvectors of A this would be even better,
+        because the definition of A would be then extremely simple.
+        After inserting the identity | k &gt;&lt; k | between the
+        operator A and vector | x &gt; in the above equation one gets
+<pre>
+        | y > = A | k > < k | x >            (sum over k)
+</pre>
+        This will be implemented in Haskell as:
+<pre>
+        y = a >< x
+</pre>
+        The closure formula will take care of the rest and it will
+        produce the result | y &gt; . The examples previously given
+        do just that. One caveat though: since operator A will
+        only be defined for the basis, but not for other vectors,
+        skipping the closure formula and coding directly
+<pre>
+        y = a' x
+</pre>
+        is not advisable.
+        This will certainly fail for vectors other than basis unless
+        one makes extra provisions for that. This is what we did
+        in module Momenta, before we had the closure support ready.
+        Using the closure is safe and this is the way to go!
+
+
+<p>
+<hr>
+<p>
+<b>
+        6.6. Inverse operator
+</b>
+<p>
+        An operator B = A<sup>-1</sup> that inverses the
+        equation
+<pre>
+        | y > = A | x >
+          y   = a >< x -- where a :: Ket a -> Ket b
+</pre>
+        into
+<pre>
+        | x > = B | y >
+          x   = b >< y -- where b :: Ket b -> Ket a
+</pre>
+        is called the inverse operator.
+<p>
+        For example, the inverse operator to the operator <em>label i</em>
+        is:
+<pre>
+
+> label' :: (Ord a, Ord b) => Ket (a, b) -> Ket b
+> label' (Ket (_, x)) = Ket x
+
+</pre>
+        It is easy to check that applying the operator A and its inverse
+        A<sup>-1</sup> in succession to any ket | x &gt; one should
+        obtain the same vector | x &gt; again, as in:
+
+<pre>
+        A<sup>-1</sup> A | x > = | x >
+
+        -- Haskell example
+        label' >< (label 0 >< x) == x
+           where
+                x = Ket 1 +> 10 |> Ket 7
+        ==> True
+</pre>
+        Once again, notice the omnipresent closure operator in Haskell
+        implementation. Tempting as it might be to implement the
+        above example as
+<pre>
+        -- Do not do it in Haskell!!!
+        (label' . label 0) >< x == x
+            where
+               x = Ket 1 +> 10 |> Ket 7
+        ==> True
+</pre>
+        this is not a recommended way. Although this example would work,
+        but a similar example for <em>rotation</em> operations would
+        fail in a spectacular way. The correct way is to insert the
+        closure operator between two rotations:
+<pre>
+        rot' >< (rot >< x) == x
+            where
+                x = Ket 1 +> 10 |> Ket 2
+        ==> True
+</pre>
+        where the inverse operator <em>rot'</em> is defined below:
+
+<pre>
+
+> rot' :: Ket (Int, Int) -> Ket (Int)
+> rot' (Ket (1,1)) = normalize $ Ket 1 +> Ket 2
+> rot' (Ket (1,2)) = normalize $ Ket 1 +> (-1) |> Ket 2
+> rot' (Ket (_,_)) = error "exceeded space dimension"
+
+</pre>
+<p>
+<hr>
+<p>
+<b>
+        6.7. Matrix representation of an operator
+</b>
+<p>
+<p>
+        The scalar products
+<pre>
+        < k | A l' > = < k | A | l' >
+</pre>
+        such that | k &gt; and | l' &gt; are the base vectors
+        (in general belonging to two different bases), form a transformation
+        matrix Akl'.
+<p>
+        In Haskell this matrix is formed as
+<pre>
+        k <> a >< l'
+            where
+               k  = ... :: Bra b
+               l' = ... :: Ket a
+               a  = ... :: Ket a -> Ket b
+</pre>
+
+<p>
+<hr>
+<p>
+<b>
+        6.8. Adjoint operator
+</b>
+<font color="teal">
+<p>
+        Our definition of adjoint operator is different
+        than that in theory of determinants. Many books, not necessarily
+        quantum mechanical oriented, refer to the latter as <em>
+        classical adjoint operator</em>.
+</font>
+
+<p>
+        With every linear operator A we can associate an adjoint
+        operator B = A<sup>+</sup>, also known as Hermitian conjugate
+        operator, such that equality of the two scalar
+        products
+<pre>
+        < A<sup>+</sup> u | x > = < u | A x >
+</pre>
+        holds for every vector | u &gt; and | x &gt;.
+        In Haskell notation the above can be written as:
+<pre>
+        (toBra (b >< u) <> x) == toBra u <> a >< x
+            where
+                 a = ... :: Ket a -> Ket b
+                 b = ... :: Ket b -> Ket a
+                 x = ... :: Ket a
+                 u = ... :: Ket b
+
+</pre>
+        For example, the operator <em>rot'</em> is adjoint
+        to operator <em>rot</em>
+<pre>
+        (toBra (rot' >< u) <> x) == (toBra u <> rot >< x)
+            where
+                x = Ket 1 +> 10 |> Ket 2
+                u = Ket (1,1) +> 4 |> Ket (1,2)
+        ==> True
+
+</pre>
+        It can be shown that
+<pre>
+        (A<sup>+</sup>)<sup>+</sup> = A
+</pre>
+        Matrix A<sup>+</sup> is conjugate transposed to A, as
+        proven below
+
+<pre>
+        = A<sup>+</sup>kl'
+        = < k | A<sup>+</sup> | l' >
+        = < k | A<sup>+</sup> l' >
+        = < A<sup>+</sup> l' | k ><sup>*</sup>
+        = < l' | A | k ><sup>*</sup>
+        = A<sup>*</sup>l'k
+</pre>
+
+
+<p>
+<hr>
+<p>
+<b>
+        6.9. Unitary operator
+</b>
+<p>
+        Unitary transformations preserve norms of vectors.
+        We say, that the norm of a vector is invariant under unitary
+        transformation.
+        Operators describing such transformations are called
+        unitary operators.
+<pre>
+        < A x | A x > = < x | x >
+
+</pre>
+        The example of this is rotation transformation, which indeed
+        preserves the norm of any vector x, as shown in this Haskell
+        example
+<pre>
+        (toBra u <> u) == (toBra x <> x)
+            where
+                u = rot >< x
+                x = Ket 1 +> 10 |> Ket 2
+
+        ==> True
+</pre>
+<p>
+        Inverse and adjoint operators of unitary operators are equal
+<pre>
+        A<sup>-1</sup> = A<sup>+</sup>
+</pre>
+        which indeed is true for our example operator <em>rot</em>.
+<p>
+        Computation of the adjont operators A<sup>+</sup> from A
+        is quite easy since the process is rather mechanical, as
+        described in the previous section. On the other hand, finding
+        inverse operators is not that easy, with the exception of
+        some simple cases, such as our example 2D rotation.
+        It is therefore important to know whether a given operator
+        is unitary, as this would allow us to replace inverse
+        operators by adjoint operators.
+
+
+<p>
+<hr>
+<p>
+<b>
+        6.10. Hermitian operator
+</b>
+<p>
+        A Hermitian operator is a self adjoint operator; that is
+<pre>
+        < A u | x > = < u | A x >
+</pre>
+        Another words: A<sup>+</sup> = A.
+<p>
+        Notice however, that this relation holds only for the
+        vectors in the same representation, since in general
+        the operators
+        A and A<sup>+</sup> have distinct signatures, unless
+        types a, b are the same:
+<pre>
+        a  :: Ket a -> Ket b -- operator A
+        a' :: Ket b -> Ket a -- operator A<sup>+</sup>
+</pre>
+        Elements of hermitian matrices must therefore satisfy:
+<pre>
+         Aij = (Aji)<sup>*</sup>
+</pre>
+        In particular, their diagonal elements must be real.
+<p>
+        Our example operator <em>rot</em> is not hermitian,
+        since it describes transformation from one basis
+        to another.
+        But here is a simple example of a hermitian operator, which
+        multiplies any ket by scalar 4. It satisfies our definition:
+<pre>
+        (toBra (a >< u) <> x) == (toBra u <> a >< x)
+        where
+            a v = 4 |> v
+
+            x = Ket 1 +> Ket 2
+            u = Ket 2
+
+        ==> True
+</pre>
+        Here is a short quote from [3].
+<blockquote>
+        Why do we care whether an operator is Hermitian?
+        It's because of a few theorems:
+
+<ol>
+<li>
+        The eigenvalues of Hermitian operators are always real.
+<li>
+        The expectation values of Hermitian operators are always real.
+<li>
+        The eigenvectors of Hermitian operators span the Hilbert space.
+<li>
+        The eigenvectors of Hermitian operators belonging to distinct eigenvalues are orthogonal.
+</ol>
+        In quantum mechanics, these characteristics are essential if you
+        want to represent measurements with operators. Operators must be
+        Hermitian so that observables are real. And, you must be able to
+        expand in the eigenfunctions - the expansion coefficients
+        give you probabilities!
+</blockquote>
+<p>
+<hr>
+<p>
+<b>
+        7. Showing kets and bras
+</b>
+<p>
+        Lastly, here are show functions for pretty printing of Dirac
+        vectors.
+<pre>
+
+> instance (Show a, Eq a, Ord a) => Show (Ket a)  where
+>     showsPrec _ KetZero   = showString "| Zero >"
+>     showsPrec n (Ket j)   = showString "|" . showsPrec n j . showString ">"
+>     showsPrec n (x :|> k) = showsScalar n x . showsPrec n k
+>     showsPrec n (j :+> k) = showsPrec n j . showString " + " . showsPrec n k
+
+> instance (Show a, Eq a, Ord a) => Show (Bra a)  where
+>     showsPrec _ BraZero   = showString "< Zero |"
+>     showsPrec n (Bra j)   = showString "<" . showsPrec n j . showString "|"
+>     showsPrec n (x :<| k) = showsScalar n x . showsPrec n k
+>     showsPrec n (j :<+ k) = showsPrec n j . showString " + " . showsPrec n k
+
+
+> showsScalar :: (RealFloat t) => Int -> Complex t -> String -> String
+> showsScalar n x@(a :+ b)
+>     | b == 0    = showsPrec n a . showString " "
+>     | otherwise = showString "(" .showsPrec n x . showString ") "
+
+</pre>
+<p>
+<hr>
+<p>
+<b>
+        8. Data Tuple for tensor products
+</b>
+<p>
+        A state vector of several subsystems is modelled as a ket parametrized
+        by a type variable Tuple, which is similar to ordinary () but is
+        shown differently. Tensor product of several simple states leads
+        to deeply entangled structure, with many parenthesis obstructing
+        readability. What we really want is a simple notation for easy
+        visualization of products of several states, as in:
+<pre>
+        Ket 1 *> Ket (2, 1) * Ket '+' ==> | 1; (2,1); '+' >
+</pre>
+        See module Momenta for practical example of tensor products
+        of vector spaces.
+<pre>
+
+> data Tuple a b =  a :* b
+>     deriving (Eq, Ord)
+
+> instance (Show a, Show b) => Show (Tuple a b) where
+>     showsPrec n (a :* b) = showsPrec n a . showString "; " . showsPrec n b
+
+</pre>
+<p>
+<hr>
+<p>
+<b>
+        9. References
+</b>
+<p>
+<ul>
+<p>
+<li>
+
+        [1] Jerzy Karczmarczuk, Scientific computation and functional
+        programming, Dept. of Computer Science, University of Caen, France,
+        Jan 20, 1999, <a href="http://www.info.unicaen.fr/~karczma/">
+        http://www.info.unicaen.fr/~karczma/</a>
+<p>
+<li>
+        [2] Jan Skibinski, Collection of Haskell modules,
+        Numeric Quest Inc., <a href="http://www.numeric-quest.com/haskell/">
+        http://www.numeric-quest.com/haskell/"</a>
+<p>
+<li>
+        [3] Steven Pollock, University of Colorado,
+        <a href="http://www.colorado.edu/physics/phys3220/3220_fa97/notes/notes_table.html">
+        Quantum Mechanics, Physics 3220 Fall 97, lecture notes</a>
+
+</ul>
+<p>
+<hr>
+<p>
+<b>
+        10. Copyright and license
+</b>
+
+<pre>
+--
+-- Copyright:
+--
+--      (C) 2000 Numeric Quest, All rights reserved
+--
+--      Email: jans@numeric-quest.com
+--
+--      http://www.numeric-quest.com
+--
+-- License:
+--
+--      GNU General Public License, GPL
+--
+
+</pre>
+</blockquote>
+</body>
+
+<SCRIPT language="Javascript">
+<!--
+
+// FILE ARCHIVED ON 20010421035521 AND RETRIEVED FROM THE
+// INTERNET ARCHIVE ON 20030715011358.
+// JAVASCRIPT APPENDED BY WAYBACK MACHINE, COPYRIGHT INTERNET ARCHIVE.
+// ALL OTHER CONTENT MAY ALSO BE PROTECTED BY COPYRIGHT (17 U.S.C.
+// SECTION 108(a)(3)).
+
+   var sWayBackCGI = "http://web.archive.org/web/20010421035521/";
+
+   function xLateUrl(aCollection, sProp) {
+      var i = 0;
+      for(i = 0; i < aCollection.length; i++)
+         if (aCollection[i][sProp].indexOf("mailto:") == -1 &&
+             aCollection[i][sProp].indexOf("javascript:") == -1)
+            aCollection[i][sProp] = sWayBackCGI + aCollection[i][sProp];
    }
 
    if (document.links)  xLateUrl(document.links, "href");
diff --git a/README b/README
--- a/README
+++ b/README
@@ -3,3 +3,6 @@
 The Literate Haskell files are actually HTML files.
 To make your browser happy, you can start 'make html'
 in order to make links *.html links to *.lhs files.
+
+Haskell-Cafe 08 Dec 2007 on "Literate HTML":
+   ghc --make -x lhs index.html
diff --git a/Roots.hs b/Roots.hs
--- a/Roots.hs
+++ b/Roots.hs
@@ -1,4 +1,5 @@
-module Roots where                
+module Roots where
+
 import Data.Complex
 import Data.List(genericLength)
 
@@ -12,23 +13,23 @@
       --     eps is a desired accuracy
       --     count is a maximum count of iterations allowed
       -- Require: list 'as' must have at least two elements
-      --     and the last element must not be zero 
+      --     and the last element must not be zero
       roots' eps count as []
       where
-          roots' eps count as xs 
-              | length as <= 2  = x:xs
-              | otherwise       = 
-                  roots' eps count (deflate x bs [last as]) (x:xs)
+          roots' epr cnt cs xs
+              | length cs <= 2  = x:xs
+              | otherwise       =
+                  roots' epr cnt (deflate x bs [last cs]) (x:xs)
               where
-                  x  = laguerre eps count as 0
-                  bs = drop 1 (reverse (drop 1 as))
-                  deflate z bs cs
-                      | bs == []   = cs
-                      | otherwise  = 
-                          deflate z (tail bs) (((head bs)+z*(head cs)):cs)
+                  x  = laguerre epr cnt as 0
+                  bs = drop 1 $ reverse $ drop 1 cs
+                  deflate z es fs
+                      | es == []  = fs
+                      | otherwise =
+                          deflate z (tail fs) (((head fs)+z*(head es)):es)
 
 
-laguerre :: RealFloat a => a -> Int -> [Complex a] -> Complex a -> Complex a       
+laguerre :: RealFloat a => a -> Int -> [Complex a] -> Complex a -> Complex a
 laguerre eps count as x
       --
       -- One of the roots of the polynomial 'as',
@@ -44,25 +45,25 @@
       where
           x'     = laguerre2 eps as as' as'' x
           as'    = polynomial_derivative as
-          as''   = polynomial_derivative as' 
-          laguerre2 eps as as' as'' x
+          as''   = polynomial_derivative as'
+          laguerre2 epr bs bs' bs'' y
               -- One iteration step
-              | magnitude b < eps           = x
-              | magnitude gp < magnitude gm = 
-                  if gm == 0 then x - 1 else x - n/gm
-              | otherwise                   = 
-                  if gp == 0 then x - 1 else x - n/gp
+              | magnitude b < epr           = y
+              | magnitude gp < magnitude gm =
+                  if gm == 0 then y - 1 else y - n/gm
+              | otherwise                   =
+                  if gp == 0 then y - 1 else y - n/gp
               where
                   gp    = g + delta
                   gm    = g - delta
                   g     = d/b
                   delta = sqrt ((n-1)*(n*h - g2))
                   h     = g2 - f/b
-                  b     = polynomial_value as x
-                  d     = polynomial_value as' x
-                  f     = polynomial_value as'' x
-                  g2    = g^2
-                  n     = genericLength as
+                  b     = polynomial_value bs y
+                  d     = polynomial_value bs' y
+                  f     = polynomial_value bs'' y
+                  g2    = g^(2::Int)
+                  n     = genericLength bs
 
 polynomial_value :: Num a => [a] -> a -> a
 polynomial_value as x =
@@ -73,7 +74,7 @@
       --
       foldr (u x) 0 as
       where
-          u x a b = a + b*x
+          u y a b = a + b*y
 
 polynomial_derivative :: Num a => [a] -> [a]
 polynomial_derivative as
@@ -86,13 +87,11 @@
       where
           deriv n bs cs
              | bs == []   = reverse2 cs
-             | otherwise  = deriv (n+1) (tail bs) ((n*(head bs)):cs) 
+             | otherwise  = deriv (n+1) (tail bs) ((n*(head bs)):cs)
           reverse2 cs
               | cs == []  = []
               | otherwise = reverse cs
 
-
-
 -----------------------------------------------------------------------------
 --
 -- Copyright:
@@ -106,5 +105,5 @@
 -- License:
 --
 --      GNU General Public License, GPL
--- 
+--
 -----------------------------------------------------------------------------
diff --git a/Tensor.lhs b/Tensor.lhs
--- a/Tensor.lhs
+++ b/Tensor.lhs
@@ -3,111 +3,111 @@
 <BASE HREF="http://www.numeric-quest.com/haskell/Tensor.html">
 
 <title>
-	N-dimensional tensors
+        N-dimensional tensors
 </title>
 </head>
 <body>
 <ul>
 <center>
 <h1>
-			***
+                        ***
 </h1>
 <h1>
-	N-dimensional tensors
+        N-dimensional tensors
 </h1>
 <b>
 <br>
-	Literate Haskell module <i>Tensor.lhs</i>
+        Literate Haskell module <i>Tensor.lhs</i>
 </b>
 <p>
-	Jan Skibinski, <a href="http://www.numeric-quest.com/news/">
-	Numeric Quest Inc.</a>, Huntsville, Ontario, Canada
+        Jan Skibinski, <a href="http://www.numeric-quest.com/news/">
+        Numeric Quest Inc.</a>, Huntsville, Ontario, Canada
 <p>
-	1999.10.08, last modified 1999.10.16
+        1999.10.08, last modified 1999.10.16
 
 </center>
 <p>
 <hr>
 <p>
 <i>
-	This is a quick sketch of what might be a basis of a real
-	Tensor module. This module has quite a few limitations (listed below).
-	I'd like to get some feedback on what should be a better
-	way to design it properly. Nevertheless, this module works
-	and is able to tackle complex and mundane manipulations
-	in the very straightforward way.
+        This is a quick sketch of what might be a basis of a real
+        Tensor module. This module has quite a few limitations (listed below).
+        I'd like to get some feedback on what should be a better
+        way to design it properly. Nevertheless, this module works
+        and is able to tackle complex and mundane manipulations
+        in the very straightforward way.
 <p>
-	There are few arbitrary decisions we have taken. For example,
-	we consider a scalar to be a tensor of rank 0. This forces us to
-	do conversions between true scalars and such tensors, but it also
-	saves us a lot of headache related to typing restrictions. This
-	is a typical price paid for (too much?) generalization.
+        There are few arbitrary decisions we have taken. For example,
+        we consider a scalar to be a tensor of rank 0. This forces us to
+        do conversions between true scalars and such tensors, but it also
+        saves us a lot of headache related to typing restrictions. This
+        is a typical price paid for (too much?) generalization.
 <p>
-	To get rid of those awful sums appearing in multiplications
-	of tensors we do introduce Einstein's summation convention by the way of
-	text examples -- followed by the equivalent Haskell examples.
-	Hopefully it is clear and be well appreciated for its economy
-	of notation, which is standard in the tensor calculus.
+        To get rid of those awful sums appearing in multiplications
+        of tensors we do introduce Einstein's summation convention by the way of
+        text examples -- followed by the equivalent Haskell examples.
+        Hopefully it is clear and be well appreciated for its economy
+        of notation, which is standard in the tensor calculus.
 <p>
-	Datatype <code>Tensor</code> defined here is an instance
-	of class <code>Eq</code>, <code>Show</code> and <code>Num</code>.
-	That means that one can compare tensors for equality and perform
-	basic numerical calculations, such as addition, negation,
-	subtraction, multiplication, etc. -- using standard notation
-	<code>(==), (/=), (+), (-), (*)</code>. In addition, several
-	customized operations, such as <code> (&lt;*&gt;)</code>
-	and <code>(&lt;&lt;*&gt;&gt;)</code> are defined for
-	variety of inner products.
+        Datatype <code>Tensor</code> defined here is an instance
+        of class <code>Eq</code>, <code>Show</code> and <code>Num</code>.
+        That means that one can compare tensors for equality and perform
+        basic numerical calculations, such as addition, negation,
+        subtraction, multiplication, etc. -- using standard notation
+        <code>(==), (/=), (+), (-), (*)</code>. In addition, several
+        customized operations, such as <code> (&lt;*&gt;)</code>
+        and <code>(&lt;&lt;*&gt;&gt;)</code> are defined for
+        variety of inner products.
 
 <p>
-	Limitations of this module:
+        Limitations of this module:
 <ul>
 
 <p>
 <li>
-	Tensor components are Doubles. Why not Fraction, Complex, etc?
-	For a moment we will leave this question aside, and
-	return to it some time later. But we consider it
-	the important question -- which is evident from the attempts of
-	such generalization in some of our other modules:
-	<a href="http://www.numeric-quest.com/haskell/Orthogonals.html">
-	Orthogonals</a> and
-	<a href="http://www.numeric-quest.com/haskell/fractions.html">
-	Fraction</a>.
+        Tensor components are Doubles. Why not Fraction, Complex, etc?
+        For a moment we will leave this question aside, and
+        return to it some time later. But we consider it
+        the important question -- which is evident from the attempts of
+        such generalization in some of our other modules:
+        <a href="http://www.numeric-quest.com/haskell/Orthogonals.html">
+        Orthogonals</a> and
+        <a href="http://www.numeric-quest.com/haskell/fractions.html">
+        Fraction</a>.
 <p>
 <li>
-	We are well aware that the decision to represent tensors
-	as nested objects will have significant impact on access
-	(and update -- if supported) of such data structure. Linear
-	arrays seem to be better suited for such tasks, where all
-	indices must be explicitely computed first, but the access
-	time is linear. In contrary, the hierarchical data structure
-	defined here require very little effort in index computing
-	but the access time depends on the depth of the data tree.
+        We are well aware that the decision to represent tensors
+        as nested objects will have significant impact on access
+        (and update -- if supported) of such data structure. Linear
+        arrays seem to be better suited for such tasks, where all
+        indices must be explicitely computed first, but the access
+        time is linear. In contrary, the hierarchical data structure
+        defined here require very little effort in index computing
+        but the access time depends on the depth of the data tree.
 <p>
-	But speed has not been tested yet, so we really do not know
-	how inefficient this module is and all of the above is
-	just a pure speculation. Certain operations of this module
-	seem to be quite well matched with this tree-like data structure,
-	and because of it this design decision might be not so bad
-	after all.
+        But speed has not been tested yet, so we really do not know
+        how inefficient this module is and all of the above is
+        just a pure speculation. Certain operations of this module
+        seem to be quite well matched with this tree-like data structure,
+        and because of it this design decision might be not so bad
+        after all.
 
 <p>
 <li>
-	The shape of tensors defined here involves two parameters:
-	dimension and rank. Rank is associated with the
-	depth of the tensor tree and corresponds to a total number
-	of indices by which you can access the individual components.
-	No limits are imposed on ranks and there are binary operations
-	which involve tensors of different ranks.
-	Dimension is associated with the breadth of the tree and
-	correspond to a number of values each index can take.
-	Dimension is fixed via constant <code>dims</code>. At first it might
-	seem as a severe limitation, but in fact one should never
-	mix tensors with different dimensions. One usually works
-	either with three-dimensional tensors (classical mechanics,
-	electrodynamics, elasticity, etc.) or the four-dimentional
-	tensors (relativity theory).
+        The shape of tensors defined here involves two parameters:
+        dimension and rank. Rank is associated with the
+        depth of the tensor tree and corresponds to a total number
+        of indices by which you can access the individual components.
+        No limits are imposed on ranks and there are binary operations
+        which involve tensors of different ranks.
+        Dimension is associated with the breadth of the tree and
+        correspond to a number of values each index can take.
+        Dimension is fixed via constant <code>dims</code>. At first it might
+        seem as a severe limitation, but in fact one should never
+        mix tensors with different dimensions. One usually works
+        either with three-dimensional tensors (classical mechanics,
+        electrodynamics, elasticity, etc.) or the four-dimentional
+        tensors (relativity theory).
 </ul>
 <p>
 </i>
@@ -115,7 +115,7 @@
 <hr>
 <p>
 <b>
-	Tensor datatype
+        Tensor datatype
 </b>
 <p>
 <pre>
@@ -128,11 +128,11 @@
 > infixl 7 <<*>>  -- inner product with two bounds
 
 </pre>
-	Indices will assume values from range (1,dims) (defined below).
+        Indices will assume values from range (1,dims) (defined below).
 <p>
 
-	Tensor can contain a scalar value or a list of tensors.
-	This recursively defines tensor of any rank in n-D space.
+        Tensor can contain a scalar value or a list of tensors.
+        This recursively defines tensor of any rank in n-D space.
 
 <pre>
 
@@ -141,31 +141,31 @@
 
 
 </pre>
-	There is no way we could specify the length of the list
-	<code>[Tensor]</code> in the data declaration. Typing is not
-	concerned with shapes.
-	We could of course use more specific representation of
-	this data structure, such as:
+        There is no way we could specify the length of the list
+        <code>[Tensor]</code> in the data declaration. Typing is not
+        concerned with shapes.
+        We could of course use more specific representation of
+        this data structure, such as:
 <pre>
-	data Tensor = S Double | T Tensor Tensor Tensor
+        data Tensor = S Double | T Tensor Tensor Tensor
 </pre>
-	but then we would severily limit ourselves to three-dimensional
-	tensors.
+        but then we would severily limit ourselves to three-dimensional
+        tensors.
 <p>
 
-	Rank is either 0 (scalars), 1 (vectors), or higher: 2, 3, 4 ...
+        Rank is either 0 (scalars), 1 (vectors), or higher: 2, 3, 4 ...
 <pre>
 
 > rank :: Tensor -> Int
 > rank t = rank' 0 t where
->       rank' n (S a)     = n
+>       rank' n (S _)     = n
 >       rank' n (T xs)    = rank' (n+1) (head xs)
 
 </pre>
-	Here we define our tensor dimension as constant for this
-	module. All binary operations on tensors require the
-	same dimensions, so it makes sense to treat dimensions
-	as constants. But ranks can be different.
+        Here we define our tensor dimension as constant for this
+        module. All binary operations on tensors require the
+        same dimensions, so it makes sense to treat dimensions
+        as constants. But ranks can be different.
 <pre>
 
 > dims :: Int
@@ -177,11 +177,11 @@
 <hr>
 <p>
 <b>
-	Showing
+        Showing
 </b>
 <p>
-	Tensors are printed as recursive lists with a word "Tensor"
-	prepended
+        Tensors are printed as recursive lists with a word "Tensor"
+        prepended
 
 <pre>
 
@@ -192,37 +192,38 @@
 >       showsPrec 0 (T xs)    = showString "Tensor " . showList' 0 xs
 >       showsPrec n (T xs)    = showList' n xs
 
-> showList' n [] = showString "[]"
+> showList' :: (Show t) => Int -> [t] -> String -> String
+> showList' _ [] = showString "[]"
 > showList' n (x:xs) = showChar '[' . showsPrec (n+1) x . showRem (n+1) xs
 >       where
->               showRem n [] = showChar ']'
->               showRem n (x:xs) = showChar ',' . showsPrec n x . showRem n xs
+>               showRem _ [] = showChar ']'
+>               showRem o (y:ys) = showChar ',' . showsPrec o y . showRem o ys
 
 </pre>
 <p>
 <hr>
 <p>
 <b>
-	Input
+        Input
 </b>
 <p>
 
-	Although tensors are printed as structured list
-	it is easier to input data via flat lists.
-	But make sure that the length of the list is one
-	of: dims^0, dims^1, dims^2, dims^3, dims^4, etc.
+        Although tensors are printed as structured list
+        it is easier to input data via flat lists.
+        But make sure that the length of the list is one
+        of: dims^0, dims^1, dims^2, dims^3, dims^4, etc.
 <p>
-	This function is quite inefficient for ranks higher than 4.
-	Compare, for example, timings of:
+        This function is quite inefficient for ranks higher than 4.
+        Compare, for example, timings of:
 <pre>
-	tensor [1..3^6]
-	tensor [1..3^3] * tensor [1..3^3]
+        tensor [1..3^6]
+        tensor [1..3^3] * tensor [1..3^3]
 </pre>
-	Although both expressions create tensors of the same rank 6,
-	but the execution of the latter is much faster. This is
-	because the function <code>tensor</code> spends much
-	of its effort on recursively restructuring the flat lists
-	into the lists-of-lists-of-lists...
+        Although both expressions create tensors of the same rank 6,
+        but the execution of the latter is much faster. This is
+        because the function <code>tensor</code> spends much
+        of its effort on recursively restructuring the flat lists
+        into the lists-of-lists-of-lists...
 <pre>
 
 
@@ -235,39 +236,39 @@
 >           (p,q) = rnk 1 (quotRem size dims)
 >           rnk m (1, v) = (m, v)
 >           rnk m (u, 0) = rnk (m+1) (quotRem u dims)
->           rnk m (u, v) = (m, v)
+>           rnk m (_, v) = (m, v)
 >           size   = length xs
->           group n xs = group' n xs [] where
->               group' n xs as
->                   | length xs == 0 = reverse as
->                   | length xs < n  = reverse (xs:as)
->                   | otherwise      = group' n (drop n xs) ((take n xs):as)
+>           group n ys = group' n ys [] where
+>               group' o zs as
+>                   | length zs == 0 = reverse as
+>                   | length zs < o  = reverse (zs:as)
+>                   | otherwise      = group' o (drop o zs) ((take o zs):as)
 >
->           tlist 1   xs = map S xs
->           tlist rnk xs = tlist' (rnk-1) (map S xs)
+>           tlist :: Int -> [Double] -> [Tensor]
+>           tlist 1 zs   = map S zs
+>           tlist rnl zs = tlist' (rnl-1) (map S zs)
 >               where
->                   tlist' 0 zs = zs
->                   tlist' n zs = tlist' (n-1) (map T (group dims zs))
->
+>                   tlist' 0 fs = fs
+>                   tlist' o fs = tlist' (o-1) $ map T $ group dims fs
 
 </pre>
 <p>
 <hr>
 <p>
 <b>
-	Extraction and conversion
+        Extraction and conversion
 </b>
 <p>
 
-	Tensor components are also tensors and can be extracted
-	via (#) operator
+        Tensor components are also tensors and can be extracted
+        via (#) operator
 
 <pre>
 
 > ( # ) :: Tensor -> Int -> Tensor
-> a@(S a1) # 1  = S a1
-> a@(S a1) # i  = error "out of range"
-> a@(T xs) # i  = xs!!(i-1)
+> (S a1) # 1  = S a1
+> (S _) # _  = error "out of range"
+> (T xs) # i  = xs!!(i-1)
 
 > ( ## ) :: Tensor -> [Int] -> Tensor
 > a ## [] = a
@@ -275,22 +276,22 @@
 
 </pre>
 
-	Tensors of rank 0 can be converted to scalars; i.e.,
-	simple numbers of type Double.
+        Tensors of rank 0 can be converted to scalars; i.e.,
+        simple numbers of type Double.
 <pre>
 
 > scalar :: Tensor -> Double
 > scalar (S a)  = a
-> scalar (T xs) = error "rank not 0"
+> scalar (T _) = error "rank not 0"
 
 </pre>
 
-	Tensors of rank 1 can be converted to vectors; i.e.,
-	lists with "dims" components of type Double
+        Tensors of rank 1 can be converted to vectors; i.e.,
+        lists with "dims" components of type Double
 <pre>
 
 > vector :: Tensor -> [Double]
-> vector (S a)         = error "rank not 1"
+> vector (S _)         = error "rank not 1"
 > vector a@(T xs)
 >       | rank a /= 1  = error "rank not 1"
 >       | otherwise    = map scalar xs
@@ -300,14 +301,14 @@
 <hr>
 <p>
 <b>
-	Useful tensors: epsilon and delta
+        Useful tensors: epsilon and delta
 </b>
 <p>
-	Function "epsilon' i j k" emulates values of the pseudo-tensor Eijk.
-	It is valid only for three-dimensional tensors.
-	It takes three indices i,j,k from the range (1,3)
-	and returns one of the three values:
-	0.0, 1.0, -1.0 -- depending on the rules specified below:
+        Function "epsilon' i j k" emulates values of the pseudo-tensor Eijk.
+        It is valid only for three-dimensional tensors.
+        It takes three indices i,j,k from the range (1,3)
+        and returns one of the three values:
+        0.0, 1.0, -1.0 -- depending on the rules specified below:
 <pre>
 
 > epsilon' :: Int -> Int -> Int -> Double
@@ -317,17 +318,17 @@
 >       | (i == j) || (i == k) || (j == k)   =  0
 >       | otherwise = epsilon1 i j k
 >       where
->               epsilon1 i j k
->                       | (i == 1) && (j == 2) && (k == 3)   =  1
->                       | (i == 3) && (j == 2) && (k == 1)   = -1
->                       | otherwise = epsilon1 j k i
+>               epsilon1 m n o
+>                       | (m == 1) && (n == 2) && (o == 3)   =  1
+>                       | (m == 3) && (n == 2) && (o == 1)   = -1
+>                       | otherwise = epsilon1 n o m
 >               outside (p,q) a b c =
 >                       (not $ inRange (p,q) a) ||
 >                       (not $ inRange (p,q) b) ||
 >                       (not $ inRange (p,q) c)
 
 </pre>
-	Function "delta' i j" emulates Kronecker's delta:
+        Function "delta' i j" emulates Kronecker's delta:
 <pre>
 
 > delta' :: Int -> Int -> Double
@@ -337,32 +338,33 @@
 
 </pre>
 
-	Delta' and epsilon' can be converted to tensors
+        Delta' and epsilon' can be converted to tensors
 
 <pre>
 
+> delta, epsilon :: Tensor
 > delta   = tensor [delta' i j     | i <- [1..dims], j <- [1..dims]]
 > epsilon = tensor [epsilon' i j k | i <- [1..3], j <- [1..3], k <- [1..3]]
 
 </pre>
-	The components delta[ij] and epsilon[i,j,k] can be extracted
-	and converted to numbers. For example:
+        The components delta[ij] and epsilon[i,j,k] can be extracted
+        and converted to numbers. For example:
 <pre>
-	scalar (epsilon#1#2#3) = 1
-	scalar (epsilon#1#1#3) = 0,
-	scalar (epsilon#3#2#1) = -1
+        scalar (epsilon#1#2#3) = 1
+        scalar (epsilon#1#1#3) = 0,
+        scalar (epsilon#3#2#1) = -1
 </pre>
 <p>
 <hr>
 <p>
 <b>
-	Dot product
+        Dot product
 </b>
 <p>
-	Dot product of two tensors of rank 1 could be defined as
-	tensor of rank 0. This is not the most efficient implementation
-	but we still want the dot product to be recognised as
-	tensor, so we loose on speed here:
+        Dot product of two tensors of rank 1 could be defined as
+        tensor of rank 0. This is not the most efficient implementation
+        but we still want the dot product to be recognised as
+        tensor, so we loose on speed here:
 <pre>
 
 > dot :: Tensor -> Tensor -> Tensor
@@ -374,14 +376,14 @@
 <hr>
 <p>
 <b>
-	Cross product - valid for 3D space only
+        Cross product - valid for 3D space only
 </b>
 <p>
-	The cross product of two vectors is another vector:
-	C = A x B. The pseudotensor Eijk is used to compute
-	such cross product.
+        The cross product of two vectors is another vector:
+        C = A x B. The pseudotensor Eijk is used to compute
+        such cross product.
 <p>
-	First, here are numerical components of C, C[i]:
+        First, here are numerical components of C, C[i]:
 <pre>
 
 > cross'       :: Tensor -> Tensor -> Int -> Double
@@ -389,7 +391,7 @@
 >                       j<-[1..3],k<-[1..3], j/=k]
 
 </pre>
-	And here is the full vector C (as tensor of rank 1):
+        And here is the full vector C (as tensor of rank 1):
 
 <pre>
 
@@ -398,22 +400,22 @@
 
 </pre>
 
-	Example:
+        Example:
 <pre>
-	cross (tensor [1..3]) (tensor [1,8,1]) ==> Tensor [-22.0, 2.0, 6.0]
+        cross (tensor [1..3]) (tensor [1,8,1]) ==> Tensor [-22.0, 2.0, 6.0]
 </pre>
 
 <p>
 <hr>
 <p>
 <b>
-	Equality of tensors
+        Equality of tensors
 </b>
 <p>
-	Tensor can be admitted to class <code>Eq</code>. We only need to
-	define either equality or nonequality operation. We've chosen
-	to define the former: two tensors are equal if they have the same
-	rank and equal components:
+        Tensor can be admitted to class <code>Eq</code>. We only need to
+        define either equality or nonequality operation. We've chosen
+        to define the former: two tensors are equal if they have the same
+        rank and equal components:
 <pre>
 
 > instance Eq Tensor where
@@ -432,12 +434,12 @@
 <hr>
 <p>
 <b>
-	Tensor as instance of class Num
+        Tensor as instance of class Num
 </b>
 <p>
-	To admit tensors to class <code>Num</code> we have to
-	support all the operations from that class. Here is
-	the class Num declaration taken from the Prelude:
+        To admit tensors to class <code>Num</code> we have to
+        support all the operations from that class. Here is
+        the class Num declaration taken from the Prelude:
 <pre>
 class (Eq a, Show a) => Num a where
     (+), (-), (*)  :: a -> a -> a
@@ -449,26 +451,26 @@
     x - y           = x + negate y
     negate x        = 0 - x
 </pre>
-	All operations but <code>(*)</code> are straightforward,
-	meaningful and easy to implement. The semantics of multiplication
-	<code>(*)</code> is, however, not so obvious and it is up to us
-	how to define it: as an inner product or as an outer
-	product. We have chosen the latter, which means that the
-	operation <code>c = a * b</code> produces a new tensor <code>c</code>
-	whose rank is a sum of the ranks of tensors being
-	multiplied:
+        All operations but <code>(*)</code> are straightforward,
+        meaningful and easy to implement. The semantics of multiplication
+        <code>(*)</code> is, however, not so obvious and it is up to us
+        how to define it: as an inner product or as an outer
+        product. We have chosen the latter, which means that the
+        operation <code>c = a * b</code> produces a new tensor <code>c</code>
+        whose rank is a sum of the ranks of tensors being
+        multiplied:
 <pre>
-	rank c = rank a + rank b
+        rank c = rank a + rank b
 </pre>
 
-	Suffice to add that tensor products are generally not
-	commutative; that is:
+        Suffice to add that tensor products are generally not
+        commutative; that is:
 <pre>
-	a * b /= b * a
+        a * b /= b * a
 
 </pre>
-	That said, here is the instantiation of <code>Num</code>
-	for datatype Tensor:
+        That said, here is the instantiation of <code>Num</code>
+        for datatype Tensor:
 <pre>
 
 > instance Num Tensor where
@@ -479,73 +481,73 @@
 >               where
 >                       ranka = rank a
 
->       negate a@(S a1)           = S (negate a1)
->       negate a@(T xs)           = T (map negate xs)
+>       negate (S a1)           = S (negate a1)
+>       negate (T xs)           = T (map negate xs)
 
->       abs a@(S a1)              = S (abs a1)
->       abs a@(T xs)              = T (map abs xs)
+>       abs (S a1)              = S (abs a1)
+>       abs (T xs)              = T (map abs xs)
 
->       signum a@(S a1)           = S (signum a1)
->       signum a@(T xs)           = T (map signum xs)
+>       signum (S a1)           = S (signum a1)
+>       signum (T xs)           = T (map signum xs)
 
 >       fromInteger n             = S (fromInteger n)
 
->       (*) a@(S a1) b@(S b1)     = S (a1*b1)
->       (*) a@(S a1) b@(T xs)     = T (map (a*) (take dims xs))
->       (*) a@(T xs) b            = T (map (*b) (take dims xs))
+>       (*) (S a1) (S b1)     = S (a1*b1)
+>       (*) a@(S _) (T xs)     = T (map (a*) (take dims xs))
+>       (*) (T xs) b            = T (map (*b) (take dims xs))
 
 </pre>
-	Having defined the operation <code>(*)</code> as an outer product
-	such operation will generally increase the rank of the outcome.
-	For example, if <code>a</code> is a tensor of rank 2 (matrix) and
-	<code>b</code> is a tensor of rank 1 (vector) then the result is
-	a tensor of rank 3:
+        Having defined the operation <code>(*)</code> as an outer product
+        such operation will generally increase the rank of the outcome.
+        For example, if <code>a</code> is a tensor of rank 2 (matrix) and
+        <code>b</code> is a tensor of rank 1 (vector) then the result is
+        a tensor of rank 3:
 <pre>
-	c = a * b, that is
-	c[ijk] = a[ij] b[k]
+        c = a * b, that is
+        c[ijk] = a[ij] b[k]
 </pre>
-	But this is not what is typically considered a multiplication
-	of tensors; we are more often than not interested in the inner
-	products, informally described below.
+        But this is not what is typically considered a multiplication
+        of tensors; we are more often than not interested in the inner
+        products, informally described below.
 
 <p>
 <hr>
 <p>
 <b>
-	Contraction
+        Contraction
 </b>
 <p>
 <p>
-	Eistein's indexing convention of tensors is based on
-	the distinction between free indices and bound indices.
-	Free indices appear in the tensorial expressions, such
-	as <code>A[ijkl]</code>, once only and they indicate
-	a freedom for substitution of any specific index
-	from the range of valid indices. This range is (1,3)
-	for 3D tensors. The expression <code>A[ijkl]</code>
-	represents in fact one of 3^4 possible components
-	of the tensor <code>A</code>.
+        Eistein's indexing convention of tensors is based on
+        the distinction between free indices and bound indices.
+        Free indices appear in the tensorial expressions, such
+        as <code>A[ijkl]</code>, once only and they indicate
+        a freedom for substitution of any specific index
+        from the range of valid indices. This range is (1,3)
+        for 3D tensors. The expression <code>A[ijkl]</code>
+        represents in fact one of 3^4 possible components
+        of the tensor <code>A</code>.
 <p>
-	Bound indices, on the other hand, appear in pairs
-	(and only in pairs) and they indicate the summation of
-	tensor expression over the valid range. For example,
+        Bound indices, on the other hand, appear in pairs
+        (and only in pairs) and they indicate the summation of
+        tensor expression over the valid range. For example,
 <pre>
-	A[kkj] = A[11j] + A[22j] + A[33j]
+        A[kkj] = A[11j] + A[22j] + A[33j]
 </pre>
-	Note that the index "j" is still free, and that means
-	that the above represents three equations for j = 1,2,3.
+        Note that the index "j" is still free, and that means
+        that the above represents three equations for j = 1,2,3.
 <p>
-	A process of converting of a pair of free indices
-	to a pair of bound indices is called contraction. As
-	a result a rank of a tensor (or expression involving
-	several tensors) is being reduced
-	by two.
+        A process of converting of a pair of free indices
+        to a pair of bound indices is called contraction. As
+        a result a rank of a tensor (or expression involving
+        several tensors) is being reduced
+        by two.
 <p>
-	The function <code>contract</code> below accepts a tensor of a
-	rank bigger or equal 2 and two integers m,n from the range (1,rank a)
-	which indicate positions of the two indices to be used for
-	contraction. The result is a tensor with its rank reduced
-	by two.
+        The function <code>contract</code> below accepts a tensor of a
+        rank bigger or equal 2 and two integers m,n from the range (1,rank a)
+        which indicate positions of the two indices to be used for
+        contraction. The result is a tensor with its rank reduced
+        by two.
 
 <pre>
 
@@ -562,31 +564,31 @@
 >
 >        outside p q = (not $ inRange (1,ranka) p)
 >                            ||(not $ inRange (1,ranka) q)
->        summa p q xs a = sum [scalar (a##(insert p q xs r)) |
+>        summa p q xs b = sum [scalar (b##(insert p q xs r)) |
 >               r <- [1..dims]]
 
 >        -- Insert element r at positions m n to the list
 >        -- of indices xs
->        insert m n xs r = us++[r]++ws++[r]++zs
+>        insert o p xs r = us++[r]++ws++[r]++zs
 >               where
->                       (us,vs) = splitAt (m-1) xs
->                       (ws,zs) = splitAt (n - m - 1) vs
+>                       (us,vs) = splitAt (o-1) xs
+>                       (ws,zs) = splitAt (p - o - 1) vs
 >
 >        freeIndices 1 = [[x] | x <- [1..dims]]
->        freeIndices n = [x:y | x <- [1..dims], y <- freeIndices (n-1)]
+>        freeIndices o = [x:y | x <- [1..dims], y <- freeIndices (o-1)]
 
 
 </pre>
 
-	Let's take for example tensor <code>delta</code> and contract
-	it in its two indices:
+        Let's take for example tensor <code>delta</code> and contract
+        it in its two indices:
 <pre>
-	delta [kk] = delta[1,1] + delta[2,2] + delta[3,3] = 1 + 1 + 1 = 3
+        delta [kk] = delta[1,1] + delta[2,2] + delta[3,3] = 1 + 1 + 1 = 3
 </pre>
-	The same can be done in Haskell:
+        The same can be done in Haskell:
 <pre>
-	contract 1 2 delta        ==> Tensor 3.0
-	rank (contract 1 2 delta) ==> 0
+        contract 1 2 delta        ==> Tensor 3.0
+        rank (contract 1 2 delta) ==> 0
 </pre>
 
 
@@ -594,99 +596,100 @@
 <hr>
 <p>
 <b>
-	Inner product
+        Inner product
 </b>
 <p>
-	The inner product of two tensors can be considered
-	as two-phase process: first the outer product is
-	formed and then a contraction is applied to a selected
-	pair of indices. There are countless possibilities
-	of defining such inner products, since we can choose
-	any pair, or even more than one pair, of indices
-	to become bound.
+        The inner product of two tensors can be considered
+        as two-phase process: first the outer product is
+        formed and then a contraction is applied to a selected
+        pair of indices. There are countless possibilities
+        of defining such inner products, since we can choose
+        any pair, or even more than one pair, of indices
+        to become bound.
 <p>
-	How do we usually multiply tensors? Here is one example,
-	which is equivalent to matrix-vector multiplication:
+        How do we usually multiply tensors? Here is one example,
+        which is equivalent to matrix-vector multiplication:
 <pre>
-	C[i] = A[ij] B[j]
+        C[i] = A[ij] B[j]
 </pre>
-	Notice two types of indices: index "i" is free since
-	it appears only once on both sides of the equation. It means
-	that you can freely substitute 1,2 or 3 for "i". So in fact
-	we have here three equations:
+        Notice two types of indices: index "i" is free since
+        it appears only once on both sides of the equation. It means
+        that you can freely substitute 1,2 or 3 for "i". So in fact
+        we have here three equations:
 <pre>
-	C[1] = A[1j] B[j]
-	C[2] = A[2j] B[j]
-	C[3] = A[3j] B[j]
+        C[1] = A[1j] B[j]
+        C[2] = A[2j] B[j]
+        C[3] = A[3j] B[j]
 </pre>
-	Index "j" is bound - it appears two times on the right hand
-	side, but not on the left side. Bound indices signify summation
-	from 1 to 3. So the above in fact means:
+        Index "j" is bound - it appears two times on the right hand
+        side, but not on the left side. Bound indices signify summation
+        from 1 to 3. So the above in fact means:
 <pre>
-	C[1] = A[11] B[1] + A[12] B[2] + A[13] B[3]
-	C[2] = A[21] B[1] + A[22] B[2] + A[23] B[3]
-	C[3] = A[31] B[1] + A[32] B[2] + A[33] B[3]
+        C[1] = A[11] B[1] + A[12] B[2] + A[13] B[3]
+        C[2] = A[21] B[1] + A[22] B[2] + A[23] B[3]
+        C[3] = A[31] B[1] + A[32] B[2] + A[33] B[3]
 </pre>
-	The economy of notation is evident in our first form above.
-	How will we do it in Haskell?
+        The economy of notation is evident in our first form above.
+        How will we do it in Haskell?
 <p>
-	To obtain the above result we will first form the outer product
-	of matrix A and vector B, obtain a tensor of rank 3,
-	and then contract it in indices 2 and 3 to obtain a
-	the final expected result (inner product):
+        To obtain the above result we will first form the outer product
+        of matrix A and vector B, obtain a tensor of rank 3,
+        and then contract it in indices 2 and 3 to obtain a
+        the final expected result (inner product):
 <pre>
-	c = contract 2 3 (a * b)
+        c = contract 2 3 (a * b)
 </pre>
-	This approach is quite inefficient storage-wise and
-	speed-wise and a direct customized encoding which avoids creating
-	outer products is recommended instead.
+        This approach is quite inefficient storage-wise and
+        speed-wise and a direct customized encoding which avoids creating
+        outer products is recommended instead.
 <p>
-	The system of equations
+        The system of equations
 <pre>
-	C[i] = A[ij] B[j]
+        C[i] = A[ij] B[j]
 </pre>
-	could obviously be represented explicite as:
+        could obviously be represented explicite as:
 <pre>
-	c i = sum [scalar(a#i#j) * scalar(b#j) | j <- [1..dims]]
-	-- valid for i = 1..dims
+        c i = sum [scalar(a#i#j) * scalar(b#j) | j <- [1..dims]]
+        -- valid for i = 1..dims
 </pre>
-	But when efficiency is not a premium we could still
-	take advantage of function <code>contract</code>
-	to write clear code that avoids the explicit sums. The
-	operator <code> &lt;*&gt;</code>, introduced below, allows
-	us to write the same function as:
+        But when efficiency is not a premium we could still
+        take advantage of function <code>contract</code>
+        to write clear code that avoids the explicit sums. The
+        operator <code> &lt;*&gt;</code>, introduced below, allows
+        us to write the same function as:
 <pre>
-	c      = a <*> b              -- the output is a tensor of rank 1
-	c'  i  = (a <*> b)#i          -- the output is a tensor of rank 0
-	c'' i  = scalar ((a <*> b)#i) -- the output is a number
+        c      = a <*> b              -- the output is a tensor of rank 1
+        c'  i  = (a <*> b)#i          -- the output is a tensor of rank 0
+        c'' i  = scalar ((a <*> b)#i) -- the output is a number
 </pre>
 
 <p>
 <hr>
 <p>
 <b>
-	Convenience operators for inner products
+        Convenience operators for inner products
 </b>
 <p>
-	Variety of specialized functions for inner products
-	could be defined. We will show few examples here
-	and introduce specialized convenience operators
-	for most common types of inner products. Please
-	note that the proposed operators are not standard
-	in any way, and we are not trying to suggest that
-	they are important. Just treat them as examples.
+        Variety of specialized functions for inner products
+        could be defined. We will show few examples here
+        and introduce specialized convenience operators
+        for most common types of inner products. Please
+        note that the proposed operators are not standard
+        in any way, and we are not trying to suggest that
+        they are important. Just treat them as examples.
 <p>
-	The semantics of operator <code> <*> </code> has
-	been chosen to support matrix-vector or vector-matrix
-	multiplications. But this operator is more general
-	than that, because it also handles products with scalars
-	(tensors of rank 0), and generally any products
-	of any two tensors with bounds imposed on one pair
-	of indices: last index of the first tensor and first
-	index of the second tensor.
+        The semantics of operator <code> <*> </code> has
+        been chosen to support matrix-vector or vector-matrix
+        multiplications. But this operator is more general
+        than that, because it also handles products with scalars
+        (tensors of rank 0), and generally any products
+        of any two tensors with bounds imposed on one pair
+        of indices: last index of the first tensor and first
+        index of the second tensor.
 
 <pre>
 
+> (<*>) :: Tensor -> Tensor -> Tensor
 > a <*> b
 >       | (ranka == 0) || (rankb == 0) = a * b
 >       | otherwise = contract ranka (ranka + 1) (a * b)
@@ -696,33 +699,34 @@
 
 </pre>
 
-	Take for example a classical identity:
+        Take for example a classical identity:
 <pre>
-	A[i] = delta[ij] B[j], where delta is a Kronecker's delta
+        A[i] = delta[ij] B[j], where delta is a Kronecker's delta
 </pre>
-	Here is an example of how we can use it in Haskell:
+        Here is an example of how we can use it in Haskell:
 <pre>
-	delta <*> tensor [4,5,6])    ==> Tensor [4.0, 5.0, 6.0]
-	(delta <*> tensor [4,5,6])#1 ==> Tensor 4.0
+        delta <*> tensor [4,5,6])    ==> Tensor [4.0, 5.0, 6.0]
+        (delta <*> tensor [4,5,6])#1 ==> Tensor 4.0
 </pre>
 
-	Let's try something more complex, for example a constitutive equation
-	relating the stress tensor S[ij] with the deformation tensor G[kl].
-	The tensor C[ijkl] is an anisotropic tensor of material constants:
-	81 altogether. In fact, due to all sorts of symmetries this number
-	could be reduced to twenty-something for the most complex crystals,
-	and to two independent components for the isotropic materials.
-	Anyway, the relation is linear and can be written as follows:
+        Let's try something more complex, for example a constitutive equation
+        relating the stress tensor S[ij] with the deformation tensor G[kl].
+        The tensor C[ijkl] is an anisotropic tensor of material constants:
+        81 altogether. In fact, due to all sorts of symmetries this number
+        could be reduced to twenty-something for the most complex crystals,
+        and to two independent components for the isotropic materials.
+        Anyway, the relation is linear and can be written as follows:
 <pre>
-	S[ij] = C[ijkl] G[kl]
+        S[ij] = C[ijkl] G[kl]
 </pre>
-	This represents 9 equations (i,j->1,2,3) and expands heavily
-	to sums over k and l on the right-hand side.
-	We need to impose two bounds in two pairs of indices to
-	support above example. Here is another specialized operator
-	for inner product with two specificly selected bounds.
+        This represents 9 equations (i,j->1,2,3) and expands heavily
+        to sums over k and l on the right-hand side.
+        We need to impose two bounds in two pairs of indices to
+        support above example. Here is another specialized operator
+        for inner product with two specificly selected bounds.
 <pre>
 
+> (<<*>>) :: Tensor -> Tensor -> Tensor
 > a <<*>> b
 >       | (ranka < 2) || (rankb < 2) = error "rank too small"
 >       | otherwise = contract (ranka-1) ranka
@@ -732,88 +736,90 @@
 >               rankb = rank b
 
 </pre>
-	Here is a dummy, but easy to generate example of the above:
+        Here is a dummy, but easy to generate example of the above:
 
 <pre>
-	tensor [1..81] <<*>> tensor [1..9]
+        tensor [1..81] <<*>> tensor [1..9]
 
-		==> s = Tensor [[ 285.0,  690.0, 1095.0],
-				[1500.0, 1905.0, 2310.0],
-				[2715.0, 3120.0, 3525.0]]
+                ==> s = Tensor [[ 285.0,  690.0, 1095.0],
+                                [1500.0, 1905.0, 2310.0],
+                                [2715.0, 3120.0, 3525.0]]
 
-	(tensor [1..81] <<*>> tensor [1..9])#1#1 = Tensor 285.0
+        (tensor [1..81] <<*>> tensor [1..9])#1#1 = Tensor 285.0
 </pre>
 <p>
 <hr>
 <p>
 <b>
-	Double cross products
+        Double cross products
 </b>
 <p>
-	Here is another useful example of tensor multiplication.
-	Say you want to compute a cross product of three vectors:
+        Here is another useful example of tensor multiplication.
+        Say you want to compute a cross product of three vectors:
 <pre>
-	D = C X (A x B )
+        D = C X (A x B )
 </pre>
-	In index notation this could be expressed as:
+        In index notation this could be expressed as:
 <pre>
-	D[i] = E[ijk] C[j] E[kpq] A[p] B[q]
+        D[i] = E[ijk] C[j] E[kpq] A[p] B[q]
 </pre>
-	This represents three equations for i=1,2,3. All other indices
-	j,k,p,q are bound; that is, they appear in pairs on the right
-	hand side, indicating four sums. Although you can calculate
-	it directly, and this Haskell module can do it easily, we can
-	simplify this equation by organizing it differently and
-	using this identity:
+        This represents three equations for i=1,2,3. All other indices
+        j,k,p,q are bound; that is, they appear in pairs on the right
+        hand side, indicating four sums. Although you can calculate
+        it directly, and this Haskell module can do it easily, we can
+        simplify this equation by organizing it differently and
+        using this identity:
 <pre>
-	E[ijk] = E[kij]
+        E[ijk] = E[kij]
 </pre>
-	(Even permutation of indices does not change a sign of pseudo-tensor
-	E.)
+        (Even permutation of indices does not change a sign of pseudo-tensor
+        E.)
 <pre>
-	D[i] = E[kij] E[kpq] C[j] A[p] B[q]
+        D[i] = E[kij] E[kpq] C[j] A[p] B[q]
 </pre>
-	Now here is another useful identity, which gets rid of the
-	bound index "k" (sitting in the first position above):
+        Now here is another useful identity, which gets rid of the
+        bound index "k" (sitting in the first position above):
 <pre>
-	E[kij] E[kpq] = delta[ip] delta[jq] - delta[iq] delta[jp]
+        E[kij] E[kpq] = delta[ip] delta[jq] - delta[iq] delta[jp]
 </pre>
-	After substitution and using identity <code>delta[ij] G[j] = G[i]</code>
-	the <code>C x (A x B)</code> transforms to:
+        After substitution and using identity <code>delta[ij] G[j] = G[i]</code>
+        the <code>C x (A x B)</code> transforms to:
 <pre>
-	D[i] = C[j] B[j] A[i] - C[j] A[j] B[i]
+        D[i] = C[j] B[j] A[i] - C[j] A[j] B[i]
 </pre>
-	We still have three scalar equations, but they are less complex:
-	there is only one summation (over the "j") on the right hand side.
+        We still have three scalar equations, but they are less complex:
+        there is only one summation (over the "j") on the right hand side.
 <p>
-	You should easily recognize that <code>C[j] B[j]</code>
-	represents the scalar product. Therefore our double cross product
-	can be represented as a difference of two vectors:
+        You should easily recognize that <code>C[j] B[j]</code>
+        represents the scalar product. Therefore our double cross product
+        can be represented as a difference of two vectors:
 <pre>
-	D = C x (A x B) = (C o B) A - (C o A) B
+        D = C x (A x B) = (C o B) A - (C o A) B
 </pre>
 
-	Now, let us see how this module handles this. Let's take an
-	example of three randomly chosen vectors A, B, C. The direct
-	method is straightforward, although it involves quite a lot
-	of multiplications and summations (which would not be so
-	evident if we have not done all those preliminary examinations
-	above).
+        Now, let us see how this module handles this. Let's take an
+        example of three randomly chosen vectors A, B, C. The direct
+        method is straightforward, although it involves quite a lot
+        of multiplications and summations (which would not be so
+        evident if we have not done all those preliminary examinations
+        above).
 <pre>
 
+> d_standard :: Tensor
 > d_standard  = cross c (cross a b) where
 >       a = tensor [1,2,3]
 >       b = tensor [3,1,8]
 >       c = tensor [5,2,4]
 
 </pre>
-	On the other hand we could encode the equivalent equation:
+        On the other hand we could encode the equivalent equation:
 <pre>
-	D = (C o B) A - (C o A) B
+        D = (C o B) A - (C o A) B
 </pre>
-	as:
+        as:
 <pre>
 
+> d_simpler :: Tensor
 > d_simpler =
 >       tensor [n1 * scalar (a#i) - n2 * scalar (b#i) | i <- [1..dims]] where
 >
@@ -825,102 +831,102 @@
 
 </pre>
 
-	Both <code>d_standard</code> and <code>d_simpler</code>
-	lead to the same result:
+        Both <code>d_standard</code> and <code>d_simpler</code>
+        lead to the same result:
 <pre>
-	==> Tensor [-14.0, 77.0, -21.0]
+        ==> Tensor [-14.0, 77.0, -21.0]
 </pre>
 <p>
 <hr>
 <p>
 <b>
-	Vector transformation
+        Vector transformation
 </b>
 <p>
-	A vector can be decomposed in any system of reference. The best
-	choice is any orthogonal system of reference, where all base
-	unit vectors are mutually perpendicular (orthogonal), since this
-	simplifies the computations. The base vectors <code>e[1], e[2], e[3]</code>
-	are usually chosen as vectors of length one (we say that they are
-	normalized to one), and hence they are called "orthonormal".
-	They obey the orthonormality relations for their scalar products:
+        A vector can be decomposed in any system of reference. The best
+        choice is any orthogonal system of reference, where all base
+        unit vectors are mutually perpendicular (orthogonal), since this
+        simplifies the computations. The base vectors <code>e[1], e[2], e[3]</code>
+        are usually chosen as vectors of length one (we say that they are
+        normalized to one), and hence they are called "orthonormal".
+        They obey the orthonormality relations for their scalar products:
 <pre>
-	e[i] o e[j] = delta[ij]
+        e[i] o e[j] = delta[ij]
 </pre>
-	where the Kronecker's "delta" has been defined before.
+        where the Kronecker's "delta" has been defined before.
 <p>
-	Here is an example of the vector decomposition:
+        Here is an example of the vector decomposition:
 <pre>
-	A = A[i] e[i]     (summation over "i"!)
+        A = A[i] e[i]     (summation over "i"!)
 </pre>
-	The components A[i] of the vector A obviously depend on the choice
-	of the base system. The same vector A will have different
-	components in two different systems of references:
+        The components A[i] of the vector A obviously depend on the choice
+        of the base system. The same vector A will have different
+        components in two different systems of references:
 <pre>
-	A'[i] e'[i] = A[i] e[i]
+        A'[i] e'[i] = A[i] e[i]
 </pre>
-	where primes refer to the new system. Now, if we multiply both
-	sides of the above equation by a base vector <code>e'[k]</code>,
-	using the scalar (dot) product definition, we will get:
+        where primes refer to the new system. Now, if we multiply both
+        sides of the above equation by a base vector <code>e'[k]</code>,
+        using the scalar (dot) product definition, we will get:
 <pre>
-	A'[i] e'[k] o e'[i] = A[i] e'[k] o e[i]
+        A'[i] e'[k] o e'[i] = A[i] e'[k] o e[i]
 </pre>
-	The new base vectors are mutually orthonormal, so
+        The new base vectors are mutually orthonormal, so
 <pre>
-	e'[k] o e'[i] = delta[ki]
+        e'[k] o e'[i] = delta[ki]
 </pre>
-	and the left hand side will be transformed to:
+        and the left hand side will be transformed to:
 <pre>
-	A'[i] delta[ki] = A'[k]
+        A'[i] delta[ki] = A'[k]
 </pre>
-	But the base vectors on the right hand side are taken from
-	two different systems, and therefore they are not mutually
-	orthonormal. All such nine scalar products form the components of the
-	transormation tensor, R:
+        But the base vectors on the right hand side are taken from
+        two different systems, and therefore they are not mutually
+        orthonormal. All such nine scalar products form the components of the
+        transormation tensor, R:
 <pre>
-	R[ki] = e'[k] o e[i]
+        R[ki] = e'[k] o e[i]
 </pre>
-	As a result, our original equation can be expressed as
-	a new equation defining transformation of the vector A:
+        As a result, our original equation can be expressed as
+        a new equation defining transformation of the vector A:
 <pre>
-	A'[k] = R[ki] A[i]
+        A'[k] = R[ki] A[i]
 </pre>
-	This gives us a rule how to compute new components A'[k] of vector
-	A from its old components and transformation tensor R[ki].
+        This gives us a rule how to compute new components A'[k] of vector
+        A from its old components and transformation tensor R[ki].
 <p>
-	You might want to run some exercise choosing the old
-	system with the base vectors:
+        You might want to run some exercise choosing the old
+        system with the base vectors:
 <pre>
-	e#1=tensor [1,0,0]
-	e#2=tensor [0,1,0]
-	e#3=tensor [0,0,1],
+        e#1=tensor [1,0,0]
+        e#2=tensor [0,1,0]
+        e#3=tensor [0,0,1],
 </pre>
-	where "e" can be considered a tensor of rank 2:
+        where "e" can be considered a tensor of rank 2:
 <pre>
-	e = tensor [1,0,0,
-		    0,1,0,
-		    0,0,1]
+        e = tensor [1,0,0,
+                    0,1,0,
+                    0,0,1]
 </pre>
-	and the new system obtained from the old one by rotation
-	around the axis 3 (x3, or z) by an angle "alpha". Some
-	trigonometry will be involved to compute the new base
-	vectors, e'[i]. The next step is to compute tensor R[ki]
+        and the new system obtained from the old one by rotation
+        around the axis 3 (x3, or z) by an angle "alpha". Some
+        trigonometry will be involved to compute the new base
+        vectors, e'[i]. The next step is to compute tensor R[ki]
 <pre>
 
-	r     = tensor [scalar (e'#k `dot` e#i)|k<-[1..dims], i<-[1..dims]]
+        r     = tensor [scalar (e'#k `dot` e#i)|k<-[1..dims], i<-[1..dims]]
 
 </pre>
-	and finally use operator <code> <*></code> to compute new components
-	of vector A:
+        and finally use operator <code> <*></code> to compute new components
+        of vector A:
 <pre>
-	a' = r <*> a
+        a' = r <*> a
 </pre>
 <p>
 <hr>
 <p>
-	Related page on this site:
-	<a href="http://www.numeric-quest.com/haskell/index.html">
-	Collection of Haskell modules</a>
+        Related page on this site:
+        <a href="http://www.numeric-quest.com/haskell/index.html">
+        Collection of Haskell modules</a>
 
 <pre>
 -----------------------------------------------------------------------------
@@ -956,9 +962,9 @@
    function xLateUrl(aCollection, sProp) {
       var i = 0;
       for(i = 0; i < aCollection.length; i++)
-	 if (aCollection[i][sProp].indexOf("mailto:") == -1 &&
-	     aCollection[i][sProp].indexOf("javascript:") == -1)
-	    aCollection[i][sProp] = sWayBackCGI + aCollection[i][sProp];
+         if (aCollection[i][sProp].indexOf("mailto:") == -1 &&
+             aCollection[i][sProp].indexOf("javascript:") == -1)
+            aCollection[i][sProp] = sWayBackCGI + aCollection[i][sProp];
    }
 
    if (document.links)  xLateUrl(document.links, "href");
diff --git a/numeric-quest.cabal b/numeric-quest.cabal
--- a/numeric-quest.cabal
+++ b/numeric-quest.cabal
@@ -1,25 +1,39 @@
 Name:           numeric-quest
-Version:        0.1
+Version:        0.1.1
 License:        GPL
+License-File:   LICENSE
 Author:         Jan Skibinski
 Maintainer:     Henning Thielemann <numeric-quest@henning-thielemann.de>
 Homepage:       http://www.haskell.org/haskellwiki/Numeric_Quest
 Package-URL:    http://darcs.haskell.org/numeric-quest/
 Category:       Math
-Build-Depends:  base, haskell98
 Synopsis:       Math and quantum mechanics
 Description:    List based linear algebra, similtaneous linear equations, eigenvalues and eigenvectors, roots of polynomials, transcendent functions with arbitrary precision implemented by continued fractions, quantum operations, tensors
-GHC-Options:    -Wall
-Hs-source-dirs: .
-Exposed-modules:
-   Eigensystem
-   EigensystemNum
-   Fraction
-   LinearAlgorithms
-   Orthogonals
-   QuantumVector
-   Roots
-   Tensor
+Tested-With:    GHC==6.4.1, GHC==6.6.1, GHC==6.8.2
+Cabal-Version:  >=1.2
+Build-Type:     Simple
+
 Data-Files:
    Makefile
    README
+
+Flag splitBase
+  description: Choose the new smaller, split-up base package.
+
+Library
+  If flag(splitBase)
+    Build-Depends: base >= 2, haskell98, array
+  Else
+    Build-Depends: base >= 1.0 && < 2, haskell98
+
+  GHC-Options:    -Wall
+  Hs-source-dirs: .
+  Exposed-modules:
+     Eigensystem
+     EigensystemNum
+     Fraction
+     LinearAlgorithms
+     Orthogonals
+     QuantumVector
+     Roots
+     Tensor
