The R Project SVN R

Rev

Rev 87894 | 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
87894 ripley 3
 *  Copyright (C) 1997--2025  The R Core Team
76724 maechler 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
 
86655 luke 105
attribute_hidden
73727 luke 106
void formatLogical(const int *x, R_xlen_t n, int *fieldwidth)
2 r 107
{
571 ihaka 108
    *fieldwidth = 1;
60241 ripley 109
    for(R_xlen_t i = 0 ; i < n; i++) {
20509 ripley 110
	if (x[i] == NA_LOGICAL) {
111
	    if(*fieldwidth < R_print.na_width)
76734 luke 112
		*fieldwidth = R_print.na_width;
90097 maechler 113
	} else if (x[i] != 0 && *fieldwidth < 4) { // 'TRUE'
571 ihaka 114
	    *fieldwidth = 4;
90097 maechler 115
	} else if (x[i] == 0 && *fieldwidth < 5 ) {// 'FALSE'
571 ihaka 116
	    *fieldwidth = 5;
117
	    break;
90097 maechler 118
	    // FIXME: Need to ensure that  na_width > 5  is not allowed (*and* document in ?print.default)
19285 ripley 119
	    /* this is the widest it can be,  so stop */
2 r 120
	}
571 ihaka 121
    }
2 r 122
}
123
 
86655 luke 124
attribute_hidden
76734 luke 125
void formatLogicalS(SEXP x, R_xlen_t n, int *fieldwidth) {
126
    *fieldwidth = 1;
127
    int tmpfieldwidth = 1;
76854 luke 128
    ITERATE_BY_REGION_PARTIAL(x, px, idx, nb, int, LOGICAL, 0, n,
129
			      {
130
				  formatLogical(px, nb, &tmpfieldwidth);
131
				  if( tmpfieldwidth > *fieldwidth )
132
				      *fieldwidth = tmpfieldwidth;
133
				  if( *fieldwidth == 5)
134
				      break;  /* break iteration loop */
135
			      });
76734 luke 136
    return;
137
}
138
 
139
 
140
/* needed in 2 places so rolled out into macro
141
   to avoid divergence
142
*/
143
#define FORMATINT_RETLOGIC do {					\
144
	if (naflag) *fieldwidth = R_print.na_width;		\
145
	else *fieldwidth = 1;					\
146
								\
147
	if (xmin < 0) {						\
148
	    l = IndexWidth(-xmin) + 1;	/* +1 for sign */	\
149
	    if (l > *fieldwidth) *fieldwidth = l;		\
150
	}							\
151
	if (xmax > 0) {						\
152
	    l = IndexWidth(xmax);				\
153
	    if (l > *fieldwidth) *fieldwidth = l;		\
154
	}							\
155
    } while(0)
156
 
86655 luke 157
attribute_hidden
73727 luke 158
void formatInteger(const int *x, R_xlen_t n, int *fieldwidth)
2 r 159
{
571 ihaka 160
    int xmin = INT_MAX, xmax = INT_MIN, naflag = 0;
60241 ripley 161
    int l;
2 r 162
 
60241 ripley 163
    for (R_xlen_t i = 0; i < n; i++) {
571 ihaka 164
	if (x[i] == NA_INTEGER)
165
	    naflag = 1;
166
	else {
167
	    if (x[i] < xmin) xmin = x[i];
168
	    if (x[i] > xmax) xmax = x[i];
2 r 169
	}
571 ihaka 170
    }
76734 luke 171
    FORMATINT_RETLOGIC;
172
}
2 r 173
 
86655 luke 174
attribute_hidden
76734 luke 175
void formatIntegerS(SEXP x, R_xlen_t n, int *fieldwidth)
176
{
2 r 177
 
76734 luke 178
    int xmin = INT_MAX, xmax = INT_MIN, naflag = 0,
179
	sorted;
180
    SEXP tmpmin = NULL, tmpmax = NULL;
181
    /*
182
       min and max should be VERY cheap when sortedness
183
       is known, so better to call them both than loop
184
       through whole vector even once
185
 
186
       Shouldn't need to check for ALTREPness here
187
       because KNOWN_SORTED(sorted) will never be
188
       true for non-ALTREPs or "exploded" ALTREPs
189
    */
190
    sorted = INTEGER_IS_SORTED(x);
85252 maechler 191
    /* if we're not formatting/printing the whole thing
76854 luke 192
       ALTINTEGER_MIN/MAX will give us the wrong thing
193
       anyway */
194
    if(n == XLENGTH(x) && KNOWN_SORTED(sorted)) {
80527 luke 195
	tmpmin = PROTECT(ALTINTEGER_MIN(x, TRUE));
196
	tmpmax = PROTECT(ALTINTEGER_MAX(x, TRUE));
76734 luke 197
	naflag = KNOWN_NA_1ST(sorted) ?
198
	    INTEGER_ELT(x, 0) == NA_INTEGER :
76757 ripley 199
	    INTEGER_ELT(x, XLENGTH(x) - 1) == NA_INTEGER;
80527 luke 200
	UNPROTECT(2); /* tmpmin, tmpmax */
571 ihaka 201
    }
76734 luke 202
 
203
    /*
204
       If we don't have min/max methods or they need to punt
205
       for some reason we will get NULL.
206
 
207
       The data are integers, so the only reason we would not
208
       get INTSXP answers is if we got Inf/-Inf because
209
       everything was NA.
210
 
211
       In both of the above cases we will
212
       do things the hard way below
213
    */
214
    if(tmpmin != NULL && tmpmax != NULL &&
215
       TYPEOF(tmpmin) == INTSXP && TYPEOF(tmpmax) == INTSXP) {
216
	int l; /* only needed here so defined locally */
80527 luke 217
	PROTECT(tmpmin);
218
	PROTECT(tmpmax);
76734 luke 219
	xmin = INTEGER_ELT(tmpmin, 0);
220
	xmax = INTEGER_ELT(tmpmax, 0);
80527 luke 221
	UNPROTECT(2); /* tmpmin, tmpmax */
76734 luke 222
	/* naflag set above */
223
 
224
	/* this is identical logic to what formatInteger
225
	   does */
226
	FORMATINT_RETLOGIC;
227
    } else {
228
	/*
229
	   no fastpass so just format using formatInteger
230
	   by region. No need for FORMATINT_RETLOGIC
231
	   here because it happens inside all the
232
	   formatInteger calls.
233
	*/
234
	int tmpfw = 1;
235
	*fieldwidth = 1;
76854 luke 236
	ITERATE_BY_REGION_PARTIAL(x, px, idx, nb, int, INTEGER, 0, n,
76734 luke 237
			  {
238
			      formatInteger(px, nb, &tmpfw);
239
			      if(tmpfw > *fieldwidth)
240
				  *fieldwidth = tmpfw;
241
			  });
571 ihaka 242
    }
2 r 243
}
244
 
245
/*---------------------------------------------------------------------------
246
 * scientific format determination for real numbers.
247
 * This is time-critical code.	 It is worth optimizing.
571 ihaka 248
 *
2 r 249
 *    nsig		digits altogether
250
 *    kpower+1		digits to the left of "."
251
 *    kpower+1+sgn	including sign
4619 maechler 252
 *
4929 maechler 253
 * Using GLOBAL	 R_print.digits	 -- had	 #define MAXDIG R_print.digits
4619 maechler 254
*/
2 r 255
 
74321 ripley 256
/*  Very likely everyone has nearbyintl now (2018), but it took until
257
    2012 for FreeBSD to get it, and longer for Cygwin.
258
*/
60268 ripley 259
#if defined(HAVE_LONG_DOUBLE) && (SIZEOF_LONG_DOUBLE > SIZEOF_DOUBLE)
54672 maechler 260
# ifdef HAVE_NEARBYINTL
261
# define R_nearbyintl nearbyintl
54737 ripley 262
# elif defined(HAVE_RINTL)
263
# define R_nearbyintl rintl
54672 maechler 264
# else
265
# define R_nearbyintl private_nearbyintl
60268 ripley 266
LDOUBLE private_nearbyintl(LDOUBLE x)
2 r 267
{
60268 ripley 268
    LDOUBLE x1;
54737 ripley 269
    x1 = - floorl(-x + 0.5);
54672 maechler 270
    x = floorl(x + 0.5);
54737 ripley 271
    if (x == x1) return(x);
272
    else {
54738 ripley 273
	/* FIXME: we should really test for floorl, also C99.
274
	   But FreeBSD 7.x does have it, but not nearbyintl */
54737 ripley 275
        if (x/2.0 == floorl(x/2.0)) return(x); else return(x1);
54672 maechler 276
    }
277
}
278
# endif
279
#endif
280
 
281
#define NB 1000
282
static void format_via_sprintf(double r, int d, int *kpower, int *nsig)
283
{
284
    static char buff[NB];
285
    int i;
286
    snprintf(buff, NB, "%#.*e", d - 1, r);
59096 ripley 287
    *kpower = (int) strtol(buff + (d + 2), NULL, 10);
54737 ripley 288
    for (i = d; i >= 2; i--)
54672 maechler 289
        if (buff[i] != '0') break;
290
    *nsig = i;
291
}
292
 
293
 
63751 ripley 294
#if defined(HAVE_LONG_DOUBLE) && (SIZEOF_LONG_DOUBLE > SIZEOF_DOUBLE)
56023 ripley 295
static const long double tbl[] =
54672 maechler 296
{
80330 maechler 297
    /* Powers exactly representable with 64 bit mantissa */
54672 maechler 298
    1e00, 1e01, 1e02, 1e03, 1e04, 1e05, 1e06, 1e07, 1e08, 1e09,
299
    1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
300
    1e20, 1e21, 1e22, 1e23, 1e24, 1e25, 1e26, 1e27
2 r 301
};
64240 ripley 302
#define KP_MAX 27
63751 ripley 303
#else
304
static const double tbl[] =
305
{
306
    1e00, 1e01, 1e02, 1e03, 1e04, 1e05, 1e06, 1e07, 1e08, 1e09,
307
    1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
308
    1e20, 1e21, 1e22
309
};
64240 ripley 310
#define KP_MAX 22
63751 ripley 311
#endif
2 r 312
 
66774 maechler 313
static void
87894 ripley 314
scientific(const double *x, int *neg, int *kpower, int *nsig, bool *roundingwidens)
2 r 315
{
25249 maechler 316
    /* for a number x , determine
70613 maechler 317
     *	neg    = 1_{x < 0}  {0/1}
571 ihaka 318
     *	kpower = Exponent of 10;
25249 maechler 319
     *	nsig   = min(R_print.digits, #{significant digits of alpha})
87894 ripley 320
     *  roundingwidens = true iff rounding causes x to increase in width
571 ihaka 321
     *
2309 maechler 322
     * where  |x| = alpha * 10^kpower	and	 1 <= alpha < 10
571 ihaka 323
     */
324
    register double alpha;
325
    register double r;
326
    register int kp;
327
    int j;
2 r 328
 
571 ihaka 329
    if (*x == 0.0) {
330
	*kpower = 0;
331
	*nsig = 1;
70613 maechler 332
	*neg = 0;
87894 ripley 333
	*roundingwidens = false;
54737 ripley 334
    } else {
571 ihaka 335
	if(*x < 0.0) {
70613 maechler 336
	    *neg = 1; r = -*x;
571 ihaka 337
	} else {
70613 maechler 338
	    *neg = 0; r = *x;
2 r 339
	}
54672 maechler 340
        if (R_print.digits >= DBL_DIG + 1) {
341
            format_via_sprintf(r, R_print.digits, kpower, nsig);
87894 ripley 342
	    *roundingwidens = false;
54672 maechler 343
            return;
344
        }
59096 ripley 345
        kp = (int) floor(log10(r)) - R_print.digits + 1;/* r = |x|; 10^(kp + digits - 1) <= r */
60268 ripley 346
#if defined(HAVE_LONG_DOUBLE) && (SIZEOF_LONG_DOUBLE > SIZEOF_DOUBLE)
56023 ripley 347
        long double r_prec = r;
54672 maechler 348
        /* use exact scaling factor in long double precision, if possible */
79397 maechler 349
        if (abs(kp) <= KP_MAX) {
80330 maechler 350
            if (kp > 0) r_prec /= tbl[kp]; else if (kp < 0) r_prec *= tbl[ -kp];
54774 ripley 351
        }
90097 maechler 352
#  ifdef HAVE_POWL
74321 ripley 353
	// powl is C99 but only added to FreeBSD in 2017.
54774 ripley 354
	else
56023 ripley 355
            r_prec /= powl(10.0, (long double) kp);
90097 maechler 356
#  else
54774 ripley 357
        else if (kp <= R_dec_min_exponent)
64658 ripley 358
            r_prec = (r_prec * 1e+303)/Rexp10((double)(kp+303));
54774 ripley 359
        else
64658 ripley 360
            r_prec /= Rexp10((double) kp);
90097 maechler 361
#  endif
80330 maechler 362
        if (r_prec < tbl[R_print.digits - 1]) {
54672 maechler 363
            r_prec *= 10.0;
364
            kp--;
365
        }
54737 ripley 366
        /* round alpha to integer, 10^(digits-1) <= alpha <= 10^digits
54910 maechler 367
	   accuracy limited by double rounding problem,
54737 ripley 368
	   alpha already rounded to 64 bits */
59096 ripley 369
        alpha = (double) R_nearbyintl(r_prec);
74321 ripley 370
#else /* not using long doubles */
63751 ripley 371
	double r_prec = r;
54672 maechler 372
        /* use exact scaling factor in double precision, if possible */
79397 maechler 373
        if (abs(kp) <= KP_MAX) {
80330 maechler 374
            if (kp >= 0) r_prec /= tbl[kp]; else r_prec *= tbl[ -kp];
54672 maechler 375
        }
74321 ripley 376
        /* For IEC60559 1e-308 is not representable except by gradual underflow.
54672 maechler 377
           Shifting by 303 allows for any potential denormalized numbers x,
378
           and makes the reasonable assumption that R_dec_min_exponent+303
379
           is in range. Representation of 1e+303 has low error.
380
         */
54737 ripley 381
        else if (kp <= R_dec_min_exponent)
64658 ripley 382
            r_prec = (r_prec * 1e+303)/Rexp10((double)(kp+303));
54672 maechler 383
        else
64658 ripley 384
            r_prec /= Rexp10((double)kp);
80330 maechler 385
        if (r_prec < tbl[R_print.digits - 1]) {
63751 ripley 386
            r_prec *= 10.0;
54672 maechler 387
            kp--;
388
        }
389
        /* round alpha to integer, 10^(digits-1) <= alpha <= 10^digits */
66774 maechler 390
        /* accuracy limited by double rounding problem,
63751 ripley 391
	   alpha already rounded to 53 bits */
74321 ripley 392
        alpha = nearbyint(r_prec);
54672 maechler 393
#endif
394
        *nsig = R_print.digits;
395
        for (j = 1; j <= R_print.digits; j++) {
396
            alpha /= 10.0;
397
            if (alpha == floor(alpha)) {
398
                (*nsig)--;
399
            } else {
400
                break;
401
            }
402
        }
63723 murdoch 403
        if (*nsig == 0 && R_print.digits > 0) {
54672 maechler 404
            *nsig = 1;
405
            kp += 1;
406
        }
407
        *kpower = kp + R_print.digits - 1;
64406 murdoch 408
 
409
	/* Scientific format may do more rounding than fixed format, e.g.
410
	   9996 with 3 digits is 1e+04 in scientific, but 9996 in fixed.
411
	   This happens when the true value r is less than 10^(kpower+1)
412
	   and would not round up to it in fixed format.
413
	   Here rgt is the decimal place that will be cut off by rounding */
66774 maechler 414
 
64406 murdoch 415
	int rgt = R_print.digits - *kpower;
416
	/* bound rgt by 0 and KP_MAX */
417
	rgt = rgt < 0 ? 0 : rgt > KP_MAX ? KP_MAX : rgt;
80330 maechler 418
	double fuzz = 0.5/(double)tbl[rgt];
66774 maechler 419
	// kpower can be bigger than the table.
80330 maechler 420
	*roundingwidens = *kpower > 0 && *kpower <= KP_MAX && r < tbl[*kpower] - fuzz;
571 ihaka 421
    }
2 r 422
}
423
 
45446 ripley 424
/*
35251 ripley 425
   The return values are
426
     w : the required field width
427
     d : use %w.df in fixed format, %#w.de in scientific format
35253 ripley 428
     e : use scientific format if != 0, value is number of exp digits - 1
35251 ripley 429
 
430
   nsmall specifies the minimum number of decimal digits in fixed format:
45446 ripley 431
   it is 0 except when called from do_format.
35251 ripley 432
*/
433
 
86655 luke 434
/* not hidden: used in graphics/src/plot.c */
73727 luke 435
void formatReal(const double *x, R_xlen_t n, int *w, int *d, int *e, int nsmall)
2 r 436
{
87894 ripley 437
    bool
438
	naflag = false, nanflag = false,
439
	posinf = false, neginf = false;
79397 maechler 440
    int neg = 0;
441
    int mnl = INT_MAX,
442
	mxl, rgt, mxsl, mxns;
443
    mxl = rgt = mxsl = mxns = INT_MIN;
2 r 444
 
60241 ripley 445
    for (R_xlen_t i = 0; i < n; i++) {
5107 maechler 446
	if (!R_FINITE(x[i])) {
87894 ripley 447
	    if(ISNA(x[i])) naflag = true;
448
	    else if(ISNAN(x[i])) nanflag = true;
449
	    else if(x[i] > 0) posinf = true;
450
	    else neginf = true;
571 ihaka 451
	} else {
79397 maechler 452
	    int neg_i, kpower, nsig;
87894 ripley 453
	    bool roundingwidens;
70613 maechler 454
	    scientific(&x[i], &neg_i, &kpower, &nsig, &roundingwidens);
466 maechler 455
 
79397 maechler 456
	    int left = kpower + 1;
63723 murdoch 457
	    if (roundingwidens) left--;
66774 maechler 458
 
79397 maechler 459
	    int sleft = neg_i + ((left <= 0) ? 1 : left); /* >= 1 */
460
	    int right = nsig - left; /* #{digits} right of '.' ( > 0 often)*/
70613 maechler 461
	    if (neg_i) neg = 1;	 /* if any < 0, need extra space for sign */
466 maechler 462
 
571 ihaka 463
	    /* Infinite precision "F" Format : */
90097 maechler 464
	    if (right > rgt)  rgt = right;	/* max digits to right of . */
465
	    if (left  > mxl)  mxl = left;	/* max digits to  left of . */
466
	    if (left  < mnl)  mnl = left;	/* min digits to  left of . */
467
	    if (sleft > mxsl) mxsl = sleft;	/* max left including sign(s)*/
468
	    if (nsig  > mxns) mxns = nsig;	/* max sig digits */
2 r 469
	}
571 ihaka 470
    }
90097 maechler 471
     /* F Format: use "F" format WHENEVER we use not more space than  'E' + scipen
25249 maechler 472
     *		and still satisfy 'R_print.digits' {but as if nsmall==0 !}
1839 ihaka 473
     *
571 ihaka 474
     * E Format has the form   [S]X[.XXX]E+XX[X]
475
     *
476
     * This is indicated by setting *e to non-zero (usually 1)
477
     * If the additional exponent digit is required *e is set to 2
478
     */
2 r 479
 
25249 maechler 480
    /*-- These	'mxsl' & 'rgt'	are used in F Format
10866 maechler 481
     *	 AND in the	____ if(.) "F" else "E" ___   below: */
63723 murdoch 482
    if (R_print.digits == 0) rgt = 0;
45446 ripley 483
    if (mxl < 0) mxsl = 1 + neg;  /* we use %#w.dg, so have leading zero */
25249 maechler 484
 
485
    /* use nsmall only *after* comparing "F" vs "E": */
90097 maechler 486
    if (rgt < 0) rgt = 0;// rgt != 0  <==> needs decimal point (OutDec) "."
79397 maechler 487
    int wF = mxsl + rgt + (rgt != 0);	/* width for F format */
2 r 488
 
10866 maechler 489
    /*-- 'see' how "E" Exponential format would be like : */
48021 maechler 490
    *e = (mxl > 100 || mnl <= -99) ? 2 /* 3 digit exponent */ : 1;
63723 murdoch 491
    if (mxns != INT_MIN) {
48021 maechler 492
	*d = mxns - 1;
493
	*w = neg + (*d > 0) + *d + 4 + *e; /* width for E format */
494
	if (wF <= *w + R_print.scipen) { /* Fixpoint if it needs less space */
495
	    *e = 0;
496
	    if (nsmall > rgt) {
497
		rgt = nsmall;
498
		wF = mxsl + rgt + (rgt != 0);
499
	    }
500
	    *d = rgt;
501
	    *w = wF;
502
	} /* else : "E" Exponential format -- all done above */
503
    }
504
    else { /* when all x[i] are non-finite */
505
	*w = 0;/* to be increased */
506
	*d = 0;
571 ihaka 507
	*e = 0;
48021 maechler 508
    }
35251 ripley 509
    if (naflag && *w < R_print.na_width)
510
	*w = R_print.na_width;
511
    if (nanflag && *w < 3) *w = 3;
90097 maechler 512
    if (posinf  && *w < 3) *w = 3;
513
    if (neginf  && *w < 4) *w = 4;
2 r 514
}
580 ihaka 515
 
86655 luke 516
attribute_hidden
76734 luke 517
void formatRealS(SEXP x, R_xlen_t n, int *w, int *d, int *e, int nsmall)
518
{
519
    /*
520
     *  iterate by region and just take the most extreme
521
     *  values across all the regions for final w, d, and e
522
     */
523
    int tmpw, tmpd, tmpe;
524
 
525
    *w = 0;
526
    *d = 0;
527
    *e = 0;
528
 
76854 luke 529
    ITERATE_BY_REGION_PARTIAL(x, px, idx, nb, double, REAL, 0, n,
76734 luke 530
		      {
531
			  formatReal(px, nb, &tmpw, &tmpd, &tmpe, nsmall);
90097 maechler 532
			  if( tmpw > *w ) *w = tmpw;
76734 luke 533
			  if(!*d && tmpd) *d = tmpd;
90097 maechler 534
			  if( tmpe > *e ) *e = tmpe;
76734 luke 535
		      });
536
}
537
 
85252 maechler 538
#ifdef formatComplex_tricky
76724 maechler 539
#ifdef formatComplex_USING_signif
74321 ripley 540
/*   From complex.c. */
541
void z_prec_r(Rcomplex *r, const Rcomplex *x, double digits);
76724 maechler 542
#endif
85252 maechler 543
#endif
74321 ripley 544
 
85252 maechler 545
/* From R 2.2.0 to 4.3.z, the number of digits applied to real and imaginary parts
90097 maechler 546
   together, not separately.  Since R 4.4.0, Re(.) and Im(.) are treated separately. */
76724 maechler 547
void formatComplex(const Rcomplex *x, R_xlen_t n,
548
		   int *wr, int *dr, int *er, // (w,d,e) for Re(.)
549
		   int *wi, int *di, int *ei, // (w,d,e) for Im(.)
550
		   int nsmall)
2 r 551
{
70613 maechler 552
/* format.info() for  x[1..n] for both Re & Im */
85252 maechler 553
#ifdef formatComplex_tricky // R 4.3.z and earlier
87894 ripley 554
    bool all_re_zero = true, all_im_zero = true,
555
	naflag = false,
556
	rnan = false, rposinf = false, rneginf = false,
557
	inan = false, iposinf = false;
79397 maechler 558
    int neg = 0;
35253 ripley 559
    int rt, mnl, mxl, mxsl, mxns, wF, i_wF;
580 ihaka 560
    int i_rt, i_mnl, i_mxl, i_mxsl, i_mxns;
2309 maechler 561
    rt	=  mxl =  mxsl =  mxns = INT_MIN;
580 ihaka 562
    i_rt= i_mxl= i_mxsl= i_mxns= INT_MIN;
563
    i_mnl = mnl = INT_MAX;
2 r 564
 
60241 ripley 565
    for (R_xlen_t i = 0; i < n; i++) {
79397 maechler 566
	Rcomplex tmp;
76724 maechler 567
#ifdef formatComplex_USING_signif
35253 ripley 568
	/* Now round */
569
	z_prec_r(&tmp, &(x[i]), R_print.digits);
76724 maechler 570
#else
85252 maechler 571
 	tmp.r = x[i].r;
572
 	tmp.i = x[i].i;
76724 maechler 573
#endif
35253 ripley 574
	if(ISNA(tmp.r) || ISNA(tmp.i)) {
87894 ripley 575
	    naflag = true;
35251 ripley 576
	} else {
87894 ripley 577
	    bool roundingwidens;
79397 maechler 578
	    int left, right, sleft,
579
		neg_i, kpower, nsig;
580
 
571 ihaka 581
	    /* real part */
582
 
35253 ripley 583
	    if(!R_FINITE(tmp.r)) {
87894 ripley 584
		if (ISNAN(tmp.r)) rnan = true;
585
		else if (tmp.r > 0) rposinf = true;
586
		else rneginf = true;
35251 ripley 587
	    } else {
87894 ripley 588
		if(x[i].r != 0) all_re_zero = false;
70613 maechler 589
		scientific(&(tmp.r), &neg_i, &kpower, &nsig, &roundingwidens);
2 r 590
 
591
		left = kpower + 1;
63723 murdoch 592
		if (roundingwidens) left--;
70613 maechler 593
		sleft = neg_i + ((left <= 0) ? 1 : left); /* >= 1 */
2 r 594
		right = nsig - left; /* #{digits} right of '.' ( > 0 often)*/
70613 maechler 595
		if (neg_i) neg = 1; /* if any < 0, need extra space for sign */
2 r 596
 
597
		if (right > rt) rt = right;	/* max digits to right of . */
598
		if (left > mxl) mxl = left;	/* max digits to left of . */
599
		if (left < mnl) mnl = left;	/* min digits to left of . */
600
		if (sleft> mxsl) mxsl = sleft;	/* max left including sign(s) */
601
		if (nsig > mxns) mxns = nsig;	/* max sig digits */
602
 
571 ihaka 603
	    }
580 ihaka 604
	    /* imaginary part */
571 ihaka 605
 
580 ihaka 606
	    /* this is always unsigned */
607
	    /* we explicitly put the sign in when we print */
466 maechler 608
 
35253 ripley 609
	    if(!R_FINITE(tmp.i)) {
87894 ripley 610
		if (ISNAN(tmp.i)) inan = true;
611
		else iposinf = true;
35251 ripley 612
	    } else {
87894 ripley 613
		if(x[i].i != 0) all_im_zero = false;
70613 maechler 614
		scientific(&(tmp.i), &neg_i, &kpower, &nsig, &roundingwidens);
466 maechler 615
 
2 r 616
		left = kpower + 1;
63723 murdoch 617
		if (roundingwidens) left--;
2 r 618
		sleft = ((left <= 0) ? 1 : left);
619
		right = nsig - left;
466 maechler 620
 
2 r 621
		if (right > i_rt) i_rt = right;
622
		if (left > i_mxl) i_mxl = left;
623
		if (left < i_mnl) i_mnl = left;
624
		if (sleft> i_mxsl) i_mxsl = sleft;
625
		if (nsig > i_mxns) i_mxns = nsig;
571 ihaka 626
	    }
1016 maechler 627
	    /* done: ; */
2 r 628
	}
580 ihaka 629
    }
2 r 630
 
580 ihaka 631
    /* see comments in formatReal() for details on this */
2 r 632
 
580 ihaka 633
    /* overall format for real part	*/
2 r 634
 
63723 murdoch 635
    if (R_print.digits == 0) rt = 0;
580 ihaka 636
    if (mxl != INT_MIN) {
2 r 637
	if (mxl < 0) mxsl = 1 + neg;
25249 maechler 638
	if (rt < 0) rt = 0;
35251 ripley 639
	wF = mxsl + rt + (rt != 0);
2 r 640
 
48021 maechler 641
	*er = (mxl > 100 || mnl < -99) ? 2 : 1;
35251 ripley 642
	*dr = mxns - 1;
643
	*wr = neg + (*dr > 0) + *dr + 4 + *er;
644
    } else {
580 ihaka 645
	*er = 0;
35251 ripley 646
	*wr = 0;
647
	*dr = 0;
35253 ripley 648
	wF = 0;
580 ihaka 649
    }
2 r 650
 
580 ihaka 651
    /* overall format for imaginary part */
2 r 652
 
63723 murdoch 653
    if (R_print.digits == 0) i_rt = 0;
580 ihaka 654
    if (i_mxl != INT_MIN) {
2 r 655
	if (i_mxl < 0) i_mxsl = 1;
25249 maechler 656
	if (i_rt < 0) i_rt = 0;
35253 ripley 657
	i_wF = i_mxsl + i_rt + (i_rt != 0);
2 r 658
 
48021 maechler 659
	*ei = (i_mxl > 100 || i_mnl < -99) ? 2 : 1;
35251 ripley 660
	*di = i_mxns - 1;
661
	*wi = (*di > 0) + *di + 4 + *ei;
662
    } else {
580 ihaka 663
	*ei = 0;
35251 ripley 664
	*wi = 0;
665
	*di = 0;
35253 ripley 666
	i_wF = 0;
580 ihaka 667
    }
35253 ripley 668
 
669
    /* Now make the fixed/scientific decision */
670
    if(all_re_zero) {
671
	*er = *dr = 0;
672
	*wr = wF;
673
	if (i_wF <= *wi + R_print.scipen) {
674
	    *ei = 0;
675
	    if (nsmall > i_rt) {i_rt = nsmall; i_wF = i_mxsl + i_rt + (i_rt != 0);}
676
	    *di = i_rt;
677
	    *wi = i_wF;
45446 ripley 678
	}
35253 ripley 679
    } else if(all_im_zero) {
680
	if (wF <= *wr + R_print.scipen) {
681
	    *er = 0;
682
	    if (nsmall > rt) {rt = nsmall; wF = mxsl + rt + (rt != 0);}
683
	    *dr = rt;
684
	    *wr = wF;
79397 maechler 685
	}
35253 ripley 686
	*ei = *di = 0;
687
	*wi = i_wF;
688
    } else if(wF + i_wF < *wr + *wi + 2*R_print.scipen) {
689
	    *er = 0;
690
	    if (nsmall > rt) {rt = nsmall; wF = mxsl + rt + (rt != 0);}
691
	    *dr = rt;
692
	    *wr = wF;
693
 
694
	    *ei = 0;
695
	    if (nsmall > i_rt) {
45446 ripley 696
		i_rt = nsmall;
35253 ripley 697
		i_wF = i_mxsl + i_rt + (i_rt != 0);
698
	    }
699
	    *di = i_rt;
700
	    *wi = i_wF;
701
    } /* else scientific for both */
35251 ripley 702
    if(*wr < 0) *wr = 0;
703
    if(*wi < 0) *wi = 0;
580 ihaka 704
 
35253 ripley 705
    /* Ensure space for Inf and NaN */
79397 maechler 706
    if (rnan    && *wr < 3) *wr = 3;
707
    if (rposinf && *wr < 3) *wr = 3;
708
    if (rneginf && *wr < 4) *wr = 4;
709
    if (inan    && *wi < 3) *wi = 3;
710
    if (iposinf && *wi < 3) *wi = 3;
35253 ripley 711
 
85252 maechler 712
#else // R >= 4.4.0 : no longer "tricky"
713
    double
714
	*Re = (double *) R_alloc(n, sizeof(double)),
715
	*Im = (double *) R_alloc(n, sizeof(double));
716
 
717
# ifdef formatComplex_NA_give_NA // as previously in all S and R versions:
87894 ripley 718
    bool naflag = false;
85252 maechler 719
    R_xlen_t i1 = 0;
720
    for (R_xlen_t i = 0; i < n; i++) {
721
	if(ISNA(x[i].r) || ISNA(x[i].i)) {
87894 ripley 722
	    naflag |= true;
85252 maechler 723
	} else {
724
	    Re[i1] =      x[i].r;
725
	    Im[i1] = fabs(x[i].i); // in "Re +/- Im", the '-' does not take more space
726
	    i1++;
727
	} // 0 <= i1 <= i < n; i1 == length(Re) == length(Im)
728
    }
729
    formatReal(Re, i1, wr, dr, er, nsmall);
730
    formatReal(Im, i1, wi, di, ei, nsmall);
731
 
580 ihaka 732
    /* finally, ensure that there is space for NA */
35251 ripley 733
    if (naflag && *wr+*wi+2 < R_print.na_width)
734
	*wr += (R_print.na_width -(*wr + *wi + 2));
85252 maechler 735
 
736
# else // even simpler: can lead to extra " " e.g. for c(NA, 1+2i)
737
    for (R_xlen_t i = 0; i < n; i++) {
738
	Re[i] =      x[i].r;
739
	Im[i] = fabs(x[i].i); // in "Re +/- Im", the '-' does not take more space
740
    }
741
    formatReal(Re, n, wr, dr, er, nsmall);
742
    formatReal(Im, n, wi, di, ei, nsmall);
743
# endif
744
#endif
2 r 745
}
76734 luke 746
 
85252 maechler 747
 
748
 
86655 luke 749
attribute_hidden
76734 luke 750
void formatComplexS(SEXP x, R_xlen_t n, int *wr, int *dr, int *er,
751
		   int *wi, int *di, int *ei, int nsmall)
752
{
753
/* format.info() for  x[1..n] for both Re & Im */
754
    int tmpwr, tmpdr, tmper, tmpwi, tmpdi, tmpei;
755
 
756
    *wr = 0;
757
    *wi = 0;
758
    *dr = 0;
759
    *di = 0;
760
    *er = 0;
761
    *ei = 0;
76854 luke 762
    ITERATE_BY_REGION_PARTIAL(x, px, idx, nb, Rcomplex, COMPLEX, 0, n,
76734 luke 763
		      {
764
			  formatComplex(px, nb, &tmpwr, &tmpdr, &tmper,
765
					&tmpwi, &tmpdi, &tmpei, nsmall);
766
			  if(tmpwr > *wr) *wr = tmpwr;
767
			  if(tmpdr && !*dr) *dr = tmpdr;
768
			  if(tmper > *er) *er = tmper;
769
			  if(tmpwi > *wi) *wi = tmpwi;
770
			  if(tmpdi && !*di) *di = tmpdi;
771
			  if(tmpei > *ei) *ei = tmpei;
772
		      });
773
}