Algorithm-Cluster

 view release on metacpan or  search on metacpan

perl/Cluster.xs  view on Meta::CPAN

    } else {
        return 0;
    }
}



/* -------------------------------------------------
 * Convert a Perl 2D matrix into a 2D matrix of C doubles.
 * If no data are masked, mask can be passed as NULL.
 * NOTE: on errors this function returns a value greater than zero.
 */
static double**
parse_data(pTHX_ SV * matrix_ref, int** mask) {

    AV * matrix_av;
    SV * row_ref;
    AV * row_av;
    SV * cell;

    int type, i, j, nrows, ncols, n;

    double** matrix;

    /* NOTE -- we will just assume that matrix_ref points to an arrayref,
     * and that the first item in the array is itself an arrayref.
     * The calling perl functions must check this before we get this pointer.  
     * (It's easier to implement these checks in Perl rather than C.)
     * The value of perl_rows is now fixed. But the value of
     * rows will be decremented, if we skip any (invalid) Perl rows.
     */
    matrix_av  = (AV *) SvRV(matrix_ref);
    nrows = (int) av_len(matrix_av) + 1;

    if(nrows <= 0) {
        return NULL;
    }
    matrix   = malloc(nrows*sizeof(double*));
    if (!matrix) {
        return NULL;
    }

    row_ref  = *(av_fetch(matrix_av, (I32) 0, 0)); 
    row_av   = (AV *) SvRV(row_ref);
    ncols    = (int) av_len(row_av) + 1;


    /* ------------------------------------------------------------ 
     * Loop once for each row in the Perl matrix, and convert it to
     * C doubles. 
     */
    for (i=0; i < nrows; i++) { 

        row_ref = *(av_fetch(matrix_av, (I32) i, 0)); 

        if(! SvROK(row_ref) ) {

            if(warnings_enabled(aTHX))
                Perl_warn(aTHX_ 
                    "Row %d: Wanted array reference, but "
                    "got a scalar. No row to process?\n", i);
            break;
        }

        row_av = (AV *) SvRV(row_ref);
        type = SvTYPE(row_av); 
    
        /* Handle unexpected cases */
        if(type != SVt_PVAV ) {

             /* Reference doesn't point to an array at all. */
            if(warnings_enabled(aTHX))
                Perl_warn(aTHX_ 
                    "Row %d: Wanted array reference, but got "
                    "a reference to something else (%d)\n",
                    i, type);
            break;

        }

        n = (int) av_len(row_av) + 1;
        if (n != ncols) {
            /* All rows in the matrix should have the same
             * number of columns. */
            if(warnings_enabled(aTHX))
                Perl_warn(aTHX_ 
                    "Row %d: Contains %d columns "
                    "(expected %d)\n", i, n, ncols);
            break;
        }

        matrix[i] = malloc(ncols*sizeof(double));
        if (!matrix[i])
            break;

        /* Loop once for each cell in the row. */
        for (j=0; j < ncols; j++) { 
        
            double num;
            if (!mask || mask[i][j]) {
                cell = *(av_fetch(row_av, (I32) j, 0)); 
                if(extract_double_from_scalar(aTHX_ cell,&num) <= 0) {    
                    if(warnings_enabled(aTHX))
                        Perl_warn(aTHX_ 
                            "Row %d col %d: Value is not "
                                                    "a number.\n", i, j);
                    free(matrix[i]); /* not included below */
                    break;
                }
            }
            else {
                /* Don't read the value if it is masked.
                 * Set it to some arbitrary value. */
                num = 0.0;
            }
            matrix[i][j] = num;

        } /* End for (j=0; j < ncols; j++) */
        if (j < ncols) break;

    } /* End for (i=0; i < nrows; i++) */

perl/Cluster.xs  view on Meta::CPAN

        free(matrix);
        matrix = NULL;
    }

    return matrix;
}


/* -------------------------------------------------
 * Convert a Perl 2D matrix into a 2D matrix of C ints.
 * On errors this function returns a value greater than zero.
 */
static int**
parse_mask(pTHX_ SV * matrix_ref) {

    AV * matrix_av;
    SV * row_ref;
    AV * row_av;
    SV * cell;

    int type, i, j, nrows, ncols, n;

    int** matrix;

    /* NOTE -- we will just assume that matrix_ref points to an arrayref,
     * and that the first item in the array is itself an arrayref.
     * The calling perl functions must check this before we get this pointer.  
     * (It's easier to implement these checks in Perl rather than C.)
     * The value of perl_rows is now fixed. But the value of
     * rows will be decremented, if we skip any (invalid) Perl rows.
     */
    matrix_av = (AV *) SvRV(matrix_ref);
    nrows = (int) av_len(matrix_av) + 1;

    if(nrows <= 0) {
        return NULL;  /* Caller must handle this case!! */
    }
    matrix    = malloc(nrows * sizeof(int *) );
    if (!matrix) {
        return NULL;
    }

    row_ref   = *(av_fetch(matrix_av, (I32) 0, 0)); 
    row_av    = (AV *) SvRV(row_ref);
    ncols     = (int) av_len(row_av) + 1;



    /* ------------------------------------------------------------ 
     * Loop once for each row in the Perl matrix, and convert it to C ints. 
     */
    for (i=0; i < nrows; i++) { 

        row_ref = *(av_fetch(matrix_av, (I32) i, 0)); 

        if(! SvROK(row_ref) ) {

            if(warnings_enabled(aTHX))
                Perl_warn(aTHX_ 
                    "Row %d: Wanted array reference, but "
                    "got a scalar. No row to process?\n", i);
            break;
        }

        row_av = (AV *) SvRV(row_ref);
        type = SvTYPE(row_av); 
    
        /* Handle unexpected cases */
        if(type != SVt_PVAV ) {

             /* Reference doesn't point to an array at all. */
            if(warnings_enabled(aTHX))
                Perl_warn(aTHX_ 
                    "Row %d: Wanted array reference, but got "
                    "a reference to something else (%d)\n",
                    i, type);
            break;

        }

        n = (int) av_len(row_av) + 1;
        if (n != ncols) {
            /* All rows in the matrix should have the same
             * number of columns. */
            if(warnings_enabled(aTHX))
                Perl_warn(aTHX_ 
                    "Row %d: Contains %d columns "
                    "(expected %d)\n", i, n, ncols);
            break;
        }

        matrix[i] = malloc(ncols * sizeof(int) );
        if (!matrix[i]) {
            break;
        }

        /* Loop once for each cell in the row. */
        for (j=0; j < ncols; ++j) { 
            double num;
            cell = *(av_fetch(row_av, (I32) j, 0)); 
            if(extract_double_from_scalar(aTHX_ cell,&num) <= 0) {    
                if(warnings_enabled(aTHX))
                    Perl_warn(aTHX_
                        "Row %d col %d: Value is not "
                        "a number.\n", i, j);
                free(matrix[i]); /* not included below */
                break;
            }
            matrix[i][j] = (int) num;

        } /* End for (j=0; j < ncols; j++) */
        if (j < ncols) break;

    } /* End for (i=0; i < nrows; i++) */

    if (i < nrows) { /* break statement encountered */
        nrows = i;
        for (i = 0; i < nrows; i++) free(matrix[i]);
        free(matrix);
        matrix = NULL;
    }



( run in 1.764 second using v1.01-cache-2.11-cpan-7fcb06a456a )