src/matrix.js
export function __matrix__ ( zero , one , mul , add ) {
/**
* @param {nth} n > 0
*/
var matrix = function ( n ) {
// We can compute simultaneously,
//
// a = b
// b = a + b
//
// Using matrix multiplication,
//
// X M
// : :
// | a | | 0 1 |
// | b | . | 1 1 |
//
// With this we can compute F_{n-1} and F_n using matrix exponentiation
//
// n
// | F_{n-1} | | 0 | | 0 1 |
// | F_n | = | 1 | . | 1 1 |
//
// Matrix exponentiation can be achieved in log n steps using the
// binary decomposition of n
//
// n = ( n % 2 ) * 1 + ( ( n >> 1 ) % 2 ) * 2 + ... + ( ( n >> i ) % 2 ) * ( i + 1 ) + ...
//
// And computing M raised to successive powers of 2,
//
// 2
// n / (n//2) \ (n%2)
// | 0 1 | | | 0 1 | | | 0 1 |
// | 1 1 | = \ | 1 1 | / . | 1 1 |
//
// The matrix is encoded as
//
// | t u |
// | v w |
var a , b , t , u , v , w , a2 , b2 , t2 , u2 , v2 , w2 ;
a = zero( ) ; b = one( ) ;
t = zero( ) ; u = one( ) ; v = one( ) ; w = one( ) ;
while ( true ) {
if ( n % 2 === 1 ) {
a2 = add( mul( a , t ) , mul( b , u ) ) ;
b2 = add( mul( a , v ) , mul( b , w ) ) ;
a = a2 ; b = b2 ;
if ( n === 1 ) break ;
}
t2 = add( mul( t , t ) , mul( u , v ) ) ;
u2 = add( mul( t , u ) , mul( u , w ) ) ;
v2 = add( mul( v , t ) , mul( w , v ) ) ;
w2 = add( mul( v , u ) , mul( w , w ) ) ;
t = t2 ; u = u2 ; v = v2 ; w = w2 ;
n >>>= 1 ;
}
return [ a , b ] ;
} ;
return matrix ;
}