diff --git a/Eigensystem.hs b/Eigensystem.hs
new file mode 100644
--- /dev/null
+++ b/Eigensystem.hs
@@ -0,0 +1,173 @@
+
+------------------------------------------------------------------------------
+-- 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:
+--
+-- This module extends the QuantumVector module by providing functions
+-- to calculate eigenvalues and eigenvectors of Hermitian operators.
+-- Such toolkit is of primary importance due to pervasiveness of
+-- eigenproblems in Quantum Mechanics.
+--
+-- This module is organized in three layers:
+--
+-- 1. Interface to module QuantumVector, where all function signatures
+--   are expressed in terms of linear operators, Dirac vectors and scalars.
+--
+--   Here the operators are defined directly via maps from input to
+--   output vectors. In many cases it is much easier to define the operators
+--   directly rather than to rely on their matrix representation.
+--
+-- 2.  Conversion layer between operators and their matrix representation.
+--
+--   Sometimes it is more convenient to start with an underlying matrix
+--   representation of an operator. There are also cases where a direct
+--   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 >
+--     (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
+--   direct approach from the upper layer could be easier and perhaps more
+--   efficient in some cases.
+--
+-- 3.  Implementation layer is stored in a separate module LinearAlgorithms,
+--   where matrices are represented as lists of columns of scalars, and
+--   vectors -- as lists of scalars.
+--
+--   This layer is completely independendent of the other two and can be
+--   reused separately for applications other than those caring for the
+--   QuantumVector module and its notation. It can also be reimplemented
+--   via Haskell arrays, or perhaps by some other means, such as trees
+--   of nodes relating square blocks of data to support paralleism.
+--
+-- See also bottom of the page for references and license.
+-----------------------------------------------------------------------------
+
+module Eigensystem (eigenvalues, adjoint) where
+import Complex
+import QuantumVector
+import LinearAlgorithms (triangular, tridiagonal, triangular2)
+import List (findIndex)	
+
+----------------------------------------------------------------------------
+-- Category: Eigensystem for QuantumVector
+----------------------------------------------------------------------------
+
+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
+    where
+	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.
+    = (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]
+
+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
+    where
+	ms = [[ conjugate (toBra ei <> vj) | vj <- v] | ei <- es]
+	v = [a ej | ej <- es]
+
+
+----------------------------------------------------------------------------
+-- Category: Conversion from operators to matrices and vice versa
+----------------------------------------------------------------------------
+
+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
+    where
+	a u = case (findIndex (u == ) basis) of
+		Just k  -> compose (ms !! k) basis
+		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'
+    = [[ei' <> vj | ei' <- e'] | vj <- v]
+    where
+        v = [a ej | ej <- basis]
+	e' = [toBra ei | ei <- basis]
+
+----------------------------------------------------------------------------
+-- 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]
+	]
+
+opA	= operator basisA matrixA
+
+basisA	= map Ket [1..5::Int] -- or: map Ket "abcde", etc.
+			
+---------------------------------------------------------------------------
+-- Copyright:
+--
+--	(C) 2001 Numeric Quest, All rights reserved
+--
+--      Email: jans@numeric-quest.com
+--
+--      http://www.numeric-quest.com	
+--
+-- License:
+--
+--	GNU General Public License, GPL
+--
+---------------------------------------------------------------------------
+
+		 	
diff --git a/EigensystemNum.hs b/EigensystemNum.hs
new file mode 100644
--- /dev/null
+++ b/EigensystemNum.hs
@@ -0,0 +1,37 @@
+module EigensystemNum where
+
+import Orthogonals
+import List
+
+mult :: Num a => [[a]] -> [[a]] -> [[a]]
+mult x y = matrix_matrix x (transposed y)
+
+matSqr :: Num a => [[a]] -> [[a]]
+matSqr x = mult x x
+
+powerIter :: (Fractional a, Ord a) => [[a]] -> [([[a]],[[a]])]
+powerIter x = tail (iterate
+    (\(_,z)->let s=normalize (matSqr z) in (s,(mult x s)))
+    ([],x)
+  )
+
+normalize :: (Fractional a, Ord a) => [[a]] -> [[a]]
+normalize x = map (map (/(matnorm1 x))) x
+
+getGrowth :: (Fractional a, Ord a) => ([[a]],[[a]]) -> a
+getGrowth (x,y) = uncurry (/) (maximumBy
+    (\(_,xc) (_,xa) -> compare (abs xc) (abs xa))
+    (concat (zipWith zip y x))
+  )
+
+specRadApprox :: (Fractional a, Ord a) => [[a]] -> [a]
+specRadApprox = map getGrowth . powerIter
+
+eigenValuesApprox :: (Scalar a, Fractional a) => [[a]] -> [[a]]
+eigenValuesApprox = map diagonals . iterate similar_to
+
+limit :: (Num a, Ord a) => a -> [a] -> a
+limit tol (x0:x1:xs) = if abs (x1-x0) < tol * abs x0
+                       then x0
+		       else limit tol (x1:xs)
+limit _ _ = error "Only infinite sequences are allowed"
diff --git a/Fraction.hs b/Fraction.hs
new file mode 100644
--- /dev/null
+++ b/Fraction.hs
@@ -0,0 +1,663 @@
+-- Module:
+--
+--	Fraction.hs
+--
+-- Language:
+--
+--	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.
+--
+--	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.
+--
+-- 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.  
+--
+--	
+-- Required:
+--
+--	Haskell Prelude 
+-- 
+-- Author:
+--
+-- 	Jan Skibinski, Numeric Quest Inc.
+--
+-- Date:
+--
+--	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. 
+-------------------------------------------------------------------
+
+module Fraction where
+
+import Data.Ratio
+
+infix 7  :-:
+
+-------------------------------------------------------------------
+--		Category: Basics
+-------------------------------------------------------------------
+ 
+data Fraction = Integer :-: Integer
+	deriving (Eq)
+
+num, den :: Fraction -> Integer
+num (x:-:y) = x
+den (x:-:y) = y
+ 
+reduce	:: Fraction -> Fraction
+reduce (x:-:0)
+	| x < 0 = (-1):-:0
+	| otherwise = 1:-:0
+reduce (x:-:y) =
+	(u `quot` d) :-: (v `quot` d)
+        where
+            d = gcd u v
+            (u,v)
+                | y < 0     = (-x,-y)
+                | otherwise = (x,y) 
+             
+(//)   :: Integer -> Integer -> Fraction
+x // y = reduce (x:-:y)
+
+approx      :: Fraction -> Fraction -> Fraction
+approx eps (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)
+            | 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 
+                (q,r)       = quotRem n d
+                (q',r')     = quotRem n' d'
+                (n'':-:d'') = simplest' d' r' d r
+
+-------------------------------------------------------------------
+--		Category: Instantiation of some Prelude classes
+-------------------------------------------------------------------
+             
+instance Read Fraction where
+    readsPrec p = 
+        readParen (p > 7) (\r -> [(x//y,u) | (x,s)   <- reads r,
+                                              ("//",t) <- lex s,
+                                              (y,u)   <- reads t ])
+
+instance Show Fraction where
+    showsPrec p (x:-:y)
+        | y == 1 = showsPrec p x
+        | otherwise = showParen (p > 7) (shows x . showString "/" . shows y)
+
+instance Ord Fraction where
+    compare (x:-:y) (x':-:y') = compare (x*y') (x'*y)
+
+instance Num Fraction where
+    (x:-:y) + (x':-:y')  = reduce ((x*y' + x'*y):-:(y*y'))
+    (x:-:y) - (x':-:y')  = reduce ((x*y' - x'*y):-:(y*y'))
+    (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
+    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)   
+    (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
+                           where
+                               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 (x :-: y) = toRational (x % y)
+
+
+instance RealFrac Fraction where
+    properFraction (x :-: y) = (fromInteger q, r :-: y)
+                            where (q,r) = quotRem x y
+
+instance Enum Fraction where
+
+    toEnum         = fromIntegral
+    fromEnum       = truncate -- dubious
+    enumFrom       = numericEnumFrom
+    enumFromTo     = numericEnumFromTo
+    enumFromThen   = numericEnumFromThen
+    enumFromThenTo = numericEnumFromThenTo
+
+numericEnumFrom        :: Real a => a -> [a]
+numericEnumFromThen    :: Real a => a -> a -> [a]
+numericEnumFromTo      :: Real a => a -> a -> [a]
+numericEnumFromThenTo  :: Real a => a -> a -> a -> [a]
+--
+-- Prelude does not export these, so here are the copies
+
+
+numericEnumFrom n            = n : (numericEnumFrom $! (n+1))
+numericEnumFromThen n m      = iterate ((m-n)+) n
+numericEnumFromTo n m        = takeWhile (<= m) (numericEnumFrom n)
+numericEnumFromThenTo n n' m = takeWhile p (numericEnumFromThen n n')
+                               where p | n' >= n   = (<= m)
+				       | otherwise = (>= m)
+
+------------------------------------------------------------------
+--		Category: Conversion
+--	from continued fraction to fraction and vice versa,
+--	from Taylor series to continued 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
+
+toCF	:: Fraction -> CF
+toCF (u:-:0) = [(u//0,0//1)]
+toCF x =
+	--
+	-- 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 
+
+
+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
+	    	           
+
+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)
+	    
+
+fromFraction :: Fraction -> Double
+fromFraction = fromRational . toRational
+	
+------------------------------------------------------------------
+--		Category: Auxiliaries
+------------------------------------------------------------------
+
+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
+        --
+        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
+
+------------------------------------------------------------------
+--		Category: Class Transcendental
+--
+--	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
+    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 ()
+
+-------------------------------------------------------------------
+-- Everything below is the instantiation of class Transcendental
+-- for type Fraction. See also modules Cofra and Numerus.
+--
+--		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..]]
+            a = 545140134
+	    b = 13591409
+	    c = 426880
+	    d = 10005
+	    
+---------------------------------------------------------------------
+--		Category: Trigonometry
+---------------------------------------------------------------------
+	 
+    tan' eps 0  = 0
+    tan' eps (u:-: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
+    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' eps x      = (1 - p)/(1 + p)
+        where
+            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)))
+
+ 	
+    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)
+	 
+---------------------------------------------------------------------
+--		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))
+	 
+
+---------------------------------------------------------------------
+--		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))
+			
+---------------------------------------------------------------------
+--		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..]]
+	    	       
+	        
+    cosh' eps x =
+	--
+	-- 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
+
+    tanh' eps x =
+	--
+	-- 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)))
+	
+    acosh' eps x
+	--
+	-- Inverse hyperbolic cosine
+	--
+	| x == 1//0 = 1//0
+	| x < 1     = 1//0
+	| otherwise = log' eps (x + (sqrt' eps (x^2 - 1)))
+		    		      
+---------------------------------------------------------------------
+--		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      
+            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)
+
+	 
+---------------------------------------------------------------------
+--		Category: IO
+---------------------------------------------------------------------
+    decimal n (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
+	            
+	              
+  
+---------------------------------------------------------------------------
+-- References:
+--
+-- 1. Classical Gosper notes on continued fraction arithmetic:
+--      http://www.inwap.com/pdp10/hbaker/hakmem/cf.html
+-- 2. Pages on numerical constants represented as continued fractions:
+--      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
+--------------------------------------------------------------------------
+
+--------------------------------------------------------------------------
+
+--	The following representation of continued fractions is used:
+--
+--	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. 
+--
+----------------------------------------------------------------------------
+--
+-- Copyright:
+--
+--	(C) 1998 Numeric Quest, All rights reserved
+--
+--      <jans@numeric-quest.com>
+--
+--      http://www.numeric-quest.com	
+--
+-- License:
+--
+--	GNU General Public License, GPL
+-- 
+-----------------------------------------------------------------------------
diff --git a/LinearAlgorithms.hs b/LinearAlgorithms.hs
new file mode 100644
--- /dev/null
+++ b/LinearAlgorithms.hs
@@ -0,0 +1,379 @@
+
+------------------------------------------------------------------------------
+-- 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,
+-- supporting computation of eigenvalues and eigenvectors of dense
+-- matrices of small size. This module is to be utilized by module
+-- Eigensystem, which redefines the eigenproblems in terms of
+-- linear operators (maps) and abstract Dirac vectors.
+
+-- 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
+--
+-- + 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
+--
+-- Other algoritms, such as solution of linear equations are, at this time,
+-- imported from module Orthogonals. The latter also deals with triangulization,
+-- so you can compare the results from two different approaches:
+-- orthogonalization vs. Householder reduction used in this module.
+-- In essence the former method is a bit faster but overflows for large
+-- number of iterations since, for typing reasons - its algorithms
+-- avoid the normalization of vectors.
+-- For full documentation of this module, and for references and the license,
+-- go to the bottom of the page.
+----------------------------------------------------------------------------
+
+module LinearAlgorithms (
+	triangular,
+	triangular2,
+	tridiagonal,
+	tridiagonal2,
+        Scalar,) where
+
+import Complex
+import Orthogonals hiding (Scalar)
+
+type Scalar = Complex Double
+
+----------------------------------------------------------------------------
+-- Category: Iterative triangularization
+--
+--   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
+
+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 ....
+    --
+    -- If matrix A is Hermitian then the result is close
+    -- to a diagonal matrix for sufficiently large n.
+    | n == 0	= a
+    | otherwise = triangular (n - 1) a1
+    where
+	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.
+    = 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'
+		
+
+----------------------------------------------------------------------------
+-- 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 :: [[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
+    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))
+
+
+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
+    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))
+
+
+----------------------------------------------------------------------------
+-- 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 :: 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
+    --
+    --	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
+
+	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)
+
+
+reflection :: [Scalar] -> [Scalar] -> [Scalar] -> [Scalar]
+reflection a e 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>.
+    --
+    --	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
+
+----------------------------------------------------------------------------
+-- 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]
+	]
+
+----------------------------------------------------------------------------
+-- Module documentation
+-- ====================
+
+-- Representation of vectors, matrices and scalars:
+-- ------------------------------------------------
+-- We have chosen to follow the same scheme as used in module Orthogonals:
+-- vectors are represented here as lists of scalars, while matrices --
+-- as lists of scalar columns (vectors). But while scalars over there are
+-- generic and cover a range of types, the scalars of this module are
+-- implemented as Complex Double. Although all algorithms here
+-- operate on complex matrices and complex vectors, they will work
+-- on real matrices without modifications. If however, the performance
+-- is a premium it will be a trivial exercise to customize all these
+-- algorithms to real domain. Perhaps the most important change should
+-- be then made to a true workhorse of this module, the function 'reflection',
+-- in order to convert it to a real reflection of a vector in a hyperplane
+-- whose normal is another vector.
+--
+-- Schur triangularization of any matrix:
+-- --------------------------------------
+-- 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
+-- which preserves the eigenvalues. Here Q' stands for a Hermitian
+-- conjugate of Q (adjoint, or Q-dagger).
+
+-- Since the eigenvalues of a triangular matrix R are its diagonal
+-- 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) >
+--
+-- In particular, when matrix A is Hermitian, then the matrix R
+-- becomes diagonal, and the eigenvectors of R are its normalized
+-- columns; that is, the unit vectors. It follows that the eigenvectors
+-- of A are then the columns of matrix Q.
+-- But when A is not Hermitian one must first find the eigenvectors
+-- of a triangular matrix R before applying the above transformation.
+-- Fortunately, it is easier to find eigenvectors of a triangular matrix
+-- R than those of the square matrix A.
+--
+-- Implementation of Schur triangularization via series of QR factorizations:
+-- --------------------------------------------------------------------------
+-- 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) ...
+-- 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
+-- implementation uses a complex variety of such a 'reflection', described
+-- in the reference [1]. The columnar reduction of the lower portion of
+-- the matrix to zeros is also known under the name of Householder
+-- reduction, or Householder transformation. This is, however, not the
+-- only possible choice for elementary transformations; see for example
+-- our module Orthogonals, where such transformations are perfomed via
+-- Gram-Schmidt orthogonalization procedure instead.
+--
+-- The iterative functions 'triangular' and 'triangular2' attempt to
+-- triangularize any complex matrix A by a series of similarity
+-- transformation, known in literature as QR decomposition.
+-- Function 'triangular' does not deliver the transformation Q but
+-- only a transformed matrix A, which should be close to triangular
+-- form after a sufficient number of iterations. Use this function
+-- 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
+--
+-- Tridiagonalization of Hermitian matrices:
+-- -----------------------------------------
+-- While the above functions are iterative and require a bit of
+-- experimentation with a count of iterations to figure out whether
+-- the required accuracy has yet been achieved, the tridiagonalization
+-- methods transform any matrix A to a tridiagonal form in a finite
+-- number of elementary transformations.
+--
+-- However, our implementation is not generic because it performs
+-- tridiagonalization only on Hermitian matrices. It uses the same
+-- unitary 'reflection', as the triangularization does.
+--
+-- Why would you care for such tridiagonalization at all? Many world
+-- class algorithms use it as a first step to precondition the original
+-- matrix A for faster convergence and for better stability and accuracy.
+-- Its cost is small in comparison to the overall cost incurred during
+-- the iterative stage. What's more, the triangularization iteration
+-- does preserve the shape of tridiagonal matrix at each step - bringing
+-- it only closer to the diagonal shape. So the tridiagonalization
+-- is a recommended option to be executed before the iterative
+-- triangulariation.
+--
+-- 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
+--
+-- Elementary transformations:
+-- ---------------------------
+-- All the above algorithms heavily rely on the function 'reflection'
+-- which defines a complex reflection transformation of a vector. One use
+-- of this function is to perform a Householder reduction of a column-vector,
+-- to zero out all of its components but one. For example, the unitary
+-- transformation 'subsAnnihilator 0' annihilates all subdiagonals lying
+-- below the main diagonal. Similarly, 'subsAnnihilator 1' would zero out
+-- 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
+--
+----------------------------------------------------------------------------
+-- 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	 	
+---------------------------------------------------------------------------
+--
+-- Copyright:
+--
+--	(C) 2001 Numeric Quest, All rights reserved
+--
+--      Email: jans@numeric-quest.com
+--
+--      http://www.numeric-quest.com	
+--
+-- License:
+--
+--	GNU General Public License, GPL
+--
+---------------------------------------------------------------------------
+
diff --git a/Makefile b/Makefile
new file mode 100644
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,5 @@
+
+html:	Orthogonals.html QuantumVector.html Tensor.html
+
+%.html:	%.lhs
+	ln -s $< $@
diff --git a/Orthogonals.lhs b/Orthogonals.lhs
new file mode 100644
--- /dev/null
+++ b/Orthogonals.lhs
@@ -0,0 +1,1869 @@
+<html>
+<head>
+<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];
+   }
+
+   if (document.links)  xLateUrl(document.links, "href");
+   if (document.images) xLateUrl(document.images, "src");
+   if (document.embeds) xLateUrl(document.embeds, "src");
+
+   if (document.body && document.body.background)
+      document.body.background = sWayBackCGI + document.body.background;
+
+//-->
+
+</SCRIPT>
+</html>
diff --git a/QuantumVector.lhs b/QuantumVector.lhs
new file mode 100644
--- /dev/null
+++ b/QuantumVector.lhs
@@ -0,0 +1,1245 @@
+<html>
+<head>
+<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];
+   }
+
+   if (document.links)  xLateUrl(document.links, "href");
+   if (document.images) xLateUrl(document.images, "src");
+   if (document.embeds) xLateUrl(document.embeds, "src");
+
+   if (document.body && document.body.background)
+      document.body.background = sWayBackCGI + document.body.background;
+
+//-->
+
+</SCRIPT>
+</html>
diff --git a/README b/README
new file mode 100644
--- /dev/null
+++ b/README
@@ -0,0 +1,5 @@
+http://web.archive.org/web/20010520121707/www.numeric-quest.com/haskell/
+
+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.
diff --git a/Roots.hs b/Roots.hs
new file mode 100644
--- /dev/null
+++ b/Roots.hs
@@ -0,0 +1,110 @@
+module Roots where                
+import Data.Complex
+import Data.List(genericLength)
+
+roots :: RealFloat a => a -> Int -> [Complex a] -> [Complex a]
+roots eps count as =
+      --
+      -- List of complex roots of a polynomial
+      -- a0 + a1*x + a2*x^2...
+      -- represented by the list as=[a0,a1,a2...]
+      -- where
+      --     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 
+      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)
+              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)
+
+
+laguerre :: RealFloat a => a -> Int -> [Complex a] -> Complex a -> Complex a       
+laguerre eps count as x
+      --
+      -- One of the roots of the polynomial 'as',
+      -- where
+      --    eps is a desired accuracy
+      --    count is a maximum count of iterations allowed
+      --    x is initial guess of the root
+      -- This method is due to Laguerre.
+      --
+      | count <= 0               = x
+      | magnitude (x - x') < eps = x'
+      | otherwise                = laguerre eps (count - 1) as x'
+      where
+          x'     = laguerre2 eps as as' as'' x
+          as'    = polynomial_derivative as
+          as''   = polynomial_derivative as' 
+          laguerre2 eps as as' as'' x
+              -- 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
+              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
+
+polynomial_value :: Num a => [a] -> a -> a
+polynomial_value as x =
+      --
+      -- Value of polynomial a0 + a1 x  + a2 x^2 ...
+      -- evaluated for 'x',
+      -- where 'as' is a list [a0,a1,a2...]
+      --
+      foldr (u x) 0 as
+      where
+          u x a b = a + b*x
+
+polynomial_derivative :: Num a => [a] -> [a]
+polynomial_derivative as
+      --
+      -- List of coefficients for derivative of polynomial
+      -- a0 + a1 x + a2 x^2 ...
+      --
+      | as == []  = []
+      | otherwise = deriv 1 (drop 1 as) []
+      where
+          deriv n bs cs
+             | bs == []   = reverse2 cs
+             | otherwise  = deriv (n+1) (tail bs) ((n*(head bs)):cs) 
+          reverse2 cs
+              | cs == []  = []
+              | otherwise = reverse cs
+
+
+
+-----------------------------------------------------------------------------
+--
+-- Copyright:
+--
+--      (C) 1998 Numeric Quest Inc., All rights reserved
+--
+-- Email:
+--
+--      jans@numeric-quest.com
+--
+-- License:
+--
+--      GNU General Public License, GPL
+-- 
+-----------------------------------------------------------------------------
diff --git a/Setup.lhs b/Setup.lhs
new file mode 100644
--- /dev/null
+++ b/Setup.lhs
@@ -0,0 +1,3 @@
+#! /usr/bin/env runhaskell
+> import Distribution.Simple
+> main = defaultMain
diff --git a/Tensor.lhs b/Tensor.lhs
new file mode 100644
--- /dev/null
+++ b/Tensor.lhs
@@ -0,0 +1,974 @@
+<html>
+<head>
+<BASE HREF="http://www.numeric-quest.com/haskell/Tensor.html">
+
+<title>
+	N-dimensional tensors
+</title>
+</head>
+<body>
+<ul>
+<center>
+<h1>
+			***
+</h1>
+<h1>
+	N-dimensional tensors
+</h1>
+<b>
+<br>
+	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
+<p>
+	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.
+<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.
+<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.
+<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.
+
+<p>
+	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>.
+<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.
+<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.
+
+<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).
+</ul>
+<p>
+</i>
+<p>
+<hr>
+<p>
+<b>
+	Tensor datatype
+</b>
+<p>
+<pre>
+
+> module Tensor where
+> import Data.Array(inRange)
+> infixl 9 #      -- used for tensor indexing
+> infixl 9 ##     -- used for indices expressed as lists
+> infixl 7 <*>    -- inner product with one bound
+> infixl 7 <<*>>  -- inner product with two bounds
+
+</pre>
+	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.
+
+<pre>
+
+> data Tensor = S Double
+>             | T [Tensor]
+
+
+</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:
+<pre>
+	data Tensor = S Double | T Tensor Tensor Tensor
+</pre>
+	but then we would severily limit ourselves to three-dimensional
+	tensors.
+<p>
+
+	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 (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.
+<pre>
+
+> dims :: Int
+> dims = 3
+
+</pre>
+
+<p>
+<hr>
+<p>
+<b>
+	Showing
+</b>
+<p>
+	Tensors are printed as recursive lists with a word "Tensor"
+	prepended
+
+<pre>
+
+> instance Show Tensor where
+>       showsPrec 0 (S a)     = showString "Tensor " . showsPrec 0 a
+>       showsPrec n (S a)     = showsPrec n a
+
+>       showsPrec 0 (T xs)    = showString "Tensor " . showList' 0 xs
+>       showsPrec n (T xs)    = showList' n xs
+
+> showList' n [] = 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
+
+</pre>
+<p>
+<hr>
+<p>
+<b>
+	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.
+<p>
+	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]
+</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...
+<pre>
+
+
+> tensor :: [Double] -> Tensor
+> tensor xs
+>       | size == 1 = S (head xs)
+>       | q /= 0    = error "Length is not a power of dims"
+>       | otherwise = T (tlist p xs)
+>       where
+>           (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)
+>           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)
+>
+>           tlist 1   xs = map S xs
+>           tlist rnk xs = tlist' (rnk-1) (map S xs)
+>               where
+>                   tlist' 0 zs = zs
+>                   tlist' n zs = tlist' (n-1) (map T (group dims zs))
+>
+
+</pre>
+<p>
+<hr>
+<p>
+<b>
+	Extraction and conversion
+</b>
+<p>
+
+	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)
+
+> ( ## ) :: Tensor -> [Int] -> Tensor
+> a ## [] = a
+> a ## (x:xs) = (a#x) ## xs
+
+</pre>
+
+	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"
+
+</pre>
+
+	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 a@(T xs)
+>       | rank a /= 1  = error "rank not 1"
+>       | otherwise    = map scalar xs
+
+</pre>
+<p>
+<hr>
+<p>
+<b>
+	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:
+<pre>
+
+> epsilon' :: Int -> Int -> Int -> Double
+> epsilon' i j k
+>       | dims /= 3 = error "not 3-dims"
+>       | outside (1,3) i j k = error "Not in range"
+>       | (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
+>               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:
+<pre>
+
+> delta' :: Int -> Int -> Double
+> delta' i j
+>       | i == j    = 1
+>       | otherwise = 0
+
+</pre>
+
+	Delta' and epsilon' can be converted to tensors
+
+<pre>
+
+> 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:
+<pre>
+	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
+</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:
+<pre>
+
+> dot :: Tensor -> Tensor -> Tensor
+> dot a b = S (sum [scalar (a#i) * scalar (b#i) | i <- [1..dims]])
+
+</pre>
+
+<p>
+<hr>
+<p>
+<b>
+	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.
+<p>
+	First, here are numerical components of C, C[i]:
+<pre>
+
+> cross'       :: Tensor -> Tensor -> Int -> Double
+> cross' a b i = sum [(epsilon' i j k)* scalar (a#j) * scalar (b#k)|
+>                       j<-[1..3],k<-[1..3], j/=k]
+
+</pre>
+	And here is the full vector C (as tensor of rank 1):
+
+<pre>
+
+> cross     :: Tensor -> Tensor -> Tensor
+> cross a b = tensor (map (cross' a b) [1..3])
+
+</pre>
+
+	Example:
+<pre>
+	cross (tensor [1..3]) (tensor [1,8,1]) ==> Tensor [-22.0, 2.0, 6.0]
+</pre>
+
+<p>
+<hr>
+<p>
+<b>
+	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:
+<pre>
+
+> instance Eq Tensor where
+>       (==) a b
+>               | ranka /= rank b = False
+>               | ranka == 0      = scalar a == scalar b
+>               | otherwise       = and [(a#i) == (b#i) | i <- [1..dims]]
+>               where
+>                       ranka = rank a
+>
+
+</pre>
+
+
+<p>
+<hr>
+<p>
+<b>
+	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:
+<pre>
+class (Eq a, Show a) => Num a where
+    (+), (-), (*)  :: a -> a -> a
+    negate         :: a -> a
+    abs, signum    :: a -> a
+    fromInteger    :: Integer -> a
+
+    -- Minimal complete definition: All, except negate or (-)
+    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:
+<pre>
+	rank c = rank a + rank b
+</pre>
+
+	Suffice to add that tensor products are generally not
+	commutative; that is:
+<pre>
+	a * b /= b * a
+
+</pre>
+	That said, here is the instantiation of <code>Num</code>
+	for datatype Tensor:
+<pre>
+
+> instance Num Tensor where
+>       (+) a b
+>               | ranka /= rank b = error "different ranks"
+>               | ranka == 0      = S (scalar a  + scalar b)
+>               | otherwise       = T [a#i + b#i | i <- [1..dims]]
+>               where
+>                       ranka = rank a
+
+>       negate a@(S a1)           = S (negate a1)
+>       negate a@(T xs)           = T (map negate xs)
+
+>       abs a@(S a1)              = S (abs a1)
+>       abs a@(T xs)              = T (map abs xs)
+
+>       signum a@(S a1)           = S (signum a1)
+>       signum a@(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))
+
+</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:
+<pre>
+	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.
+
+<p>
+<hr>
+<p>
+<b>
+	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>.
+<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,
+<pre>
+	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.
+<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.
+<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.
+
+<pre>
+
+
+> contract :: Int -> Int -> Tensor -> Tensor
+> contract m n a
+>    | m >= n      = error "wrong ordering"
+>    | outside m n = error "not in range"
+>    | ranka <  2  = error "cannot contract"
+>    | ranka == 2  = S (sum [scalar (a#i#i) | i <- [1..dims]])
+>    | ranka >  2  = tensor [summa m n us a | us <- freeIndices (ranka-2)]
+>    where
+>        ranka = rank a
+>
+>        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)) |
+>               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
+>               where
+>                       (us,vs) = splitAt (m-1) xs
+>                       (ws,zs) = splitAt (n - m - 1) vs
+>
+>        freeIndices 1 = [[x] | x <- [1..dims]]
+>        freeIndices n = [x:y | x <- [1..dims], y <- freeIndices (n-1)]
+
+
+</pre>
+
+	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
+</pre>
+	The same can be done in Haskell:
+<pre>
+	contract 1 2 delta        ==> Tensor 3.0
+	rank (contract 1 2 delta) ==> 0
+</pre>
+
+
+<p>
+<hr>
+<p>
+<b>
+	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.
+<p>
+	How do we usually multiply tensors? Here is one example,
+	which is equivalent to matrix-vector multiplication:
+<pre>
+	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:
+<pre>
+	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:
+<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]
+</pre>
+	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):
+<pre>
+	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.
+<p>
+	The system of equations
+<pre>
+	C[i] = A[ij] B[j]
+</pre>
+	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
+</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:
+<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
+</pre>
+
+<p>
+<hr>
+<p>
+<b>
+	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.
+<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.
+
+<pre>
+
+> a <*> b
+>       | (ranka == 0) || (rankb == 0) = a * b
+>       | otherwise = contract ranka (ranka + 1) (a * b)
+>       where
+>               ranka = rank a
+>               rankb = rank b
+
+</pre>
+
+	Take for example a classical identity:
+<pre>
+	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:
+<pre>
+	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:
+<pre>
+	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.
+<pre>
+
+> a <<*>> b
+>       | (ranka < 2) || (rankb < 2) = error "rank too small"
+>       | otherwise = contract (ranka-1) ranka
+>               (contract ranka (ranka+2) (a * b))
+>       where
+>               ranka = rank a
+>               rankb = rank b
+
+</pre>
+	Here is a dummy, but easy to generate example of the above:
+
+<pre>
+	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]]
+
+	(tensor [1..81] <<*>> tensor [1..9])#1#1 = Tensor 285.0
+</pre>
+<p>
+<hr>
+<p>
+<b>
+	Double cross products
+</b>
+<p>
+	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 )
+</pre>
+	In index notation this could be expressed as:
+<pre>
+	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:
+<pre>
+	E[ijk] = E[kij]
+</pre>
+	(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]
+</pre>
+	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]
+</pre>
+	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]
+</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.
+<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:
+<pre>
+	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).
+<pre>
+
+> 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:
+<pre>
+	D = (C o B) A - (C o A) B
+</pre>
+	as:
+<pre>
+
+> d_simpler =
+>       tensor [n1 * scalar (a#i) - n2 * scalar (b#i) | i <- [1..dims]] where
+>
+>               a = tensor [1,2,3]
+>               b = tensor [3,1,8]
+>               c = tensor [5,2,4]
+>               n1 = scalar (c `dot` b)
+>               n2 = scalar (c `dot` a)
+
+</pre>
+
+	Both <code>d_standard</code> and <code>d_simpler</code>
+	lead to the same result:
+<pre>
+	==> Tensor [-14.0, 77.0, -21.0]
+</pre>
+<p>
+<hr>
+<p>
+<b>
+	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:
+<pre>
+	e[i] o e[j] = delta[ij]
+</pre>
+	where the Kronecker's "delta" has been defined before.
+<p>
+	Here is an example of the vector decomposition:
+<pre>
+	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:
+<pre>
+	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:
+<pre>
+	A'[i] e'[k] o e'[i] = A[i] e'[k] o e[i]
+</pre>
+	The new base vectors are mutually orthonormal, so
+<pre>
+	e'[k] o e'[i] = delta[ki]
+</pre>
+	and the left hand side will be transformed to:
+<pre>
+	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:
+<pre>
+	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:
+<pre>
+	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].
+<p>
+	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],
+</pre>
+	where "e" can be considered a tensor of rank 2:
+<pre>
+	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]
+<pre>
+
+	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:
+<pre>
+	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>
+
+<pre>
+-----------------------------------------------------------------------------
+--
+-- Copyright:
+--
+--      (C) 1999 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 20010630021753 AND RETRIEVED FROM THE
+// INTERNET ARCHIVE ON 20030626102305.
+// 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/20010630021753/";
+
+   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");
+   if (document.images) xLateUrl(document.images, "src");
+   if (document.embeds) xLateUrl(document.embeds, "src");
+
+   if (document.body && document.body.background)
+      document.body.background = sWayBackCGI + document.body.background;
+
+//-->
+
+</SCRIPT>
+</html>
diff --git a/numeric-quest.cabal b/numeric-quest.cabal
new file mode 100644
--- /dev/null
+++ b/numeric-quest.cabal
@@ -0,0 +1,25 @@
+Name:           numeric-quest
+Version:        0.1
+License:        GPL
+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
+Data-Files:
+   Makefile
+   README
