Rev 81461 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed
/** R : A Computer Language for Statistical Data Analysis* Copyright (C) 1998-2022 The R Core Team.* Copyright (C) 1995-1998 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, a copy is available at* https://www.R-project.org/Licenses/** EXPORTS printVector()* printNamedVector()* printRealVector()* printRealVectorS()* printIntegerVector()* printIntegerVectorS()* printComplexVector()* printComplexVectorS()** See ./printutils.c for remarks on Printing and the Encoding utils.* See ./format.c for the formatXXXX functions used below.*/#ifdef HAVE_CONFIG_H#include <config.h>#endif#include "Defn.h"#include "Print.h"#include <R_ext/Itermacros.h> /* for ITERATE_BY_REGION */#ifdef Win32#include <trioremap.h> /* for %lld */#endif#define DO_first_lab \if (indx) { \labwidth = IndexWidth(n) + 2; \/* labwidth may well be \one more than desired ..*/ \VectorIndex(1, labwidth); \width = labwidth; \} \else width = 0#define DO_newline \Rprintf("\n"); \if (indx) { \VectorIndex(i + 1, labwidth); \width = labwidth; \} \else \width = 0/* print*Vector (* in {Real, Integer, Complex}) are exported, but nolonger directly called by internal R sources (which now callprint*VectorS for ALTREP support). Macros are used to prevent driftbetween print*Vector and print*VectorS.printIntegerVector(INTEGER(x)) and printIntegerVector(x) mustalways give identical output, unless INTEGER(x) fails, en.g. duringallocation. *//* i must be defined and contain the overall position in the vectorbecause DO_newline uses itENCCALL is the full invocation of Encode*() whichis passed to Rprintf*//* used for logical, integer, numeric and complex vectors */#define NUMVECTOR_TIGHTLOOP(ENCCALL) do { \if (i > 0 && width + w > R_print.width) { \DO_newline; \} \Rprintf("%s", ENCCALL); \width += w; \} while(0)/* used when printing character vectors */#define CHARVECTOR_TIGHTLOOP(ENCCALL) do { \if (i > 0 && width + w + R_print.gap > R_print.width) { \DO_newline; \} \Rprintf("%*s%s", R_print.gap, "", \ENCCALL); \width += w + R_print.gap; \} while (0)/* used for raw vectors. Could be combined with character vectorsabove but NB the different second conditions for the if(width + w vs width + w + R_print.gap) and the different incrementon width.*/#define RAWVECTOR_TIGHTLOOP(ptr, pos) do { \if (i > 0 && width + w > R_print.width) { \DO_newline; \} \Rprintf("%*s%s", R_print.gap, "", EncodeRaw(ptr[pos], "")); \width += w; \} while (0)staticvoid printLogicalVectorS(SEXP x, R_xlen_t n, int indx) {int w, labwidth=0, width;R_xlen_t i;DO_first_lab;formatLogicalS(x, n, &w);w += R_print.gap;ITERATE_BY_REGION_PARTIAL(x, px, idx, nb, int, LOGICAL, 0, n,for(R_xlen_t j = 0; j < nb; j++) {i = idx + j; /* for Do_newline */NUMVECTOR_TIGHTLOOP( EncodeLogical(px[j], w) );});Rprintf("\n");}attribute_hiddenvoid printIntegerVector(const int *x, R_xlen_t n, int indx){int w, labwidth=0, width;DO_first_lab;formatInteger(x, n, &w);w += R_print.gap;for (R_xlen_t i = 0; i < n; i++) {NUMVECTOR_TIGHTLOOP(EncodeInteger(x[i], w));}Rprintf("\n");}attribute_hiddenvoid printIntegerVectorS(SEXP x, R_xlen_t n, int indx){int w, labwidth=0, width;R_xlen_t i;DO_first_lab;formatIntegerS(x, n, &w);w += R_print.gap;ITERATE_BY_REGION_PARTIAL(x, px, idx, nb, int, INTEGER, 0, n,for (R_xlen_t j = 0; j < nb; j++) {i = idx + j; /* for macros */NUMVECTOR_TIGHTLOOP(EncodeInteger(px[j], w));});Rprintf("\n");}// used in uncmin.c// Not easily converted to printRealVectorS callsattribute_hiddenvoid printRealVector(const double *x, R_xlen_t n, int indx){int w, d, e, labwidth=0, width;DO_first_lab;formatReal(x, n, &w, &d, &e, 0);w += R_print.gap;for (R_xlen_t i = 0; i < n; i++) {NUMVECTOR_TIGHTLOOP( EncodeReal0(x[i], w, d, e, OutDec) );}Rprintf("\n");}attribute_hiddenvoid printRealVectorS(SEXP x, R_xlen_t n, int indx){int w, d, e, labwidth=0, width;R_xlen_t i;DO_first_lab;formatRealS(x, n, &w, &d, &e, 0);w += R_print.gap;ITERATE_BY_REGION_PARTIAL(x, px, idx, nb, double, REAL, 0, n,for(R_xlen_t j = 0; j < nb; j++) {i = idx + j; /* for macros */NUMVECTOR_TIGHTLOOP(EncodeReal0(px[j], w, d, e, OutDec));});Rprintf("\n");}#define CMPLX_ISNA(cplx) (ISNA(cplx.r) || ISNA(cplx.i))attribute_hiddenvoid printComplexVector(const Rcomplex *x, R_xlen_t n, int indx){int w, wr, dr, er, wi, di, ei, labwidth=0, width;DO_first_lab;formatComplex(x, n, &wr, &dr, &er, &wi, &di, &ei, 0);w = wr + wi + 2; /* +2 for "+" and "i" */w += R_print.gap;for (R_xlen_t i = 0; i < n; i++) {NUMVECTOR_TIGHTLOOP(CMPLX_ISNA(x[i]) ?EncodeReal0(NA_REAL, w, 0, 0, OutDec) :EncodeComplex(x[i], wr + R_print.gap,dr, er, wi, di, ei, OutDec));}Rprintf("\n");}attribute_hiddenvoid printComplexVectorS(SEXP x, R_xlen_t n, int indx){int w, wr, dr, er, wi, di, ei, labwidth=0, width;R_xlen_t i;DO_first_lab;formatComplexS(x, n, &wr, &dr, &er, &wi, &di, &ei, 0);w = wr + wi + 2; /* +2 for "+" and "i" */w += R_print.gap;ITERATE_BY_REGION_PARTIAL(x, px, idx, nb, Rcomplex, COMPLEX, 0, n,for(R_xlen_t j = 0; j < nb; j++) {i = idx + j; /* for macros */NUMVECTOR_TIGHTLOOP(CMPLX_ISNA(px[j]) ?EncodeReal0(NA_REAL, w, 0, 0, OutDec) :EncodeComplex(px[j], wr + R_print.gap , dr, er, wi, di, ei, OutDec));});Rprintf("\n");}static void printStringVector(const SEXP *x, R_xlen_t n, int quote, int indx){int w, labwidth=0, width;DO_first_lab;formatString(x, n, &w, quote);for (R_xlen_t i = 0; i < n; i++) {if (i > 0 && width + w + R_print.gap > R_print.width) {DO_newline;}Rprintf("%*s%s", R_print.gap, "",EncodeString(x[i], w, quote, R_print.right));width += w + R_print.gap;}Rprintf("\n");}static void printStringVectorS(SEXP x, R_xlen_t n, int quote, int indx){/* because there's no get_region method for ALTSTRINGswe hit the old version if we can to avoid theSTRING_ELT in the tight loop.This will work for all nonALTREP STRSXPs as well as wheneverthe ALTSTRING class is willing to give us a full dataptr fromDataptr_or_null method. */const SEXP *xptr = (const SEXP *) DATAPTR_OR_NULL(x);if(xptr != NULL) {printStringVector(xptr, n, quote, indx);return;}int w, labwidth=0, width;DO_first_lab;formatStringS(x, n, &w, quote);for (R_xlen_t i = 0; i < n; i++) {CHARVECTOR_TIGHTLOOP(EncodeString(STRING_ELT(x, i), w, quote, R_print.right));}Rprintf("\n");}attribute_hiddenvoid printRawVector(const Rbyte *x, R_xlen_t n, int indx){int w, labwidth=0, width;DO_first_lab;formatRaw(x, n, &w);w += R_print.gap;for (R_xlen_t i = 0; i < n; i++) {RAWVECTOR_TIGHTLOOP(x, i);}Rprintf("\n");}staticvoid printRawVectorS(SEXP x, R_xlen_t n, int indx){int w, labwidth=0, width;R_xlen_t i;DO_first_lab;formatRawS(x, n, &w);w += R_print.gap;ITERATE_BY_REGION_PARTIAL(x, px, idx, nb, Rbyte, RAW, 0, n,for(R_xlen_t j = 0; j < nb; j++) {i = idx + j; /* for macros */RAWVECTOR_TIGHTLOOP(px, j);});Rprintf("\n");}void printVector(SEXP x, int indx, int quote){/* print R vector x[]; if(indx) print indices; if(quote) quote strings */R_xlen_t n;if ((n = XLENGTH(x)) != 0) {R_xlen_t n_pr = (n <= R_print.max +1) ? n : R_print.max;/* '...max +1' ==> will omit at least 2 ==> plural in msg below */switch (TYPEOF(x)) {case LGLSXP:printLogicalVectorS(x, n_pr, indx);break;case INTSXP:printIntegerVectorS(x, n_pr, indx);break;case REALSXP:printRealVectorS(x, n_pr, indx);break;case STRSXP:if (quote)printStringVectorS(x, n_pr, '"', indx);elseprintStringVectorS(x, n_pr, 0, indx);break;case CPLXSXP:printComplexVectorS(x, n_pr, indx);break;case RAWSXP:printRawVectorS(x, n_pr, indx);break;}if(n_pr < n)Rprintf(" [ reached getOption(\"max.print\") -- omitted %lld entries ]\n",(long long)n - n_pr);}else#define PRINT_V_0 \switch (TYPEOF(x)) { \case LGLSXP: Rprintf("logical(0)\n"); break; \case INTSXP: Rprintf("integer(0)\n"); break; \case REALSXP: Rprintf("numeric(0)\n"); break; \case CPLXSXP: Rprintf("complex(0)\n"); break; \case STRSXP: Rprintf("character(0)\n"); break; \case RAWSXP: Rprintf("raw(0)\n"); break; \}PRINT_V_0;}#undef DO_first_lab#undef DO_newline/* The following code prints vectors which have every element named.* Primitives for each type of vector are presented first, followed* by the main (dispatching) function.* 1) These primitives are almost identical... ==> use PRINT_N_VECTOR_SEXP macro* 2) S prints a _space_ in the first column for named vectors; we dont.*/#define PRINT_N_VECTOR_SEXP(INI_FORMAT, PRINT_1) \{ \int nperline, w, wn; \R_xlen_t i, j, k, nlines; \INI_FORMAT; \\formatStringS(names, n, &wn, 0); \if (w < wn) w = wn; \nperline = R_print.width / (w + R_print.gap); \if (nperline <= 0) nperline = 1; \nlines = n / nperline; \if (n % nperline) nlines += 1; \\for (i = 0; i < nlines; i++) { \if (i) Rprintf("\n"); \for (j = 0; j < nperline && (k = i * nperline + j) < n; j++) \Rprintf("%s%*s", \EncodeString(STRING_ELT(names, k), w, 0, \Rprt_adj_right), \R_print.gap, ""); \Rprintf("\n"); \for (j = 0; j < nperline && (k = i * nperline + j) < n; j++) \PRINT_1; \} \Rprintf("\n"); \}static void printNamedLogicalVectorS(SEXP x, R_xlen_t n, SEXP names)PRINT_N_VECTOR_SEXP(formatLogicalS(x, n, &w),Rprintf("%s%*s", EncodeLogical(LOGICAL_ELT(x, k), w),R_print.gap,""))static void printNamedIntegerVectorS(SEXP x, R_xlen_t n, SEXP names)PRINT_N_VECTOR_SEXP(formatIntegerS(x, n, &w),Rprintf("%s%*s", EncodeInteger(INTEGER_ELT(x, k), w),R_print.gap,""))#undef INI_F_REAL_S#define INI_F_REAL_S int d, e; formatRealS(x, n, &w, &d, &e, 0)static void printNamedRealVectorS(SEXP x, R_xlen_t n, SEXP names)PRINT_N_VECTOR_SEXP(INI_F_REAL_S,Rprintf("%s%*s",EncodeReal0(REAL_ELT(x, k), w, d, e, OutDec),R_print.gap,""))#undef INI_F_CPLX_S#define INI_F_CPLX_S \int wr, dr, er, wi, di, ei; \formatComplexS(x, n, &wr, &dr, &er, &wi, &di, &ei, 0); \w = wr + wi + 2; \Rcomplex tmp#undef P_IMAG_NA#define P_IMAG_NA(VALUE) \if(ISNAN(VALUE.i)) \Rprintf("+%si", "NaN"); \elsestatic void printNamedComplexVectorS(SEXP x, R_xlen_t n, SEXP names)PRINT_N_VECTOR_SEXP(INI_F_CPLX_S,{ /* PRINT_1 */tmp = COMPLEX_ELT(x, k);if(j) Rprintf("%*s", R_print.gap, "");if (ISNA(tmp.r) || ISNA(tmp.i)) {Rprintf("%s", EncodeReal0(NA_REAL, w, 0, 0, OutDec));}else {Rprintf("%s", EncodeReal0(tmp.r, wr, dr, er, OutDec));P_IMAG_NA(tmp)if (tmp.i >= 0)Rprintf("+%si", EncodeReal0(tmp.i, wi, di, ei, OutDec));elseRprintf("-%si", EncodeReal0(-tmp.i, wi, di, ei, OutDec));}})static void printNamedStringVectorS(SEXP x, R_xlen_t n, int quote, SEXP names)PRINT_N_VECTOR_SEXP(formatStringS(x, n, &w, quote),Rprintf("%s%*s",EncodeString(STRING_ELT(x, k), w, quote,Rprt_adj_right),R_print.gap, ""))static void printNamedRawVectorS(SEXP x, R_xlen_t n, SEXP names)PRINT_N_VECTOR_SEXP(formatRawS(x, n, &w),Rprintf("%*s%s%*s", w - 2, "",EncodeRaw(RAW_ELT(x, k), ""), R_print.gap,""))attribute_hiddenvoid printNamedVector(SEXP x, SEXP names, int quote, const char *title){if (title != NULL)Rprintf("%s\n", title);R_xlen_t n = XLENGTH(x);if (n != 0) {R_xlen_t n_pr = (n <= R_print.max +1) ? n : R_print.max;/* '...max +1' ==> will omit at least 2 ==> plural in msg below */switch (TYPEOF(x)) {case LGLSXP:printNamedLogicalVectorS(x, n_pr, names);break;case INTSXP:printNamedIntegerVectorS(x, n_pr, names);break;case REALSXP:printNamedRealVectorS(x, n_pr, names);break;case CPLXSXP:printNamedComplexVectorS(x, n_pr, names);break;case STRSXP:if(quote) quote = '"';printNamedStringVectorS(x, n_pr, quote, names);break;case RAWSXP:printNamedRawVectorS(x, n_pr, names);break;}if(n_pr < n)Rprintf(" [ reached getOption(\"max.print\") -- omitted %lld entries ]\n",(long long)n - n_pr);}else {Rprintf("named ");PRINT_V_0;}}