The R Project SVN R

Rev

Rev 1112 | Rev 1858 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

/*
 *  R : A Computer Language for Statistical Data Analysis
 *  Copyright (C) 1995, 1996  Robert Gentleman and Ross Ihaka
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

/*  EXPORTS printMatrix()
 *          printArray()
 *
 *== see ./printutils.c  for general remarks on Printing and the Encode.. utils.
 *== see ./format.c  for the  format_FOO_  functions used below.
 */
#include "Defn.h"
#include "Print.h"

static void printLogicalMatrix(SEXP sx, int offset, int r, int c, SEXP rl, SEXP cl)
{
    SEXP sw;
    int *x, *w;
    int width, rlabw, clabw;
    int i, j, jmin, jmax;

    if (!isNull(rl)) formatString(STRING(rl), r, &rlabw, 0);
    else rlabw = IndexWidth(r + 1) + 3;

    sw = allocVector(INTSXP, c);
    x = INTEGER(sx)+offset;
    w = INTEGER(sw);

    for (j=0; j<c; j++) {
        formatLogical(&x[j * r], r, &w[j]);
        if (!isNull(cl)) clabw = strlen(CHAR(STRING(cl)[j]));
        else clabw = IndexWidth(j+1) + 3;   /* changed j+1 to c and back */
        if (w[j] < clabw) w[j] = clabw;
        w[j] += PRINT_GAP;
    }

    jmin = 0;
    jmax = 0;
    while(jmin < c) {
        width = rlabw;
        do {
            width += w[jmax];
            jmax++;
        }while(jmax < c && width+w[jmax] < PRINT_WIDTH);

        Rprintf("%*s", rlabw, " ");
        for(j=jmin; j<jmax ; j++)
            MatrixColumnLabel(cl, j, w[j]);
        for (i = 0; i < r; i++) {
            MatrixRowLabel(rl, i, rlabw);
            for (j = jmin; j < jmax; j++) {
                Rprintf("%s",
                    EncodeLogical(x[i+j*r], w[j]));
            }
        }
        Rprintf("\n");
        jmin = jmax;
    }
}

static void printIntegerMatrix(SEXP sx, int offset, int r, int c, SEXP rl, SEXP cl)
{
    SEXP sw;
    int *x, *w;
    int width, rlabw, clabw;
    int i, j, jmin, jmax;

    if (!isNull(rl)) formatString(STRING(rl), r, &rlabw, 0);
    else rlabw = IndexWidth(r + 1) + 3;

    sw = allocVector(INTSXP, c);
    x = INTEGER(sx)+offset;
    w = INTEGER(sw);

    for (j=0; j<c; j++) {
        formatInteger(&x[j * r], r, &w[j]);
        if (!isNull(cl)) clabw = strlen(CHAR(STRING(cl)[j]));
        else clabw = IndexWidth(j+1) + 3;       /* replaced j+1 by c and back */
        if (w[j] < clabw) w[j] = clabw;
        w[j] += PRINT_GAP;
    }

    jmin = 0;
    jmax = 0;
    while(jmin < c) {
        width = rlabw;
        do {
            width += w[jmax];
            jmax++;
        }while(jmax < c && width+w[jmax] < PRINT_WIDTH);

        Rprintf("%*s", rlabw, " ");
        for(j=jmin; j<jmax ; j++)
            MatrixColumnLabel(cl, j, w[j]);
        for (i = 0; i < r; i++) {
            MatrixRowLabel(rl, i, rlabw);
            for (j = jmin; j < jmax; j++) {
                Rprintf("%s",
                    EncodeInteger(x[i+j*r], w[j]));
            }
        }
        Rprintf("\n");
        jmin = jmax;
    }
}

static void printRealMatrix(SEXP sx, int offset, int r, int c, SEXP rl, SEXP cl)
{
    SEXP sd, se, sw;
    double *x;
    int *d, *e, *w;
    int width, rlabw, clabw;
    int i, j, jmin, jmax;

    if (!isNull(rl)) formatString(STRING(rl), r, &rlabw, 0);
    else rlabw = IndexWidth(r + 1) + 3;

    PROTECT(sd = allocVector(INTSXP, c));
    PROTECT(se = allocVector(INTSXP, c));
    sw = allocVector(INTSXP, c);
    UNPROTECT(2);
    x = REAL(sx)+offset;
    d = INTEGER(sd);
    e = INTEGER(se);
    w = INTEGER(sw);

    for (j=0; j<c; j++) {
        formatReal(&x[j * r], r, &w[j], &d[j], &e[j]);
        if (!isNull(cl)) clabw = strlen(CHAR(STRING(cl)[j]));
        else clabw = IndexWidth(j+1) + 3;   /* replaced j+1 by c and back */
        if (w[j] < clabw) w[j] = clabw;
        w[j] += PRINT_GAP;
    }

    jmin = 0;
    jmax = 0;
    while(jmin < c) {
        width = rlabw;
        do {
            width += w[jmax];
            jmax++;
        }while(jmax < c && width+w[jmax] < PRINT_WIDTH);

        Rprintf("%*s", rlabw, " ");
        for(j=jmin; j<jmax ; j++)
            MatrixColumnLabel(cl, j, w[j]);
        for (i = 0; i < r; i++) {
            MatrixRowLabel(rl, i, rlabw);
            for (j = jmin; j < jmax; j++) {
                Rprintf("%s",
                    EncodeReal(x[i+j*r], w[j], d[j], e[j]));
            }
        }
        Rprintf("\n");
        jmin = jmax;
    }
}

static void printComplexMatrix(SEXP sx, int offset, int r, int c, SEXP rl, SEXP cl)
{
    SEXP sdr, ser, swr, sdi, sei, swi, sw;
    complex *x;
    int *dr, *er, *wr, *di, *ei, *wi, *w;
    int width, rlabw, clabw;
    int i, j, jmin, jmax;

    if (!isNull(rl)) formatString(STRING(rl), r, &rlabw, 0);
    else rlabw = IndexWidth(r + 1) + 3;

    PROTECT(sdr = allocVector(INTSXP, c));
    PROTECT(ser = allocVector(INTSXP, c));
    PROTECT(swr = allocVector(INTSXP, c));
    PROTECT(sdi = allocVector(INTSXP, c));
    PROTECT(sei = allocVector(INTSXP, c));
    PROTECT(swi = allocVector(INTSXP, c));
    PROTECT(sw = allocVector(INTSXP, c));
    UNPROTECT(7);
    x = COMPLEX(sx)+offset;
    dr = INTEGER(sdr);
    er = INTEGER(ser);
    wr = INTEGER(swr);
    di = INTEGER(sdi);
    ei = INTEGER(sei);
    wi = INTEGER(swi);
    w = INTEGER(sw);

    /* Determine the column widths */

    for (j=0; j<c; j++) {
    formatComplex(&x[j * r], r, &wr[j], &dr[j], &er[j],
              &wi[j], &di[j], &ei[j]);
    if (!isNull(cl)) clabw = strlen(CHAR(STRING(cl)[j]));
    else clabw = IndexWidth(j+1) + 3;
    w[j] = wr[j] + wi[j] + 2;
    if (w[j] < clabw) w[j] = clabw;
    w[j] += PRINT_GAP;
    }

    jmin = 0;
    jmax = 0;
    while(jmin < c) {
    width = rlabw;
    do {
        width += w[jmax];
        jmax++;
    } while(jmax < c && width+w[jmax] < PRINT_WIDTH);

    Rprintf("%*s", rlabw, " ");
    for(j=jmin; j<jmax ; j++)
        MatrixColumnLabel(cl, j, w[j]);
    for (i = 0; i < r; i++) {
        MatrixRowLabel(rl, i, rlabw);
        for (j=jmin; j<jmax; j++) {
        if (ISNA(x[i+j*r].r) || ISNA(x[i+j*r].i))
            Rprintf("%s", EncodeReal(NA_REAL, w[j], 0, 0));
        else
#ifdef OLD
            Rprintf("%*s%s", PRINT_GAP, "",
            EncodeComplex(x[i+j*r], wr[j], dr[j], er[j],
                wi[j], dr[j], er[j]));
#else
            Rprintf("%s", EncodeComplex(x[i+j*r],
                wr[j] + PRINT_GAP, dr[j], er[j],
                wi[j], dr[j], er[j]));
#endif
        }
    }
    Rprintf("\n");
    jmin = jmax;
    }
}

static void printStringMatrix(SEXP sx, int offset, int r, int c, int quote, int right, SEXP rl, SEXP cl)
{
    SEXP sw;
    SEXP *x;
    int *w;
    int width, rlabw, clabw;
    int i, j, jmin, jmax;

    if (!isNull(rl)) formatString(STRING(rl), r, &rlabw, 0);
    else rlabw = IndexWidth(r + 1) + 3;

    sw = allocVector(INTSXP, c);
    x = STRING(sx)+offset;
    w = INTEGER(sw);

    for (j=0; j<c; j++) {
        formatString(&x[j * r], r, &w[j], quote);
        if (!isNull(cl)) clabw = strlen(CHAR(STRING(cl)[j]));
        else clabw = IndexWidth(j+1) + 3;   /* replaced j+1 by c and back */
        if (w[j] < clabw) w[j] = clabw;
        /* w[j] += PRINT_GAP; */
    }

    jmin = 0;
    jmax = 0;
    while(jmin < c) {
        width = rlabw;
        do {
            width += w[jmax]+PRINT_GAP;
            jmax++;
        }while(jmax < c && width+w[jmax]+PRINT_GAP < PRINT_WIDTH);

        Rprintf("%*s", rlabw, " ");
        if (right) {
            for(j=jmin; j<jmax ; j++)
                RightMatrixColumnLabel(cl, j, w[j]);
        }
        else {
            for(j=jmin; j<jmax ; j++)
                LeftMatrixColumnLabel(cl, j, w[j]);
        }
        for (i = 0; i < r; i++) {
            MatrixRowLabel(rl, i, rlabw);
            for (j = jmin; j < jmax; j++) {
                Rprintf("%*s%s", PRINT_GAP, "",
                    EncodeString(CHAR(x[i+j*r]), w[j], quote, right));
            }
        }
        Rprintf("\n");
        jmin = jmax;
    }
}

void printMatrix(SEXP x, int offset, SEXP dim, int quote, int right)
{
    SEXP dimnames, rl, cl;
    int r, c;

    r = INTEGER(dim)[0];
    c = INTEGER(dim)[1];
    rl = R_NilValue;
    cl = R_NilValue;
    dimnames = getAttrib(x, R_DimNamesSymbol);
    if (dimnames != R_NilValue) {
        if (!isNull(CAR(dimnames))) rl = CAR(dimnames);
        if (!isNull(CADR(dimnames))) cl = CADR(dimnames);
    }

    switch (TYPEOF(x)) {
    case LGLSXP:
        printLogicalMatrix(x, offset, r, c, rl, cl);
        break;
    case INTSXP:
        printIntegerMatrix(x, offset, r, c, rl, cl);
        break;
    case REALSXP:
        printRealMatrix(x, offset, r, c, rl, cl);
        break;
    case CPLXSXP:
        printComplexMatrix(x, offset, r, c, rl, cl);
        break;
    case STRSXP:
        if (quote) quote = '"';
        printStringMatrix(x, offset, r, c, quote, right, rl, cl);
        break;
    }
}

static void printArrayGeneral(SEXP x, SEXP dim, int quote)
{
    SEXP dimnames, ii, nn, dn;
    int i, j, k, l, b, nb, ndim;
    int nr, nc;

    ndim = LENGTH(dim);
    if (ndim == 1)
        printVector(x, 1, quote);
    else if (ndim == 2)
        printMatrix(x, 0, dim, quote, 0);
    else {
        dimnames = getAttrib(x, R_DimNamesSymbol);
        PROTECT(ii = allocVector(INTSXP, ndim));
        PROTECT(nn = allocVector(INTSXP, ndim));
        /* use the above to do higher indexing */
        nr = INTEGER(dim)[0];
        nc = INTEGER(dim)[1];
        b = nr * nc;
        nb = 1;
        for (i = 2; i < ndim; i++)
            nb *= INTEGER(dim)[i];
        for (i = 0; i < nb; i++) {
            Rprintf(", ");
            k = 1;
            dn = CDDR(dimnames);
            for(j=2 ; j< ndim; j++) {
                l = (i/k)%INTEGER(dim)[j]+1;
                if(CAR(dn) != R_NilValue)
                    Rprintf(", %s",CHAR(STRING(CAR(dn))[l-1]));
                else
                    Rprintf(", %d", l);
                k = k*INTEGER(dim)[j];
                dn = CDR(dn);
            }
            printf("\n\n");

            switch (TYPEOF(x)) {
            case LGLSXP:
                printLogicalMatrix(x, i*b, nr, nc, CAR(dimnames), CADR(dimnames));
                break;
            case INTSXP:
                printIntegerMatrix(x, i*b, nr, nc, CAR(dimnames), CADR(dimnames));
                break;
            case REALSXP:
                printRealMatrix(x, i*b, nr, nc, CAR(dimnames), CADR(dimnames));
                break;
            case CPLXSXP:
                printComplexMatrix(x, i*b, nr, nc, CAR(dimnames), CADR(dimnames));
                break;
            case STRSXP:
                if (quote) quote = '"';
                printStringMatrix(x, i*b, nr, nc, quote, 0, CAR(dimnames), CADR(dimnames));
                break;
            }
            Rprintf("\n");
        }
        UNPROTECT(2);
    }
}

void printArray(SEXP x, int quote)
{
    printArrayGeneral(x, getAttrib(x, R_DimSymbol), quote);
}

/* not used (0.62;  April 23, 1998 -- MM (-Wall)
static int CountColumns(SEXP x)
{
    int k =0;
    while(x != R_NilValue && isList(x) ) {
        k += ncols(CAR(x));
        x = CDR(x);
    }
    return k;
}
--*/