The R Project SVN R

Rev

Rev 80166 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 80166 Rev 80679
Line 1... Line 1...
1
/*
1
/*
2
 *  R : A Computer Language for Statistical Data Analysis
2
 *  R : A Computer Language for Statistical Data Analysis
3
 *  Copyright (C) 1997--2020  The R Core Team
3
 *  Copyright (C) 1997--2021  The R Core Team
4
 *  Copyright (C) 2002--2009  The R Foundation
4
 *  Copyright (C) 2002--2009  The R Foundation
5
 *  Copyright (C) 1995, 1996  Robert Gentleman and Ross Ihaka
5
 *  Copyright (C) 1995, 1996  Robert Gentleman and Ross Ihaka
6
 *
6
 *
7
 *  This program is free software; you can redistribute it and/or modify
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
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
9
 *  the Free Software Foundation; either version 3 of the License, or
10
 *  (at your option) any later version.
10
 *  (at your option) any later version.
11
 *
11
 *
12
 *  This program is distributed in the hope that it will be useful,
12
 *  This program is distributed in the hope that it will be useful,
13
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Line 28... Line 28...
28
#include <Graphics.h>
28
#include <Graphics.h>
29
#include <Print.h>
29
#include <Print.h>
30
#include <Rmath.h> // for imax2
30
#include <Rmath.h> // for imax2
31
 
31
 
32
/* used in graphics and grid */
32
/* used in graphics and grid */
33
SEXP CreateAtVector(double *axp, double *usr, int nint, Rboolean logflag)
33
SEXP CreateAtVector(double axp[], const double usr[], int nint, Rboolean logflag)
34
{
34
{
35
/*	Create an  'at = ...' vector for  axis(.)
35
/*	Create an  'at = ...' vector for  axis(.)
36
 *	i.e., the vector of tick mark locations,
36
 *	i.e., the vector of tick mark locations,
37
 *	when none has been specified (= default).
37
 *	when none has been specified (= default).
38
 *
38
 *
39
 *	axp[0:2] = (x1, x2, nInt), where x1..x2 are the extreme tick marks
39
 *	axp[0:2] = (x1, x2, nInt), where x1..x2 are the extreme tick marks
40
 *		   {unless in log case, where nInt \in {1,2,3 ; -1,-2,....}
40
 *		   {unless in log case, where nInt \in {1,2,3 ; -1,-2,....}
41
 *		    and the `nint' argument is used *instead*.}
41
 *		    and the `nint' argument is used *instead*.}
-
 
42
 *
-
 
43
 * only if(logflag && axp[2] >= 0)
-
 
44
 *			usr[0:1] is used, additionally
42
 
45
 *
43
 *	The resulting REAL vector must have length >= 1, ideally >= 2
46
 *	The resulting REAL vector must have length >= 1, ideally >= 2
44
 */
47
 */
45
    SEXP at = R_NilValue;/* -Wall*/
48
    SEXP at = R_NilValue;/* -Wall*/
46
    double umin, umax, dn, rng, small;
49
    double dn, rng, small;
47
    int i, n;
50
    int i, n;
-
 
51
    // "arbitrary" threshold: |delta_tick| / SMALL  is "barely visible" in plot
-
 
52
#define SMALL_F 100.
48
    if (!logflag || axp[2] < 0) { /* --- linear axis --- Only use axp[] arg. */
53
    if (!logflag || axp[2] < 0) { /* --- linear axis --- Only use axp[] arg. */
49
	n = (int)(fabs(axp[2]) + 0.25);/* >= 0 */
54
	n = (int)(fabs(axp[2]) + 0.25);/* >= 0 */
50
	dn = imax2(1, n);
55
	dn = imax2(1, n);
51
	rng = axp[1] - axp[0];
56
	rng = axp[1] - axp[0];
52
	small = fabs(rng)/(100.*dn);
-
 
53
	at = allocVector(REALSXP, n + 1);
57
	at = allocVector(REALSXP, n + 1);
-
 
58
	double a_i;
-
 
59
	if(!R_FINITE(rng)) { // need to carefully work around overflow
-
 
60
	    double at_ = axp[0]/dn; // 2021-07: "/dn" avoids overflow
-
 
61
	    rng = axp[1]/dn - at_;
-
 
62
	    small = fabs(rng)/SMALL_F;
-
 
63
#ifdef DEBUG_axis
-
 
64
	    REprintf("CreateAtVector(axp=(%g,%g, %g), log=F, diff(*)=Inf: at_=%g, rng=%g, small=%g\n",
-
 
65
		     axp[0],axp[1], axp[2], at_, rng, small);
-
 
66
#endif
-
 
67
	    int n2 = n/2; // integer division
-
 
68
	    for (i = 0; i <= n2; i++) { // from the left
-
 
69
		a_i = axp[0] + i * rng;
-
 
70
		// REprintf(" at[i=%2d]=%g\n", i+1, a_i);
-
 
71
		REAL(at)[i] = (fabs(a_i) < small) ? 0. : a_i;
-
 
72
	    }
-
 
73
	    for (int i2 = 0; i2 < n-n2; i2++) { // from the right
-
 
74
		i = n-i2; // for(i in n:k) where k = n-(n-n2-1) = n2+1
-
 
75
		a_i = axp[1] - i2 * rng;
-
 
76
		// REprintf(" at[i=%2d]=%g\n", i+1, a_i);
-
 
77
		REAL(at)[i] = (fabs(a_i) < small) ? 0. : a_i;
-
 
78
	    }
-
 
79
	}
-
 
80
	else { // rng is finite (normal case):
-
 
81
	    small = fabs(rng)/SMALL_F/dn;
54
	for (i = 0; i <= n; i++) {
82
	    for (i = 0; i <= n; i++) {
55
	    REAL(at)[i] = axp[0] + (i / dn) * rng;
83
		a_i = axp[0] + (i / dn) * rng;
56
	    if (fabs(REAL(at)[i]) < small)
84
		REAL(at)[i] = (fabs(a_i) < small) ? 0. : a_i;
57
		REAL(at)[i] = 0;
85
	    }
58
	}
86
	}
59
    }
87
    }
60
    else { /* ------ log axis ----- */
88
    else { /* ------ log axis ----- */
61
	Rboolean reversed = FALSE;
89
	Rboolean reversed = FALSE;
62
 
90
	double
-
 
91
	    umin = usr[0],
-
 
92
	    umax = usr[1];
63
	n = (int)(axp[2] + 0.5);
93
	n = (int)(axp[2] + 0.5);
64
	/* {xy}axp[2] for 'log': GLpretty() [./graphics.c] sets
94
	/* {xy}axp[2] for 'log': GLpretty() [./graphics.c] sets
65
	   n < 0: very small scale ==> linear axis, above, or
95
	   n < 0: very small scale ==> linear axis, above, or
66
	   n = 1,2,3.  see switch() below */
96
	   n = 1,2,3.  see switch() below */
67
	umin = usr[0];
-
 
68
	umax = usr[1];
-
 
69
#ifdef DEBUG_axis
97
#ifdef DEBUG_axis
70
	REprintf("CreateAtVector(axp=(%g,%g,%g), usr=(%g,%g), _log_):",
98
	REprintf("CreateAtVector(axp=(%g,%g,%g), usr=(%g,%g), _log_):",
71
		 axp[0],axp[1],axp[2],  usr[0],usr[1]);
99
		 axp[0],axp[1],axp[2],  usr[0],usr[1]);
72
#endif
100
#endif
73
	if (umin > umax) {
101
	if (umin > umax) {
Line 84... Line 112...
84
		/* can the following still happen... ? */
112
		/* can the following still happen... ? */
85
		warning("CreateAtVector \"log\"(from axis()): "
113
		warning("CreateAtVector \"log\"(from axis()): "
86
			"usr[0] = %g > %g = usr[1] !", umin, umax);
114
			"usr[0] = %g > %g = usr[1] !", umin, umax);
87
	    }
115
	    }
88
	}
116
	}
89
	/* allow a fuzz since we will do things like 0.2*dn >= umin */
117
	/* allow a fuzz (iff we don't under-/over-flow) since we will do things like 0.2*dn >= umin */
90
	umin *= 1 - 1e-12;
118
	dn = 1 - 1e-12; if(fabs(umin*dn) >     0.  ) umin *= dn;
91
	umax *= 1 + 1e-12;
119
	dn = 1 + 1e-12; if(fabs(umax*dn) <= DBL_MAX) umax *= dn;
92
 
120
 
93
	dn = axp[0];
121
	dn = axp[0];
94
	if (dn < DBL_MIN) {/* was 1e-300; now seems too cautious */
122
	if (dn < DBL_MIN) {/* was 1e-300; now seems too cautious */
95
	    if (dn <= 0) /* real trouble (once for Solaris) later on */
123
	    if (dn <= 0) /* real trouble (once for Solaris) later on */
96
		error("CreateAtVector [log-axis()]: axp[0] = %g < 0!", dn);
124
		error("CreateAtVector [log-axis()]: axp[0] = %g < 0!", dn);
Line 143... Line 171...
143
	    double d1 = d0 - nint*ne; // >= 0
171
	    double d1 = d0 - nint*ne; // >= 0
144
#ifdef DEBUG_axis
172
#ifdef DEBUG_axis
145
	    REprintf("expo.diff d0 - nint*ne =: d1=%g\n", d1);
173
	    REprintf("expo.diff d0 - nint*ne =: d1=%g\n", d1);
146
#endif
174
#endif
147
	    d0 = dn;
175
	    d0 = dn;
-
 
176
 
-
 
177
#define Large_D1 5
-
 
178
//              === was '3' all up into R 4.1.0
148
	    if(d1 > 3) {
179
	    if(d1 > Large_D1) {
149
		d0 = dn * Rexp10(floor(d1/2));
180
		d0 = dn * Rexp10(floor(d1/2));
150
#ifdef DEBUG_axis
181
#ifdef DEBUG_axis
151
		REprintf(" d0 := dn * 10 ^ fl(d1/2) = dn * 10^%d = %g\n",
182
		REprintf("large d1 => d0 := dn * 10 ^ fl(d1/2) = dn * 10^%d = %g\n",
152
			 (int)floor(d1/2), d0);
183
			 (int)floor(d1/2), d0);
153
#endif
184
#endif
154
	    }
185
	    }
155
	    rng = Rexp10((double)ne/k); // = 10^(ne/k) >= 10
186
	    rng = Rexp10((double)ne/k); // = 10^(ne/k) >= 10
156
	    n=0;
187
	    n=0;
Line 159... Line 190...
159
		for(int j=0; j < k; j++)
190
		for(int j=0; j < k; j++)
160
		    dn *= rng;
191
		    dn *= rng;
161
		n++;
192
		n++;
162
	    }
193
	    }
163
#ifdef DEBUG_axis
194
#ifdef DEBUG_axis
164
	    REprintf(" rng:=10^(ne/%d) = %g => n=%d, final dn=%g\n", k, rng, n, dn);
195
	    REprintf(" rng:=10^(ne/(k=%d)) = %g => n=%d, final dn=%g\n", k, rng, n, dn);
165
#endif
196
#endif
166
	    if (!n)
197
	    if (!n)
167
		error("log - axis(), 'at' creation, _LARGE_ range: "
198
		error("log - axis(), 'at' creation, _LARGE_ range: "
168
		      "invalid {xy}axp or par; nint=%d\n"
199
		      "invalid {xy}axp or par; nint=%d\n"
169
		      "	 axp[0:1]=(%g,%g), usr[0:1]=(%g,%g); i=%d, ni=%d",
200
		      "	 axp[0:1]=(%g,%g), usr[0:1]=(%g,%g); i=%d, ni=%d",
Line 222... Line 253...
222
		if (5 * dn > umax) break;
253
		if (5 * dn > umax) break;
223
		n++;
254
		n++;
224
		dn *= 10;
255
		dn *= 10;
225
	    }
256
	    }
226
#ifdef DEBUG_axis
257
#ifdef DEBUG_axis
227
	    REprintf(" .. case 3: (umin,umax) = (%g, %g); n=%d, dn=%g\n",
258
	    REprintf(" .. case 3: (umin,umax)-usr[*] = (%g, %g); n=%d, dn=%g\n",
-
 
259
		     umin-usr[reversed? 1: 0],
228
		     umin, umax, n, dn);
260
		     umax-usr[reversed? 0: 1], n, dn);
229
#endif
261
#endif
230
	    if (!n)
262
	    if (!n)
231
		error("log - axis(), 'at' creation, _SMALL_ range: "
263
		error("log - axis(), 'at' creation, _SMALL_ range: "
232
		      "invalid {xy}axp or par;\n"
264
		      "invalid {xy}axp or par;\n"
233
		      "	 axp[0]= %g, usr[0:1]=(%g,%g)",
265
		      "	 axp[0]= %g, usr[0:1]=(%g,%g)",
Line 253... Line 285...
253
	}
285
	}
254
 
286
 
255
	if (reversed) {/* reverse back again - last assignment was at[n++]= . */
287
	if (reversed) {/* reverse back again - last assignment was at[n++]= . */
256
	    for (i = 0; i < n/2; i++) { /* swap( at[i], at[n-i-1] ) : */
288
	    for (i = 0; i < n/2; i++) { /* swap( at[i], at[n-i-1] ) : */
257
		dn = REAL(at)[i];
289
		dn = REAL(at)[i];
258
		REAL(at)[i] = REAL(at)[n-i-1];
290
		     REAL(at)[i] = REAL(at)[n-i-1];
259
		REAL(at)[n-i-1] = dn;
291
		                   REAL(at)[n-i-1] = dn;
260
	    }
292
	    }
261
	}
293
	}
262
    } /* linear / log */
294
    } /* linear / log */
263
    return at;
295
    return at;
264
}
296
}
265
 
-