<commit_before>/*
   Copyright (c) 2009-2015, <NAME>
                      2013, <NAME>
   All rights reserved.

   This file is part of Elemental and is under the BSD 2-Clause License, 
   which can be found in the LICENSE file in the root directory, or at 
   http://opensource.org/licenses/BSD-2-Clause
*/
#include "El.hpp"
#ifdef EL_HAVE_QT5
 #include <QApplication>
#endif

namespace {
using namespace El;

Int numElemInits = 0;
bool elemInitializedMpi = false;

std::stack<Int> blocksizeStack;
Grid* defaultGrid = 0;
Args* args = 0;

// Default blocksizes for BlockMatrix
Int blockHeight=32, blockWidth=32;

// A common Mersenne twister configuration
std::mt19937 generator;

// Debugging
DEBUG_ONLY(std::stack<string> callStack)

// LogFile in Debugging
DEBUG_ONLY(std::ofstream logFile)

// Output/logging
Int indentLevel=0;
Int spacesPerIndent=2;

// Tuning parameters for basic routines
Int localSymvIntBlocksize = 64;
Int localSymvFloatBlocksize = 64;
Int localSymvDoubleBlocksize = 64;
#ifdef EL_HAVE_QUAD
Int localSymvQuadBlocksize = 64;
#endif
Int localSymvComplexFloatBlocksize = 64;
Int localSymvComplexDoubleBlocksize = 64;
#ifdef EL_HAVE_QUAD
Int localSymvComplexQuadBlocksize = 64;
#endif

Int localTrr2kFloatBlocksize = 64;
Int localTrr2kDoubleBlocksize = 64;
Int localTrr2kComplexFloatBlocksize = 64;
Int localTrr2kComplexDoubleBlocksize = 64;

Int localTrrkFloatBlocksize = 64;
Int localTrrkDoubleBlocksize = 64;
Int localTrrkComplexFloatBlocksize = 64;
Int localTrrkComplexDoubleBlocksize = 64;

// Qt5
ColorMap colorMap=RED_BLACK_GREEN;
Int numDiscreteColors = 15;
#ifdef EL_HAVE_QT5
// The command-line arguments should be passed into Qt5 in a manner which
// ensures that they do not fall out of scope until the last Qt5 call.
// The best way to do so is to make a copy and pass in the copy.
int argcSave;
char** argvSave;

bool guiDisabled;
bool elemInitializedQt = false;
bool elemOpenedWindow = false;
QCoreApplication* coreApp;
bool haveMinRealWindowVal=false, haveMaxRealWindowVal=false,
     haveMinImagWindowVal=false, haveMaxImagWindowVal=false;
double minRealWindowVal, maxRealWindowVal,
       minImagWindowVal, maxImagWindowVal;
#endif
}

namespace El {

void PrintVersion( ostream& os )
{
    os << "Elemental version information:\n"
       << "  Git revision: " << EL_GIT_SHA1 << "\n"
       << "  Version:      " << EL_VERSION_MAJOR << "."
                             << EL_VERSION_MINOR << "\n"
       << "  Build type:   " << EL_CMAKE_BUILD_TYPE << "\n"
       << endl;
}

void PrintConfig( ostream& os )
{
    os << 
      "Elemental configuration:\n" <<
      "  Math libraries:               " << EL_MATH_LIBS << "\n"
#ifdef EL_HAVE_FLA_BSVD
      "  Have FLAME bidiagonal SVD:    YES\n"
#else
      "  Have FLAME bidiagonal SVD:    NO\n"
#endif
#ifdef EL_HYBRID
      "  Hybrid mode:                  YES\n"
#else
      "  Hybrid mode:                  NO\n"
#endif
#ifdef EL_HAVE_QT5
      "  Have Qt5:                     YES\n"
#else
      "  Have Qt5:                     NO\n"
#endif
#ifdef EL_AVOID_COMPLEX_MPI
      "  Avoiding complex MPI:         YES\n"
#else
      "  Avoiding complex MPI:         NO\n"
#endif
#ifdef EL_HAVE_MPI_REDUCE_SCATTER_BLOCK
      "  Have MPI_Reducescatter_block: YES\n"
#else
      "  Have MPI_Reducescatter_block: NO\n"
#endif
#ifdef EL_HAVE_MPI_IN_PLACE
      "  Have MPI_IN_PLACE:            YES\n"
#else
      "  Have MPI_IN_PLACE:            NO\n"
#endif
#ifdef EL_REDUCE_SCATTER_BLOCK_VIA_ALLREDUCE
      "  AllReduce ReduceScatterBlock: YES\n"
#else
      "  AllReduce ReduceScatterBlock: NO\n"
#endif
#ifdef EL_USE_BYTE_ALLGATHERS
      "  Use byte AllGathers:          YES\n"
#else
      "  Use byte AllGathers:          NO\n"
#endif
       << endl;
}

void PrintCCompilerInfo( ostream& os )
{
    os << "Elemental's C compiler info:\n"
       << "  EL_CMAKE_C_COMPILER:    " << EL_CMAKE_C_COMPILER << "\n"
       << "  EL_MPI_C_COMPILER:      " << EL_MPI_C_COMPILER << "\n"
       << "  EL_MPI_C_INCLUDE_PATH:  " << EL_MPI_C_INCLUDE_PATH << "\n"
       << "  EL_MPI_C_COMPILE_FLAGS: " << EL_MPI_C_COMPILE_FLAGS << "\n"
       << "  EL_MPI_LINK_FLAGS:      " << EL_MPI_LINK_FLAGS << "\n"
       << "  EL_MPI_C_LIBRARIES:     " << EL_MPI_C_LIBRARIES << "\n"
       << endl;
}

void PrintCxxCompilerInfo( ostream& os )
{
    os << "Elemental's C++ compiler info:\n"
       << "  EL_CMAKE_CXX_COMPILER:    " << EL_CMAKE_CXX_COMPILER << "\n"
       << "  EL_CXX_FLAGS:             " << EL_CXX_FLAGS << "\n"
       << "  EL_MPI_CXX_COMPILER:      " << EL_MPI_CXX_COMPILER << "\n"
       << "  EL_MPI_CXX_INCLUDE_PATH:  " << EL_MPI_CXX_INCLUDE_PATH << "\n"
       << "  EL_MPI_CXX_COMPILE_FLAGS: " << EL_MPI_CXX_COMPILE_FLAGS << "\n"
       << "  EL_MPI_LINK_FLAGS:        " << EL_MPI_LINK_FLAGS << "\n"
       << "  EL_MPI_CXX_LIBRARIES:     " << EL_MPI_CXX_LIBRARIES << "\n"
       << endl;
}

bool Using64BitInt()
{
#ifdef EL_USE_64BIT_INTS
    return true;
#else
    return false;
#endif
}

bool Using64BitBlasInt()
{
#ifdef EL_USE_64BIT_BLAS_INTS
    return true;
#else
    return false;
#endif
}

void SetColorMap( ColorMap map )
{ ::colorMap = map; }

ColorMap GetColorMap()
{ return ::colorMap; }

void SetNumDiscreteColors( Int numChunks )
{ ::numDiscreteColors = numChunks; }

Int NumDiscreteColors()
{ return ::numDiscreteColors; }

#ifdef EL_HAVE_QT5
bool GuiDisabled()
{ return ::guiDisabled; }

void OpenedWindow()
{ ::elemOpenedWindow = true; }

double MinRealWindowVal()
{
    if( ::haveMinRealWindowVal )
        return ::minRealWindowVal;
    else
        return 0;
}

double MaxRealWindowVal()
{
    if( ::haveMaxRealWindowVal )
        return ::maxRealWindowVal;
    else
        return 0;
}

double MinImagWindowVal()
{
    if( ::haveMinImagWindowVal )
        return ::minImagWindowVal;
    else
        return 0;
}

double MaxImagWindowVal()
{
    if( ::haveMaxImagWindowVal )
        return ::maxImagWindowVal;
    else
        return 0;
}

void UpdateMinRealWindowVal( double minVal )
{
    if( ::haveMinRealWindowVal )
        ::minRealWindowVal = Min( ::minRealWindowVal, minVal );
    else
        ::minRealWindowVal = minVal;
    ::haveMinRealWindowVal = true;
}

void UpdateMaxRealWindowVal( double maxVal )
{
    if( ::haveMaxRealWindowVal )
        ::maxRealWindowVal = Max( ::maxRealWindowVal, maxVal );
    else
        ::maxRealWindowVal = maxVal;
    ::haveMaxRealWindowVal = true;
}

void UpdateMinImagWindowVal( double minVal )
{
    if( ::haveMinImagWindowVal )
        ::minImagWindowVal = Min( ::minImagWindowVal, minVal );
    else
        ::minImagWindowVal = minVal;
    ::haveMinImagWindowVal = true;
}

void UpdateMaxImagWindowVal( double maxVal )
{
    if( ::haveMaxImagWindowVal )
        ::maxImagWindowVal = Max( ::maxImagWindowVal, maxVal );
    else
        ::maxImagWindowVal = maxVal;
    ::haveMaxImagWindowVal = true;
}
#endif // ifdef EL_HAVE_QT5

bool Initialized()
{ return ::numElemInits > 0; }

void Initialize()
{
    int argc=0;
    char** argv=NULL;
    Initialize( argc, argv );
}

void Initialize( int& argc, char**& argv )
{
    if( ::numElemInits > 0 )
    {
        ++::numElemInits;
        return;
    }

    ::args = new Args( argc, argv );

    ::numElemInits = 1;
    if( !mpi::Initialized() )
    {
        if( mpi::Finalized() )
        {
            LogicError
            ("Cannot initialize elemental after finalizing MPI");
        }
#ifdef EL_HYBRID
        const Int provided = 
            mpi::InitializeThread
            ( argc, argv, mpi::THREAD_MULTIPLE );
        const int commRank = mpi::Rank( mpi::COMM_WORLD );
        if( provided != mpi::THREAD_MULTIPLE && commRank == 0 )
        {
            cerr << "WARNING: Could not achieve THREAD_MULTIPLE support."
                 << endl;
        }
#else
        mpi::Initialize( argc, argv );
#endif
        ::elemInitializedMpi = true;
    }
    else
    {
#ifdef EL_HYBRID
        const Int provided = mpi::QueryThread();
        if( provided != mpi::THREAD_MULTIPLE )
        {
            throw std::runtime_error
            ("MPI initialized with inadequate thread support for Elemental");
        }
#endif
    }

#ifdef EL_HAVE_QT5
    ::coreApp = QCoreApplication::instance();
    if( ::coreApp == 0 )
    {
        // Test for whether the GUI should be disabled
        ::guiDisabled = false;
        for( int i=1; i<argc; ++i )
            if( !qstrcmp(argv[i],"-no-gui") )
                ::guiDisabled = true;

        ::argcSave = argc;
        ::argvSave = new char*[argc+1];
        for( int i=0; i<argc; ++i )
        {
            ::argvSave[i] = new char[std::strlen(argv[i])+1];
            std::strcpy( ::argvSave[i], argv[i] );
        }
       ::argvSave[argc] = nullptr;
       
        if( ::guiDisabled )
            ::coreApp = new QCoreApplication( ::argcSave, ::argvSave );
        else
            ::coreApp = new QApplication( ::argcSave, ::argvSave );        
        ::elemInitializedQt = true;
    }
#endif

    // Queue a default algorithmic blocksize
    while( ! ::blocksizeStack.empty() )
        ::blocksizeStack.pop();
    ::blocksizeStack.push( 128 );

    // Build the default grid
    defaultGrid = new Grid( mpi::COMM_WORLD );

    // Create the types and ops
    mpi::CreateCustom();

    const unsigned rank = mpi::Rank( mpi::COMM_WORLD );
    // TODO: Allow for switching on/off reproducibility?
    //const long secs = time(NULL);
    const long secs = 21;
    const long seed = (secs<<16) | (rank & 0xFFFF);
    ::generator.seed( seed );
    srand( seed );

DEBUG_ONLY(
        ostringstream fileOS;
        fileOS << "El-Proc" << std::setfill('0') << std::setw(3)
               << rank << ".log";
        OpenLog( fileOS.str().c_str() );
)
}

void Finalize()
{
    DEBUG_ONLY(CSE cse("Finalize"))
    if( ::numElemInits <= 0 )
    { 
        cerr << "Finalized Elemental more times than initialized" << endl;
        return;
    }
    --::numElemInits;

    if( mpi::Finalized() )
        cerr << "Warning: MPI was finalized before Elemental." << endl;
    if( ::numElemInits == 0 )
    {
        delete ::args;
        ::args = 0;
       
        // Destroy the types and ops
        mpi::DestroyCustom();

        // Delete the default grid
        delete ::defaultGrid;
        ::defaultGrid = 0;

#ifdef EL_HAVE_QT5
        if( ::elemInitializedQt )
        {
            if( ::elemOpenedWindow )
                ::coreApp->exec();
            else
                ::coreApp->exit();
            delete ::coreApp;

            // Delete the copies of argc and argv
            for( int i=0; i< ::argcSave; ++i )
                delete[] ::argvSave[i]; 
            delete[] ::argvSave;
        }
#endif
        if( ::elemInitializedMpi )
            mpi::Finalize();


        while( ! ::blocksizeStack.empty() )
            ::blocksizeStack.pop();
    }

    DEBUG_ONLY( CloseLog() )
}

Args& GetArgs()
{ 
    if( args == 0 )
        throw std::runtime_error("No available instance of Args");
    return *::args; 
}

Int Blocksize()
{ 
    DEBUG_ONLY(
      if( ::blocksizeStack.empty() )
          LogicError("Attempted to extract blocksize from empty stack");
    )
    return ::blocksizeStack.top(); 
}

void SetBlocksize( Int blocksize )
{ 
    DEBUG_ONLY(
      if( ::blocksizeStack.empty() )
          LogicError("Attempted to set blocksize at top of empty stack");
    )
    ::blocksizeStack.top() = blocksize; 
}

void PushBlocksizeStack( Int blocksize )
{ ::blocksizeStack.push( blocksize ); }

void PopBlocksizeStack()
{
    DEBUG_ONLY(
      if( ::blocksizeStack.empty() )
          LogicError("Attempted to pop an empty blocksize stack");
    )
    ::blocksizeStack.pop();
}

const Grid& DefaultGrid() EL_NO_RELEASE_EXCEPT
{
    DEBUG_ONLY(
      CSE cse("DefaultGrid");
      if( ::defaultGrid == 0 )
          LogicError
          ("Attempted to return a non-existant default grid. Please ensure "
           "that Elemental is initialized before creating a DistMatrix.");
    )
    return *::defaultGrid;
}

Int DefaultBlockHeight()
{ return ::blockHeight; }

Int DefaultBlockWidth()
{ return ::blockWidth; }

void SetDefaultBlockHeight( Int mb )
{ ::blockHeight = mb; }

void SetDefaultBlockWidth( Int nb )
{ ::blockWidth = nb; }

std::mt19937& Generator()
{ return ::generator; }

void Args::HandleVersion( ostream& os ) const
{
    string version = "--version";
    char** arg = std::find( argv_, argv_+argc_, version );
    const bool foundVersion = ( arg != argv_+argc_ );
    if( foundVersion )
    {
        if( mpi::WorldRank() == 0 )
            PrintVersion();
        throw ArgException();
    }
}

void Args::HandleBuild( ostream& os ) const
{
    string build = "--build";
    char** arg = std::find( argv_, argv_+argc_, build );
    const bool foundBuild = ( arg != argv_+argc_ );
    if( foundBuild )
    {
        if( mpi::WorldRank() == 0 )
        {
            PrintVersion();
            PrintConfig();
            PrintCCompilerInfo();
            PrintCxxCompilerInfo();
        }
        throw ArgException();
    }
}

void ReportException( const exception& e, ostream& os )
{
    try
    {
        const ArgException& argExcept = dynamic_cast<const ArgException&>(e);
        if( string(argExcept.what()) != "" )
            os << argExcept.what() << endl;
        DEBUG_ONLY(DumpCallStack(os))
    }
    catch( UnrecoverableException& recovExcept )
    {
        if( string(e.what()) != "" )
        {
            os << "Process " << mpi::WorldRank() 
               << " caught an unrecoverable exception with message:\n"
               << e.what() << endl;
        }
        DEBUG_ONLY(DumpCallStack(os))
    }
    catch( exception& castExcept ) 
    { 
        if( string(e.what()) != "" )
        {
            os << "Process " << mpi::WorldRank() << " caught error message:\n"
               << e.what() << endl;
        }
        DEBUG_ONLY(DumpCallStack(os))
        mpi::Abort( mpi::COMM_WORLD, 1 );
    }
}

void ComplainIfDebug()
{
    DEBUG_ONLY(
        if( mpi::WorldRank() == 0 )
        {
            Output("=======================================================");
            Output(" In debug mode! Do not expect competitive performance! ");
            Output("=======================================================");
        }
    )
}

// If we are not in RELEASE mode, then implement wrappers for a CallStack
DEBUG_ONLY(

    void PushCallStack( string s )
    { 
#ifdef EL_HYBRID
        if( omp_get_thread_num() != 0 )
            return;
#endif
        ::callStack.push(s); 
    }
<commit_msg>Moving the mpi::Abort into the appropriate place within ReportException (the corresponding bug was noticed by @andreasnoack)<commit_after>/*
   Copyright (c) 2009-2015, <NAME>
                      2013, <NAME>
   All rights reserved.

   This file is part of Elemental and is under the BSD 2-Clause License, 
   which can be found in the LICENSE file in the root directory, or at 
   http://opensource.org/licenses/BSD-2-Clause
*/
#include "El.hpp"
#ifdef EL_HAVE_QT5
 #include <QApplication>
#endif

namespace {
using namespace El;

Int numElemInits = 0;
bool elemInitializedMpi = false;

std::stack<Int> blocksizeStack;
Grid* defaultGrid = 0;
Args* args = 0;

// Default blocksizes for BlockMatrix
Int blockHeight=32, blockWidth=32;

// A common Mersenne twister configuration
std::mt19937 generator;

// Debugging
DEBUG_ONLY(std::stack<string> callStack)

// LogFile in Debugging
DEBUG_ONLY(std::ofstream logFile)

// Output/logging
Int indentLevel=0;
Int spacesPerIndent=2;

// Tuning parameters for basic routines
Int localSymvIntBlocksize = 64;
Int localSymvFloatBlocksize = 64;
Int localSymvDoubleBlocksize = 64;
#ifdef EL_HAVE_QUAD
Int localSymvQuadBlocksize = 64;
#endif
Int localSymvComplexFloatBlocksize = 64;
Int localSymvComplexDoubleBlocksize = 64;
#ifdef EL_HAVE_QUAD
Int localSymvComplexQuadBlocksize = 64;
#endif

Int localTrr2kFloatBlocksize = 64;
Int localTrr2kDoubleBlocksize = 64;
Int localTrr2kComplexFloatBlocksize = 64;
Int localTrr2kComplexDoubleBlocksize = 64;

Int localTrrkFloatBlocksize = 64;
Int localTrrkDoubleBlocksize = 64;
Int localTrrkComplexFloatBlocksize = 64;
Int localTrrkComplexDoubleBlocksize = 64;

// Qt5
ColorMap colorMap=RED_BLACK_GREEN;
Int numDiscreteColors = 15;
#ifdef EL_HAVE_QT5
// The command-line arguments should be passed into Qt5 in a manner which
// ensures that they do not fall out of scope until the last Qt5 call.
// The best way to do so is to make a copy and pass in the copy.
int argcSave;
char** argvSave;

bool guiDisabled;
bool elemInitializedQt = false;
bool elemOpenedWindow = false;
QCoreApplication* coreApp;
bool haveMinRealWindowVal=false, haveMaxRealWindowVal=false,
     haveMinImagWindowVal=false, haveMaxImagWindowVal=false;
double minRealWindowVal, maxRealWindowVal,
       minImagWindowVal, maxImagWindowVal;
#endif
}

namespace El {

void PrintVersion( ostream& os )
{
    os << "Elemental version information:\n"
       << "  Git revision: " << EL_GIT_SHA1 << "\n"
       << "  Version:      " << EL_VERSION_MAJOR << "."
                             << EL_VERSION_MINOR << "\n"
       << "  Build type:   " << EL_CMAKE_BUILD_TYPE << "\n"
       << endl;
}

void PrintConfig( ostream& os )
{
    os << 
      "Elemental configuration:\n" <<
      "  Math libraries:               " << EL_MATH_LIBS << "\n"
#ifdef EL_HAVE_FLA_BSVD
      "  Have FLAME bidiagonal SVD:    YES\n"
#else
      "  Have FLAME bidiagonal SVD:    NO\n"
#endif
#ifdef EL_HYBRID
      "  Hybrid mode:                  YES\n"
#else
      "  Hybrid mode:                  NO\n"
#endif
#ifdef EL_HAVE_QT5
      "  Have Qt5:                     YES\n"
#else
      "  Have Qt5:                     NO\n"
#endif
#ifdef EL_AVOID_COMPLEX_MPI
      "  Avoiding complex MPI:         YES\n"
#else
      "  Avoiding complex MPI:         NO\n"
#endif
#ifdef EL_HAVE_MPI_REDUCE_SCATTER_BLOCK
      "  Have MPI_Reducescatter_block: YES\n"
#else
      "  Have MPI_Reducescatter_block: NO\n"
#endif
#ifdef EL_HAVE_MPI_IN_PLACE
      "  Have MPI_IN_PLACE:            YES\n"
#else
      "  Have MPI_IN_PLACE:            NO\n"
#endif
#ifdef EL_REDUCE_SCATTER_BLOCK_VIA_ALLREDUCE
      "  AllReduce ReduceScatterBlock: YES\n"
#else
      "  AllReduce ReduceScatterBlock: NO\n"
#endif
#ifdef EL_USE_BYTE_ALLGATHERS
      "  Use byte AllGathers:          YES\n"
#else
      "  Use byte AllGathers:          NO\n"
#endif
       << endl;
}

void PrintCCompilerInfo( ostream& os )
{
    os << "Elemental's C compiler info:\n"
       << "  EL_CMAKE_C_COMPILER:    " << EL_CMAKE_C_COMPILER << "\n"
       << "  EL_MPI_C_COMPILER:      " << EL_MPI_C_COMPILER << "\n"
       << "  EL_MPI_C_INCLUDE_PATH:  " << EL_MPI_C_INCLUDE_PATH << "\n"
       << "  EL_MPI_C_COMPILE_FLAGS: " << EL_MPI_C_COMPILE_FLAGS << "\n"
       << "  EL_MPI_LINK_FLAGS:      " << EL_MPI_LINK_FLAGS << "\n"
       << "  EL_MPI_C_LIBRARIES:     " << EL_MPI_C_LIBRARIES << "\n"
       << endl;
}

void PrintCxxCompilerInfo( ostream& os )
{
    os << "Elemental's C++ compiler info:\n"
       << "  EL_CMAKE_CXX_COMPILER:    " << EL_CMAKE_CXX_COMPILER << "\n"
       << "  EL_CXX_FLAGS:             " << EL_CXX_FLAGS << "\n"
       << "  EL_MPI_CXX_COMPILER:      " << EL_MPI_CXX_COMPILER << "\n"
       << "  EL_MPI_CXX_INCLUDE_PATH:  " << EL_MPI_CXX_INCLUDE_PATH << "\n"
       << "  EL_MPI_CXX_COMPILE_FLAGS: " << EL_MPI_CXX_COMPILE_FLAGS << "\n"
       << "  EL_MPI_LINK_FLAGS:        " << EL_MPI_LINK_FLAGS << "\n"
       << "  EL_MPI_CXX_LIBRARIES:     " << EL_MPI_CXX_LIBRARIES << "\n"
       << endl;
}

bool Using64BitInt()
{
#ifdef EL_USE_64BIT_INTS
    return true;
#else
    return false;
#endif
}

bool Using64BitBlasInt()
{
#ifdef EL_USE_64BIT_BLAS_INTS
    return true;
#else
    return false;
#endif
}

void SetColorMap( ColorMap map )
{ ::colorMap = map; }

ColorMap GetColorMap()
{ return ::colorMap; }

void SetNumDiscreteColors( Int numChunks )
{ ::numDiscreteColors = numChunks; }

Int NumDiscreteColors()
{ return ::numDiscreteColors; }

#ifdef EL_HAVE_QT5
bool GuiDisabled()
{ return ::guiDisabled; }

void OpenedWindow()
{ ::elemOpenedWindow = true; }

double MinRealWindowVal()
{
    if( ::haveMinRealWindowVal )
        return ::minRealWindowVal;
    else
        return 0;
}

double MaxRealWindowVal()
{
    if( ::haveMaxRealWindowVal )
        return ::maxRealWindowVal;
    else
        return 0;
}

double MinImagWindowVal()
{
    if( ::haveMinImagWindowVal )
        return ::minImagWindowVal;
    else
        return 0;
}

double MaxImagWindowVal()
{
    if( ::haveMaxImagWindowVal )
        return ::maxImagWindowVal;
    else
        return 0;
}

void UpdateMinRealWindowVal( double minVal )
{
    if( ::haveMinRealWindowVal )
        ::minRealWindowVal = Min( ::minRealWindowVal, minVal );
    else
        ::minRealWindowVal = minVal;
    ::haveMinRealWindowVal = true;
}

void UpdateMaxRealWindowVal( double maxVal )
{
    if( ::haveMaxRealWindowVal )
        ::maxRealWindowVal = Max( ::maxRealWindowVal, maxVal );
    else
        ::maxRealWindowVal = maxVal;
    ::haveMaxRealWindowVal = true;
}

void UpdateMinImagWindowVal( double minVal )
{
    if( ::haveMinImagWindowVal )
        ::minImagWindowVal = Min( ::minImagWindowVal, minVal );
    else
        ::minImagWindowVal = minVal;
    ::haveMinImagWindowVal = true;
}

void UpdateMaxImagWindowVal( double maxVal )
{
    if( ::haveMaxImagWindowVal )
        ::maxImagWindowVal = Max( ::maxImagWindowVal, maxVal );
    else
        ::maxImagWindowVal = maxVal;
    ::haveMaxImagWindowVal = true;
}
#endif // ifdef EL_HAVE_QT5

bool Initialized()
{ return ::numElemInits > 0; }

void Initialize()
{
    int argc=0;
    char** argv=NULL;
    Initialize( argc, argv );
}

void Initialize( int& argc, char**& argv )
{
    if( ::numElemInits > 0 )
    {
        ++::numElemInits;
        return;
    }

    ::args = new Args( argc, argv );

    ::numElemInits = 1;
    if( !mpi::Initialized() )
    {
        if( mpi::Finalized() )
        {
            LogicError
            ("Cannot initialize elemental after finalizing MPI");
        }
#ifdef EL_HYBRID
        const Int provided = 
            mpi::InitializeThread
            ( argc, argv, mpi::THREAD_MULTIPLE );
        const int commRank = mpi::Rank( mpi::COMM_WORLD );
        if( provided != mpi::THREAD_MULTIPLE && commRank == 0 )
        {
            cerr << "WARNING: Could not achieve THREAD_MULTIPLE support."
                 << endl;
        }
#else
        mpi::Initialize( argc, argv );
#endif
        ::elemInitializedMpi = true;
    }
    else
    {
#ifdef EL_HYBRID
        const Int provided = mpi::QueryThread();
        if( provided != mpi::THREAD_MULTIPLE )
        {
            throw std::runtime_error
            ("MPI initialized with inadequate thread support for Elemental");
        }
#endif
    }

#ifdef EL_HAVE_QT5
    ::coreApp = QCoreApplication::instance();
    if( ::coreApp == 0 )
    {
        // Test for whether the GUI should be disabled
        ::guiDisabled = false;
        for( int i=1; i<argc; ++i )
            if( !qstrcmp(argv[i],"-no-gui") )
                ::guiDisabled = true;

        ::argcSave = argc;
        ::argvSave = new char*[argc+1];
        for( int i=0; i<argc; ++i )
        {
            ::argvSave[i] = new char[std::strlen(argv[i])+1];
            std::strcpy( ::argvSave[i], argv[i] );
        }
       ::argvSave[argc] = nullptr;
       
        if( ::guiDisabled )
            ::coreApp = new QCoreApplication( ::argcSave, ::argvSave );
        else
            ::coreApp = new QApplication( ::argcSave, ::argvSave );        
        ::elemInitializedQt = true;
    }
#endif

    // Queue a default algorithmic blocksize
    while( ! ::blocksizeStack.empty() )
        ::blocksizeStack.pop();
    ::blocksizeStack.push( 128 );

    // Build the default grid
    defaultGrid = new Grid( mpi::COMM_WORLD );

    // Create the types and ops
    mpi::CreateCustom();

    const unsigned rank = mpi::Rank( mpi::COMM_WORLD );
    // TODO: Allow for switching on/off reproducibility?
    //const long secs = time(NULL);
    const long secs = 21;
    const long seed = (secs<<16) | (rank & 0xFFFF);
    ::generator.seed( seed );
    srand( seed );

DEBUG_ONLY(
        ostringstream fileOS;
        fileOS << "El-Proc" << std::setfill('0') << std::setw(3)
               << rank << ".log";
        OpenLog( fileOS.str().c_str() );
)
}

void Finalize()
{
    DEBUG_ONLY(CSE cse("Finalize"))
    if( ::numElemInits <= 0 )
    { 
        cerr << "Finalized Elemental more times than initialized" << endl;
        return;
    }
    --::numElemInits;

    if( mpi::Finalized() )
        cerr << "Warning: MPI was finalized before Elemental." << endl;
    if( ::numElemInits == 0 )
    {
        delete ::args;
        ::args = 0;
       
        // Destroy the types and ops
        mpi::DestroyCustom();

        // Delete the default grid
        delete ::defaultGrid;
        ::defaultGrid = 0;

#ifdef EL_HAVE_QT5
        if( ::elemInitializedQt )
        {
            if( ::elemOpenedWindow )
                ::coreApp->exec();
            else
                ::coreApp->exit();
            delete ::coreApp;

            // Delete the copies of argc and argv
            for( int i=0; i< ::argcSave; ++i )
                delete[] ::argvSave[i]; 
            delete[] ::argvSave;
        }
#endif
        if( ::elemInitializedMpi )
            mpi::Finalize();


        while( ! ::blocksizeStack.empty() )
            ::blocksizeStack.pop();
    }

    DEBUG_ONLY( CloseLog() )
}

Args& GetArgs()
{ 
    if( args == 0 )
        throw std::runtime_error("No available instance of Args");
    return *::args; 
}

Int Blocksize()
{ 
    DEBUG_ONLY(
      if( ::blocksizeStack.empty() )
          LogicError("Attempted to extract blocksize from empty stack");
    )
    return ::blocksizeStack.top(); 
}

void SetBlocksize( Int blocksize )
{ 
    DEBUG_ONLY(
      if( ::blocksizeStack.empty() )
          LogicError("Attempted to set blocksize at top of empty stack");
    )
    ::blocksizeStack.top() = blocksize; 
}

void PushBlocksizeStack( Int blocksize )
{ ::blocksizeStack.push( blocksize ); }

void PopBlocksizeStack()
{
    DEBUG_ONLY(
      if( ::blocksizeStack.empty() )
          LogicError("Attempted to pop an empty blocksize stack");
    )
    ::blocksizeStack.pop();
}

const Grid& DefaultGrid() EL_NO_RELEASE_EXCEPT
{
    DEBUG_ONLY(
      CSE cse("DefaultGrid");
      if( ::defaultGrid == 0 )
          LogicError
          ("Attempted to return a non-existant default grid. Please ensure "
           "that Elemental is initialized before creating a DistMatrix.");
    )
    return *::defaultGrid;
}

Int DefaultBlockHeight()
{ return ::blockHeight; }

Int DefaultBlockWidth()
{ return ::blockWidth; }

void SetDefaultBlockHeight( Int mb )
{ ::blockHeight = mb; }

void SetDefaultBlockWidth( Int nb )
{ ::blockWidth = nb; }

std::mt19937& Generator()
{ return ::generator; }

void Args::HandleVersion( ostream& os ) const
{
    string version = "--version";
    char** arg = std::find( argv_, argv_+argc_, version );
    const bool foundVersion = ( arg != argv_+argc_ );
    if( foundVersion )
    {
        if( mpi::WorldRank() == 0 )
            PrintVersion();
        throw ArgException();
    }
}

void Args::HandleBuild( ostream& os ) const
{
    string build = "--build";
    char** arg = std::find( argv_, argv_+argc_, build );
    const bool foundBuild = ( arg != argv_+argc_ );
    if( foundBuild )
    {
        if( mpi::WorldRank() == 0 )
        {
            PrintVersion();
            PrintConfig();
            PrintCCompilerInfo();
            PrintCxxCompilerInfo();
        }
        throw ArgException();
    }
}

void ReportException( const exception& e, ostream& os )
{
    try
    {
        const ArgException& argExcept = dynamic_cast<const ArgException&>(e);
        if( string(argExcept.what()) != "" )
            os << argExcept.what() << endl;
        DEBUG_ONLY(DumpCallStack(os))
    }
    catch( UnrecoverableException& recovExcept )
    {
        if( string(e.what()) != "" )
        {
            os << "Process " << mpi::WorldRank() 
               << " caught an unrecoverable exception with message:\n"
               << e.what() << endl;
        }
        DEBUG_ONLY(DumpCallStack(os))
        mpi::Abort( mpi::COMM_WORLD, 1 );
    }
    catch( exception& castExcept ) 
    { 
        if( string(e.what()) != "" )
        {
            os << "Process " << mpi::WorldRank() << " caught error message:\n"
               << e.what() << endl;
        }
        DEBUG_ONLY(DumpCallStack(os))
    }
}

void ComplainIfDebug()
{
    DEBUG_ONLY(
        if( mpi::WorldRank() == 0 )
        {
            Output("=======================================================");
            Output(" In debug mode! Do not expect competitive performance! ");
            Output("=======================================================");
        }
    )
}

// If we are not in RELEASE mode, then implement wrappers for a CallStack
DEBUG_ONLY(

    void PushCallStack( string s )
    { 
#ifdef EL_HYBRID
        if( omp_get_thread_num() != 0 )
            return;
#endif
        ::callStack.push(s); 
    }

{'fraction_non_alphanumeric': 0.12949960612391684, 'fraction_numerical': 0.008631023735315272, 'mean_word_length': 2.487577639751553, 'pattern_counts': {'":': 0, '<': 363, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6496988', 'n_tokens_mistral': 9981, 'n_tokens_neox': 9580, 'n_words': 2277}