CALresult integrateCAL(const AstronomyParameters* ap,
                       const IntegralArea* ia,
                       const StreamGauss sg,
                       EvaluationState* es,
                       const CLRequest* clr,
                       MWCALInfo* ci)
{
    CALresult err;
    SeparationCALMem cm;
    CALSeparationSizes sizes;

    calculateCALSeparationSizes(&sizes, ap, ia);

    memset(&cm, 0, sizeof(cm));
    err = createSeparationBuffers(ci, &cm, ap, ia, sg, &sizes);
    if (err != CAL_RESULT_OK)
        return err;

    err = runIntegral(ap, ia, es, clr, ci, &cm);

    err |= releaseSeparationBuffers(ci, &cm);
    if (err != CAL_RESULT_OK)
        return err;

    separationIntegralApplyCorrection(es);

    return CAL_RESULT_OK;
}
cl_int integrateCL(const AstronomyParameters* ap,
                   const IntegralArea* ia,
                   const StreamConstants* sc,
                   const StreamGauss sg,
                   EvaluationState* es,
                   const CLRequest* clr,
                   CLInfo* ci)
{
    cl_int err;
    RunSizes runSizes;
    SeparationSizes sizes;
    SeparationCLMem cm = EMPTY_SEPARATION_CL_MEM;

    /* Need to test sizes for each integral, since the area size can change */
    calculateSizes(&sizes, ap, ia);

    if (findRunSizes(&runSizes, ci, &ci->di, ap, ia, clr))
    {
        mw_printf("Failed to find good run sizes\n");
        return MW_CL_ERROR;
    }

    err = createSeparationBuffers(ci, &cm, ap, ia, sc, sg, &sizes);
    if (err != CL_SUCCESS)
    {
        mwPerrorCL(err, "Failed to create CL buffers");
        return err;
    }

    err = separationSetKernelArgs(&cm, &runSizes);
    if (err != CL_SUCCESS)
    {
        mwPerrorCL(err, "Failed to set integral kernel arguments");
        return err;
    }

    err = runIntegral(ci, &cm, &runSizes, es, clr, ap, ia);

    releaseSeparationBuffers(&cm);

    separationIntegralGetSums(es);

    return err;
}