#include "validate.h"
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <mpi.h>
static int predicate(double real, double imag, double beta, void *arg)
{
    if (0.0 < real && beta != 0.0)
        return 1;
    return 0;
}
int main(int argc, char **argv)
{
    const int n = 3000; 
    const int root = 0; 
    
    int thread_support;
    MPI_Init_thread(
        &argc, (char ***)&argv, MPI_THREAD_MULTIPLE, &thread_support);
    int world_rank;
    MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
    
    int ldA = 0, ldB = 0, ldQ = 0, ldZ = 0, ldC = 0, ldD = 0;
    double *A = NULL, *B = NULL, *Q = NULL, *Z = NULL, *C = NULL, *D = NULL;
    if (world_rank == root) {
        srand((unsigned) time(NULL));
        
        ldA = ((n/8)+1)*8, ldC = ((n/8)+1)*8;
        A = malloc(n*ldA*sizeof(double));
        C = malloc(n*ldC*sizeof(double));
        for (int j = 0; j < n; j++)
            for (int i = 0; i < n; i++)
                A[j*ldA+i] = C[j*ldC+i] = 2.0*rand()/RAND_MAX - 1.0;
        
        ldB = ((n/8)+1)*8, ldD = ((n/8)+1)*8;
        B = malloc(n*ldB*sizeof(double));
        D = malloc(n*ldD*sizeof(double));
        for (int j = 0; j < n; j++)
            for (int i = 0; i < n; i++)
                B[j*ldB+i] = D[j*ldD+i] = 2.0*rand()/RAND_MAX - 1.0;
        
        ldQ = ((n/8)+1)*8;
        Q = malloc(n*ldA*sizeof(double));
        for (int j = 0; j < n; j++)
            for (int i = 0; i < n; i++)
                Q[j*ldQ+i] = i == j ? 1.0 : 0.0;
        
        ldZ = ((n/8)+1)*8;
        Z = malloc(n*ldZ*sizeof(double));
        for (int j = 0; j < n; j++)
            for (int i = 0; i < n; i++)
                Z[j*ldZ+i] = i == j ? 1.0 : 0.0;
    }
    
    double *real = malloc(n*sizeof(double));
    double *imag = malloc(n*sizeof(double));
    double *beta = malloc(n*sizeof(double));
    int *select = malloc(n*sizeof(int));
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    printf("Hessenberg-triangular reduction...\n");
    
    
    printf("Schur reduction...\n");
    
    int num_selected;
    printf("Selected %d eigenvalues out of %d.\n", num_selected, n);
    
    
    printf("Reordering...\n");
    
    
    
    
    
    
    
    
    
    MPI_Finalize();
    if (world_rank == root) {
        
        check_residual(n, ldQ, ldA, ldZ, ldC, Q, A, Z, C);
        
        check_residual(n, ldQ, ldB, ldZ, ldD, Q, B, Z, D);
        
        check_orthogonality(n, ldQ, Q);
        
        check_orthogonality(n, ldZ, Z);
    }
    
    free(A);
    free(C);
    free(B);
    free(D);
    free(Q);
    free(Z);
    free(real);
    free(imag);
    free(beta);
    free(select);
    return 0;
}