Example #1
0
int fibonacci (int n)
{
    int unit [4] = {0, 1, 1, 1};
    int m [4];

    if (0 == n || 1 == n)
        return n;

    matrix_power (unit, n, m);

    return m [1];
}
Example #2
0
void matrix_power (int* base, int n, int* result)
{
    int tmp [2][4];

    if (1 == n)
        memcpy (result, base, sizeof (int) * 4);
    else {
        matrix_power (base, n / 2, tmp [0]);

        if (n % 2) {
            mul_2x2_2x2 (tmp [0], tmp [0], tmp [1]);
            mul_2x2_2x2 (base, tmp [1], result);
        }
        else
            mul_2x2_2x2 (tmp [0], tmp [0], result);
    }
}
Example #3
0
// exponentiate exactly a hermitian matrix "Q" into SU(NC) matrix "U"
void
exponentiate( GLU_complex U[ NCNC ] , 
	      const GLU_complex Q[ NCNC ] )
{
#if NC == 3
  GLU_real *qq = ( GLU_real* )Q ;
  const double REQ0 = *( qq + 0 ) ;
  const double REQ1 = *( qq + 2 ) ;
  const double IMQ1 = *( qq + 3 ) ;
  const double REQ2 = *( qq + 4 ) ;
  const double IMQ2 = *( qq + 5 ) ;
  const double REQ4 = *( qq + 8 ) ;
  const double REQ5 = *( qq + 10 ) ;
  const double IMQ5 = *( qq + 11 ) ;
  const double REQ8 = *( qq + 16 ) ;

  // speed this up too (use determinant relation)
  const double c1 = ( REQ0 * REQ0 + REQ0 * REQ4 + REQ4 * REQ4		\
		      + REQ1 * REQ1 + IMQ1 * IMQ1			\
		      + REQ2 * REQ2 + IMQ2 * IMQ2			\
		      + REQ5 * REQ5 + IMQ5 * IMQ5 ) * OneO3 ; 
 
  //Iff c0_max < ( smallest representable double) the matrix Q is zero and its
  //exponential is the identity matrix ..
  if( unlikely( c1 < DBL_MIN ) ) {
    *( U + 0 ) = 1. ; 
    *( U + 1 ) = 0. ; 
    *( U + 2 ) = 0. ; 
    *( U + 3 ) = 0. ; 
    *( U + 4 ) = 1. ; 
    *( U + 5 ) = 0. ; 
    *( U + 6 ) = 0. ; 
    *( U + 7 ) = 0. ; 
    *( U + 8 ) = 1. ; 
    return ;
  }

  // will write this out as it can be done cheaper
  // 1/3 * tr AAA is just det( A ) 
  // Below is a quickened determinant
  double c0 =  REQ0  * ( REQ4 * REQ8				\
			 - REQ5  * REQ5  - IMQ5  * IMQ5  ) ;
  // from the middle
  c0 -= REQ1  * ( REQ1 * REQ8 		\
		  - REQ5  * REQ2  - IMQ5  * IMQ2  ) ;
  c0 += IMQ1  * ( - IMQ1 * REQ8		\
		  + REQ5  * IMQ2  - IMQ5  * REQ2 ) ;
  // final column
  c0 += REQ2  * ( - REQ4  * REQ2			\
		  + REQ1 * REQ5  - IMQ1 * IMQ5  ) ;
  c0 -= IMQ2  * ( REQ4  * IMQ2				\
		  - REQ1 * IMQ5  - IMQ1 * REQ5 ) ;

  // so if c0 is negative we flip the sign ...
  const double flag = c0 < 0 ? -1.0 : 1.0 ;
  c0 *= flag ;
 
  // compute the constants c0_max and the root of c1 ...
  const double rc1 = sqrt( c1 ) ;
  const double c0_max = 2. * rc1 * c1 ; 
  const double theta = acos( c0 / c0_max ) * OneO3 ; 
  const double ctheta = cos( theta ) ;
  register const double u = rc1 * ctheta ; 
  register const double w = r3 * rc1 * sin( theta ) ;
  const double uu = u * u  ,  ww = w * w  ,  cw = cos( w ) ; 
  const double denom = 1.0 / ( 9. * uu - ww ) ;
  const double cu = cos( u ) ;
  const double su = sin( u ) ;
  // and I thought double angle formulas were useless!
  //double complex one , two ;
  const double complex one = cu - I * su ;
  double complex two = conj( one ) ; //cu + I * su ;
  two *= two ;
 
  // taylor expand if getting toward the numerically unstable end
  const double E0 = fabs( w ) < SINTOL ? ( 1 - ww / 6. * ( 1 - ww / 20. * ( 1 - ww / 42. ) ) ) : sin( w ) / w ; 

  double complex f0 = ( uu - ww ) * two + one * ( 8. * uu * cw + 2. * I * u * ( 3. * uu + ww ) * E0 ) ; 
  double complex f1 = 2. * u * two - one * ( 2. * u * cw - I * ( 3. * uu - ww ) * E0 ) ; 
  double complex f2 = two - one * ( cw + 3. * I * u * E0 ) ; 

  f0 = denom * ( creal( f0 ) + I * cimag( f0 ) * flag ) ;
  f1 = denom * ( flag * creal( f1 ) + I * cimag( f1 ) ) ;
  f2 = denom * ( creal( f2 ) + I * cimag( f2 ) * flag ) ;

  // QQ[0].
  const double temp0 = REQ0 * REQ0 + REQ1 * REQ1 +	\
    IMQ1 * IMQ1 + REQ2 * REQ2 + IMQ2 * IMQ2 ;
  // QQ[1]
  const double complex temp1 = -REQ1 * ( REQ8 ) + REQ2 * REQ5 + IMQ2 * IMQ5 
    + I * ( REQ5 * IMQ2 - REQ2 * IMQ5 - IMQ1 * REQ8 ) ;
  // QQ[2]
  const double complex temp2 = REQ1 * REQ5 - IMQ1 * IMQ5 - REQ2 * REQ4 +
    I * ( IMQ1 * REQ5 + IMQ5 * REQ1 - IMQ2 * REQ4 ) ;
  // QQ[4]
  const double temp3 = REQ4 * REQ4 + REQ1 * REQ1	\
    + IMQ1 * IMQ1 + REQ5 * REQ5 + IMQ5 * IMQ5 ;
  // QQ[5]
  const double complex temp4 = REQ1 * REQ2 + IMQ2 * IMQ1 - REQ0 * REQ5 +
    I * ( REQ1 * IMQ2 - REQ2 * IMQ1 - REQ0 * IMQ5 ) ;
  // QQ[8]
  const double temp5 = REQ8 * REQ8 + REQ2 * REQ2 +	\
    IMQ2 * IMQ2 + REQ5 * REQ5 + IMQ5 * IMQ5 ;
  // U = f0I + f1 Q + f2 QQ 
  *( U + 0 ) = f0 + f1 * REQ0 + f2 * temp0  ; 
  *( U + 1 ) = f1 * Q[1] + f2 * temp1 ; 
  *( U + 2 ) = f1 * Q[2] + f2 * temp2 ; 
  //
  *( U + 3 ) = f1 * Q[3] + f2 * conj( temp1 ) ; 
  *( U + 4 ) = f0 + f1 * REQ4 + f2 * temp3 ; 
  *( U + 5 ) = f1 * Q[5] + f2 * temp4 ; 
  //
  *( U + 6 ) = f1 * Q[6] + f2 * conj( temp2 ) ; 
  *( U + 7 ) = f1 * Q[7] + f2 * conj( temp4 ) ; 
  *( U + 8 ) = f0 + f1 * REQ8 + f2 * temp5 ; 
#elif NC == 2
  double f0 , f1 ; // f1 is purely imaginary
  // eigenvalues are pretty simple +/- sqrt( |a|^2 + |b|^2 ) Only need one
  const double z = sqrt( creal( Q[0] ) * creal( Q[0] ) +	\
			 creal( Q[1] ) * creal( Q[1] ) +	\
			 cimag( Q[1] ) * cimag( Q[1] ) ) ;

  // have eigenvalues, now for the "fun" bit.
  f0 = cos( z ) ;
  // taylor expand 
  f1 = fabs ( z ) < SINTOLSU2 ? ( 1 - z / 6. * ( 1 - z / 20. * ( 1 - z / 42. ) ) ) : sin( z ) / z ;

  const double complex f1Q0 = I * f1 * creal( Q[0] ) ;
  const double complex f1Q1 = I * f1 * Q[1] ;
  *( U + 0 ) = (GLU_complex)( f0 + f1Q0 ) ;
  *( U + 1 ) = (GLU_complex)( f1Q1 ) ;
  *( U + 2 ) = (GLU_complex)( -conj( f1Q1 ) ) ;
  *( U + 3 ) = (GLU_complex)( f0 - f1Q0 ) ; 
#else
  // hmmm could be a toughy
  #if ( defined HAVE_LAPACKE_H || defined HAVE_GSL )
  double complex f[ NC ] ;
  double z[ NC ] ;
  Eigenvalues_hermitian( z , Q ) ;
  calculate_effs_VDM_herm( f , z ) ;
  // matrix expansion reversing horner's rule
  int i , j ;
  diag( U , f[ NC - 1 ] ) ; 
  for( i = NC-1 ; i > 0 ; i-- ) {
    multab_atomic_left( U , Q ) ; // left multiply U with Q
    for( j = 0 ; j < NC ; j++ ) { U[ j*(NC+1) ] += f[ i-1 ] ; }
  }
  #else
  // exponentiate routine from stephan durr's paper
  // Performs the nesting
  // U = ( exp{ A / DIV^n ) ) ^ ( DIV * n )
  GLU_complex EOLD[ NCNC ] GLUalign , SN[ NCNC ] GLUalign ;
  GLU_complex RN_MIN[ NCNC ] GLUalign , RN[ NCNC ] GLUalign ;

  // set to zero
  zero_mat( EOLD ) ;

  // set up the divisor and the minimum 
  double sum = 0.0 ;
  size_t j , n ;
  const int nmin = 3 ;

  // use precomputed factorials  
  for( n = nmin ; n < 10 ; n++ ) {

    // compute the multiplicative factor ...
    const int iter = 2 << ( n - 1 ) ;
    const GLU_complex fact = I / (GLU_real)iter ;

    // and the rational approximations
#ifdef USE_PADE
    for( j = 0 ; j < NCNC ; j++ ) { SN[ j ] = ( Q[j] * fact ) ; }
    horners_pade( RN , SN ) ;

    for( j = 0 ; j < NCNC ; j++ ) { SN[ j ] *= -1.0 ; }
    horners_pade( RN_MIN , SN ) ; 
#else
    for( j = 0 ; j < NCNC ; j++ ) { SN[ j ] = ( Q[j] * fact ) / 2.0 ; }
    horners_exp( RN , SN , 14 ) ;

    for( j = 0 ; j < NCNC ; j++ ) { SN[ j ] *= -1.0 ; }
    horners_exp( RN_MIN , SN , 14 ) ; 
#endif

    inverse( SN , RN_MIN ) ;         // uses our numerical inverse
    multab_atomic_right( RN , SN ) ; // gets the correct rational approx

    // and remove the nested scalings ...
    matrix_power( U , RN , iter ) ; // uses a fast-power like routine 
    
    // for the convergence criteria, I use the absolute difference between
    // evaluations
    sum = 0.0 ;
    for( j = 0 ; j < NCNC ; j++ ) {
      sum += (double)cabs( EOLD[j] - U[j] ) ;
      EOLD[ j ] = U[ j ] ;
    }
    sum /= NCNC ;

    // convergence ....
    if( sum < PREC_TOL ) { break ; } 
    // warning for non-convergence ..
    if( n >= ( MAX_FACTORIAL - 1 ) ) { 
      printf( "[EXPONENTIAL] not converging .. %zu %e \n" , n , sum ) ; 
      break ;
    }
  }
  // gramschmidt orthogonalisation just to make sure
  // has been seen to help preserve gauge invariance of log smearing
  gram_reunit( U ) ;
  #endif
#endif
  return ;
}
void operator_matrix() {
    matrix result;
    char in[USHRT_MAX];
    int m;
    int n;
    while (1) {
        printf("Entre com o número de linhas da 1ª matriz: ");
        scanf("%s", in);
        m = atoi(in);
        printf("\n");
        if (m == 0)
            printf("Valor inválido!\n\n");
        else
            break;
    }
    while (1) {
        printf("Entre com o número de colunas da 1ª matriz: ");
        scanf("%s", in);
        n = atoi(in);
        printf("\n");
        if (n == 0)
            printf("Valor inválido!\n\n");
        else
            break;
    }
    result = matrix_constructor(m, n);
    printf("Entre com os elementos da 1ª matriz, separando-os por espaços e/ou quebras de linha:\n");
    for (int i = 0; i < m; i++)
        for (int j = 0; j < n; j++) {
            scanf("%s", in);
            result.table[i][j] = atof(in);
        }
    printf("\n");
    int keep_going = 1;
    while (keep_going) {
        matrix next;
        switch (menu_matrix()) {
            case 1:
                // Add
                while (1) {
                    while (1) {
                        printf("Entre com o número de linhas da proxima matriz: ");
                        scanf("%s", in);
                        m = atoi(in);
                        printf("\n");
                        if (m == 0)
                            printf("Valor inválido!\n\n");
                        else
                            break;
                    }
                    while (1) {
                        printf("Entre com o número de colunas da proxima matriz: ");
                        scanf("%s", in);
                        n = atoi(in);
                        printf("\n");
                        if (n == 0)
                            printf("Valor inválido!\n\n");
                        else
                            break;
                    }
                    next = matrix_constructor(m, n);
                    if (!matrix_can_add(result, next))
                        printf("Não é possivel fazer a operação desejada com as matrizes de ordens previamente informadas!\n\n");
                    else
                        break;
                }
                printf("Entre com os elementos da proxima matriz, separando-os por espaços e/ou quebras de linha:\n");
                for (int i = 0; i < m; i++)
                    for (int j = 0; j < n; j++) {
                        scanf("%s", in);
                        next.table[i][j] = atof(in);
                    }
                printf("\n");
                matrix_add(&result, next);
                break;
            case 2:
                // Subtract
                while (1) {
                    while (1) {
                        printf("Entre com o número de linhas da proxima matriz: ");
                        scanf("%s", in);
                        m = atoi(in);
                        printf("\n");
                        if (m == 0)
                            printf("Valor inválido!\n\n");
                        else
                            break;
                    }
                    while (1) {
                        printf("Entre com o número de colunas da proxima matriz: ");
                        scanf("%s", in);
                        n = atoi(in);
                        printf("\n");
                        if (n == 0)
                            printf("Valor inválido!\n\n");
                        else
                            break;
                    }
                    next = matrix_constructor(m, n);
                    if (!matrix_can_subtract(result, next))
                        printf("Não é possivel fazer a operação desejada com as matrizes de ordens previamente informadas!\n\n");
                    else
                        break;
                }
                printf("Entre com os elementos da proxima matriz, separando-os por espaços e/ou quebras de linha:\n");
                for (int i = 0; i < m; i++)
                    for (int j = 0; j < n; j++) {
                        scanf("%s", in);
                        next.table[i][j] = atof(in);
                    }
                printf("\n");
                matrix_subtract(&result, next);
                break;
            case 3:
                // Multiply
                while (1) {
                    while (1) {
                        printf("Entre com o número de linhas da proxima matriz: ");
                        scanf("%s", in);
                        m = atoi(in);
                        printf("\n");
                        if (m == 0)
                            printf("Valor inválido!\n\n");
                        else
                            break;
                    }
                    while (1) {
                        printf("Entre com o número de colunas da proxima matriz: ");
                        scanf("%s", in);
                        n = atoi(in);
                        printf("\n");
                        if (n == 0)
                            printf("Valor inválido!\n\n");
                        else
                            break;
                    }
                    next = matrix_constructor(m, n);
                    if (!matrix_can_multiply(result, next))
                        printf("Não é possivel fazer a operação desejada com as matrizes de ordens previamente informadas!\n\n");
                    else
                        break;
                }
                printf("Entre com os elementos da proxima matriz, separando-os por espaços e/ou quebras de linha:\n");
                for (int i = 0; i < m; i++)
                    for (int j = 0; j < n; j++) {
                        scanf("%s", in);
                        next.table[i][j] = atof(in);
                    }
                printf("\n");
                matrix_multiply(&result, next);
                break;
            case 4:
                // Power
                if (matrix_can_power(result)) {
                    while (1) {
                        printf("Entre com o próximo valor: ");
                        scanf("%s", in);
                        printf("\n");
                        if (atoll(in) >= 0) {
                            matrix_power(&result, (unsigned long long int) atoll(in));
                            break;
                        } else
                            printf("Valor inválido!\n\n");
                    }
                } else
                    printf("Não é possivel realizar a operação desejada com a matrix atual!\n\n");
                break;
            default:
                keep_going = 0;
                break;
        }
        matrix_destructor(&next);
        printf("Resultado:\n\n");
        matrix_print(result);
        printf("\n");
        if (!keep_going)
            matrix_destructor(&result);
    }
}