Home Manual Reference Source Test Repository

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 ;

}