int ProcRank;             
  int ProcNum;              
int main(int argc, char *argv[]) {
  double *pProcData;      
  int     ProcDataSize;  
  MPI_Init(&argc, &argv);
  MPI_Comm_rank(MPI_COMM_WORLD, &ProcRank);
  MPI_Comm_size(MPI_COMM_WORLD, &ProcNum);
  DataInitialization ( &pProcData, &ProcDataSize);  
  ParallelHyperQuickSort ( pProcData, ProcDataSize );
  ProcessTermination ( pProcData, ProcDataSize );
  MPI_Finalize();
}
void DataInitialization( double **pProcData, double *ProcDataSize){
  int DataSize; 
  double *pData;
  
  if ( ProcRank == 0 ) {
    DataSize = GetDataSize();
    *pData = new double[DataSize];
    DataGeneration ( pData, DataSize);
  }
  
  DataDistribution ( *pProcData, DataSize, *ProcDataSize);
}
void DataDistribution (double *pProcData, int DataSize, int *ProcDataSize) {
  if ( rank == 0 ) { 
    *ProcDataSize = DataSize / ProcNum;
  }
  MPI_Bcast ( ProcDataSize, 1, MPI_INT, 0, MPI_COMM_WORLD );
  *ProcData = new double[*ProcDataSize];
  MPI_Scatter ( &pData[(ProcRank)*(*ProcDataSize)], *ProcDataSize, 
    MPI_DOUBLE, *ProcData, *ProcDataSize, MPI_DOUBLE, 0, MPI_COMM_WORLD );
}
void ParallelHyperQuickSort ( double *pProcData, int ProcDataSize) { 
  MPI_Status status;
  int CommProcRank;   
  double *pData,      
         *pSendData,  
         *pRecvData,  
         *pMergeData; 
  int     DataSize, SendDataSize, RecvDataSize, MergeDataSize;
  int HypercubeDim = (int)ceil(log(ProcNum)/log(2)); 
  int Mask = ProcNum; 
  double Pivot; 
  
  LocalDataSort ( pProcData, ProcDataSize ); 
  
  for ( int i = HypercubeDim; i > 0; i-- ) {
    
    PivotDistribution (pProcData,ProcDataSize,HypercubeDim,Mask,i,&Pivot);
    Mask = Mask >>  1;
    
    int pos = GetProcDataDivisionPos (pProcData, ProcDataSize, Pivot);
    
    if ( ( (rank&Mask) >> (i-1) ) == 0 ) { 
      pSendData = & pProcData[pos+1];
      SendDataSize = ProcDataSize - pos – 1;
      if ( SendDataSize < 0 ) SendDataSize = 0;
      CommProcRank = ProcRank + Mask
      pData = & pProcData[0];
      DataSize = pos + 1; 
    }
    else { 
      pSendData = & pProcData[0];
      SendDataSize = pos + 1;
      if ( SendDataSize > ProcDataSize ) SendDataSize = pos;
      CommProcRank = ProcRank – Mask
      pData = & pProcData[pos+1];
      DataSize = ProcDataSize - pos - 1; 
      if ( DataSize < 0 ) DataSize = 0;
    }
    
    MPI_Sendrecv(&SendDataSize, 1, MPI_INT, CommProcRank, 0, 
      &RecvDataSize, 1, MPI_INT, CommProcRank, 0, MPI_COMM_WORLD, &status);
    
    pRecvData = new double[RecvDataSize];
    MPI_Sendrecv(pSendData, SendDataSize, MPI_DOUBLE,
      CommProcRank, 0, pRecvData, RecvDataSize, MPI_DOUBLE,
      CommProcRank, 0, MPI_COMM_WORLD, &status);
    
    
    MergeDataSize = DataSize + RecvDataSize;
    pMergeData = new double[MergeDataSize];
    DataMerge(pMergeData, pMergeData, pData, DataSize, 
              pRecvData, RecvDataSize); 
    delete [] pProcData;
    delete [] pRecvData;
    pProcData = pMergeData;
    ProcDataSize = MergeDataSize; 
  }
}