/* SinglePoly + SinglePoly*/
int iAddScilabPolynomToScilabPolynom(double* _pCoef1R, int _iRank1, double* _pCoef2R, int _iRank2, double* _pCoefOutR, int _iRanOut)
{
    int iRankMin			= Min(_iRank1, _iRank2);
    int iRankMax			= Max(_iRank1, _iRank2);
    int iRank				= 0;
    double dblSum 			= 0.0;
    double* pCoefMaxR	= (_iRank1 > _iRank2) ? _pCoef1R : _pCoef2R;

    for (iRank = 0; iRank < iRankMin ; iRank++)
    {
        dblSum = _pCoef1R[iRank] + _pCoef2R[iRank];
        if (fabs(dblSum) > Max(fabs(_pCoef1R[iRank]), fabs(_pCoef2R[iRank])) * 2 * nc_eps())
        {
            _pCoefOutR[iRank] = dblSum;
        }
        else
        {
            _pCoefOutR[iRank] = 0.0;
        }
    }

    for (iRank = iRankMin ; iRank < iRankMax ; iRank++)
    {
        _pCoefOutR[iRank] = pCoefMaxR[iRank];
    }
    return 0;
}
Beispiel #2
0
/* part of API. cf lsq.h */
int iLsqM(double* pData1, int iRows, int iCols, double* pData2, int iNRhs, int complexArgs, double* pResult, double* pTreshold, int* piRank)
{
    int ret = 0;
    double* pRwork = NULL;
    doublecomplex* pWork = NULL;
    double* pXb = NULL;
    int* pPivot = NULL;
    int worksize = 0 ;
    int unusedRank;
    double const treshold = pTreshold ? *pTreshold : sqrt(nc_eps());

    if ( (pRwork = (double*)( complexArgs ? (double*)MALLOC(2 * iCols * sizeof(double)) : allocDgelsyWorkspace(iRows, iCols, iNRhs, &worksize)))
            && (pXb = (double*)MALLOC(Max(iRows, iCols) * iNRhs * (complexArgs ? sizeof(doublecomplex) : sizeof(double))))
            && (pPivot = (int*)MALLOC(iCols * sizeof(int)))
            && (!complexArgs || (pWork = allocZgelsyWorkspace(iRows, iCols, iNRhs, &worksize))) )
    {
        int const maxRowsCols = Max(iRows, iCols);
        memset(pPivot, 0, iCols * sizeof(int));
        if (complexArgs)
        {
            /* cf supra : if(maxRowsCols == iRows){ memcpy(pXb, pData2, iRows * iNRhs) } else { zlacpy } */
            C2F(zlacpy)("F", &iRows, &iNRhs, (doublecomplex*)pData2, &iRows, (doublecomplex*)pXb, &maxRowsCols );
            C2F(zgelsy)(&iRows, &iCols, &iNRhs, (doublecomplex*)pData1, &iRows, (doublecomplex*)pXb, &maxRowsCols, pPivot
                        , &treshold, piRank ? piRank : &unusedRank, pWork, &worksize, pRwork, &ret);
            if (!ret)
            {
                /* cf supra : if(maxRowsCols == iCols){ memcpy(pResult, pXb, iCols * iNRhs) } else { zlacpy } */
                C2F(zlacpy)("F", &iCols, &iNRhs, (doublecomplex*)pXb, &maxRowsCols, (doublecomplex*)pResult, &iCols);
            }
        }
        else
        {
            C2F(dlacpy)("F", &iRows, &iNRhs, pData2, &iRows, pXb, &maxRowsCols );
            C2F(dgelsy)(&iRows, &iCols, &iNRhs, pData1, &iRows, pXb, &maxRowsCols, pPivot
                        , &treshold, piRank ? piRank : &unusedRank, pRwork, &worksize, &ret);
            if (!ret)
            {
                C2F(dlacpy)("F", &iCols, &iNRhs, pXb, &maxRowsCols, pResult, &iCols);
            }
        }
    }
    else
    {
        ret = -1; /* report MALLOC failure */
    }
    FREE(pRwork);
    FREE(pXb);
    FREE(pPivot);
    FREE(pWork);
    return ret;
}
Beispiel #3
0
static void decompInf(double x, int *xk, int *xa, int b)
{
    if (x == 0.0)
    {
        *xk = 0;
        *xa = 1; /* jpc */
    }
    else
    {
        if (x > 0)
        {
            double xup;
            static double epsilon;
            static int first = 0;
            if (first == 0)
            {
                epsilon = 10.0 * nc_eps();
                first++;
            }
            *xa = (int) floor(log10(x)) - b + 1;
            *xk = (int) floor(x / exp10((double) * xa));
            /* if x is very near (k+1)10^a (epsilon machine)
             * we increment xk
             */
            xup = (*xk + 1) * exp10((double) * xa);
            if (Abs((x - xup) / x) < epsilon)
            {
                *xk += 1;
            }
        }
        else
        {
            decompSup(-x, xk, xa, b);
            *xk = -(*xk);
        }
    }
}
Beispiel #4
0
/*--------------------------------------------------------------------------*/
int sci_qld(char *fname, void* pvApiCtx)
{
    SciErr sciErr;
    static int un = 1, zero = 0;
    static int n = 0, nbis = 0;
    static int unbis = 0;
    static int mmax = 0, m = 0, mnn = 0;
    static int mbis = 0;
    static int pipo = 0;
    static int ifail = 0;
    int next = 0;

    static int lwar = 0, iout = 0, k = 0, l = 0;
    static double eps1 = 0;

    int* piAddr1 = NULL;
    int* piAddr2 = NULL;
    int* piAddr3 = NULL;
    int* piAddr4 = NULL;
    int* piAddr5 = NULL;
    int* piAddr6 = NULL;
    int* piAddr7 = NULL;

    double* Q  = NULL;
    double* p  = NULL;
    double* C  = NULL;
    double* b  = NULL;
    double* lb = NULL;
    double* ub = NULL;
    int* me    = NULL;

    double* x       = NULL;
    double* lambda  = NULL;
    int* inform     = NULL;
    double* war     = NULL;
    int* iwar       = NULL;

    /*   Check rhs and lhs   */
    CheckInputArgument(pvApiCtx, 7, 8) ;
    CheckOutputArgument(pvApiCtx, 1, 3) ;

    /* RhsVar: qld(Q,p,C,b,lb,ub,me,eps) */
    /*             1,2,3,4,5 ,6 ,7, 8  */
    eps1 = nc_eps();
    next = nbInputArgument(pvApiCtx) + 1;
    /*   Variable 1 (Q)   */
    //get variable address

    sciErr = getVarAddressFromPosition(pvApiCtx, 1, &piAddr1);
    if (sciErr.iErr)
    {
        printError(&sciErr, 0);
        return 1;
    }

    // Retrieve a matrix of double at position 1.
    sciErr = getMatrixOfDouble(pvApiCtx, piAddr1, &n, &nbis, &Q);
    if (sciErr.iErr)
    {
        Scierror(202, _("%s: Wrong type for argument #%d: A real expected.\n"), fname, 1);
        printError(&sciErr, 0);
        return 1;
    }

    //CheckSquare
    if (n != nbis)
    {
        Scierror(999, _("%s: Wrong size for input argument #%d: A square matrix expected.\n"), fname, 1);
        return 1;
    }


    /*   Variable 2 (p)   */
    //get variable address
    sciErr = getVarAddressFromPosition(pvApiCtx, 2, &piAddr2);
    if (sciErr.iErr)
    {
        printError(&sciErr, 0);
        return 1;
    }

    // Retrieve a matrix of double at position 2.
    sciErr = getMatrixOfDouble(pvApiCtx, piAddr2, &nbis, &unbis, &p);
    if (sciErr.iErr)
    {
        Scierror(202, _("%s: Wrong type for argument #%d: A real expected.\n"), fname, 2);
        printError(&sciErr, 0);
        return 1;
    }

    //CheckLength
    if (nbis * unbis != n)
    {
        Scierror(999, _("%s: Wrong size for input argument #%d: %d expected.\n"), fname, 2, nbis * unbis);
        return 1;
    }


    /*   Variable 3 (C)   */
    //get variable address
    sciErr = getVarAddressFromPosition(pvApiCtx, 3, &piAddr3);
    if (sciErr.iErr)
    {
        printError(&sciErr, 0);
        return 1;
    }

    // Retrieve a matrix of double at position 3.
    sciErr = getMatrixOfDouble(pvApiCtx, piAddr3, &m, &nbis, &C);
    if (sciErr.iErr)
    {
        Scierror(202, _("%s: Wrong type for argument #%d: A real expected.\n"), fname, 3);
        printError(&sciErr, 0);
        return 1;
    }

    if (( nbis != n ) && (m > 0))
    {
        Scierror(205, _("%s: Wrong size for input argument #%d: number of columns %d expected.\n"), fname, 3, n);
        return 0;
    }
    mmax = m;
    mnn = m + n + n;

    /*   Variable 4 (b)   */
    //get variable address
    sciErr = getVarAddressFromPosition(pvApiCtx, 4, &piAddr4);
    if (sciErr.iErr)
    {
        printError(&sciErr, 0);
        return 1;
    }

    // Retrieve a matrix of double at position 4.
    sciErr = getMatrixOfDouble(pvApiCtx, piAddr4, &mbis, &unbis, &b);
    if (sciErr.iErr)
    {
        Scierror(202, _("%s: Wrong type for argument #%d: A real expected.\n"), fname, 4);
        printError(&sciErr, 0);
        return 1;
    }

    //CheckLength
    if (mbis * unbis != m)
    {
        Scierror(999, _("%s: Wrong size for input argument #%d: %d expected.\n"), fname, 4, mbis * unbis);
        return 1;
    }


    /*   Variable 5 (lb)   */
    //get variable address
    sciErr = getVarAddressFromPosition(pvApiCtx, 5, &piAddr5);
    if (sciErr.iErr)
    {
        printError(&sciErr, 0);
        return 1;
    }

    // Retrieve a matrix of double at position 5.
    sciErr = getMatrixOfDouble(pvApiCtx, piAddr5, &nbis, &unbis, &lb);
    if (sciErr.iErr)
    {
        Scierror(202, _("%s: Wrong type for argument #%d: A real expected.\n"), fname, 5);
        printError(&sciErr, 0);
        return 1;
    }

    if (nbis * unbis == 0)
    {
        sciErr = allocMatrixOfDouble(pvApiCtx, next, n, un, &lb);
        if (sciErr.iErr)
        {
            printError(&sciErr, 0);
            Scierror(999, _("%s: Memory allocation error.\n"), fname);
            return 1;
        }

        for (k = 0; k < n; k++)
        {
            (lb)[k] = -nc_double_max();
        }
        next = next + 1;
    }
    else if (nbis * unbis != n) //CheckLength
    {
        Scierror(999, _("%s: Wrong size for input argument #%d: %d expected.\n"), fname, 5, nbis * unbis);
        return 1;
    }

    /*   Variable 6 (ub)   */
    //get variable address
    sciErr = getVarAddressFromPosition(pvApiCtx, 6, &piAddr6);
    if (sciErr.iErr)
    {
        printError(&sciErr, 0);
        return 1;
    }

    // Retrieve a matrix of double at position 6.
    sciErr = getMatrixOfDouble(pvApiCtx, piAddr6, &nbis, &unbis, &ub);
    if (sciErr.iErr)
    {
        Scierror(202, _("%s: Wrong type for argument #%d: A real expected.\n"), fname, 6);
        printError(&sciErr, 0);
        return 1;
    }

    if (nbis * unbis == 0)
    {
        sciErr = allocMatrixOfDouble(pvApiCtx, next, n, un, &ub);
        if (sciErr.iErr)
        {
            printError(&sciErr, 0);
            Scierror(999, _("%s: Memory allocation error.\n"), fname);
            return 1;
        }

        for (k = 0; k < n; k++)
        {
            (ub)[k] = nc_double_max();
        }
        next = next + 1;
    }
    else if (nbis * unbis != n)//CheckLength
    {
        Scierror(999, _("%s: Wrong size for input argument #%d: %d expected.\n"), fname, 6, nbis * unbis);
        return 1;
    }


    /*   Variable 7 (me)   */
    //get variable address
    sciErr = getVarAddressFromPosition(pvApiCtx, 7, &piAddr7);
    if (sciErr.iErr)
    {
        printError(&sciErr, 0);
        return 1;
    }

    // Retrieve a matrix of double at position 7.
    sciErr = getMatrixOfDoubleAsInteger(pvApiCtx, piAddr7, &pipo, &unbis, &me);
    if (sciErr.iErr)
    {
        Scierror(202, _("%s: Wrong type for argument #%d: A real expected.\n"), fname, 7);
        printError(&sciErr, 0);
        return 1;
    }

    //CheckScalar
    if (pipo != 1 || unbis != 1)
    {
        Scierror(999, _("%s: Wrong size for input argument #%d: A real scalar expected.\n"), fname, 7);
        return 1;
    }

    if ((*(me) < 0) || (*(me) > n))
    {
        // FIX ME
        //        Err = 7;
        SciError(116);
        return 0;
    }

    if (nbInputArgument(pvApiCtx) == 8)
    {
        /*   Variable 8 (eps1)   */
        //get variable address
        int* piAddr8 = NULL;
        double* leps = NULL;
        sciErr = getVarAddressFromPosition(pvApiCtx, 8, &piAddr8);
        if (sciErr.iErr)
        {
            printError(&sciErr, 0);
            return 1;
        }

        // Retrieve a matrix of double at position 8.
        sciErr = getMatrixOfDouble(pvApiCtx, piAddr8, &pipo, &unbis, &leps);
        if (sciErr.iErr)
        {
            Scierror(202, _("%s: Wrong type for argument #%d: A real expected.\n"), fname, 8);
            printError(&sciErr, 0);
            return 1;
        }

        //CheckScalar
        if (pipo != 1 || unbis != 1)
        {
            Scierror(999, _("%s: Wrong size for input argument #%d: A real scalar expected.\n"), fname, 8);
            return 1;
        }

        eps1 = Max(eps1, *leps);
    }

    /* Internal variables: x, lambda, inform, C_mmax, b_mmax */
    sciErr = allocMatrixOfDouble(pvApiCtx, next, n, un, &x);
    if (sciErr.iErr)
    {
        printError(&sciErr, 0);
        Scierror(999, _("%s: Memory allocation error.\n"), fname);
        return 1;
    }

    sciErr = allocMatrixOfDouble(pvApiCtx, next + 1, mnn, un, &lambda);
    if (sciErr.iErr)
    {
        printError(&sciErr, 0);
        Scierror(999, _("%s: Memory allocation error.\n"), fname);
        return 1;
    }

    sciErr = allocMatrixOfDoubleAsInteger(pvApiCtx, next + 2, un, un, &inform);
    if (sciErr.iErr)
    {
        printError(&sciErr, 0);
        Scierror(999, _("%s: Memory allocation error.\n"), fname);
        return 1;
    }


    lwar = 3 * n * n / 2 + 10 * n + 2 * mmax + 2;
    sciErr = allocMatrixOfDouble(pvApiCtx, next + 3, lwar, un, &war);
    if (sciErr.iErr)
    {
        printError(&sciErr, 0);
        Scierror(999, _("%s: Memory allocation error.\n"), fname);
        return 1;
    }

    sciErr = allocMatrixOfDoubleAsInteger(pvApiCtx, next + 4, n, un, &iwar);
    if (sciErr.iErr)
    {
        printError(&sciErr, 0);
        Scierror(999, _("%s: Memory allocation error.\n"), fname);
        return 1;
    }

    (iwar)[0] = 1; /*Cholesky factorization required*/

    /* Change the sign of C*/
    for (k = 0; k < n; k++)
    {
        for (l = 0; l < m; l++)
        {
            (C)[k * m + l] = -(C)[k * m + l];
        }
    }

    iout = 0;
    ifail = 0;
    C2F(ql0001)(&m, (me), &mmax, &n, &n, &mnn, (Q), (p), (C),
                (b), (lb), (ub), (x), (lambda), &iout,
                &ifail, &zero, (war), &lwar, (iwar), &n, &eps1);


    /* LhsVar: [x, lambda, inform] = qld(...) */
    if (ifail == 0)
    {
        AssignOutputVariable(pvApiCtx, 1) = next;
        AssignOutputVariable(pvApiCtx, 2) = next + 1;
        if (nbOutputArgument(pvApiCtx) == 3)
        {
            AssignOutputVariable(pvApiCtx, 3) = next + 2;
            *(inform) = ifail;
        }
        ReturnArguments(pvApiCtx);
    }
    else if (ifail == 1)
    {
        Scierror(24, _("%s: Too many iterations (more than %d).\n"), fname, 40 * (n + m));
    }
    else if (ifail == 2)
    {
        Scierror(24, _("%s: Accuracy insufficient to satisfy convergence criterion.\n"), fname);
    }
    else if (ifail == 5)
    {
        Scierror(999, _("%s: Length of working array is too short.\n"), fname);
    }
    else if (ifail > 10)
    {
        Scierror(999, _("%s: The constraints are inconsistent.\n"), fname);
    }
    else
    {
    }
    return 0;
}
/*Complex matrices left division*/
int iLeftDivisionOfComplexMatrix(
    double *_pdblReal1,     double *_pdblImg1,      int _iRows1,    int _iCols1,
    double *_pdblReal2,     double *_pdblImg2,      int _iRows2,    int _iCols2,
    double *_pdblRealOut,   double *_pdblImgOut,    int _iRowsOut,  int _iColsOut,  double *_pdblRcond)
{
    int iReturn = 0;
    int iIndex  = 0;
    char cNorm  = 0;
    int iExit   = 0;

    /*temporary variables*/
    int iWorkMin    = 0;
    int iInfo       = 0;
    int iMax        = 0;
    double dblRcond = 0;

    double dblEps       = 0;
    double RCONDthresh  = 0;
    double dblAnorm     = 0;

    doublecomplex *pAf      = NULL;
    doublecomplex *pXb      = NULL;
    doublecomplex *pDwork   = NULL;
    doublecomplex *poVar1   = NULL;
    doublecomplex *poVar2   = NULL;
    doublecomplex *poOut    = NULL;

    double *pRwork  = NULL;

    int iRank       = 0;
    int *pIpiv      = NULL;
    int *pJpvt      = NULL;

    iWorkMin    = Max(2 * _iCols1, Min(_iRows1, _iCols1) + Max(2 * Min(_iRows1, _iCols1), Max(_iCols1, Min(_iRows1, _iCols1) + _iCols2)));

    /* Array allocations*/
    poVar1      = oGetDoubleComplexFromPointer(_pdblReal1, _pdblImg1, _iRows1 * _iCols1);
    poVar2      = oGetDoubleComplexFromPointer(_pdblReal2, _pdblImg2, _iRows2 * _iCols2);

    pIpiv       = (int*)malloc(sizeof(int) * _iCols1);
    pJpvt       = (int*)malloc(sizeof(int) * _iCols1);
    pRwork      = (double*)malloc(sizeof(double) * _iCols1 * 2);

    cNorm       = '1';
    pDwork      = (doublecomplex*)malloc(sizeof(doublecomplex) * iWorkMin);
    dblEps      = nc_eps();
    RCONDthresh = 10 * dblEps;
    dblAnorm    = C2F(zlange)(&cNorm, &_iRows1, &_iCols1, (double*)poVar1, &_iRows1, (double*)pDwork);

    if (_iRows1 == _iCols1)
    {
        C2F(zgetrf)(&_iCols1, &_iCols1, poVar1, &_iCols1, pIpiv, &iInfo);
        if (iInfo == 0)
        {
            C2F(zgecon)(&cNorm, &_iCols1, poVar1, &_iCols1, &dblAnorm, &dblRcond, pDwork, pRwork, &iInfo);
            if (dblRcond > RCONDthresh)
            {
                cNorm    = 'N';
                C2F(zgetrs)(&cNorm, &_iCols1, &_iCols2, poVar1, &_iCols1, pIpiv, poVar2, &_iCols1, &iInfo);
                vGetPointerFromDoubleComplex(poVar2, _iRowsOut * _iColsOut, _pdblRealOut, _pdblImgOut);
                iExit = 1;
            }
            else
            {
                //how to extract that ? Oo
                iReturn = -1;
                *_pdblRcond = dblRcond;
            }
        }
    }

    if (iExit == 0)
    {
        dblRcond = RCONDthresh;
        iMax = Max(_iRows1, _iCols1);
        memset(pJpvt, 0x00, sizeof(int) * _iCols1);
        pXb = (doublecomplex*)malloc(sizeof(doublecomplex) * iMax * _iColsOut);
        cNorm = 'F';
        C2F(zlacpy)(&cNorm, &_iRows2, &_iCols2, (double*)poVar2, &_iRows2, (double*)pXb, &iMax);
        // pXb : in input pXb is of size rows1 x col2
        //       in output pXp is of size col1 x col2
        iInfo = 1;
        C2F(zgelsy1)(&_iRows1, &_iCols1, &_iCols2, poVar1, &_iRows1, pXb, &iMax,
                     pJpvt, &dblRcond, &iRank, pDwork, &iWorkMin, pRwork, &iInfo);

        if (iInfo == 0)
        {
            // In the case where "pXb" has more rows that the output,
            // the output values are the first lines of pXb
            // and not the size of output first elements of pXb.
            double* tmpRealPart = (double*)malloc(iMax * _iColsOut * sizeof(double));
            double* tmpImagPart = (double*)malloc(iMax * _iColsOut * sizeof(double));
            vGetPointerFromDoubleComplex(pXb, iMax * _iColsOut, tmpRealPart, tmpImagPart);

            if ( _iRows1 != _iCols1 && iRank < Min(_iRows1, _iCols1))
            {
                //how to extract that ? Oo
                iReturn = -2;
                *_pdblRcond = (double)iRank;
            }

            C2F(dlacpy)(&cNorm, &_iRowsOut, &_iColsOut, tmpRealPart, &iMax, _pdblRealOut, &_iRowsOut);
            C2F(dlacpy)(&cNorm, &_iRowsOut, &_iColsOut, tmpImagPart, &iMax, _pdblImgOut, &_iRowsOut);

            free(tmpRealPart);
            free(tmpImagPart);
        }
        free(pXb);
    }

    vFreeDoubleComplexFromPointer(poVar1);
    vFreeDoubleComplexFromPointer(poVar2);
    free(pIpiv);
    free(pJpvt);
    free(pRwork);
    free(pDwork);
    return 0;
}
/*Matrix left division*/
int iLeftDivisionOfRealMatrix(
    double *_pdblReal1,     int _iRows1,    int _iCols1,
    double *_pdblReal2,     int _iRows2,    int _iCols2,
    double *_pdblRealOut,   int _iRowsOut,  int _iColsOut,  double *_pdblRcond)
{
    int iReturn = 0;
    int iIndex  = 0;
    char cNorm  = 0;
    int iExit   = 0;

    /*temporary variables*/
    int iWorkMin    = 0;
    int iInfo       = 0;
    int iMax        = 0;
    double dblRcond = 0;

    double dblEps       = 0;
    double RCONDthresh  = 0;
    double dblAnorm     = 0;

    double *pAf     = NULL;
    double *pXb     = NULL;
    double *pDwork  = NULL;

    double* dblTemp = NULL;
    int iOne        = 1;
    int iSize       = 0;

    int *pRank  = NULL;
    int *pIpiv  = NULL;
    int *pJpvt  = NULL;
    int *pIwork = NULL;

    iWorkMin    = Max(4 * _iCols1, Max(Min(_iRows1, _iCols1) + 3 * _iCols1 + 1, 2 * Min(_iRows1, _iCols1) + _iCols2));

    /* Array allocations*/
    pAf         = (double*)malloc(sizeof(double) * _iRows1 * _iCols1);
    pXb         = (double*)malloc(sizeof(double) * Max(_iRows1, _iCols1) * _iCols2);

    pRank       = (int*)malloc(sizeof(int));
    pIpiv       = (int*)malloc(sizeof(int) * _iCols1);
    pJpvt       = (int*)malloc(sizeof(int) * _iCols1);
    pIwork      = (int*)malloc(sizeof(int) * _iCols1);

    cNorm       = '1';
    pDwork      = (double*)malloc(sizeof(double) * iWorkMin);
    dblEps      = nc_eps();
    RCONDthresh = 10 * dblEps;
    dblAnorm    = C2F(dlange)(&cNorm, &_iRows1, &_iCols1, _pdblReal1, &_iRows1, pDwork);

    if (_iRows1 == _iCols1)
    {
        cNorm = 'F';
        C2F(dlacpy)(&cNorm, &_iCols1, &_iCols1, _pdblReal1, &_iCols1, pAf, &_iCols1);
        C2F(dgetrf)(&_iCols1, &_iCols1, pAf, &_iCols1, pIpiv, &iInfo);
        if (iInfo == 0)
        {
            cNorm = '1';
            C2F(dgecon)(&cNorm, &_iCols1, pAf, &_iCols1, &dblAnorm, &dblRcond, pDwork, pIwork, &iInfo);
            if (dblRcond > RCONDthresh)
            {
                // _pdblReal2 will be overwrite by dgetrs
                iSize = _iRows2 * _iCols2;
                dblTemp = (double*)malloc(iSize * sizeof(double));
                C2F(dcopy)(&iSize, _pdblReal2, &iOne, dblTemp, &iOne);

                cNorm = 'N';
                C2F(dgetrs)(&cNorm, &_iCols1, &_iCols2, pAf, &_iCols1, pIpiv, dblTemp, &_iCols1, &iInfo);
                cNorm = 'F';
                C2F(dlacpy)(&cNorm, &_iCols1, &_iCols2, dblTemp, &_iCols1, _pdblRealOut, &_iCols1);
                iExit = 1;

                free(dblTemp);
            }
        }

        if (iExit == 0)
        {
            *_pdblRcond = dblRcond;
            iReturn = -1;
        }
    }

    if (iExit == 0)
    {
        dblRcond = RCONDthresh;
        cNorm = 'F';
        iMax = Max(_iRows1, _iCols1);
        C2F(dlacpy)(&cNorm, &_iRows1, &_iCols2, _pdblReal2, &_iRows1, pXb, &iMax);
        memset(pJpvt, 0x00, sizeof(int) * _iCols1);
        // _pdblReal1 will be overwrite by dgelsy1
        iSize = _iRows1 * _iCols1;
        dblTemp = (double*)malloc(iSize * sizeof(double));
        C2F(dcopy)(&iSize, _pdblReal1, &iOne, dblTemp, &iOne);
        iInfo = 1;
        C2F(dgelsy1)(&_iRows1, &_iCols1, &_iCols2, dblTemp, &_iRows1, pXb, &iMax,
                     pJpvt, &dblRcond, &pRank[0], pDwork, &iWorkMin, &iInfo);
        free(dblTemp);

        if (iInfo == 0)
        {
            if ( _iRows1 != _iCols1 && pRank[0] < Min(_iRows1, _iCols1))
            {
                iReturn = -2;
                *_pdblRcond = pRank[0];
            }

            cNorm = 'F';
            C2F(dlacpy)(&cNorm, &_iCols1, &_iCols2, pXb, &iMax, _pdblRealOut, &_iCols1);
        }
    }

    free(pAf);
    free(pXb);
    free(pRank);
    free(pIpiv);
    free(pJpvt);
    free(pIwork);
    free(pDwork);
    return 0;
}
int iRightDivisionOfComplexMatrix(
    double *_pdblReal1,     double *_pdblImg1,      int _iRows1,    int _iCols1,
    double *_pdblReal2,     double *_pdblImg2,      int _iRows2,    int _iCols2,
    double *_pdblRealOut,   double *_pdblImgOut,    int _iRowsOut,  int _iColsOut,  double *_pdblRcond)
{
    int iReturn     = 0;
    int iIndex1     = 0;
    int iIndex2     = 0;
    char cNorm      = 0;
    int iExit       = 0;

    /*temporary variables*/
    int iWorkMin    = 0;
    int iInfo       = 0;
    int iMax        = 0;
    double dblRcond = 0;

    double dblEps       = 0;
    double RCONDthresh  = 0;
    double dblAnorm     = 0;

    doublecomplex *poVar1   = NULL;
    doublecomplex *poVar2   = NULL;
    doublecomplex *poOut    = NULL;
    doublecomplex *poAf     = NULL;
    doublecomplex *poAt     = NULL;
    doublecomplex *poBt     = NULL;
    doublecomplex *poDwork  = NULL;

    int *pRank    = NULL;
    int *pIpiv    = NULL;
    int *pJpvt    = NULL;
    double *pRwork    = NULL;

    iWorkMin    = Max(2 * _iCols2, Min(_iRows2, _iCols2) + Max(2 * Min(_iRows2, _iCols2), Max(_iRows2 + 1, Min(_iRows2, _iCols2) + _iRows1)));

    /* Array allocations*/
    poVar1      = oGetDoubleComplexFromPointer(_pdblReal1,        _pdblImg1,        _iRows1 * _iCols1);
    poVar2      = oGetDoubleComplexFromPointer(_pdblReal2,        _pdblImg2,        _iRows2 * _iCols2);
    poOut       = oGetDoubleComplexFromPointer(_pdblRealOut,    _pdblImgOut,    _iRowsOut * _iColsOut);

    poAf        = (doublecomplex*)malloc(sizeof(doublecomplex) * _iRows2 * _iCols2);
    poAt        = (doublecomplex*)malloc(sizeof(doublecomplex) * _iRows2 * _iCols2);
    poBt        = (doublecomplex*)malloc(sizeof(doublecomplex) * Max(_iRows2, _iCols2) * _iRows1);
    poDwork     = (doublecomplex*)malloc(sizeof(doublecomplex) * iWorkMin);

    pRank       = (int*)malloc(sizeof(int));
    pIpiv       = (int*)malloc(sizeof(int) * _iCols2);
    pJpvt       = (int*)malloc(sizeof(int) * _iRows2);
    pRwork      = (double*)malloc(sizeof(double) * 2 * _iRows2);

    dblEps      = nc_eps();
    RCONDthresh = 10 * dblEps;
    cNorm       = '1';
    dblAnorm    = C2F(zlange)(&cNorm, &_iRows2, &_iCols2, (double*)poVar2, &_iRows2, (double*)poDwork);

    //tranpose A and B

    vTransposeDoubleComplexMatrix(poVar2, _iRows2, _iCols2, poAt, 1);

    {
        int i, j, ij, ji;
        for (j = 0 ; j < _iRows1 ; j++)
        {
            for (i = 0 ; i < _iCols2 ; i++)
            {
                ij = i + j * Max(_iRows2, _iCols2);
                ji = j + i * _iRows1;
                poBt[ij].r    = poVar1[ji].r;
                //Conjugate
                poBt[ij].i    = -poVar1[ji].i;
            }//for(j = 0 ; j < _iRows1 ; j++)
        }//for(i = 0 ; i < _iCols2 ; i++)
    }//bloc esthetique


    if (_iRows2 == _iCols2)
    {
        cNorm = 'F';
        C2F(zlacpy)(&cNorm, &_iCols2, &_iCols2, (double*)poAt, &_iCols2, (double*)poAf, &_iCols2);
        C2F(zgetrf)(&_iCols2, &_iCols2, poAf, &_iCols2, pIpiv, &iInfo);
        if (iInfo == 0)
        {
            cNorm = '1';
            C2F(zgecon)(&cNorm, &_iCols2, poAf, &_iCols2, &dblAnorm, &dblRcond, poDwork, pRwork, &iInfo);
            if (dblRcond > RCONDthresh)
            {
                cNorm = 'N';
                C2F(zgetrs)(&cNorm, &_iCols2, &_iRows1, poAf, &_iCols2, pIpiv, poBt, &_iCols2, &iInfo);
                vTransposeDoubleComplexMatrix(poBt, _iCols2, _iRows1, poOut, 1);
                vGetPointerFromDoubleComplex(poOut, _iRowsOut * _iColsOut, _pdblRealOut, _pdblImgOut);
                iExit = 1;
            }
        }

        if (iExit == 0)
        {
            //how to extract that ? Oo
            *_pdblRcond = dblRcond;
            iReturn = -1;
        }
    }

    if (iExit == 0)
    {
        dblRcond = RCONDthresh;
        cNorm = 'F';
        iMax = Max(_iRows2, _iCols2);
        memset(pJpvt, 0x00, sizeof(int) * _iRows2);
        iInfo = 1;
        C2F(zgelsy1)(&_iCols2, &_iRows2, &_iRows1, poAt, &_iCols2, poBt, &iMax,
                     pJpvt, &dblRcond, pRank, poDwork, &iWorkMin, pRwork, &iInfo);

        if (iInfo == 0)
        {
            if ( _iRows2 != _iCols2 && pRank[0] < Min(_iRows2, _iCols2))
            {
                //how to extract that ? Oo
                iReturn = -2;
                *_pdblRcond = pRank[0];
            }

            //    TransposeRealMatrix(pBt, _iRows1, _iRows2, _pdblRealOut, Max(_iRows1,_iCols1), _iRows2);

            //Mega caca de la mort qui tue des ours a mains nues
            //mais je ne sais pas comment le rendre "beau" :(
            {
                int i, j, ij, ji;
                for (j = 0 ; j < _iRows2 ; j++)
                {
                    for (i = 0 ; i < _iRows1 ; i++)
                    {
                        ij = i + j * _iRows1;
                        ji = j + i * Max(_iRows2, _iCols2);
                        _pdblRealOut[ij]    = poBt[ji].r;
                        //Conjugate
                        _pdblImgOut[ij]        = -poBt[ji].i;
                    }//for(i = 0 ; i < _iRows2 ; i++)
                }//for(j = 0 ; j < _iRows1 ; j++)
            }//bloc esthetique
        }//if(iInfo == 0)
    }//if(iExit == 0)


    vFreeDoubleComplexFromPointer(poVar1);
    vFreeDoubleComplexFromPointer(poVar2);
    vFreeDoubleComplexFromPointer(poOut);

    free(poAf);
    free(poAt);
    free(poBt);
    free(pRank);
    free(pIpiv);
    free(pJpvt);
    free(pRwork);
    free(poDwork);
    return 0;
}
int iRightDivisionOfRealMatrix(
    double *_pdblReal1,     int _iRows1,    int _iCols1,
    double *_pdblReal2,     int _iRows2,    int _iCols2,
    double *_pdblRealOut,   int _iRowsOut,  int _iColsOut,  double* _pdblRcond)
{
    int iReturn = 0;

    int iIndex  = 0;
    char cNorm  = 0;
    int iExit   = 0;

    /*temporary variables*/
    int iWorkMin    = 0;
    int iInfo       = 0;
    int iMax        = 0;
    double dblRcond = 0;

    double dblEps       = 0;
    double RCONDthresh  = 0;
    double dblAnorm     = 0;

    double *pAf     = NULL;
    double *pAt     = NULL;
    double *pBt     = NULL;
    double *pDwork  = NULL;

    int *pRank    = NULL;
    int *pIpiv    = NULL;
    int *pJpvt    = NULL;
    int *pIwork   = NULL;

    iWorkMin    = Max(4 * _iCols2, Max(Min(_iRows2, _iCols2) + 3 * _iRows2 + 1, 2 * Min(_iRows2, _iCols2) + _iRows1));

    /* Array allocations*/
    pAf         = (double*)malloc(sizeof(double) * _iCols2 * _iRows2);
    pAt         = (double*)malloc(sizeof(double) * _iCols2 * _iRows2);
    pBt         = (double*)malloc(sizeof(double) * Max(_iRows2, _iCols2) * _iRows1);

    pRank       = (int*)malloc(sizeof(int));
    pIpiv       = (int*)malloc(sizeof(int) * _iCols2);
    pJpvt       = (int*)malloc(sizeof(int) * _iRows2);
    pIwork      = (int*)malloc(sizeof(int) * _iCols2);


    //C'est du grand nawak ca, on reserve toute la stack ! Oo

    cNorm       = '1';
    pDwork      = (double*)malloc(sizeof(double) * iWorkMin);
    dblEps      = nc_eps();
    RCONDthresh = 10 * dblEps;
    dblAnorm    = C2F(dlange)(&cNorm, &_iRows2, &_iCols2, _pdblReal2, &_iRows2, pDwork);

    //tranpose A and B

    vTransposeRealMatrix(_pdblReal2, _iRows2, _iCols2, pAt);

    {
        int i, j, ij, ji;
        for (j = 0 ; j < _iRows1 ; j++)
        {
            for (i = 0 ; i < _iCols2 ; i++)
            {
                ij = i + j * Max(_iRows2, _iCols2);
                ji = j + i * _iRows1;
                pBt[ij]    = _pdblReal1[ji];
            }//for(j = 0 ; j < _iRows1 ; j++)
        }//for(i = 0 ; i < _iCols2 ; i++)
    }//bloc esthetique

    if (_iRows2 == _iCols2)
    {
        cNorm = 'F';
        C2F(dlacpy)(&cNorm, &_iCols2, &_iCols2, pAt, &_iCols2, pAf, &_iCols2);
        C2F(dgetrf)(&_iCols2, &_iCols2, pAf, &_iCols2, pIpiv, &iInfo);
        if (iInfo == 0)
        {
            cNorm = '1';
            C2F(dgecon)(&cNorm, &_iCols2, pAf, &_iCols2, &dblAnorm, &dblRcond, pDwork, pIwork, &iInfo);
            if (dblRcond > RCONDthresh)
            {
                cNorm = 'N';
                C2F(dgetrs)(&cNorm, &_iCols2, &_iRows1, pAf, &_iCols2, pIpiv, pBt, &_iCols2, &iInfo);
                vTransposeRealMatrix(pBt, _iCols2, _iRows1, _pdblRealOut);
                iExit = 1;
            }
        }

        if (iExit == 0)
        {
            //how to extract that ? Oo
            *_pdblRcond = dblRcond;
            iReturn = -1;
        }
    }

    if (iExit == 0)
    {
        dblRcond = RCONDthresh;
        cNorm = 'F';
        iMax = Max(_iRows2, _iCols2);
        memset(pJpvt, 0x00, sizeof(int) * _iRows2);
        iInfo = 1;
        C2F(dgelsy1)(&_iCols2, &_iRows2, &_iRows1, pAt, &_iCols2, pBt, &iMax,
                     pJpvt, &dblRcond, &pRank[0], pDwork, &iWorkMin, &iInfo);

        if (iInfo == 0)
        {
            if ( _iRows2 != _iCols2 && pRank[0] < Min(_iRows2, _iCols2))
            {
                //how to extract that ? Oo
                iReturn = -2;
                *_pdblRcond = pRank[0];
            }

            //    TransposeRealMatrix(pBt, _iRows1, _iRows2, _pdblRealOut, Max(_iRows1,_iCols1), _iRows2);

            //Mega caca de la mort qui tue des ours a mains nues
            //mais je ne sais pas comment le rendre "beau" :(
            {
                int i, j, ij, ji;
                for (j = 0 ; j < _iRows2 ; j++)
                {
                    for (i = 0 ; i < _iRows1 ; i++)
                    {
                        ij = i + j * _iRows1;
                        ji = j + i * Max(_iRows2, _iCols2);
                        _pdblRealOut[ij]    = pBt[ji];
                    }//for(i = 0 ; i < _iRows2 ; i++)
                }//for(j = 0 ; j < _iRows1 ; j++)
            }//bloc esthetique
        }//if(iInfo == 0)
    }//if(bExit == 0)

    free(pAf);
    free(pAt);
    free(pBt);
    free(pRank);
    free(pIpiv);
    free(pJpvt);
    free(pIwork);
    free(pDwork);
    return iReturn;
}
Beispiel #9
0
/*--------------------------------------------------------------------------*/
SCICOS_BLOCKS_IMPEXP void matz_bksl(scicos_block *block, int flag)
{
    double *u1r = NULL, *u1i = NULL;
    double *u2r = NULL, *u2i = NULL;
    double *yr = NULL, *yi = NULL;
    int mu = 0, vu = 0, wu = 0;
    int nu1 = 0;
    int nu2 = 0;
    int info = 0;
    int i = 0, j = 0, l = 0, lw = 0, lu = 0, ij = 0, k = 0;
    mat_bksl_struct** work = (mat_bksl_struct**) block->work;
    mat_bksl_struct *ptr = NULL;
    double rcond = 0., ANORM = 0., EPS = 0.;

    vu = GetOutPortRows(block, 1);
    wu = GetOutPortCols(block, 1);
    mu = GetInPortRows(block, 1);
    nu1 = GetInPortCols(block, 1);
    nu2 = GetInPortCols(block, 2);
    u1r = GetRealInPortPtrs(block, 1);
    u1i = GetImagInPortPtrs(block, 1);
    u2r = GetRealInPortPtrs(block, 2);
    u2i = GetImagInPortPtrs(block, 2);
    yr = GetRealOutPortPtrs(block, 1);
    yi = GetImagOutPortPtrs(block, 1);
    l = Max(mu, nu1);
    lw = Max(2 * Min(mu, nu1), nu1 + 1);
    lu = Max(lw, Min(mu, nu1) + nu2);
    lw = Max(2 * nu1, Min(mu, nu1) + lu);

    /*init : initialization*/
    if (flag == 4)
    {
        if ((*work = (mat_bksl_struct*) scicos_malloc(sizeof(mat_bksl_struct))) == NULL)
        {
            set_block_error(-16);
            return;
        }
        ptr = *work;
        if ((ptr->ipiv = (int*) scicos_malloc(sizeof(int) * nu1)) == NULL)
        {
            set_block_error(-16);
            scicos_free(ptr);
            return;
        }
        if ((ptr->rank = (int*) scicos_malloc(sizeof(int))) == NULL)
        {
            set_block_error(-16);
            scicos_free(ptr->ipiv);
            scicos_free(ptr);
            return;
        }
        if ((ptr->jpvt = (int*) scicos_malloc(sizeof(int) * nu1)) == NULL)
        {
            set_block_error(-16);
            scicos_free(ptr->rank);
            scicos_free(ptr->ipiv);
            scicos_free(ptr);
            return;
        }
        if ((ptr->iwork = (double*) scicos_malloc(sizeof(double) * 2 * nu1)) == NULL)
        {
            set_block_error(-16);
            scicos_free(ptr->jpvt);
            scicos_free(ptr->rank);
            scicos_free(ptr->ipiv);
            scicos_free(ptr);
            return;
        }
        if ((ptr->dwork = (double*) scicos_malloc(sizeof(double) * 2 * lw)) == NULL)
        {
            set_block_error(-16);
            scicos_free(ptr->iwork);
            scicos_free(ptr->jpvt);
            scicos_free(ptr->rank);
            scicos_free(ptr->ipiv);
            scicos_free(ptr);
            return;
        }
        if ((ptr->IN1F = (double*) scicos_malloc(sizeof(double) * (2 * mu * nu1))) == NULL)
        {
            set_block_error(-16);
            scicos_free(ptr->dwork);
            scicos_free(ptr->iwork);
            scicos_free(ptr->jpvt);
            scicos_free(ptr->rank);
            scicos_free(ptr->ipiv);
            scicos_free(ptr);
            return;
        }
        if ((ptr->IN1 = (double*) scicos_malloc(sizeof(double) * (2 * mu * nu1))) == NULL)
        {
            set_block_error(-16);
            scicos_free(ptr->IN1F);
            scicos_free(ptr->dwork);
            scicos_free(ptr->iwork);
            scicos_free(ptr->jpvt);
            scicos_free(ptr->rank);
            scicos_free(ptr->ipiv);
            scicos_free(ptr);
            return;
        }
        if ((ptr->IN2X = (double*) scicos_malloc(sizeof(double) * (2 * l * nu2))) == NULL)
        {
            set_block_error(-16);
            scicos_free(ptr->IN1);
            scicos_free(ptr->IN1F);
            scicos_free(ptr->dwork);
            scicos_free(ptr->iwork);
            scicos_free(ptr->jpvt);
            scicos_free(ptr->rank);
            scicos_free(ptr->ipiv);
            scicos_free(ptr);
            return;
        }
        if ((ptr->IN2 = (double*) scicos_malloc(sizeof(double) * (2 * mu * nu2))) == NULL)
        {
            set_block_error(-16);
            scicos_free(ptr->IN2);
            scicos_free(ptr->IN1);
            scicos_free(ptr->IN1F);
            scicos_free(ptr->dwork);
            scicos_free(ptr->iwork);
            scicos_free(ptr->jpvt);
            scicos_free(ptr->rank);
            scicos_free(ptr->ipiv);
            scicos_free(ptr);
            return;
        }
    }

    /* Terminaison */
    else if (flag == 5)
    {
        ptr = *work;
        if ((ptr->IN2) != NULL)
        {
            scicos_free(ptr->ipiv);
            scicos_free(ptr->rank);
            scicos_free(ptr->jpvt);
            scicos_free(ptr->iwork);
            scicos_free(ptr->IN1F);
            scicos_free(ptr->IN1);
            scicos_free(ptr->IN2X);
            scicos_free(ptr->IN2);
            scicos_free(ptr->dwork);
            scicos_free(ptr);
            return;
        }
    }

    else
    {
        ptr = *work;
        for (i = 0; i < (mu * nu1); i++)
        {
            ptr->IN1[2 * i] = u1r[i];
            ptr->IN1[2 * i + 1] = u1i[i];
        }
        for (i = 0; i < (mu * nu2); i++)
        {
            ptr->IN2[2 * i] = u2r[i];
            ptr->IN2[2 * i + 1] = u2i[i];
        }
        EPS = nc_eps();
        ANORM = C2F(zlange)("1", &mu, &nu1, ptr->IN1, &mu, ptr->dwork);
        if (mu == nu1)
        {
            C2F(zlacpy)("F", &mu, &nu1, ptr->IN1, &mu, ptr->IN1F, &mu);
            C2F(zgetrf)(&nu1, &nu1, ptr->IN1F, &nu1, ptr->ipiv, &info);
            rcond = 0;
            if (info == 0)
            {
                C2F(zgecon)("1", &nu1, ptr->IN1F, &nu1, &ANORM, &rcond, ptr->dwork, ptr->iwork, &info);
                if (rcond > pow(EPS, 0.5))
                {
                    C2F(zgetrs)("N", &nu1, &nu2, ptr->IN1F, &nu1, ptr->ipiv, ptr->IN2, &nu1, &info);
                    for (i = 0; i < (mu * nu2); i++)
                    {
                        *(yr + i) = *(ptr->IN2 + 2 * i);
                        *(yi + i) = *(ptr->IN2 + (2 * i) + 1);
                    }
                    return;
                }
            }
        }
        rcond = pow(EPS, 0.5);
        for (i = 0; i < nu1; i++)
        {
            *(ptr->jpvt + i) = 0;
        }
        C2F(zlacpy)("F", &mu, &nu2, ptr->IN2, &mu, ptr->IN2X, &l);
        C2F(zgelsy1)(&mu, &nu1, &nu2, ptr->IN1, &mu, ptr->IN2X, &l, ptr->jpvt, &rcond, ptr->rank, ptr->dwork, &lw, ptr->iwork, &info);
        if (info != 0)
        {
            if (flag != 6)
            {
                set_block_error(-7);
                return;
            }
        }
        k = 0;
        for (j = 0; j < wu; j++)
        {
            for (i = 0; i < vu; i++)
            {
                ij = i + j * l;
                *(yr + k) = *(ptr->IN2X + 2 * ij);
                *(yi + k) = *(ptr->IN2X + (2 * ij) + 1);
                k++;
            }
        }
    }
}