Example #1
0
int main(void) {
  FILE *fin = fopen( "matrix2.in", "r" );

  if( fin == NULL ) {
    printf( "Error: could not open matrix2.in\n" );
    exit( EXIT_FAILURE );
  }

  Matrix *a = read_matrix( fin );
  Matrix *b = read_matrix( fin );
  fclose( fin );

  Matrix *c = product_matrix( a, b );

  FILE *output = fopen( "matrix2.out", "w" );

  if( output == NULL ) {
    printf( "Error: could not open matrix2.out\n" );
    exit( EXIT_FAILURE );
  }

  print_matrix( output, c );
  fclose( output );

	destroy_matrix( a );
	destroy_matrix( b );
	destroy_matrix( c );

  return 0;
}
Example #2
0
int main()
{
   int N, size;
   double *array1, *array2, *array3;
   printf("Please input the size of the matrix:");
   scanf("%d", &N);
   size=N*N;
   
   array1=(double *) malloc(size*sizeof(double));
   array2=(double *) malloc(size*sizeof(double));
   array3=(double *) malloc(N*sizeof(double));

   input_matrix(size, N, array1, array2);
   output_matrix(size, N, array1, array2);
   product_matrix(size, N, array1, array2, array3);
}
/*!\rst
  Check that matrix-transpose works.

  \return
    number of entries where ``A`` and ``A^T`` do not match
\endrst*/
OL_WARN_UNUSED_RESULT int TestMatrixTranspose() noexcept {
  const int size_m = 3;
  const int size_n = 5;
  int total_errors = 0;

  std::vector<double> matrix(size_m*size_n);
  std::vector<double> matrix_T(size_m*size_n);
  std::vector<double> product_matrix(size_n*size_n);
  UniformRandomGenerator uniform_generator(34187);

  BuildRandomVector(size_m*size_n, -1.0, 1.0, &uniform_generator, matrix.data());
  MatrixTranspose(matrix.data(), size_m, size_n, matrix_T.data());

  for (int j = 0; j < size_n; ++j) {
    for (int i = 0; i < size_m; ++i) {
      if (CheckDoubleWithin(matrix[j*size_m + i], matrix_T[i*size_n + j], 0.0) == false) {
        ++total_errors;
        break;
      }
    }
  }

  return total_errors;
}
/*!\rst
  Check that ``A * B`` works where ``A, B`` are matrices.
  Outline:

  1. Simple hand-checked test case.
  2. Generate a random orthogonal matrix and verify that ``Q * Q^T = I``.
  3. Generate a random SPD matrix and guarantee good conditioning: verify ``A * A^-1 = I``.

  \return
    number of cases where matrix-matrix multiply failed
\endrst*/
OL_WARN_UNUSED_RESULT int TestGeneralMatrixMatrixMultiply() noexcept {
  int total_errors = 0;

  // simple, hand-checked problems that are be minimally affected by floating point errors
  {  // hide scope
    static const int kSize_m = 3;  // rows of A, C
    static const int kSize_k = 5;  // cols of A, rows of B
    static const int kSize_n = 2;  // cols of B, C

    double matrix_A[kSize_m*kSize_k] =
        {-7.4, 0.1, 9.1,  // first COLUMN of A (col-major storage)
         1.5, -8.8, -0.3,
         -2.9, 6.4, -9.7,
         -9.1, -6.6, 3.1,
         4.6, 3.0, -1.0
        };

    double matrix_B[kSize_k*kSize_n] =
        {-1.3, -8.1, -7.2, -0.4, -5.5,
         7.4, 5.3, -3.1, -2.3, 1.9
        };

    double matrix_AB_exact[kSize_m*kSize_n] =
        {-3.309999999999995, 11.210000000000001, 64.700000000000003,
         -8.150000000000006, -44.860000000000014, 86.789999999999992
        };
    double matrix_AB_computed[kSize_m*kSize_n];

    GeneralMatrixMatrixMultiply(matrix_A, 'N', matrix_B, 1.0, 0.0, kSize_m, kSize_k, kSize_n, matrix_AB_computed);

    for (int i = 0; i < kSize_m*kSize_n; ++i) {
      if (!CheckDoubleWithinRelative(matrix_AB_computed[i], matrix_AB_exact[i], 3.0 * std::numeric_limits<double>::epsilon())) {
        ++total_errors;
      }
    }
  }

  const int num_tests = 3;
  const int sizes[num_tests] = {3, 11, 20};

  UniformRandomGenerator uniform_generator(34187);
  // in each iteration, we perform two tests on matrix-matrix multiply.
  //   1) form a matrix Q such that Q * Q^T = I (orthogonal matrix); nontrivial in that Q != I
  //      Compute Q * Q^T and check the result.
  //   2) build a random, SPD matrix, A. (ill-conditioned).
  //      Improve A's conditioning: A = A + size*I (condition number near 1 now)
  //      Form A^-1 (this is OK because A is well-conditioned)
  //      Check A * A^-1 is near I.
  for (int i = 0; i < num_tests; ++i) {
    std::vector<double> orthog_symm_matrix(sizes[i]*sizes[i]);
    std::vector<double> orthog_symm_matrix_T(sizes[i]*sizes[i]);
    std::vector<double> product_matrix(sizes[i]*sizes[i]);
    std::vector<double> spd_matrix(sizes[i]*sizes[i]);
    std::vector<double> cholesky_factor(sizes[i]*sizes[i]);
    std::vector<double> inverse_spd_matrix(sizes[i]*sizes[i]);
    std::vector<double> identity_matrix(sizes[i]*sizes[i]);

    BuildIdentityMatrix(sizes[i], identity_matrix.data());

    BuildOrthogonalSymmetricMatrix(sizes[i], orthog_symm_matrix.data());
    // not technically necessary since this orthog matrix is also symmetric
    MatrixTranspose(orthog_symm_matrix.data(), sizes[i], sizes[i], orthog_symm_matrix_T.data());

    // Q * Q^T = I if Q is orthogonal
    GeneralMatrixMatrixMultiply(orthog_symm_matrix.data(), 'N', orthog_symm_matrix_T.data(), 1.0, 0.0, sizes[i], sizes[i], sizes[i], product_matrix.data());
    VectorAXPY(sizes[i]*sizes[i], -1.0, identity_matrix.data(), product_matrix.data());
    for (int j = 0; j < sizes[i]*sizes[i]; ++j) {
      // do not use relative comparison b/c we're testing against 0
      if (!CheckDoubleWithin(product_matrix[j], 0.0, 20*std::numeric_limits<double>::epsilon())) {
        ++total_errors;
      }
    }

    // and again testing the T version
    GeneralMatrixMatrixMultiply(orthog_symm_matrix.data(), 'T', orthog_symm_matrix.data(), 1.0, 0.0, sizes[i], sizes[i], sizes[i], product_matrix.data());
    VectorAXPY(sizes[i]*sizes[i], -1.0, identity_matrix.data(), product_matrix.data());
    for (int j = 0; j < sizes[i]*sizes[i]; ++j) {
      // do not use relative comparison b/c we're testing against 0
      if (!CheckDoubleWithin(product_matrix[j], 0.0, 20*std::numeric_limits<double>::epsilon())) {
        ++total_errors;
      }
    }

    BuildRandomSPDMatrix(sizes[i], &uniform_generator, spd_matrix.data());
    // ensure spd matrix is well-conditioned (or we can't form A^-1 stably)
    ModifyMatrixDiagonal(sizes[i], static_cast<double>(sizes[i]), spd_matrix.data());

    std::copy(spd_matrix.begin(), spd_matrix.end(), cholesky_factor.begin());
    if (ComputeCholeskyFactorL(sizes[i], cholesky_factor.data()) != 0) {
      ++total_errors;
    }
    SPDMatrixInverse(cholesky_factor.data(), sizes[i], inverse_spd_matrix.data());
    GeneralMatrixMatrixMultiply(spd_matrix.data(), 'N', inverse_spd_matrix.data(), 1.0, 0.0, sizes[i], sizes[i], sizes[i], product_matrix.data());
    VectorAXPY(sizes[i]*sizes[i], -1.0, identity_matrix.data(), product_matrix.data());
    for (int j = 0; j < sizes[i]*sizes[i]; ++j) {
      // do not use relative comparison b/c we're testing against 0
      if (!CheckDoubleWithin(product_matrix[j], 0.0, 10*std::numeric_limits<double>::epsilon())) {
        ++total_errors;
      }
    }
  }

  return total_errors;
}