static int separationInit(int debugBOINC)
{
    int rc;
    MWInitType initType = MW_PLAIN;

  #if DISABLE_DENORMALS
    mwDisableDenormalsSSE();
  #endif

    mwFixFPUPrecision();

    if (debugBOINC)
        initType |= MW_DEBUG;

    if (SEPARATION_OPENCL)
        initType |= MW_OPENCL;

    rc = mwBoincInit(initType);
    if (rc)
        return rc;

    if (BOINC_APPLICATION && mwIsFirstRun())
    {
        /* Print the version, but only once for the workunit */
        printVersion(TRUE, FALSE);
    }

  #if (SEPARATION_OPENCL) && defined(_WIN32)
    /* We need to increase timer resolution to prevent big slowdown on windows when CPU is loaded. */
    mwSetTimerMinResolution();
  #endif /* defined(_WIN32) */

    return 0;
}
int main(int argc, const char* argv[])
{
    int rc;
    SeparationFlags sf;
    SeparationPrefs preferences;
    const char** argvCopy = NULL;

  #ifdef NDEBUG
    mwDisableErrorBoxes();
  #endif /* NDEBUG */

    argvCopy = mwFixArgv(argc, argv);
    rc = parseParameters(argc, argvCopy ? argvCopy : argv, &sf);
    if (rc)
    {
        if (BOINC_APPLICATION)
        {
            freeSeparationFlags(&sf);
            mwBoincInit(MW_PLAIN);
            parseParameters(argc, argvCopy, &sf);
            printVersion(TRUE, FALSE);
        }

        mw_printf("Failed to parse parameters\n");
        free(argvCopy);
        mw_finish(EXIT_FAILURE);
    }


    rc = separationInit(sf.debugBOINC);
    free(argvCopy);
    if (rc)
        return rc;

    separationReadPreferences(&preferences);
    setFlagsFromPreferences(&sf, &preferences, argv[0]);

    if (sf.processPriority != MW_PRIORITY_INVALID)
    {
        mwSetProcessPriority(sf.processPriority);
    }

    rc = worker(&sf);

    freeSeparationFlags(&sf);

    if (!sf.ignoreCheckpoint && sf.cleanupCheckpoint && rc == 0)
    {
        mw_report("Removing checkpoint file '%s'\n", CHECKPOINT_FILE);
        mw_remove(CHECKPOINT_FILE);
    }

    mw_finish(rc);
    return rc;
}
static int nbInit(const NBodyFlags* nbf)
{
    MWInitType initType = MW_PLAIN;

  #ifdef _OPENMP
    initType |= MW_MULTITHREAD;
  #endif

    if (nbf->debugBOINC)
        initType |= MW_DEBUG;

    return mwBoincInit(initType);
}
static int nbglBoincGraphicsInit(int debug)
{
    if (BOINC_APPLICATION)
    {
        MWInitType type = MW_GRAPHICS | (debug ? MW_DEBUG : 0);
        if (mwBoincInit(type))
        {
            mw_printf("BOINC graphics init failed\n");
            return 1;
        }
    }

    return 0;
}
int main(int argc, const char* argv[])
{
    NBodyFlags nbf;
    int rc = 0;
    const char** argvCopy = mwFixArgv(argc, argv);

    nbSpecialSetup();

    if (nbReadParameters(argc, argvCopy ? argvCopy : argv, &nbf))
    {
        if (BOINC_APPLICATION)
        {
            mwBoincInit(MW_PLAIN);
            nbReadParameters(argc, argvCopy ? argvCopy : argv, &nbf);
            nbPrintVersion(TRUE, FALSE);
        }

        mw_finish(EXIT_FAILURE);
    }

    if (nbInit(&nbf))
    {
        exit(EXIT_FAILURE);
    }

    if (BOINC_APPLICATION && mwIsFirstRun())
    {
        nbPrintVersion(TRUE, FALSE);
    }

    nbSetDefaultFlags(&nbf);
    if (nbSetNumThreads(nbf.numThreads))
    {
        mw_finish(EXIT_FAILURE);
    }

    if (nbf.verifyOnly)
    {
        rc = nbVerifyFile(&nbf);
    }
    else if (nbf.matchHistogram)
    {
        double emd;

        emd = nbMatchHistogramFiles(nbf.histogramFileName, nbf.matchHistogram);
        mw_printf("%.15f\n", emd);
        rc = isnan(emd);
    }
    else
    {
        rc = nbMain(&nbf);
        rc = nbStatusToRC(rc);

        if (!nbf.noCleanCheckpoint)
        {
            mw_report("Removing checkpoint file '%s'\n", nbf.checkpointFileName);
            mw_remove(nbf.checkpointFileName);
        }
    }

    fflush(stderr);
    fflush(stdout); /* Odd things happen with the OpenCL one where stdout starts disappearing */


    freeNBodyFlags(&nbf);

    if (BOINC_APPLICATION)
    {
        mw_finish(rc);
    }

    return rc;
}