The R Project SVN R

Rev

Rev 76757 | Rev 80330 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 r 1
/*
466 maechler 2
 *  R : A Computer Language for Statistical Data Analysis
76724 maechler 3
 *  Copyright (C) 1997--2019  The R Core Team
4
 *  Copyright (C) 2003--2016  The R Foundation
2 r 5
 *  Copyright (C) 1995, 1996  Robert Gentleman and Ross Ihaka
6
 *
7
 *  This program is free software; you can redistribute it and/or modify
8
 *  it under the terms of the GNU General Public License as published by
9
 *  the Free Software Foundation; either version 2 of the License, or
10
 *  (at your option) any later version.
11
 *
12
 *  This program is distributed in the hope that it will be useful,
13
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 *  GNU General Public License for more details.
16
 *
17
 *  You should have received a copy of the GNU General Public License
42307 ripley 18
 *  along with this program; if not, a copy is available at
68947 ripley 19
 *  https://www.R-project.org/Licenses/
2 r 20
 *
466 maechler 21
 *
4662 pd 22
 * Object Formatting
1839 ihaka 23
 *
66774 maechler 24
 *  See ./paste.c for do_paste() , do_format() and do_formatinfo() and
25
 *       ./util.c for do_formatC()
1839 ihaka 26
 *  See ./printutils.c for general remarks on Printing and the Encode.. utils.
22817 ripley 27
 *  See ./print.c  for do_printdefault, do_prmatrix, etc.
2309 maechler 28
 *
4619 maechler 29
 * Exports
4929 maechler 30
 *	formatString
76734 luke 31
 *	formatStringS
4619 maechler 32
 *	formatLogical
76734 luke 33
 *	formatLogicalS
4619 maechler 34
 *	formatInteger
76734 luke 35
 *	formatIntegerS
4929 maechler 36
 *	formatReal
76734 luke 37
 *	formatRealS
4619 maechler 38
 *	formatComplex
76734 luke 39
 *	formatComplexS
4929 maechler 40
 *
4619 maechler 41
 * These  formatFOO() functions determine the proper width, digits, etc.
76734 luke 42
 *
43
 * formatFOOS() functions behave identically to formatFOO
44
 * except that they accept a SEXP rather than a data pointer
2 r 45
 */
46
 
5187 hornik 47
#ifdef HAVE_CONFIG_H
7701 hornik 48
#include <config.h>
5187 hornik 49
#endif
50
 
11499 ripley 51
#include <Defn.h>
51838 ripley 52
#include <float.h> /* for DBL_EPSILON */
11499 ripley 53
#include <Rmath.h>
54
#include <Print.h>
76734 luke 55
#include <R_ext/Itermacros.h> /* for ITERATE_BY_REGION */
2 r 56
 
29902 ripley 57
/* this is just for conformity with other types */
61776 ripley 58
attribute_hidden
73727 luke 59
void formatRaw(const Rbyte *x, R_xlen_t n, int *fieldwidth)
29902 ripley 60
{
61
    *fieldwidth = 2;
62
}
1895 ihaka 63
 
61776 ripley 64
attribute_hidden
76734 luke 65
void formatRawS(SEXP x, R_xlen_t n, int *fieldwidth)
66
{
67
    *fieldwidth = 2;
68
}
69
 
70
 
71
attribute_hidden
73727 luke 72
void formatString(const SEXP *x, R_xlen_t n, int *fieldwidth, int quote)
2 r 73
{
18958 ripley 74
    int xmax = 0;
60241 ripley 75
    int l;
2 r 76
 
60241 ripley 77
    for (R_xlen_t i = 0; i < n; i++) {
18958 ripley 78
	if (x[i] == NA_STRING) {
79
	    l = quote ? R_print.na_width : R_print.na_width_noquote;
29510 ripley 80
	} else l = Rstrlen(x[i], quote) + (quote ? 2 : 0);
18958 ripley 81
	if (l > xmax) xmax = l;
571 ihaka 82
    }
83
    *fieldwidth = xmax;
2 r 84
}
85
 
76734 luke 86
/* currently there is no STRING_GET_REGION */
87
 
88
attribute_hidden
89
void formatStringS(SEXP x, R_xlen_t n, int *fieldwidth, int quote)
90
{
91
    int xmax = 0;
92
    int l;
93
 
94
    for (R_xlen_t i = 0; i < n; i++) {
95
	if (STRING_ELT(x, i) == NA_STRING) {
96
	    l = quote ? R_print.na_width : R_print.na_width_noquote;
97
	} else l = Rstrlen(STRING_ELT(x, i), quote) + (quote ? 2 : 0);
98
	if (l > xmax) xmax = l;
99
    }
100
    *fieldwidth = xmax;
101
}
102
 
103
 
104
 
73727 luke 105
void formatLogical(const int *x, R_xlen_t n, int *fieldwidth)
2 r 106
{
571 ihaka 107
    *fieldwidth = 1;
60241 ripley 108
    for(R_xlen_t i = 0 ; i < n; i++) {
20509 ripley 109
	if (x[i] == NA_LOGICAL) {
110
	    if(*fieldwidth < R_print.na_width)
76734 luke 111
		*fieldwidth = R_print.na_width;
20509 ripley 112
	} else if (x[i] != 0 && *fieldwidth < 4) {
571 ihaka 113
	    *fieldwidth = 4;
20509 ripley 114
	} else if (x[i] == 0 && *fieldwidth < 5 ) {
571 ihaka 115
	    *fieldwidth = 5;
116
	    break;
19285 ripley 117
	    /* this is the widest it can be,  so stop */
2 r 118
	}
571 ihaka 119
    }
2 r 120
}
121
 
76734 luke 122
void formatLogicalS(SEXP x, R_xlen_t n, int *fieldwidth) {
123
    *fieldwidth = 1;
124
    int tmpfieldwidth = 1;
76854 luke 125
    ITERATE_BY_REGION_PARTIAL(x, px, idx, nb, int, LOGICAL, 0, n,
126
			      {
127
				  formatLogical(px, nb, &tmpfieldwidth);
128
				  if( tmpfieldwidth > *fieldwidth )
129
				      *fieldwidth = tmpfieldwidth;
130
				  if( *fieldwidth == 5)
131
				      break;  /* break iteration loop */
132
			      });
76734 luke 133
    return;
134
}
135
 
136
 
137
/* needed in 2 places so rolled out into macro
138
   to avoid divergence
139
*/
140
#define FORMATINT_RETLOGIC do {					\
141
	if (naflag) *fieldwidth = R_print.na_width;		\
142
	else *fieldwidth = 1;					\
143
								\
144
	if (xmin < 0) {						\
145
	    l = IndexWidth(-xmin) + 1;	/* +1 for sign */	\
146
	    if (l > *fieldwidth) *fieldwidth = l;		\
147
	}							\
148
	if (xmax > 0) {						\
149
	    l = IndexWidth(xmax);				\
150
	    if (l > *fieldwidth) *fieldwidth = l;		\
151
	}							\
152
    } while(0)
153
 
73727 luke 154
void formatInteger(const int *x, R_xlen_t n, int *fieldwidth)
2 r 155
{
571 ihaka 156
    int xmin = INT_MAX, xmax = INT_MIN, naflag = 0;
60241 ripley 157
    int l;
2 r 158
 
60241 ripley 159
    for (R_xlen_t i = 0; i < n; i++) {
571 ihaka 160
	if (x[i] == NA_INTEGER)
161
	    naflag = 1;
162
	else {
163
	    if (x[i] < xmin) xmin = x[i];
164
	    if (x[i] > xmax) xmax = x[i];
2 r 165
	}
571 ihaka 166
    }
76734 luke 167
    FORMATINT_RETLOGIC;
168
}
2 r 169
 
76734 luke 170
void formatIntegerS(SEXP x, R_xlen_t n, int *fieldwidth)
171
{
2 r 172
 
76734 luke 173
    int xmin = INT_MAX, xmax = INT_MIN, naflag = 0,
174
	sorted;
175
    SEXP tmpmin = NULL, tmpmax = NULL;
176
    /*
177
       min and max should be VERY cheap when sortedness
178
       is known, so better to call them both than loop
179
       through whole vector even once
180
 
181
       Shouldn't need to check for ALTREPness here
182
       because KNOWN_SORTED(sorted) will never be
183
       true for non-ALTREPs or "exploded" ALTREPs
184
    */
185
    sorted = INTEGER_IS_SORTED(x);
76854 luke 186
    /* if we're not formatting/printing the whole thing 
187
       ALTINTEGER_MIN/MAX will give us the wrong thing
188
       anyway */
189
    if(n == XLENGTH(x) && KNOWN_SORTED(sorted)) {
76734 luke 190
	tmpmin = ALTINTEGER_MIN(x, TRUE);
191
	tmpmax = ALTINTEGER_MAX(x, TRUE);
192
	naflag = KNOWN_NA_1ST(sorted) ?
193
	    INTEGER_ELT(x, 0) == NA_INTEGER :
76757 ripley 194
	    INTEGER_ELT(x, XLENGTH(x) - 1) == NA_INTEGER;
571 ihaka 195
    }
76734 luke 196
 
197
    /*
198
       If we don't have min/max methods or they need to punt
199
       for some reason we will get NULL.
200
 
201
       The data are integers, so the only reason we would not
202
       get INTSXP answers is if we got Inf/-Inf because
203
       everything was NA.
204
 
205
       In both of the above cases we will
206
       do things the hard way below
207
    */
208
    if(tmpmin != NULL && tmpmax != NULL &&
209
       TYPEOF(tmpmin) == INTSXP && TYPEOF(tmpmax) == INTSXP) {
210
	int l; /* only needed here so defined locally */
211
	xmin = INTEGER_ELT(tmpmin, 0);
212
	xmax = INTEGER_ELT(tmpmax, 0);
213
	/* naflag set above */
214
 
215
	/* this is identical logic to what formatInteger
216
	   does */
217
	FORMATINT_RETLOGIC;
218
    } else {
219
	/*
220
	   no fastpass so just format using formatInteger
221
	   by region. No need for FORMATINT_RETLOGIC
222
	   here because it happens inside all the
223
	   formatInteger calls.
224
	*/
225
	int tmpfw = 1;
226
	*fieldwidth = 1;
76854 luke 227
	ITERATE_BY_REGION_PARTIAL(x, px, idx, nb, int, INTEGER, 0, n,
76734 luke 228
			  {
229
			      formatInteger(px, nb, &tmpfw);
230
			      if(tmpfw > *fieldwidth)
231
				  *fieldwidth = tmpfw;
232
			  });
571 ihaka 233
    }
2 r 234
}
235
 
236
/*---------------------------------------------------------------------------
237
 * scientific format determination for real numbers.
238
 * This is time-critical code.	 It is worth optimizing.
571 ihaka 239
 *
2 r 240
 *    nsig		digits altogether
241
 *    kpower+1		digits to the left of "."
242
 *    kpower+1+sgn	including sign
4619 maechler 243
 *
4929 maechler 244
 * Using GLOBAL	 R_print.digits	 -- had	 #define MAXDIG R_print.digits
4619 maechler 245
*/
2 r 246
 
74321 ripley 247
/*  Very likely everyone has nearbyintl now (2018), but it took until
248
    2012 for FreeBSD to get it, and longer for Cygwin.
249
*/
60268 ripley 250
#if defined(HAVE_LONG_DOUBLE) && (SIZEOF_LONG_DOUBLE > SIZEOF_DOUBLE)
54672 maechler 251
# ifdef HAVE_NEARBYINTL
252
# define R_nearbyintl nearbyintl
54737 ripley 253
# elif defined(HAVE_RINTL)
254
# define R_nearbyintl rintl
54672 maechler 255
# else
256
# define R_nearbyintl private_nearbyintl
60268 ripley 257
LDOUBLE private_nearbyintl(LDOUBLE x)
2 r 258
{
60268 ripley 259
    LDOUBLE x1;
54737 ripley 260
    x1 = - floorl(-x + 0.5);
54672 maechler 261
    x = floorl(x + 0.5);
54737 ripley 262
    if (x == x1) return(x);
263
    else {
54738 ripley 264
	/* FIXME: we should really test for floorl, also C99.
265
	   But FreeBSD 7.x does have it, but not nearbyintl */
54737 ripley 266
        if (x/2.0 == floorl(x/2.0)) return(x); else return(x1);
54672 maechler 267
    }
268
}
269
# endif
270
#endif
271
 
272
#define NB 1000
273
static void format_via_sprintf(double r, int d, int *kpower, int *nsig)
274
{
275
    static char buff[NB];
276
    int i;
277
    snprintf(buff, NB, "%#.*e", d - 1, r);
59096 ripley 278
    *kpower = (int) strtol(buff + (d + 2), NULL, 10);
54737 ripley 279
    for (i = d; i >= 2; i--)
54672 maechler 280
        if (buff[i] != '0') break;
281
    *nsig = i;
282
}
283
 
284
 
63751 ripley 285
#if defined(HAVE_LONG_DOUBLE) && (SIZEOF_LONG_DOUBLE > SIZEOF_DOUBLE)
56023 ripley 286
static const long double tbl[] =
54672 maechler 287
{
63723 murdoch 288
    /* Powers exactly representable with 64 bit mantissa (except the first, which is only used with digits=0) */
66774 maechler 289
    1e-1,
54672 maechler 290
    1e00, 1e01, 1e02, 1e03, 1e04, 1e05, 1e06, 1e07, 1e08, 1e09,
291
    1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
292
    1e20, 1e21, 1e22, 1e23, 1e24, 1e25, 1e26, 1e27
2 r 293
};
64240 ripley 294
#define KP_MAX 27
63751 ripley 295
#else
296
static const double tbl[] =
297
{
66774 maechler 298
    1e-1,
63751 ripley 299
    1e00, 1e01, 1e02, 1e03, 1e04, 1e05, 1e06, 1e07, 1e08, 1e09,
300
    1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
301
    1e20, 1e21, 1e22
302
};
64240 ripley 303
#define KP_MAX 22
63751 ripley 304
#endif
2 r 305
 
66774 maechler 306
static void
73727 luke 307
scientific(const double *x, int *neg, int *kpower, int *nsig, Rboolean *roundingwidens)
2 r 308
{
25249 maechler 309
    /* for a number x , determine
70613 maechler 310
     *	neg    = 1_{x < 0}  {0/1}
571 ihaka 311
     *	kpower = Exponent of 10;
25249 maechler 312
     *	nsig   = min(R_print.digits, #{significant digits of alpha})
70613 maechler 313
     *  roundingwidens = TRUE iff rounding causes x to increase in width
571 ihaka 314
     *
2309 maechler 315
     * where  |x| = alpha * 10^kpower	and	 1 <= alpha < 10
571 ihaka 316
     */
317
    register double alpha;
318
    register double r;
319
    register int kp;
320
    int j;
2 r 321
 
571 ihaka 322
    if (*x == 0.0) {
323
	*kpower = 0;
324
	*nsig = 1;
70613 maechler 325
	*neg = 0;
326
	*roundingwidens = FALSE;
54737 ripley 327
    } else {
571 ihaka 328
	if(*x < 0.0) {
70613 maechler 329
	    *neg = 1; r = -*x;
571 ihaka 330
	} else {
70613 maechler 331
	    *neg = 0; r = *x;
2 r 332
	}
54672 maechler 333
        if (R_print.digits >= DBL_DIG + 1) {
334
            format_via_sprintf(r, R_print.digits, kpower, nsig);
70613 maechler 335
	    *roundingwidens = FALSE;
54672 maechler 336
            return;
337
        }
59096 ripley 338
        kp = (int) floor(log10(r)) - R_print.digits + 1;/* r = |x|; 10^(kp + digits - 1) <= r */
60268 ripley 339
#if defined(HAVE_LONG_DOUBLE) && (SIZEOF_LONG_DOUBLE > SIZEOF_DOUBLE)
56023 ripley 340
        long double r_prec = r;
54672 maechler 341
        /* use exact scaling factor in long double precision, if possible */
342
        if (abs(kp) <= 27) {
63723 murdoch 343
            if (kp > 0) r_prec /= tbl[kp+1]; else if (kp < 0) r_prec *= tbl[ -kp+1];
54774 ripley 344
        }
345
#ifdef HAVE_POWL
74321 ripley 346
	// powl is C99 but only added to FreeBSD in 2017.
54774 ripley 347
	else
56023 ripley 348
            r_prec /= powl(10.0, (long double) kp);
54774 ripley 349
#else
350
        else if (kp <= R_dec_min_exponent)
64658 ripley 351
            r_prec = (r_prec * 1e+303)/Rexp10((double)(kp+303));
54774 ripley 352
        else
64658 ripley 353
            r_prec /= Rexp10((double) kp);
54774 ripley 354
#endif
63723 murdoch 355
        if (r_prec < tbl[R_print.digits]) {
54672 maechler 356
            r_prec *= 10.0;
357
            kp--;
358
        }
54737 ripley 359
        /* round alpha to integer, 10^(digits-1) <= alpha <= 10^digits
54910 maechler 360
	   accuracy limited by double rounding problem,
54737 ripley 361
	   alpha already rounded to 64 bits */
59096 ripley 362
        alpha = (double) R_nearbyintl(r_prec);
74321 ripley 363
#else /* not using long doubles */
63751 ripley 364
	double r_prec = r;
54672 maechler 365
        /* use exact scaling factor in double precision, if possible */
366
        if (abs(kp) <= 22) {
63751 ripley 367
            if (kp >= 0) r_prec /= tbl[kp+1]; else r_prec *= tbl[ -kp+1];
54672 maechler 368
        }
74321 ripley 369
        /* For IEC60559 1e-308 is not representable except by gradual underflow.
54672 maechler 370
           Shifting by 303 allows for any potential denormalized numbers x,
371
           and makes the reasonable assumption that R_dec_min_exponent+303
372
           is in range. Representation of 1e+303 has low error.
373
         */
54737 ripley 374
        else if (kp <= R_dec_min_exponent)
64658 ripley 375
            r_prec = (r_prec * 1e+303)/Rexp10((double)(kp+303));
54672 maechler 376
        else
64658 ripley 377
            r_prec /= Rexp10((double)kp);
63751 ripley 378
        if (r_prec < tbl[R_print.digits]) {
379
            r_prec *= 10.0;
54672 maechler 380
            kp--;
381
        }
382
        /* round alpha to integer, 10^(digits-1) <= alpha <= 10^digits */
66774 maechler 383
        /* accuracy limited by double rounding problem,
63751 ripley 384
	   alpha already rounded to 53 bits */
74321 ripley 385
        alpha = nearbyint(r_prec);
54672 maechler 386
#endif
387
        *nsig = R_print.digits;
388
        for (j = 1; j <= R_print.digits; j++) {
389
            alpha /= 10.0;
390
            if (alpha == floor(alpha)) {
391
                (*nsig)--;
392
            } else {
393
                break;
394
            }
395
        }
63723 murdoch 396
        if (*nsig == 0 && R_print.digits > 0) {
54672 maechler 397
            *nsig = 1;
398
            kp += 1;
399
        }
400
        *kpower = kp + R_print.digits - 1;
64406 murdoch 401
 
402
	/* Scientific format may do more rounding than fixed format, e.g.
403
	   9996 with 3 digits is 1e+04 in scientific, but 9996 in fixed.
404
	   This happens when the true value r is less than 10^(kpower+1)
405
	   and would not round up to it in fixed format.
406
	   Here rgt is the decimal place that will be cut off by rounding */
66774 maechler 407
 
64406 murdoch 408
	int rgt = R_print.digits - *kpower;
409
	/* bound rgt by 0 and KP_MAX */
410
	rgt = rgt < 0 ? 0 : rgt > KP_MAX ? KP_MAX : rgt;
64681 ripley 411
	double fuzz = 0.5/(double)tbl[1 + rgt];
66774 maechler 412
	// kpower can be bigger than the table.
64406 murdoch 413
	*roundingwidens = *kpower > 0 && *kpower <= KP_MAX && r < tbl[*kpower + 1] - fuzz;
571 ihaka 414
    }
2 r 415
}
416
 
45446 ripley 417
/*
35251 ripley 418
   The return values are
419
     w : the required field width
420
     d : use %w.df in fixed format, %#w.de in scientific format
35253 ripley 421
     e : use scientific format if != 0, value is number of exp digits - 1
35251 ripley 422
 
423
   nsmall specifies the minimum number of decimal digits in fixed format:
45446 ripley 424
   it is 0 except when called from do_format.
35251 ripley 425
*/
426
 
73727 luke 427
void formatReal(const double *x, R_xlen_t n, int *w, int *d, int *e, int nsmall)
2 r 428
{
571 ihaka 429
    int left, right, sleft;
35251 ripley 430
    int mnl, mxl, rgt, mxsl, mxns, wF;
70613 maechler 431
    Rboolean roundingwidens;
432
    int neg_i, neg, kpower, nsig;
60241 ripley 433
    int naflag, nanflag, posinf, neginf;
2 r 434
 
580 ihaka 435
    nanflag = 0;
571 ihaka 436
    naflag = 0;
437
    posinf = 0;
438
    neginf = 0;
439
    neg = 0;
10866 maechler 440
    rgt = mxl = mxsl = mxns = INT_MIN;
571 ihaka 441
    mnl = INT_MAX;
2 r 442
 
60241 ripley 443
    for (R_xlen_t i = 0; i < n; i++) {
5107 maechler 444
	if (!R_FINITE(x[i])) {
580 ihaka 445
	    if(ISNA(x[i])) naflag = 1;
446
	    else if(ISNAN(x[i])) nanflag = 1;
571 ihaka 447
	    else if(x[i] > 0) posinf = 1;
448
	    else neginf = 1;
449
	} else {
70613 maechler 450
	    scientific(&x[i], &neg_i, &kpower, &nsig, &roundingwidens);
466 maechler 451
 
571 ihaka 452
	    left = kpower + 1;
63723 murdoch 453
	    if (roundingwidens) left--;
66774 maechler 454
 
70613 maechler 455
	    sleft = neg_i + ((left <= 0) ? 1 : left); /* >= 1 */
571 ihaka 456
	    right = nsig - left; /* #{digits} right of '.' ( > 0 often)*/
70613 maechler 457
	    if (neg_i) neg = 1;	 /* if any < 0, need extra space for sign */
466 maechler 458
 
571 ihaka 459
	    /* Infinite precision "F" Format : */
10866 maechler 460
	    if (right > rgt) rgt = right;	/* max digits to right of . */
461
	    if (left > mxl)  mxl = left;	/* max digits to  left of . */
462
	    if (left < mnl)  mnl = left;	/* min digits to  left of . */
463
	    if (sleft> mxsl) mxsl = sleft;	/* max left including sign(s)*/
464
	    if (nsig > mxns) mxns = nsig;	/* max sig digits */
2 r 465
	}
571 ihaka 466
    }
25249 maechler 467
    /* F Format: use "F" format WHENEVER we use not more space than 'E'
468
     *		and still satisfy 'R_print.digits' {but as if nsmall==0 !}
1839 ihaka 469
     *
571 ihaka 470
     * E Format has the form   [S]X[.XXX]E+XX[X]
471
     *
472
     * This is indicated by setting *e to non-zero (usually 1)
473
     * If the additional exponent digit is required *e is set to 2
474
     */
2 r 475
 
25249 maechler 476
    /*-- These	'mxsl' & 'rgt'	are used in F Format
10866 maechler 477
     *	 AND in the	____ if(.) "F" else "E" ___   below: */
63723 murdoch 478
    if (R_print.digits == 0) rgt = 0;
45446 ripley 479
    if (mxl < 0) mxsl = 1 + neg;  /* we use %#w.dg, so have leading zero */
25249 maechler 480
 
481
    /* use nsmall only *after* comparing "F" vs "E": */
482
    if (rgt < 0) rgt = 0;
35251 ripley 483
    wF = mxsl + rgt + (rgt != 0);	/* width for F format */
2 r 484
 
10866 maechler 485
    /*-- 'see' how "E" Exponential format would be like : */
48021 maechler 486
    *e = (mxl > 100 || mnl <= -99) ? 2 /* 3 digit exponent */ : 1;
63723 murdoch 487
    if (mxns != INT_MIN) {
48021 maechler 488
	*d = mxns - 1;
489
	*w = neg + (*d > 0) + *d + 4 + *e; /* width for E format */
490
	if (wF <= *w + R_print.scipen) { /* Fixpoint if it needs less space */
491
	    *e = 0;
492
	    if (nsmall > rgt) {
493
		rgt = nsmall;
494
		wF = mxsl + rgt + (rgt != 0);
495
	    }
496
	    *d = rgt;
497
	    *w = wF;
498
	} /* else : "E" Exponential format -- all done above */
499
    }
500
    else { /* when all x[i] are non-finite */
501
	*w = 0;/* to be increased */
502
	*d = 0;
571 ihaka 503
	*e = 0;
48021 maechler 504
    }
35251 ripley 505
    if (naflag && *w < R_print.na_width)
506
	*w = R_print.na_width;
507
    if (nanflag && *w < 3) *w = 3;
508
    if (posinf && *w < 3) *w = 3;
509
    if (neginf && *w < 4) *w = 4;
2 r 510
}
580 ihaka 511
 
76734 luke 512
void formatRealS(SEXP x, R_xlen_t n, int *w, int *d, int *e, int nsmall)
513
{
514
    /*
515
     *  iterate by region and just take the most extreme
516
     *  values across all the regions for final w, d, and e
517
     */
518
    int tmpw, tmpd, tmpe;
519
 
520
    *w = 0;
521
    *d = 0;
522
    *e = 0;
523
 
76854 luke 524
    ITERATE_BY_REGION_PARTIAL(x, px, idx, nb, double, REAL, 0, n,
76734 luke 525
		      {
526
			  formatReal(px, nb, &tmpw, &tmpd, &tmpe, nsmall);
527
			  if(tmpw > *w) *w = tmpw;
528
			  if(!*d && tmpd) *d = tmpd;
529
			  if(tmpe > *e) *e = tmpe;
530
		      });
531
}
532
 
76724 maechler 533
#ifdef formatComplex_USING_signif
74321 ripley 534
/*   From complex.c. */
535
void z_prec_r(Rcomplex *r, const Rcomplex *x, double digits);
76724 maechler 536
#endif
74321 ripley 537
 
35253 ripley 538
/* As from 2.2.0 the number of digits applies to real and imaginary parts
539
   together, not separately */
76724 maechler 540
void formatComplex(const Rcomplex *x, R_xlen_t n,
541
		   int *wr, int *dr, int *er, // (w,d,e) for Re(.)
542
		   int *wi, int *di, int *ei, // (w,d,e) for Im(.)
543
		   int nsmall)
2 r 544
{
70613 maechler 545
/* format.info() for  x[1..n] for both Re & Im */
580 ihaka 546
    int left, right, sleft;
35253 ripley 547
    int rt, mnl, mxl, mxsl, mxns, wF, i_wF;
580 ihaka 548
    int i_rt, i_mnl, i_mxl, i_mxsl, i_mxns;
70613 maechler 549
    Rboolean roundingwidens;
550
    int neg_i, neg, kpower, nsig;
551
    int naflag, rnanflag, rposinf, rneginf, inanflag, iposinf;
35253 ripley 552
    Rcomplex tmp;
553
    Rboolean all_re_zero = TRUE, all_im_zero = TRUE;
2 r 554
 
580 ihaka 555
    naflag = 0;
556
    rnanflag = 0;
557
    rposinf = 0;
558
    rneginf = 0;
559
    inanflag = 0;
560
    iposinf = 0;
561
    neg = 0;
2 r 562
 
2309 maechler 563
    rt	=  mxl =  mxsl =  mxns = INT_MIN;
580 ihaka 564
    i_rt= i_mxl= i_mxsl= i_mxns= INT_MIN;
565
    i_mnl = mnl = INT_MAX;
2 r 566
 
60241 ripley 567
    for (R_xlen_t i = 0; i < n; i++) {
76724 maechler 568
#ifdef formatComplex_USING_signif
35253 ripley 569
	/* Now round */
570
	z_prec_r(&tmp, &(x[i]), R_print.digits);
76724 maechler 571
#else
572
	tmp.r = x[i].r;
573
	tmp.i = x[i].i;
574
#endif
35253 ripley 575
	if(ISNA(tmp.r) || ISNA(tmp.i)) {
580 ihaka 576
	    naflag = 1;
35251 ripley 577
	} else {
571 ihaka 578
	    /* real part */
579
 
35253 ripley 580
	    if(!R_FINITE(tmp.r)) {
581
		if (ISNAN(tmp.r)) rnanflag = 1;
582
		else if (tmp.r > 0) rposinf = 1;
580 ihaka 583
		else rneginf = 1;
35251 ripley 584
	    } else {
39481 ripley 585
		if(x[i].r != 0) all_re_zero = FALSE;
70613 maechler 586
		scientific(&(tmp.r), &neg_i, &kpower, &nsig, &roundingwidens);
2 r 587
 
588
		left = kpower + 1;
63723 murdoch 589
		if (roundingwidens) left--;
70613 maechler 590
		sleft = neg_i + ((left <= 0) ? 1 : left); /* >= 1 */
2 r 591
		right = nsig - left; /* #{digits} right of '.' ( > 0 often)*/
70613 maechler 592
		if (neg_i) neg = 1; /* if any < 0, need extra space for sign */
2 r 593
 
594
		if (right > rt) rt = right;	/* max digits to right of . */
595
		if (left > mxl) mxl = left;	/* max digits to left of . */
596
		if (left < mnl) mnl = left;	/* min digits to left of . */
597
		if (sleft> mxsl) mxsl = sleft;	/* max left including sign(s) */
598
		if (nsig > mxns) mxns = nsig;	/* max sig digits */
599
 
571 ihaka 600
	    }
580 ihaka 601
	    /* imaginary part */
571 ihaka 602
 
580 ihaka 603
	    /* this is always unsigned */
604
	    /* we explicitly put the sign in when we print */
466 maechler 605
 
35253 ripley 606
	    if(!R_FINITE(tmp.i)) {
607
		if (ISNAN(tmp.i)) inanflag = 1;
580 ihaka 608
		else iposinf = 1;
35251 ripley 609
	    } else {
39481 ripley 610
		if(x[i].i != 0) all_im_zero = FALSE;
70613 maechler 611
		scientific(&(tmp.i), &neg_i, &kpower, &nsig, &roundingwidens);
466 maechler 612
 
2 r 613
		left = kpower + 1;
63723 murdoch 614
		if (roundingwidens) left--;
2 r 615
		sleft = ((left <= 0) ? 1 : left);
616
		right = nsig - left;
466 maechler 617
 
2 r 618
		if (right > i_rt) i_rt = right;
619
		if (left > i_mxl) i_mxl = left;
620
		if (left < i_mnl) i_mnl = left;
621
		if (sleft> i_mxsl) i_mxsl = sleft;
622
		if (nsig > i_mxns) i_mxns = nsig;
571 ihaka 623
	    }
1016 maechler 624
	    /* done: ; */
2 r 625
	}
580 ihaka 626
    }
2 r 627
 
580 ihaka 628
    /* see comments in formatReal() for details on this */
2 r 629
 
580 ihaka 630
    /* overall format for real part	*/
2 r 631
 
63723 murdoch 632
    if (R_print.digits == 0) rt = 0;
580 ihaka 633
    if (mxl != INT_MIN) {
2 r 634
	if (mxl < 0) mxsl = 1 + neg;
25249 maechler 635
	if (rt < 0) rt = 0;
35251 ripley 636
	wF = mxsl + rt + (rt != 0);
2 r 637
 
48021 maechler 638
	*er = (mxl > 100 || mnl < -99) ? 2 : 1;
35251 ripley 639
	*dr = mxns - 1;
640
	*wr = neg + (*dr > 0) + *dr + 4 + *er;
641
    } else {
580 ihaka 642
	*er = 0;
35251 ripley 643
	*wr = 0;
644
	*dr = 0;
35253 ripley 645
	wF = 0;
580 ihaka 646
    }
2 r 647
 
580 ihaka 648
    /* overall format for imaginary part */
2 r 649
 
63723 murdoch 650
    if (R_print.digits == 0) i_rt = 0;
580 ihaka 651
    if (i_mxl != INT_MIN) {
2 r 652
	if (i_mxl < 0) i_mxsl = 1;
25249 maechler 653
	if (i_rt < 0) i_rt = 0;
35253 ripley 654
	i_wF = i_mxsl + i_rt + (i_rt != 0);
2 r 655
 
48021 maechler 656
	*ei = (i_mxl > 100 || i_mnl < -99) ? 2 : 1;
35251 ripley 657
	*di = i_mxns - 1;
658
	*wi = (*di > 0) + *di + 4 + *ei;
659
    } else {
580 ihaka 660
	*ei = 0;
35251 ripley 661
	*wi = 0;
662
	*di = 0;
35253 ripley 663
	i_wF = 0;
580 ihaka 664
    }
35253 ripley 665
 
666
    /* Now make the fixed/scientific decision */
667
    if(all_re_zero) {
668
	*er = *dr = 0;
669
	*wr = wF;
670
	if (i_wF <= *wi + R_print.scipen) {
671
	    *ei = 0;
672
	    if (nsmall > i_rt) {i_rt = nsmall; i_wF = i_mxsl + i_rt + (i_rt != 0);}
673
	    *di = i_rt;
674
	    *wi = i_wF;
45446 ripley 675
	}
35253 ripley 676
    } else if(all_im_zero) {
677
	if (wF <= *wr + R_print.scipen) {
678
	    *er = 0;
679
	    if (nsmall > rt) {rt = nsmall; wF = mxsl + rt + (rt != 0);}
680
	    *dr = rt;
681
	    *wr = wF;
45446 ripley 682
	    }
35253 ripley 683
	*ei = *di = 0;
684
	*wi = i_wF;
685
    } else if(wF + i_wF < *wr + *wi + 2*R_print.scipen) {
686
	    *er = 0;
687
	    if (nsmall > rt) {rt = nsmall; wF = mxsl + rt + (rt != 0);}
688
	    *dr = rt;
689
	    *wr = wF;
690
 
691
	    *ei = 0;
692
	    if (nsmall > i_rt) {
45446 ripley 693
		i_rt = nsmall;
35253 ripley 694
		i_wF = i_mxsl + i_rt + (i_rt != 0);
695
	    }
696
	    *di = i_rt;
697
	    *wi = i_wF;
698
    } /* else scientific for both */
35251 ripley 699
    if(*wr < 0) *wr = 0;
700
    if(*wi < 0) *wi = 0;
580 ihaka 701
 
35253 ripley 702
    /* Ensure space for Inf and NaN */
703
    if (rnanflag && *wr < 3) *wr = 3;
48021 maechler 704
    if (rposinf &&  *wr < 3) *wr = 3;
705
    if (rneginf &&  *wr < 4) *wr = 4;
35253 ripley 706
    if (inanflag && *wi < 3) *wi = 3;
707
    if (iposinf  && *wi < 3) *wi = 3;
708
 
580 ihaka 709
    /* finally, ensure that there is space for NA */
710
 
35251 ripley 711
    if (naflag && *wr+*wi+2 < R_print.na_width)
712
	*wr += (R_print.na_width -(*wr + *wi + 2));
2 r 713
}
76734 luke 714
 
715
void formatComplexS(SEXP x, R_xlen_t n, int *wr, int *dr, int *er,
716
		   int *wi, int *di, int *ei, int nsmall)
717
{
718
/* format.info() for  x[1..n] for both Re & Im */
719
    int tmpwr, tmpdr, tmper, tmpwi, tmpdi, tmpei;
720
 
721
    *wr = 0;
722
    *wi = 0;
723
    *dr = 0;
724
    *di = 0;
725
    *er = 0;
726
    *ei = 0;
76854 luke 727
    ITERATE_BY_REGION_PARTIAL(x, px, idx, nb, Rcomplex, COMPLEX, 0, n,
76734 luke 728
		      {
729
			  formatComplex(px, nb, &tmpwr, &tmpdr, &tmper,
730
					&tmpwi, &tmpdi, &tmpei, nsmall);
731
			  if(tmpwr > *wr) *wr = tmpwr;
732
			  if(tmpdr && !*dr) *dr = tmpdr;
733
			  if(tmper > *er) *er = tmper;
734
			  if(tmpwi > *wi) *wi = tmpwi;
735
			  if(tmpdi && !*di) *di = tmpdi;
736
			  if(tmpei > *ei) *ei = tmpei;
737
		      });
738
}