예제 #1
0
/*--------------------------------------------------------------------------*/
int sci_legendre(char *fname,unsigned long fname_len)
{
    /*
    *   Interface onto the (Slatec) dxleg.f code.
    *   Scilab calling sequence :
    *
    *   p = legendre(n, m, x [, norm_flag] )
    *
    *      x is a vector with mnx elements (it is better to
    *        have a row vector but this is not forced)
    *
    *      n : a non negative int scalar (or a vector of such
    *          int regularly speced with an increment of 1)
    *      m : same constraints than for n
    *
    *      n and m may not be both vectors
    *
    *      norm_flag : optionnal. When it is present and equal to "norm"
    *                  it is a normalised version which is computed
    *    AUTHOR
    *       Bruno Pincon <*****@*****.**>
    */
    int it = 0, lc = 0, mM = 0, nM = 0, lM = 0, m1 = 0, m2 = 0, mN = 0, nN = 0;
    int lN = 0, n1 = 0, n2 = 0, mx = 0, nx = 0, lx = 0, mnx = 0, ms = 0, ns = 0, ls = 0;
    int M_is_scalar = 0, N_is_scalar = 0, normalised = 0, MNp1 = 0, lpqa = 0, lipqa = 0, *ipqa = NULL;
    double *x = NULL, xx = 0., dnu1 = 0., *pqa = NULL;
    int id = 0, ierror = 0, i = 0, j = 0, nudiff = 0;

    CheckLhs(1, 1);
    CheckRhs(3, 4);
    GetRhsVar(1, MATRIX_OF_DOUBLE_DATATYPE, &mN, &nN, &lN);

    if ( ! verify_cstr(stk(lN), mN*nN, &n1, &n2) )
    {
        Scierror(999,_("%s: Wrong type for first input argument.\n"), fname);
        return 0;
    };

    if ( mN == 1 && nN == 1) N_is_scalar = 1;

    GetRhsVar(2,MATRIX_OF_DOUBLE_DATATYPE, &mM, &nM, &lM);
    if ( ! verify_cstr(stk(lM), mM*nM, &m1, &m2) )
    {
        Scierror(999,_("%s: Wrong type for input argument #%d.\n"), fname,2);
        return 0;
    }

    if ( mM == 1 && nM == 1) M_is_scalar = 1;

    if ( ! M_is_scalar  &&  ! N_is_scalar )
    {
        Scierror(999,_("%s: Only one of arg1 and arg2 may be a vector.\n"), fname);
        return 0;
    };

    GetRhsCVar(3,MATRIX_OF_DOUBLE_DATATYPE, &it, &mx, &nx, &lx, &lc);
    if ( it != 0 )
    {
        Scierror(999,_("%s: Wrong type for input argument #%d: Real matrix expected.\n"), fname, 3);
        return 0;
    };

    mnx = mx*nx;
    x = stk(lx);
    for ( i = 0 ; i < mnx ; i++ )
        if ( ! (fabs(x[i]) < 1.0) )
        {
            Scierror(999,_("%s: Wrong value for input argument #%d: Matrix with elements in (%d,%d) expected.\n"), fname,3,-1,1);
            return 0;
        };

    if ( Rhs == 4 )
    {
        GetRhsVar(4,STRING_DATATYPE, &ms, &ns, &ls);
        if ( strcmp(cstk(ls),"norm") == 0)
        {
            normalised = 1;
        }
        else
        {
            normalised = 0;
        }
    }
    else
    {
        normalised = 0;
    }

    MNp1 = Max (n2 - n1, m2 - m1) + 1;

    CreateVar(Rhs+1, MATRIX_OF_DOUBLE_DATATYPE, &MNp1, &mnx, &lpqa);
    pqa = stk(lpqa);
    CreateVar(Rhs+2, MATRIX_OF_INTEGER_DATATYPE, &MNp1, &mnx, &lipqa);
    ipqa = istk(lipqa);

    if ( normalised )
    {
        id = 4;
    }
    else
    {
        id = 3;
    }

    nudiff = n2 - n1;
    dnu1 = (double) n1;

    for ( i = 0 ; i < mnx ; i++ )
    {
        xx = fabs(x[i]); /* dxleg computes only for x in [0,1) */
        F2C(dxlegf) (&dnu1, &nudiff, &m1, &m2, &xx, &id,
                     stk(lpqa+i*MNp1), istk(lipqa+i*MNp1), &ierror);
        if ( ierror != 0 )
        {
            if ( ierror == 207 ) /* @TODO what is 207 ? */
            {
                Scierror(999,_("%s: overflow or underflow of an extended range number\n"), fname);
            }
            else
            {
                Scierror(999,_("%s: error number %d\n"), fname, ierror);
            }
            return 0;
        };
    }

    /*  dxlegf returns the result under a form (pqa,ipqa) (to
    *  compute internaly with an extended exponent range)
    *  When the "exponent" part (ipqa) is 0 then the number is exactly
    *  given by pqa else it leads to an overflow or an underflow.
    */
    for ( i = 0 ; i < mnx*MNp1 ; i++ )
    {
        if ( ipqa[i] < 0 )
        {
            pqa[i] = 0.0;
        }
        if ( ipqa[i] > 0 )
        {
            pqa[i] = pqa[i] * return_an_inf(); /* pqa[i] * Inf  to have the sign */
        }
    }

    /* complete the result by odd/even symmetry for negative x */
    for ( i = 0 ; i < mnx ; i++ )
    {
        if ( x[i] < 0.0 )
        {
            if ( (n1+m1) % 2 == 1 )
            {
                for ( j = 0 ; j < MNp1 ; j+=2 )
                {
                    pqa[i*MNp1 + j] = -pqa[i*MNp1 + j];
                }
            }
            else
            {
                for ( j = 1 ; j < MNp1 ; j+=2 )
                {
                    pqa[i*MNp1 + j] = -pqa[i*MNp1 + j];
                }
            }
        }
    }
    LhsVar(1) = Rhs + 1;
    PutLhsVar();
    return 0;
}
예제 #2
0
/*--------------------------------------------------------------------------*/
int sci_legendre(char *fname, unsigned long fname_len)
{
    /*
    *   Interface onto the (Slatec) dxleg.f code.
    *   Scilab calling sequence :
    *
    *   p = legendre(n, m, x [, norm_flag] )
    *
    *      x is a vector with mnx elements (it is better to
    *        have a row vector but this is not forced)
    *
    *      n : a non negative int scalar (or a vector of such
    *          int regularly speced with an increment of 1)
    *      m : same constraints than for n
    *
    *      n and m may not be both vectors
    *
    *      norm_flag : optionnal. When it is present and equal to "norm"
    *                  it is a normalised version which is computed
    *    AUTHOR
    *       Bruno Pincon <*****@*****.**>
    */
    int it = 0, lc = 0, mM = 0, nM = 0, m1 = 0, m2 = 0, mN = 0, nN = 0;
    int n1 = 0, n2 = 0, mx = 0, nx = 0, mnx = 0, ms = 0, ns = 0;
    int M_is_scalar = 0, N_is_scalar = 0, normalised = 0, MNp1 = 0, *ipqa = NULL;
    double xx = 0., dnu1 = 0.;
    int id = 0, ierror = 0, i = 0, j = 0, nudiff = 0;

    SciErr sciErr;

    int* piAddr1 = NULL;
    int* piAddr2 = NULL;
    int* piAddr3 = NULL;
    int* piAddr4 = NULL;

    int nbInputArg = nbInputArgument(pvApiCtx);

    double* pdblN   = NULL;
    double* pdblM   = NULL;
    double* pdblX   = NULL;
    double* pdblPQA = NULL;
    int* piPQA      = NULL;

    CheckInputArgument(pvApiCtx, 3, 4);
    CheckOutputArgument(pvApiCtx, 1, 1);

    /* get N */
    //get variable address of the input argument
    sciErr = getVarAddressFromPosition(pvApiCtx, 1, &piAddr1);
    if (sciErr.iErr)
    {
        printError(&sciErr, 0);
        return 1;
    }

    sciErr = getMatrixOfDouble(pvApiCtx, piAddr1, &mN, &nN, &pdblN);
    if (sciErr.iErr)
    {
        printError(&sciErr, 0);
        return 1;
    }

    if (verify_cstr(pdblN, mN * nN, &n1, &n2) == 0)
    {
        Scierror(999, _("%s: Wrong type for first input argument.\n"), fname);
        return 1;
    }

    if ( mN == 1 && nN == 1)
    {
        N_is_scalar = 1;
    }

    /* get M */
    //get variable address of the input argument
    sciErr = getVarAddressFromPosition(pvApiCtx, 2, &piAddr2);
    if (sciErr.iErr)
    {
        printError(&sciErr, 0);
        return 1;
    }

    sciErr = getMatrixOfDouble(pvApiCtx, piAddr2, &mM, &nM, &pdblM);
    if (sciErr.iErr)
    {
        printError(&sciErr, 0);
        return 1;
    }

    if (verify_cstr(pdblM, mM * nM, &m1, &m2) == 0)
    {
        Scierror(999, _("%s: Wrong type for input argument #%d.\n"), fname, 2);
        return 1;
    }

    if ( mM == 1 && nM == 1)
    {
        M_is_scalar = 1;
    }

    if ( ! M_is_scalar  &&  ! N_is_scalar )
    {
        Scierror(999, _("%s: Only one of arg1 and arg2 may be a vector.\n"), fname);
        return 1;
    }

    /* get X */
    //get variable address of the input argument
    sciErr = getVarAddressFromPosition(pvApiCtx, 3, &piAddr3);
    if (sciErr.iErr)
    {
        printError(&sciErr, 0);
        return 1;
    }

    if (isVarComplex(pvApiCtx, piAddr3))
    {
        Scierror(999, _("%s: Wrong type for input argument #%d: No complex input argument expected.\n"), fname, 3);
        return 1;
    }

    sciErr = getMatrixOfDouble(pvApiCtx, piAddr3, &mx, &nx, &pdblX);
    if (sciErr.iErr)
    {
        printError(&sciErr, 0);
        return 1;
    }

    mnx = mx * nx;

    for ( i = 0 ; i < mnx ; i++ )
    {
        if ((fabs(pdblX[i]) < 1.0) == 0)
        {
            Scierror(999, _("%s: Wrong value for input argument #%d: Matrix with elements in (%d,%d) expected.\n"), fname, 3, -1, 1);
            return 1;
        }
    }

    if ( nbInputArg == 4 )
    {
        //get variable address
        int iRet = 0;
        char* lschar = NULL;
        sciErr = getVarAddressFromPosition(pvApiCtx, 4, &piAddr4);
        if (sciErr.iErr)
        {
            printError(&sciErr, 0);
            return 1;
        }

        // Retrieve a single string at position 4
        iRet = getAllocatedSingleString(pvApiCtx, piAddr4, &lschar);
        if (iRet)
        {
            freeAllocatedSingleString(lschar);
            return iRet;
        }

        if ( strcmp(lschar, "norm") == 0)
        {
            normalised = 1;
        }
        else
        {
            normalised = 0;
        }
    }
    else
    {
        normalised = 0;
    }

    MNp1 = Max (n2 - n1, m2 - m1) + 1;

    allocMatrixOfDouble(pvApiCtx, nbInputArg + 1, MNp1, mnx, &pdblPQA);
    piPQA = (int*)MALLOC(MNp1 * mnx * sizeof(int));

    if ( normalised )
    {
        id = 4;
    }
    else
    {
        id = 3;
    }

    nudiff = n2 - n1;
    dnu1 = (double) n1;

    for ( i = 0 ; i < mnx ; i++ )
    {
        xx = fabs(pdblX[i]); /* dxleg computes only for x in [0,1) */
        C2F(dxlegf) (&dnu1, &nudiff, &m1, &m2, &xx, &id, pdblPQA + i * MNp1, piPQA + i * MNp1, &ierror);
        if ( ierror != 0 )
        {
            if ( ierror == 207 ) /* @TODO what is 207 ? */
            {
                Scierror(999, _("%s: overflow or underflow of an extended range number\n"), fname);
            }
            else
            {
                Scierror(999, _("%s: error number %d\n"), fname, ierror);
            }
            return 0;
        }
    }

    /*  dxlegf returns the result under a form (pqa,ipqa) (to
    *  compute internaly with an extended exponent range)
    *  When the "exponent" part (ipqa) is 0 then the number is exactly
    *  given by pqa else it leads to an overflow or an underflow.
    */
    for ( i = 0 ; i < mnx * MNp1 ; i++ )
    {
        if ( piPQA[i] < 0 )
        {
            pdblPQA[i] = 0.0;
        }

        if ( piPQA[i] > 0 )
        {
            pdblPQA[i] = pdblPQA[i] * return_an_inf(); /* pqa[i] * Inf  to have the sign */
        }
    }

    FREE(piPQA);

    /* complete the result by odd/even symmetry for negative x */
    for ( i = 0 ; i < mnx ; i++ )
    {
        if ( pdblX[i] < 0.0 )
        {
            if ( (n1 + m1) % 2 == 1 )
            {
                for ( j = 0 ; j < MNp1 ; j += 2 )
                {
                    pdblPQA[i * MNp1 + j] = -pdblPQA[i * MNp1 + j];
                }
            }
            else
            {
                for ( j = 1 ; j < MNp1 ; j += 2 )
                {
                    pdblPQA[i * MNp1 + j] = -pdblPQA[i * MNp1 + j];
                }
            }
        }
    }

    AssignOutputVariable(pvApiCtx, 1) = nbInputArg + 1;
    ReturnArguments(pvApiCtx);
    return 0;
}