* fibref.htm
*$MST_FROM_ENTRY;

* Calculation of sequence Fibonacci by a matrix way 
*  
* if    F(k+2) = F(k+1) + F(k), 
* then  for vectors  
*
*  ( F(k+1) , F(k+2) ) = ( F(k) , F(k+1) ) * A
*
* where a matrix  A = 
*                     ( 0  1 )
*                     ( 1  1 )
*
* The function  Fibonacci calculates the next element of sequence

$ENTRY Fibonacci {
  e.begin (e.k) (e.k1) = e.begin (e.k)
                         <MulVM ((e.k) (e.k1)) (<MatrixA >)>;
 }

* Definition of a matrix A 
MatrixA {
 = ( (0) (1) )
   ( (1) (1) );
 }

* Multiplication of a vector to a matrix 
MulVM {
  (e.vector) ( ) = ;
  (e.vector) (e.matrix) = <MulVV (e.vector) (<Mfirst e.matrix>)> 
                          <MulVM (e.vector) (<Mlast  e.matrix>)>;
 }

Mfirst {
  = ;
 ((e.1) e.2) e.3 = (e.1) <Mfirst e.3>;
 }

Mlast {
  = ;
 ((e.1)    ) e.3 =       <Mlast e.3>;
 ((e.1) e.2) e.3 = (e.2) <Mlast e.3>;
 }


* Multiplication of a vector to a vector (or scalar product) 
MulVV {
 (e.v1) (e.v2) = <MulVV1 (0) (e.v1) (e.v2)>;
 }

MulVV1 {
 (e.rez) ( ) ( ) = (e.rez);
 (e.rez) ((e.1) e.2) ((e.3) e.4) = <MulVV1
                                    (<Add (e.rez) <Mul (e.1) e.3>>)
                                    (e.2) (e.4)>;
 }

/*
  Result of supercompilation

$ENTRY Fibonacci {
 e.41 (e.102 ) (e.101 )
  , <Add (e.102 ) e.101 >:e.122
  = e.41 (e.102 ) (e.101 ) (e.122 ) ;
 }

  After elementary transformation 

$ENTRY Fibonacci {
 e.41 (e.102) (e.101) = e.41 (e.102) (e.101) (<Add (e.102) e.101>) ;
}

*/