The R Project SVN R

Rev

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

Rev Author Line No. Line
2 r 1
/*
564 maechler 2
 *  R : A Computer Language for Statistical Data Analysis
75182 maechler 3
 *  Copyright (C) 1997--2018  The R Core Team
4
 *  Copyright (C) 2002--2009  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
 *
42307 ripley 17
 *  You should have received a copy of the GNU General Public License
18
 *  along with this program; if not, a copy is available at
68947 ripley 19
 *  https://www.R-project.org/Licenses/
2 r 20
 */
21
 
5187 hornik 22
#ifdef HAVE_CONFIG_H
44031 ripley 23
# include <config.h>
5187 hornik 24
#endif
25
 
11499 ripley 26
#include <Defn.h>
51838 ripley 27
#include <float.h>  /* for DBL_MAX */
11499 ripley 28
#include <Graphics.h>
29
#include <Print.h>
64658 ripley 30
#include <Rmath.h> // for Rexp10, imax2
2 r 31
 
59266 ripley 32
/* used in graphics and grid */
13046 maechler 33
SEXP CreateAtVector(double *axp, double *usr, int nint, Rboolean logflag)
658 ihaka 34
{
59266 ripley 35
/*	Create an  'at = ...' vector for  axis(.)
2666 maechler 36
 *	i.e., the vector of tick mark locations,
37
 *	when none has been specified (= default).
38
 *
21044 maechler 39
 *	axp[0:2] = (x1, x2, nInt), where x1..x2 are the extreme tick marks
50323 maechler 40
 *		   {unless in log case, where nInt \in {1,2,3 ; -1,-2,....}
41
 *		    and the `nint' argument is used *instead*.}
21044 maechler 42
 
2666 maechler 43
 *	The resulting REAL vector must have length >= 1, ideally >= 2
44
 */
987 maechler 45
    SEXP at = R_NilValue;/* -Wall*/
759 ihaka 46
    double umin, umax, dn, rng, small;
2666 maechler 47
    int i, n, ne;
21044 maechler 48
    if (!logflag || axp[2] < 0) { /* --- linear axis --- Only use axp[] arg. */
59173 ripley 49
	n = (int)(fabs(axp[2]) + 0.25);/* >= 0 */
8267 ripley 50
	dn = imax2(1, n);
658 ihaka 51
	rng = axp[1] - axp[0];
2666 maechler 52
	small = fabs(rng)/(100.*dn);
658 ihaka 53
	at = allocVector(REALSXP, n + 1);
5507 ihaka 54
	for (i = 0; i <= n; i++) {
658 ihaka 55
	    REAL(at)[i] = axp[0] + (i / dn) * rng;
759 ihaka 56
	    if (fabs(REAL(at)[i]) < small)
783 maechler 57
		REAL(at)[i] = 0;
8552 maechler 58
	}
658 ihaka 59
    }
2669 maechler 60
    else { /* ------ log axis ----- */
34502 maechler 61
	Rboolean reversed = FALSE;
62
 
59174 ripley 63
	n = (int)(axp[2] + 0.5);
33335 maechler 64
	/* {xy}axp[2] for 'log': GLpretty() [./graphics.c] sets
2666 maechler 65
	   n < 0: very small scale ==> linear axis, above, or
66
	   n = 1,2,3.  see switch() below */
658 ihaka 67
	umin = usr[0];
68
	umax = usr[1];
34502 maechler 69
	if (umin > umax) {
70
	    reversed = (axp[0] > axp[1]);
71
	    if (reversed) {
72
		/* have *reversed* log axis -- whereas
73
		 * the switch(n) { .. } below assumes *increasing* values
74
		 * --> reverse axis direction here, and reverse back at end */
75
		umin = usr[1];
76
		umax = usr[0];
77
		dn = axp[0]; axp[0] = axp[1]; axp[1] = dn;
78
	    }
79
	    else {
80
		/* can the following still happen... ? */
81
		warning("CreateAtVector \"log\"(from axis()): "
82
			"usr[0] = %g > %g = usr[1] !", umin, umax);
83
	    }
84
	}
57362 ripley 85
	/* allow a fuzz since we will do things like 0.2*dn >= umin */
86
	umin *= 1 - 1e-12;
87
	umax *= 1 + 1e-12;
34502 maechler 88
 
2690 maechler 89
	dn = axp[0];
33405 maechler 90
	if (dn < DBL_MIN) {/* was 1e-300; now seems too cautious */
91
	    if (dn <= 0) /* real trouble (once for Solaris) later on */
92
		error("CreateAtVector [log-axis()]: axp[0] = %g < 0!", dn);
75182 maechler 93
	    else
94
		warning("CreateAtVector [log-axis()]: small axp[0] = %g", dn);
33405 maechler 95
	}
2669 maechler 96
 
2666 maechler 97
	/* You get the 3 cases below by
5507 ihaka 98
	 *  for (y in 1e-5*c(1,2,8))  plot(y, log = "y")
2666 maechler 99
	 */
658 ihaka 100
	switch(n) {
2666 maechler 101
	case 1: /* large range:	1	 * 10^k */
59173 ripley 102
	    i = (int)(floor(log10(axp[1])) - ceil(log10(axp[0])) + 0.25);
2666 maechler 103
	    ne = i / nint + 1;
50323 maechler 104
#ifdef DEBUG_axis
105
	    REprintf("CreateAtVector [log-axis(), case 1]: (nint, ne) = (%d,%d)\n",
106
		     nint, ne);
107
#endif
5507 ihaka 108
	    if (ne < 1)
2690 maechler 109
		error("log - axis(), 'at' creation, _LARGE_ range: "
110
		      "ne = %d <= 0 !!\n"
5731 ripley 111
		      "\t axp[0:1]=(%g,%g) ==> i = %d;	nint = %d",
2690 maechler 112
		      ne, axp[0],axp[1], i, nint);
64658 ripley 113
	    rng = Rexp10((double)ne); /* >= 10 */
658 ihaka 114
	    n = 0;
5507 ihaka 115
	    while (dn < umax) {
658 ihaka 116
		n++;
2016 pd 117
		dn *= rng;
658 ihaka 118
	    }
5507 ihaka 119
	    if (!n)
2666 maechler 120
		error("log - axis(), 'at' creation, _LARGE_ range: "
33125 ripley 121
		      "invalid {xy}axp or par; nint=%d\n"
5731 ripley 122
		      "	 axp[0:1]=(%g,%g), usr[0:1]=(%g,%g); i=%d, ni=%d",
2666 maechler 123
		      nint, axp[0],axp[1], umin,umax, i,ne);
658 ihaka 124
	    at = allocVector(REALSXP, n);
125
	    dn = axp[0];
126
	    n = 0;
5507 ihaka 127
	    while (dn < umax) {
658 ihaka 128
		REAL(at)[n++] = dn;
2016 pd 129
		dn *= rng;
658 ihaka 130
	    }
131
	    break;
2666 maechler 132
 
133
	case 2: /* medium range:  1, 5	  * 10^k */
658 ihaka 134
	    n = 0;
5507 ihaka 135
	    if (0.5 * dn >= umin) n++;
136
	    for (;;) {
69855 ripley 137
		if (dn > umax) break;
138
		n++;
139
		if (5 * dn > umax) break;
140
		n++;
2666 maechler 141
		dn *= 10;
658 ihaka 142
	    }
5507 ihaka 143
	    if (!n)
2666 maechler 144
		error("log - axis(), 'at' creation, _MEDIUM_ range: "
33125 ripley 145
		      "invalid {xy}axp or par;\n"
5731 ripley 146
		      "	 axp[0]= %g, usr[0:1]=(%g,%g)",
2666 maechler 147
		      axp[0], umin,umax);
148
 
658 ihaka 149
	    at = allocVector(REALSXP, n);
150
	    dn = axp[0];
151
	    n = 0;
5507 ihaka 152
	    if (0.5 * dn >= umin) REAL(at)[n++] = 0.5 * dn;
153
	    for (;;) {
154
		if (dn > umax) break;		REAL(at)[n++] = dn;
155
		if (5 * dn > umax) break;	REAL(at)[n++] = 5 * dn;
2666 maechler 156
		dn *= 10;
658 ihaka 157
	    }
158
	    break;
2666 maechler 159
 
160
	case 3: /* small range:	 1,2,5,10 * 10^k */
658 ihaka 161
	    n = 0;
5507 ihaka 162
	    if (0.2 * dn >= umin) n++;
163
	    if (0.5 * dn >= umin) n++;
164
	    for (;;) {
69855 ripley 165
		if (dn > umax) break;
166
		n++;
167
		if (2 * dn > umax) break;
168
		n++;
169
		if (5 * dn > umax) break;
170
		n++;
2666 maechler 171
		dn *= 10;
658 ihaka 172
	    }
5507 ihaka 173
	    if (!n)
2666 maechler 174
		error("log - axis(), 'at' creation, _SMALL_ range: "
33125 ripley 175
		      "invalid {xy}axp or par;\n"
5731 ripley 176
		      "	 axp[0]= %g, usr[0:1]=(%g,%g)",
2666 maechler 177
		      axp[0], umin,umax);
658 ihaka 178
	    at = allocVector(REALSXP, n);
179
	    dn = axp[0];
180
	    n = 0;
5507 ihaka 181
	    if (0.2 * dn >= umin) REAL(at)[n++] = 0.2 * dn;
182
	    if (0.5 * dn >= umin) REAL(at)[n++] = 0.5 * dn;
183
	    for (;;) {
184
		if (dn > umax) break;		REAL(at)[n++] = dn;
185
		if (2 * dn > umax) break;	REAL(at)[n++] = 2 * dn;
186
		if (5 * dn > umax) break;	REAL(at)[n++] = 5 * dn;
2666 maechler 187
		dn *= 10;
658 ihaka 188
	    }
189
	    break;
2666 maechler 190
	default:
33125 ripley 191
	    error("log - axis(), 'at' creation: INVALID {xy}axp[3] = %g",
2666 maechler 192
		  axp[2]);
658 ihaka 193
	}
34502 maechler 194
 
195
	if (reversed) {/* reverse back again - last assignment was at[n++]= . */
196
	    for (i = 0; i < n/2; i++) { /* swap( at[i], at[n-i-1] ) : */
197
		dn = REAL(at)[i];
198
		REAL(at)[i] = REAL(at)[n-i-1];
199
		REAL(at)[n-i-1] = dn;
200
	    }
201
	}
202
    } /* linear / log */
658 ihaka 203
    return at;
204
}
59282 ripley 205