The R Project SVN R

Rev

Rev 27033 | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 27033 Rev 27063
1
/*
1
/*
2
 *  R : A Computer Language for Statistical Data Analysis
2
 *  R : A Computer Language for Statistical Data Analysis
3
 *  Copyright (C) 1995, 1996  Robert Gentleman and Ross Ihaka
3
 *  Copyright (C) 1995, 1996  Robert Gentleman and Ross Ihaka
4
 *  Copyright (C) 1997-2003   Robert Gentleman, Ross Ihaka and the
4
 *  Copyright (C) 1997-2003   Robert Gentleman, Ross Ihaka and the
5
 *                            R Development Core Team
5
 *                            R Development Core Team
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 2 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
15
 *  GNU General Public License for more details.
15
 *  GNU General Public License for more details.
16
 *
16
 *
17
 *  You should have received a copy of the GNU General Public License
17
 *  You should have received a copy of the GNU General Public License
18
 *  along with this program; if not, write to the Free Software
18
 *  along with this program; if not, write to the Free Software
19
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20
 *
20
 *
21
 *
21
 *
22
 *  Model Formula Manipulation
22
 *  Model Formula Manipulation
23
 *
23
 *
24
 *  Can you say ``recurse your brains out'';
24
 *  Can you say ``recurse your brains out'';
25
 *  I knew you could. -- Mr Ro(ss)gers
25
 *  I knew you could. -- Mr Ro(ss)gers
26
 */
26
 */
27
 
27
 
28
#ifdef HAVE_CONFIG_H
28
#ifdef HAVE_CONFIG_H
29
#include <config.h>
29
#include <config.h>
30
#endif
30
#endif
31
 
31
 
32
#include "Defn.h"
32
#include "Defn.h"
33
 
33
 
34
#define WORDSIZE (8*sizeof(int))
34
#define WORDSIZE (8*sizeof(int))
35
 
35
 
36
static SEXP tildeSymbol = NULL;
36
static SEXP tildeSymbol = NULL;
37
static SEXP plusSymbol  = NULL;
37
static SEXP plusSymbol  = NULL;
38
static SEXP minusSymbol = NULL;
38
static SEXP minusSymbol = NULL;
39
static SEXP timesSymbol = NULL;
39
static SEXP timesSymbol = NULL;
40
static SEXP slashSymbol = NULL;
40
static SEXP slashSymbol = NULL;
41
static SEXP colonSymbol = NULL;
41
static SEXP colonSymbol = NULL;
42
static SEXP powerSymbol = NULL;
42
static SEXP powerSymbol = NULL;
43
static SEXP dotSymbol   = NULL;
43
static SEXP dotSymbol   = NULL;
44
static SEXP parenSymbol = NULL;
44
static SEXP parenSymbol = NULL;
45
static SEXP inSymbol    = NULL;
45
static SEXP inSymbol    = NULL;
46
/* unused static SEXP identSymbol = NULL; */
46
/* unused static SEXP identSymbol = NULL; */
47
 
47
 
48
 
48
 
49
static int intercept;		/* intercept term in the model */
49
static int intercept;		/* intercept term in the model */
50
static int parity;		/* +/- parity */
50
static int parity;		/* +/- parity */
51
static int response;		/* response term in the model */
51
static int response;		/* response term in the model */
52
static int nvar;		/* Number of variables in the formula */
52
static int nvar;		/* Number of variables in the formula */
53
static int nwords;		/* # of words (ints) to code a term */
53
static int nwords;		/* # of words (ints) to code a term */
54
static int nterm;		/* # of model terms */
54
static int nterm;		/* # of model terms */
55
static SEXP varlist;		/* variables in the model */
55
static SEXP varlist;		/* variables in the model */
56
SEXP framenames;		/* variables names for specified frame */
56
SEXP framenames;		/* variables names for specified frame */
57
/* NOTE: framenames can't be static because it must be protected from
57
/* NOTE: framenames can't be static because it must be protected from
58
   garbage collection. */
58
   garbage collection. */
59
static Rboolean haveDot;	/* does RHS of formula contain `.'? */
59
static Rboolean haveDot;	/* does RHS of formula contain `.'? */
60
 
60
 
61
static int isZeroOne(SEXP x)
61
static int isZeroOne(SEXP x)
62
{
62
{
63
    if (!isNumeric(x)) return 0;
63
    if (!isNumeric(x)) return 0;
64
    return (asReal(x) == 0.0 || asReal(x) == 1.0);
64
    return (asReal(x) == 0.0 || asReal(x) == 1.0);
65
}
65
}
66
 
66
 
67
static int isZero(SEXP x)
67
static int isZero(SEXP x)
68
{
68
{
69
    if (!isNumeric(x)) return 0;
69
    if (!isNumeric(x)) return 0;
70
    return asReal(x) == 0.0;
70
    return asReal(x) == 0.0;
71
}
71
}
72
 
72
 
73
static int isOne(SEXP x)
73
static int isOne(SEXP x)
74
{
74
{
75
    if (!isNumeric(x)) return 0;
75
    if (!isNumeric(x)) return 0;
76
    return asReal(x) == 1.0;
76
    return asReal(x) == 1.0;
77
}
77
}
78
 
78
 
79
 
79
 
80
/* MatchVar determines whether two ``variables'' are */
80
/* MatchVar determines whether two ``variables'' are */
81
/* identical.  Expressions are identical if they have */
81
/* identical.  Expressions are identical if they have */
82
/* the same list structure and their atoms are identical. */
82
/* the same list structure and their atoms are identical. */
83
/* This is just EQUAL from lisp. */
83
/* This is just EQUAL from lisp. */
84
 
84
 
85
static int MatchVar(SEXP var1, SEXP var2)
85
static int MatchVar(SEXP var1, SEXP var2)
86
{
86
{
87
    /* For expedience, and sanity... */
87
    /* For expedience, and sanity... */
88
    if ( var1 == var2 )
88
    if ( var1 == var2 )
89
    	return 1;
89
    	return 1;
90
    /* Handle Nulls */
90
    /* Handle Nulls */
91
    if (isNull(var1) && isNull(var2))
91
    if (isNull(var1) && isNull(var2))
92
	return 1;
92
	return 1;
93
    if (isNull(var1) || isNull(var2))
93
    if (isNull(var1) || isNull(var2))
94
	return 0;
94
	return 0;
95
    /* Non-atomic objects - compare CARs & CDRs */
95
    /* Non-atomic objects - compare CARs & CDRs */
96
    if ((isList(var1) || isLanguage(var1)) &&
96
    if ((isList(var1) || isLanguage(var1)) &&
97
	(isList(var2) || isLanguage(var2)))
97
	(isList(var2) || isLanguage(var2)))
98
	return MatchVar(CAR(var1), CAR(var2)) &&
98
	return MatchVar(CAR(var1), CAR(var2)) &&
99
	       MatchVar(CDR(var1), CDR(var2));
99
	       MatchVar(CDR(var1), CDR(var2));
100
    /* Symbols */
100
    /* Symbols */
101
    if (isSymbol(var1) && isSymbol(var2))
101
    if (isSymbol(var1) && isSymbol(var2))
102
	return (var1 == var2);
102
	return (var1 == var2);
103
    /* Literal Numerics */
103
    /* Literal Numerics */
104
    if (isNumeric(var1) && isNumeric(var2))
104
    if (isNumeric(var1) && isNumeric(var2))
105
	return (asReal(var1) == asReal(var2));
105
	return (asReal(var1) == asReal(var2));
106
    /* Literal Strings */
106
    /* Literal Strings */
107
    if (isString(var1) && isString(var2))
107
    if (isString(var1) && isString(var2))
108
	return (strcmp(CHAR(STRING_ELT(var1, 0)),
108
	return (strcmp(CHAR(STRING_ELT(var1, 0)),
109
		       CHAR(STRING_ELT(var2, 0))) == 0);
109
		       CHAR(STRING_ELT(var2, 0))) == 0);
110
    /* Nothing else matches */
110
    /* Nothing else matches */
111
    return 0;
111
    return 0;
112
}
112
}
113
 
113
 
114
 
114
 
115
/* InstallVar locates a ``variable'' in the model */
115
/* InstallVar locates a ``variable'' in the model */
116
/* variable list;  adding it to the list if not found. */
116
/* variable list;  adding it to the list if not found. */
117
 
117
 
118
static int InstallVar(SEXP var)
118
static int InstallVar(SEXP var)
119
{
119
{
120
    SEXP v;
120
    SEXP v;
121
    int indx;
121
    int indx;
122
    /* Check that variable is legitimate */
122
    /* Check that variable is legitimate */
123
    if (!isSymbol(var) && !isLanguage(var) && !isZeroOne(var))
123
    if (!isSymbol(var) && !isLanguage(var) && !isZeroOne(var))
124
	error("invalid term in model formula");
124
	error("invalid term in model formula");
125
    /* Lookup/Install it */
125
    /* Lookup/Install it */
126
    indx = 0;
126
    indx = 0;
127
    for (v = varlist; CDR(v) != R_NilValue; v = CDR(v)) {
127
    for (v = varlist; CDR(v) != R_NilValue; v = CDR(v)) {
128
	indx++;
128
	indx++;
129
	if (MatchVar(var, CADR(v)))
129
	if (MatchVar(var, CADR(v)))
130
	    return indx;
130
	    return indx;
131
    }
131
    }
132
    SETCDR(v, CONS(var, R_NilValue));
132
    SETCDR(v, CONS(var, R_NilValue));
133
    return indx + 1;
133
    return indx + 1;
134
}
134
}
135
 
135
 
136
 
136
 
137
/* If there is a dotsxp being expanded then we need to see */
137
/* If there is a dotsxp being expanded then we need to see */
138
/* whether any of the variables in the data frame match with */
138
/* whether any of the variables in the data frame match with */
139
/* the variable on the lhs. If so they shouldn't be included */
139
/* the variable on the lhs. If so they shouldn't be included */
140
/* in the factors */
140
/* in the factors */
141
 
141
 
142
static void CheckRHS(SEXP v)
142
static void CheckRHS(SEXP v)
143
{
143
{
144
    int i, j;
144
    int i, j;
145
    SEXP s, t;
145
    SEXP s, t;
146
    while ((isList(v) || isLanguage(v)) && v != R_NilValue) {
146
    while ((isList(v) || isLanguage(v)) && v != R_NilValue) {
147
	CheckRHS(CAR(v));
147
	CheckRHS(CAR(v));
148
	v = CDR(v);
148
	v = CDR(v);
149
    }
149
    }
150
    if (isSymbol(v)) {
150
    if (isSymbol(v)) {
151
	for (i = 0; i < length(framenames); i++) {
151
	for (i = 0; i < length(framenames); i++) {
152
	    s = install(CHAR(STRING_ELT(framenames, i)));
152
	    s = install(CHAR(STRING_ELT(framenames, i)));
153
	    if (v == s) {
153
	    if (v == s) {
154
		t=allocVector(STRSXP, length(framenames)-1);
154
		t=allocVector(STRSXP, length(framenames)-1);
155
		for (j = 0; j < length(t); j++) {
155
		for (j = 0; j < length(t); j++) {
156
		    if (j < i)
156
		    if (j < i)
157
			SET_STRING_ELT(t, j, STRING_ELT(framenames, j));
157
			SET_STRING_ELT(t, j, STRING_ELT(framenames, j));
158
		    else
158
		    else
159
			SET_STRING_ELT(t, j, STRING_ELT(framenames, j+1));
159
			SET_STRING_ELT(t, j, STRING_ELT(framenames, j+1));
160
		}
160
		}
161
		framenames=t;
161
		framenames=t;
162
	    }
162
	    }
163
	}
163
	}
164
    }
164
    }
165
}
165
}
166
 
166
 
167
 
167
 
168
/* ExtractVars recursively extracts the variables */
168
/* ExtractVars recursively extracts the variables */
169
/* in a model formula.  It calls InstallVar to do */
169
/* in a model formula.  It calls InstallVar to do */
170
/* the installation.  The code takes care of unary */
170
/* the installation.  The code takes care of unary */
171
/* + and minus.  No checks are made of the other */
171
/* + and minus.  No checks are made of the other */
172
/* ``binary'' operators.  Maybe there should be some. */
172
/* ``binary'' operators.  Maybe there should be some. */
173
 
173
 
174
static void ExtractVars(SEXP formula, int checkonly)
174
static void ExtractVars(SEXP formula, int checkonly)
175
{
175
{
176
    int len, i;
176
    int len, i;
177
    SEXP v;
177
    SEXP v;
178
 
178
 
179
    if (isNull(formula) || isZeroOne(formula))
179
    if (isNull(formula) || isZeroOne(formula))
180
	return;
180
	return;
181
    if (isSymbol(formula)) {
181
    if (isSymbol(formula)) {
182
	if (!checkonly) {
182
	if (!checkonly) {
183
	    if (formula == dotSymbol && framenames != R_NilValue) {
183
	    if (formula == dotSymbol && framenames != R_NilValue) {
184
		haveDot = TRUE;
184
		haveDot = TRUE;
185
		for (i = 0; i < length(framenames); i++) {
185
		for (i = 0; i < length(framenames); i++) {
186
		    v = install(CHAR(STRING_ELT(framenames, i)));
186
		    v = install(CHAR(STRING_ELT(framenames, i)));
187
		    if (!MatchVar(v, CADR(varlist))) InstallVar(v);
187
		    if (!MatchVar(v, CADR(varlist))) InstallVar(v);
188
		}
188
		}
189
	    } else
189
	    } else
190
		InstallVar(formula);
190
		InstallVar(formula);
191
	}
191
	}
192
	return;
192
	return;
193
    }
193
    }
194
    if (isLanguage(formula)) {
194
    if (isLanguage(formula)) {
195
	len = length(formula);
195
	len = length(formula);
196
	if (CAR(formula) == tildeSymbol) {
196
	if (CAR(formula) == tildeSymbol) {
197
	    if (response)
197
	    if (response)
198
		error("invalid model formula");
198
		error("invalid model formula");
199
	    if (isNull(CDDR(formula))) {
199
	    if (isNull(CDDR(formula))) {
200
		response = 0;
200
		response = 0;
201
		ExtractVars(CADR(formula), 0);
201
		ExtractVars(CADR(formula), 0);
202
	    }
202
	    }
203
	    else {
203
	    else {
204
		response = 1;
204
		response = 1;
205
		InstallVar(CADR(formula));
205
		InstallVar(CADR(formula));
206
		ExtractVars(CADDR(formula), 0);
206
		ExtractVars(CADDR(formula), 0);
207
	    }
207
	    }
208
	    return;
208
	    return;
209
	}
209
	}
210
	if (CAR(formula) == plusSymbol) {
210
	if (CAR(formula) == plusSymbol) {
211
	    if (length(formula) > 1)
211
	    if (length(formula) > 1)
212
		ExtractVars(CADR(formula), checkonly);
212
		ExtractVars(CADR(formula), checkonly);
213
	    if (length(formula) > 2)
213
	    if (length(formula) > 2)
214
		ExtractVars(CADDR(formula), checkonly);
214
		ExtractVars(CADDR(formula), checkonly);
215
	    return;
215
	    return;
216
	}
216
	}
217
	if (CAR(formula) == colonSymbol) {
217
	if (CAR(formula) == colonSymbol) {
218
	    ExtractVars(CADR(formula), checkonly);
218
	    ExtractVars(CADR(formula), checkonly);
219
	    ExtractVars(CADDR(formula), checkonly);
219
	    ExtractVars(CADDR(formula), checkonly);
220
	    return;
220
	    return;
221
	}
221
	}
222
	if (CAR(formula) == powerSymbol) {
222
	if (CAR(formula) == powerSymbol) {
223
	    if (!isNumeric(CADDR(formula)))
223
	    if (!isNumeric(CADDR(formula)))
224
		error("invalid power in formula");
224
		error("invalid power in formula");
225
	    ExtractVars(CADR(formula), checkonly);
225
	    ExtractVars(CADR(formula), checkonly);
226
	    return;
226
	    return;
227
	}
227
	}
228
	if (CAR(formula) == timesSymbol) {
228
	if (CAR(formula) == timesSymbol) {
229
	    ExtractVars(CADR(formula), checkonly);
229
	    ExtractVars(CADR(formula), checkonly);
230
	    ExtractVars(CADDR(formula), checkonly);
230
	    ExtractVars(CADDR(formula), checkonly);
231
	    return;
231
	    return;
232
	}
232
	}
233
	if (CAR(formula) == inSymbol) {
233
	if (CAR(formula) == inSymbol) {
234
	    ExtractVars(CADR(formula), checkonly);
234
	    ExtractVars(CADR(formula), checkonly);
235
	    ExtractVars(CADDR(formula), checkonly);
235
	    ExtractVars(CADDR(formula), checkonly);
236
	    return;
236
	    return;
237
	}
237
	}
238
	if (CAR(formula) == slashSymbol) {
238
	if (CAR(formula) == slashSymbol) {
239
	    ExtractVars(CADR(formula), checkonly);
239
	    ExtractVars(CADR(formula), checkonly);
240
	    ExtractVars(CADDR(formula), checkonly);
240
	    ExtractVars(CADDR(formula), checkonly);
241
	    return;
241
	    return;
242
	}
242
	}
243
	if (CAR(formula) == minusSymbol) {
243
	if (CAR(formula) == minusSymbol) {
244
	    if (len == 2) {
244
	    if (len == 2) {
245
		ExtractVars(CADR(formula), 1);
245
		ExtractVars(CADR(formula), 1);
246
	    }
246
	    }
247
	    else {
247
	    else {
248
		ExtractVars(CADR(formula), checkonly);
248
		ExtractVars(CADR(formula), checkonly);
249
		ExtractVars(CADDR(formula), 1);
249
		ExtractVars(CADDR(formula), 1);
250
	    }
250
	    }
251
	    return;
251
	    return;
252
	}
252
	}
253
	if (CAR(formula) == parenSymbol) {
253
	if (CAR(formula) == parenSymbol) {
254
	    ExtractVars(CADR(formula), checkonly);
254
	    ExtractVars(CADR(formula), checkonly);
255
	    return;
255
	    return;
256
	}
256
	}
257
	InstallVar(formula);
257
	InstallVar(formula);
258
	return;
258
	return;
259
    }
259
    }
260
    error("invalid model formula in ExtractVars");
260
    error("invalid model formula in ExtractVars");
261
}
261
}
262
 
262
 
263
 
263
 
264
/* AllocTerm allocates an integer array for */
264
/* AllocTerm allocates an integer array for */
265
/* bit string representation of a model term */
265
/* bit string representation of a model term */
266
 
266
 
267
static SEXP AllocTerm()
267
static SEXP AllocTerm()
268
{
268
{
269
    int i;
269
    int i;
270
    SEXP term = allocVector(INTSXP, nwords);
270
    SEXP term = allocVector(INTSXP, nwords);
271
    for (i = 0; i < nwords; i++)
271
    for (i = 0; i < nwords; i++)
272
	INTEGER(term)[i] = 0;
272
	INTEGER(term)[i] = 0;
273
    return term;
273
    return term;
274
}
274
}
275
 
275
 
276
 
276
 
277
/* SetBit sets bit ``whichBit'' to value ``value'' */
277
/* SetBit sets bit ``whichBit'' to value ``value'' */
278
/* in the bit string representation of a term. */
278
/* in the bit string representation of a term. */
279
 
279
 
280
static void SetBit(SEXP term, int whichBit, int value)
280
static void SetBit(SEXP term, int whichBit, int value)
281
{
281
{
282
    int word, offset;
282
    int word, offset;
283
    word = (whichBit - 1) / WORDSIZE;
283
    word = (whichBit - 1) / WORDSIZE;
284
    offset = (WORDSIZE - whichBit) % WORDSIZE;
284
    offset = (WORDSIZE - whichBit) % WORDSIZE;
285
    if (value)
285
    if (value)
286
	((unsigned *) INTEGER(term))[word] |= ((unsigned) 1 << offset);
286
	((unsigned *) INTEGER(term))[word] |= ((unsigned) 1 << offset);
287
    else
287
    else
288
	((unsigned *) INTEGER(term))[word] &= ~((unsigned) 1 << offset);
288
	((unsigned *) INTEGER(term))[word] &= ~((unsigned) 1 << offset);
289
}
289
}
290
 
290
 
291
 
291
 
292
/* GetBit gets bit ``whichBit'' from the */
292
/* GetBit gets bit ``whichBit'' from the */
293
/* bit string representation of a term. */
293
/* bit string representation of a term. */
294
 
294
 
295
static int GetBit(SEXP term, int whichBit)
295
static int GetBit(SEXP term, int whichBit)
296
{
296
{
297
    unsigned int word, offset;
297
    unsigned int word, offset;
298
    word = (whichBit - 1) / WORDSIZE;
298
    word = (whichBit - 1) / WORDSIZE;
299
    offset = (WORDSIZE - whichBit) % WORDSIZE;
299
    offset = (WORDSIZE - whichBit) % WORDSIZE;
300
    return ((((unsigned *) INTEGER(term))[word]) >> offset) & 1;
300
    return ((((unsigned *) INTEGER(term))[word]) >> offset) & 1;
301
}
301
}
302
 
302
 
303
 
303
 
304
/* OrBits computes a new (bit string) term */
304
/* OrBits computes a new (bit string) term */
305
/* which contains the logical OR of the bits */
305
/* which contains the logical OR of the bits */
306
/* in ``term1'' and ``term2''. */
306
/* in ``term1'' and ``term2''. */
307
 
307
 
308
static SEXP OrBits(SEXP term1, SEXP term2)
308
static SEXP OrBits(SEXP term1, SEXP term2)
309
{
309
{
310
    SEXP term;
310
    SEXP term;
311
    int i;
311
    int i;
312
    term = AllocTerm();
312
    term = AllocTerm();
313
    for (i = 0; i < nwords; i++)
313
    for (i = 0; i < nwords; i++)
314
	INTEGER(term)[i] = INTEGER(term1)[i] | INTEGER(term2)[i];
314
	INTEGER(term)[i] = INTEGER(term1)[i] | INTEGER(term2)[i];
315
    return term;
315
    return term;
316
}
316
}
317
 
317
 
318
 
318
 
319
/* BitCount counts the number of ``on'' */
319
/* BitCount counts the number of ``on'' */
320
/* bits in a term */
320
/* bits in a term */
321
 
321
 
322
static int BitCount(SEXP term)
322
static int BitCount(SEXP term)
323
{
323
{
324
    int i, sum;
324
    int i, sum;
325
    sum = 0;
325
    sum = 0;
326
    for (i = 1; i <= nvar; i++)
326
    for (i = 1; i <= nvar; i++)
327
	sum += GetBit(term, i);
327
	sum += GetBit(term, i);
328
    return sum;
328
    return sum;
329
}
329
}
330
 
330
 
331
 
331
 
332
/* TermZero tests whether a (bit string) term is zero */
332
/* TermZero tests whether a (bit string) term is zero */
333
 
333
 
334
static int TermZero(SEXP term)
334
static int TermZero(SEXP term)
335
{
335
{
336
    int i, val;
336
    int i, val;
337
    val = 1;
337
    val = 1;
338
    for (i = 0; i < nwords; i++)
338
    for (i = 0; i < nwords; i++)
339
	val = val && (INTEGER(term)[i] == 0);
339
	val = val && (INTEGER(term)[i] == 0);
340
    return val;
340
    return val;
341
}
341
}
342
 
342
 
343
 
343
 
344
/* TermEqual tests two (bit string) terms for equality. */
344
/* TermEqual tests two (bit string) terms for equality. */
345
 
345
 
346
static int TermEqual(SEXP term1, SEXP term2)
346
static int TermEqual(SEXP term1, SEXP term2)
347
{
347
{
348
    int i, val;
348
    int i, val;
349
    val = 1;
349
    val = 1;
350
    for (i = 0; i < nwords; i++)
350
    for (i = 0; i < nwords; i++)
351
	val = val && (INTEGER(term1)[i] == INTEGER(term2)[i]);
351
	val = val && (INTEGER(term1)[i] == INTEGER(term2)[i]);
352
    return val;
352
    return val;
353
}
353
}
354
 
354
 
355
 
355
 
356
/* StripTerm strips the specified term from */
356
/* StripTerm strips the specified term from */
357
/* the given list.  This mutates the list. */
357
/* the given list.  This mutates the list. */
358
 
358
 
359
static SEXP StripTerm(SEXP term, SEXP list)
359
static SEXP StripTerm(SEXP term, SEXP list)
360
{
360
{
361
    SEXP tail;
361
    SEXP tail;
362
    if (TermZero(term))
362
    if (TermZero(term))
363
	intercept = 0;
363
	intercept = 0;
364
    if (list == R_NilValue)
364
    if (list == R_NilValue)
365
	return list;
365
	return list;
366
    tail = StripTerm(term, CDR(list));
366
    tail = StripTerm(term, CDR(list));
367
    if (TermEqual(term, CAR(list)))
367
    if (TermEqual(term, CAR(list)))
368
	return tail;
368
	return tail;
369
    SETCDR(list, tail);
369
    SETCDR(list, tail);
370
    return list;
370
    return list;
371
}
371
}
372
 
372
 
373
 
373
 
374
/* TrimRepeats removes duplicates of (bit string) terms */
374
/* TrimRepeats removes duplicates of (bit string) terms */
375
/* in a model formula by repeated use of ``StripTerm''. */
375
/* in a model formula by repeated use of ``StripTerm''. */
376
/* Also drops zero terms. */
376
/* Also drops zero terms. */
377
 
377
 
378
static SEXP TrimRepeats(SEXP list)
378
static SEXP TrimRepeats(SEXP list)
379
{
379
{
380
    if (list == R_NilValue)
380
    if (list == R_NilValue)
381
	return R_NilValue;
381
	return R_NilValue;
382
    if (TermZero(CAR(list)))
382
    if (TermZero(CAR(list)))
383
	return TrimRepeats(CDR(list));
383
	return TrimRepeats(CDR(list));
384
    SETCDR(list, TrimRepeats(StripTerm(CAR(list), CDR(list))));
384
    SETCDR(list, TrimRepeats(StripTerm(CAR(list), CDR(list))));
385
    return list;
385
    return list;
386
}
386
}
387
 
387
 
388
 
388
 
389

389

390
/*==========================================================================*/
390
/*==========================================================================*/
391
 
391
 
392
/* Model Formula Manipulation */
392
/* Model Formula Manipulation */
393
/* These functions take a numerically coded */
393
/* These functions take a numerically coded */
394
/* formula and fully expand it. */
394
/* formula and fully expand it. */
395
 
395
 
396
static SEXP EncodeVars(SEXP);/* defined below */
396
static SEXP EncodeVars(SEXP);/* defined below */
397
 
397
 
398
 
398
 
399
/* PlusTerms expands ``left'' and ``right'' and */
399
/* PlusTerms expands ``left'' and ``right'' and */
400
/* concatenates their terms (removing duplicates). */
400
/* concatenates their terms (removing duplicates). */
401
 
401
 
402
static SEXP PlusTerms(SEXP left, SEXP right)
402
static SEXP PlusTerms(SEXP left, SEXP right)
403
{
403
{
404
    PROTECT(left = EncodeVars(left));
404
    PROTECT(left = EncodeVars(left));
405
    right = EncodeVars(right);
405
    right = EncodeVars(right);
406
    UNPROTECT(1);
406
    UNPROTECT(1);
407
    return TrimRepeats(listAppend(left, right));
407
    return TrimRepeats(listAppend(left, right));
408
}
408
}
409
 
409
 
410
 
410
 
411
/* InteractTerms expands ``left'' and ``right'' */
411
/* InteractTerms expands ``left'' and ``right'' */
412
/* and forms a new list of terms containing the bitwise */
412
/* and forms a new list of terms containing the bitwise */
413
/* OR of each term in ``left'' with each term in ``right''. */
413
/* OR of each term in ``left'' with each term in ``right''. */
414
 
414
 
415
static SEXP InteractTerms(SEXP left, SEXP right)
415
static SEXP InteractTerms(SEXP left, SEXP right)
416
{
416
{
417
    SEXP term, l, r, t;
417
    SEXP term, l, r, t;
418
    PROTECT(left = EncodeVars(left));
418
    PROTECT(left = EncodeVars(left));
419
    PROTECT(right = EncodeVars(right));
419
    PROTECT(right = EncodeVars(right));
420
    PROTECT(term = allocList(length(left) * length(right)));
420
    PROTECT(term = allocList(length(left) * length(right)));
421
    t = term;
421
    t = term;
422
    for (l = left; l != R_NilValue; l = CDR(l))
422
    for (l = left; l != R_NilValue; l = CDR(l))
423
	for (r = right; r != R_NilValue; r = CDR(r)) {
423
	for (r = right; r != R_NilValue; r = CDR(r)) {
424
	    SETCAR(t, OrBits(CAR(l), CAR(r)));
424
	    SETCAR(t, OrBits(CAR(l), CAR(r)));
425
	    t = CDR(t);
425
	    t = CDR(t);
426
	}
426
	}
427
    UNPROTECT(3);
427
    UNPROTECT(3);
428
    return TrimRepeats(term);
428
    return TrimRepeats(term);
429
}
429
}
430
 
430
 
431
 
431
 
432
/* CrossTerms expands ``left'' and ``right'' */
432
/* CrossTerms expands ``left'' and ``right'' */
433
/* and forms the ``cross'' of the list of terms.  */
433
/* and forms the ``cross'' of the list of terms.  */
434
/* Duplicates are removed. */
434
/* Duplicates are removed. */
435
 
435
 
436
static SEXP CrossTerms(SEXP left, SEXP right)
436
static SEXP CrossTerms(SEXP left, SEXP right)
437
{
437
{
438
    SEXP term, l, r, t;
438
    SEXP term, l, r, t;
439
    PROTECT(left = EncodeVars(left));
439
    PROTECT(left = EncodeVars(left));
440
    PROTECT(right = EncodeVars(right));
440
    PROTECT(right = EncodeVars(right));
441
    PROTECT(term = allocList(length(left) * length(right)));
441
    PROTECT(term = allocList(length(left) * length(right)));
442
    t = term;
442
    t = term;
443
    for (l = left; l != R_NilValue; l = CDR(l))
443
    for (l = left; l != R_NilValue; l = CDR(l))
444
	for (r = right; r != R_NilValue; r = CDR(r)) {
444
	for (r = right; r != R_NilValue; r = CDR(r)) {
445
	    SETCAR(t, OrBits(CAR(l), CAR(r)));
445
	    SETCAR(t, OrBits(CAR(l), CAR(r)));
446
	    t = CDR(t);
446
	    t = CDR(t);
447
	}
447
	}
448
    UNPROTECT(3);
448
    UNPROTECT(3);
449
    listAppend(right, term);
449
    listAppend(right, term);
450
    listAppend(left, right);
450
    listAppend(left, right);
451
    return TrimRepeats(left);
451
    return TrimRepeats(left);
452
}
452
}
453
 
453
 
454
 
454
 
455
/* PowerTerms expands the ``left'' form and then */
455
/* PowerTerms expands the ``left'' form and then */
456
/* raises it to the power specified by the right term. */
456
/* raises it to the power specified by the right term. */
457
/* Allocation here is wasteful, but so what ... */
457
/* Allocation here is wasteful, but so what ... */
458
 
458
 
459
static SEXP PowerTerms(SEXP left, SEXP right)
459
static SEXP PowerTerms(SEXP left, SEXP right)
460
{
460
{
461
    SEXP term, l, r, t;
461
    SEXP term, l, r, t;
462
    int i, ip;
462
    int i, ip;
463
    ip = asInteger(right);
463
    ip = asInteger(right);
464
    if (ip==NA_INTEGER || ip <= 1)
464
    if (ip==NA_INTEGER || ip <= 1)
465
	error("Invalid power in formula");
465
	error("Invalid power in formula");
466
    term = R_NilValue;		/* -Wall */
466
    term = R_NilValue;		/* -Wall */
467
    PROTECT(left = EncodeVars(left));
467
    PROTECT(left = EncodeVars(left));
468
    right = left;
468
    right = left;
469
    for (i=1; i < ip; i++)  {
469
    for (i=1; i < ip; i++)  {
470
	PROTECT(right);
470
	PROTECT(right);
471
	PROTECT(term = allocList(length(left) * length(right)));
471
	PROTECT(term = allocList(length(left) * length(right)));
472
	t = term;
472
	t = term;
473
	for (l = left; l != R_NilValue; l = CDR(l))
473
	for (l = left; l != R_NilValue; l = CDR(l))
474
	    for (r = right; r != R_NilValue; r = CDR(r)) {
474
	    for (r = right; r != R_NilValue; r = CDR(r)) {
475
		SETCAR(t, OrBits(CAR(l), CAR(r)));
475
		SETCAR(t, OrBits(CAR(l), CAR(r)));
476
		t = CDR(t);
476
		t = CDR(t);
477
	    }
477
	    }
478
	UNPROTECT(2);
478
	UNPROTECT(2);
479
	right = TrimRepeats(term);
479
	right = TrimRepeats(term);
480
    }
480
    }
481
    UNPROTECT(1);
481
    UNPROTECT(1);
482
    return term;
482
    return term;
483
}
483
}
484
 
484
 
485
 
485
 
486
/* InTerms expands ``left'' and ``right'' and */
486
/* InTerms expands ``left'' and ``right'' and */
487
/* forms the ``nest'' of the the left in the */
487
/* forms the ``nest'' of the the left in the */
488
/* interaction of the right */
488
/* interaction of the right */
489
 
489
 
490
static SEXP InTerms(SEXP left, SEXP right)
490
static SEXP InTerms(SEXP left, SEXP right)
491
{
491
{
492
    SEXP term, t;
492
    SEXP term, t;
493
    int i;
493
    int i;
494
    PROTECT(left = EncodeVars(left));
494
    PROTECT(left = EncodeVars(left));
495
    PROTECT(right = EncodeVars(right));
495
    PROTECT(right = EncodeVars(right));
496
    PROTECT(term = AllocTerm());
496
    PROTECT(term = AllocTerm());
497
    /* Bitwise or of all terms on right */
497
    /* Bitwise or of all terms on right */
498
    for (t = right; t != R_NilValue; t = CDR(t)) {
498
    for (t = right; t != R_NilValue; t = CDR(t)) {
499
	for (i = 0; i < nwords; i++)
499
	for (i = 0; i < nwords; i++)
500
	    INTEGER(term)[i] = INTEGER(term)[i] | INTEGER(CAR(t))[i];
500
	    INTEGER(term)[i] = INTEGER(term)[i] | INTEGER(CAR(t))[i];
501
    }
501
    }
502
    /* Now bitwise or with each term on the left */
502
    /* Now bitwise or with each term on the left */
503
    for (t = left; t != R_NilValue; t = CDR(t))
503
    for (t = left; t != R_NilValue; t = CDR(t))
504
	for (i = 0; i < nwords; i++)
504
	for (i = 0; i < nwords; i++)
505
	    INTEGER(CAR(t))[i] = INTEGER(term)[i] | INTEGER(CAR(t))[i];
505
	    INTEGER(CAR(t))[i] = INTEGER(term)[i] | INTEGER(CAR(t))[i];
506
    UNPROTECT(3);
506
    UNPROTECT(3);
507
    return TrimRepeats(left);
507
    return TrimRepeats(left);
508
}
508
}
509
 
509
 
510
/* NestTerms expands ``left'' and ``right'' */
510
/* NestTerms expands ``left'' and ``right'' */
511
/* and forms the ``nest'' of the list of terms.  */
511
/* and forms the ``nest'' of the list of terms.  */
512
/* Duplicates are removed. */
512
/* Duplicates are removed. */
513
 
513
 
514
static SEXP NestTerms(SEXP left, SEXP right)
514
static SEXP NestTerms(SEXP left, SEXP right)
515
{
515
{
516
    SEXP term, t;
516
    SEXP term, t;
517
    int i;
517
    int i;
518
    PROTECT(left = EncodeVars(left));
518
    PROTECT(left = EncodeVars(left));
519
    PROTECT(right = EncodeVars(right));
519
    PROTECT(right = EncodeVars(right));
520
    PROTECT(term = AllocTerm());
520
    PROTECT(term = AllocTerm());
521
    /* Bitwise or of all terms on left */
521
    /* Bitwise or of all terms on left */
522
    for (t = left; t != R_NilValue; t = CDR(t)) {
522
    for (t = left; t != R_NilValue; t = CDR(t)) {
523
	for (i = 0; i < nwords; i++)
523
	for (i = 0; i < nwords; i++)
524
	    INTEGER(term)[i] = INTEGER(term)[i] | INTEGER(CAR(t))[i];
524
	    INTEGER(term)[i] = INTEGER(term)[i] | INTEGER(CAR(t))[i];
525
    }
525
    }
526
    /* Now bitwise or with each term on the right */
526
    /* Now bitwise or with each term on the right */
527
    for (t = right; t != R_NilValue; t = CDR(t))
527
    for (t = right; t != R_NilValue; t = CDR(t))
528
	for (i = 0; i < nwords; i++)
528
	for (i = 0; i < nwords; i++)
529
	    INTEGER(CAR(t))[i] = INTEGER(term)[i] | INTEGER(CAR(t))[i];
529
	    INTEGER(CAR(t))[i] = INTEGER(term)[i] | INTEGER(CAR(t))[i];
530
    UNPROTECT(3);
530
    UNPROTECT(3);
531
    listAppend(left, right);
531
    listAppend(left, right);
532
    return TrimRepeats(left);
532
    return TrimRepeats(left);
533
}
533
}
534
 
534
 
535
 
535
 
536
/* DeleteTerms expands ``left'' and ``right'' */
536
/* DeleteTerms expands ``left'' and ``right'' */
537
/* and then removes any terms which appear in */
537
/* and then removes any terms which appear in */
538
/* ``right'' from ``left''. */
538
/* ``right'' from ``left''. */
539
 
539
 
540
static SEXP DeleteTerms(SEXP left, SEXP right)
540
static SEXP DeleteTerms(SEXP left, SEXP right)
541
{
541
{
542
    SEXP t;
542
    SEXP t;
543
    PROTECT(left = EncodeVars(left));
543
    PROTECT(left = EncodeVars(left));
544
    parity = 1-parity;
544
    parity = 1-parity;
545
    PROTECT(right = EncodeVars(right));
545
    PROTECT(right = EncodeVars(right));
546
    parity = 1-parity;
546
    parity = 1-parity;
547
    for (t = right; t != R_NilValue; t = CDR(t))
547
    for (t = right; t != R_NilValue; t = CDR(t))
548
	left = StripTerm(CAR(t), left);
548
	left = StripTerm(CAR(t), left);
549
    UNPROTECT(2);
549
    UNPROTECT(2);
550
    return left;
550
    return left;
551
}
551
}
552
 
552
 
553
 
553
 
554
/* EncodeVars performs  model expansion and bit string encoding. */
554
/* EncodeVars performs  model expansion and bit string encoding. */
555
/* This is the real workhorse of model expansion. */
555
/* This is the real workhorse of model expansion. */
556
 
556
 
557
static SEXP EncodeVars(SEXP formula)
557
static SEXP EncodeVars(SEXP formula)
558
{
558
{
559
    SEXP term;
559
    SEXP term;
560
    int len;
560
    int len;
561
 
561
 
562
    if (isNull(formula))
562
    if (isNull(formula))
563
	return R_NilValue;
563
	return R_NilValue;
564
 
564
 
565
    if (isOne(formula)) {
565
    if (isOne(formula)) {
566
	if (parity) intercept = 1;
566
	if (parity) intercept = 1;
567
	else intercept = 0;
567
	else intercept = 0;
568
	return R_NilValue;
568
	return R_NilValue;
569
    }
569
    }
570
    else if (isZero(formula)) {
570
    else if (isZero(formula)) {
571
	if (parity) intercept = 0;
571
	if (parity) intercept = 0;
572
	else intercept = 1;
572
	else intercept = 1;
573
	return R_NilValue;
573
	return R_NilValue;
574
    }
574
    }
575
    if (isSymbol(formula)) {
575
    if (isSymbol(formula)) {
576
	if (formula == dotSymbol && framenames != R_NilValue) {
576
	if (formula == dotSymbol && framenames != R_NilValue) {
577
	    /* prior to 1.7.0 this made term.labels in reverse order. */
577
	    /* prior to 1.7.0 this made term.labels in reverse order. */
578
	    SEXP r = R_NilValue, v = R_NilValue; /* -Wall */
578
	    SEXP r = R_NilValue, v = R_NilValue; /* -Wall */
579
	    int i, j; char *c;
579
	    int i, j; char *c;
580
 
580
 
581
	    if (!LENGTH(framenames)) return r;
581
	    if (!LENGTH(framenames)) return r;
582
	    for (i = 0; i < LENGTH(framenames); i++) {
582
	    for (i = 0; i < LENGTH(framenames); i++) {
583
		/* change in 1.6.0 do not use duplicated names */
583
		/* change in 1.6.0 do not use duplicated names */
584
		c = CHAR(STRING_ELT(framenames, i));
584
		c = CHAR(STRING_ELT(framenames, i));
585
		for(j = 0; j < i; j++)
585
		for(j = 0; j < i; j++)
586
		    if(!strcmp(c, CHAR(STRING_ELT(framenames, j))))
586
		    if(!strcmp(c, CHAR(STRING_ELT(framenames, j))))
587
			error("duplicated name `%s' in data frame using `.'", 
587
			error("duplicated name `%s' in data frame using `.'", 
588
			      c);
588
			      c);
589
		term = AllocTerm();
589
		term = AllocTerm();
590
		SetBit(term, InstallVar(install(c)), 1);
590
		SetBit(term, InstallVar(install(c)), 1);
591
		if(i == 0) PROTECT(v = r = cons(term, R_NilValue));
591
		if(i == 0) PROTECT(v = r = cons(term, R_NilValue));
592
		else {SETCDR(v, CONS(term, R_NilValue)); v = CDR(v);}
592
		else {SETCDR(v, CONS(term, R_NilValue)); v = CDR(v);}
593
	    }
593
	    }
594
	    UNPROTECT(1);
594
	    UNPROTECT(1);
595
	    return r;
595
	    return r;
596
	}
596
	}
597
	else {
597
	else {
598
	    term = AllocTerm();
598
	    term = AllocTerm();
599
	    SetBit(term, InstallVar(formula), 1);
599
	    SetBit(term, InstallVar(formula), 1);
600
	    return CONS(term, R_NilValue);
600
	    return CONS(term, R_NilValue);
601
	}
601
	}
602
    }
602
    }
603
    if (isLanguage(formula)) {
603
    if (isLanguage(formula)) {
604
	len = length(formula);
604
	len = length(formula);
605
	if (CAR(formula) == tildeSymbol) {
605
	if (CAR(formula) == tildeSymbol) {
606
	    if (isNull(CDDR(formula)))
606
	    if (isNull(CDDR(formula)))
607
		return EncodeVars(CADR(formula));
607
		return EncodeVars(CADR(formula));
608
	    else
608
	    else
609
		return EncodeVars(CADDR(formula));
609
		return EncodeVars(CADDR(formula));
610
	}
610
	}
611
	if (CAR(formula) == plusSymbol) {
611
	if (CAR(formula) == plusSymbol) {
612
	    if (len == 2)
612
	    if (len == 2)
613
		return EncodeVars(CADR(formula));
613
		return EncodeVars(CADR(formula));
614
	    else
614
	    else
615
		return PlusTerms(CADR(formula), CADDR(formula));
615
		return PlusTerms(CADR(formula), CADDR(formula));
616
	}
616
	}
617
	if (CAR(formula) == colonSymbol) {
617
	if (CAR(formula) == colonSymbol) {
618
	    return InteractTerms(CADR(formula), CADDR(formula));
618
	    return InteractTerms(CADR(formula), CADDR(formula));
619
	}
619
	}
620
	if (CAR(formula) == timesSymbol) {
620
	if (CAR(formula) == timesSymbol) {
621
	    return CrossTerms(CADR(formula), CADDR(formula));
621
	    return CrossTerms(CADR(formula), CADDR(formula));
622
	}
622
	}
623
	if (CAR(formula) == inSymbol) {
623
	if (CAR(formula) == inSymbol) {
624
	    return InTerms(CADR(formula), CADDR(formula));
624
	    return InTerms(CADR(formula), CADDR(formula));
625
	}
625
	}
626
	if (CAR(formula) == slashSymbol) {
626
	if (CAR(formula) == slashSymbol) {
627
	    return NestTerms(CADR(formula), CADDR(formula));
627
	    return NestTerms(CADR(formula), CADDR(formula));
628
	}
628
	}
629
	if (CAR(formula) == powerSymbol) {
629
	if (CAR(formula) == powerSymbol) {
630
	    return PowerTerms(CADR(formula), CADDR(formula));
630
	    return PowerTerms(CADR(formula), CADDR(formula));
631
	}
631
	}
632
	if (CAR(formula) == minusSymbol) {
632
	if (CAR(formula) == minusSymbol) {
633
	    if (len == 2)
633
	    if (len == 2)
634
		return DeleteTerms(R_NilValue, CADR(formula));
634
		return DeleteTerms(R_NilValue, CADR(formula));
635
	    return DeleteTerms(CADR(formula), CADDR(formula));
635
	    return DeleteTerms(CADR(formula), CADDR(formula));
636
	}
636
	}
637
	if (CAR(formula) == parenSymbol) {
637
	if (CAR(formula) == parenSymbol) {
638
	    return EncodeVars(CADR(formula));
638
	    return EncodeVars(CADR(formula));
639
	}
639
	}
640
	term = AllocTerm();
640
	term = AllocTerm();
641
	SetBit(term, InstallVar(formula), 1);
641
	SetBit(term, InstallVar(formula), 1);
642
	return CONS(term, R_NilValue);
642
	return CONS(term, R_NilValue);
643
    }
643
    }
644
    error("invalid model formula in EncodeVars");
644
    error("invalid model formula in EncodeVars");
645
    return R_NilValue;/*NOTREACHED*/
645
    return R_NilValue;/*NOTREACHED*/
646
}
646
}
647
 
647
 
648
 
648
 
649
/* TermCode decides on the encoding of a model term. */
649
/* TermCode decides on the encoding of a model term. */
650
/* Returns 1 if variable ``whichBit'' in ``thisTerm'' */
650
/* Returns 1 if variable ``whichBit'' in ``thisTerm'' */
651
/* is to be encoded by contrasts and 2 if it is to be */
651
/* is to be encoded by contrasts and 2 if it is to be */
652
/* encoded by dummy variables.  This is decided using */
652
/* encoded by dummy variables.  This is decided using */
653
/* the heuristic of Chambers and Heiberger described */
653
/* the heuristic of Chambers and Heiberger described */
654
/* in Statistical Models in S, Page 38. */
654
/* in Statistical Models in S, Page 38. */
655
 
655
 
656
static int TermCode(SEXP termlist, SEXP thisterm, int whichbit, SEXP term)
656
static int TermCode(SEXP termlist, SEXP thisterm, int whichbit, SEXP term)
657
{
657
{
658
    SEXP t;
658
    SEXP t;
659
    int allzero, i;
659
    int allzero, i;
660
 
660
 
661
    for (i = 0; i < nwords; i++)
661
    for (i = 0; i < nwords; i++)
662
	INTEGER(term)[i] = INTEGER(CAR(thisterm))[i];
662
	INTEGER(term)[i] = INTEGER(CAR(thisterm))[i];
663
 
663
 
664
    /* Eliminate factor ``whichbit'' */
664
    /* Eliminate factor ``whichbit'' */
665
 
665
 
666
    SetBit(term, whichbit, 0);
666
    SetBit(term, whichbit, 0);
667
 
667
 
668
    /* Search preceding terms for a match */
668
    /* Search preceding terms for a match */
669
    /* Zero is a possibility - it is a special case */
669
    /* Zero is a possibility - it is a special case */
670
 
670
 
671
    allzero = 1;
671
    allzero = 1;
672
    for (i = 0; i < nwords; i++) {
672
    for (i = 0; i < nwords; i++) {
673
	if (INTEGER(term)[i]) {
673
	if (INTEGER(term)[i]) {
674
	    allzero = 0;
674
	    allzero = 0;
675
	    break;
675
	    break;
676
	}
676
	}
677
    }
677
    }
678
    if (allzero)
678
    if (allzero)
679
	return 1;
679
	return 1;
680
 
680
 
681
    for (t = termlist; t != thisterm; t = CDR(t)) {
681
    for (t = termlist; t != thisterm; t = CDR(t)) {
682
	allzero = 1;
682
	allzero = 1;
683
	for (i = 0; i < nwords; i++) {
683
	for (i = 0; i < nwords; i++) {
684
	    if ((~(INTEGER(CAR(t))[i])) & INTEGER(term)[i])
684
	    if ((~(INTEGER(CAR(t))[i])) & INTEGER(term)[i])
685
		allzero = 0;
685
		allzero = 0;
686
	}
686
	}
687
	if (allzero)
687
	if (allzero)
688
	    return 1;
688
	    return 1;
689
    }
689
    }
690
    return 2;
690
    return 2;
691
}
691
}
692

692

693
 
693
 
694
/* Internal code for the ``terms'' function */
694
/* Internal code for the ``terms'' function */
695
/* The value is a formula with an assortment */
695
/* The value is a formula with an assortment */
696
/* of useful attributes. */
696
/* of useful attributes. */
697
 
697
 
698
/* .Internal(terms.formula(x, new.specials, abb, data, keep.order)) */
698
/* .Internal(terms.formula(x, new.specials, abb, data, keep.order)) */
699
 
699
 
700
static SEXP ExpandDots(SEXP object, SEXP value);
700
static SEXP ExpandDots(SEXP object, SEXP value);
701
 
701
 
702
SEXP do_termsform(SEXP call, SEXP op, SEXP args, SEXP rho)
702
SEXP do_termsform(SEXP call, SEXP op, SEXP args, SEXP rho)
703
{
703
{
704
    SEXP a, ans, v, pattern, formula, varnames, term, termlabs;
704
    SEXP a, ans, v, pattern, formula, varnames, term, termlabs;
705
    SEXP specials, t, data, rhs;
705
    SEXP specials, t, data, rhs;
706
    int i, j, k, l, n, keepOrder;
706
    int i, j, k, l, n, keepOrder;
707
 
707
 
708
    checkArity(op, args);
708
    checkArity(op, args);
709
 
709
 
710
    /* Always fetch these values rather than trying */
710
    /* Always fetch these values rather than trying */
711
    /* to remember them between calls.  The overhead */
711
    /* to remember them between calls.  The overhead */
712
    /* is minimal and we don't have to worry about */
712
    /* is minimal and we don't have to worry about */
713
    /* intervening dump/restore problems. */
713
    /* intervening dump/restore problems. */
714
 
714
 
715
    tildeSymbol = install("~");
715
    tildeSymbol = install("~");
716
    plusSymbol  = install("+");
716
    plusSymbol  = install("+");
717
    minusSymbol = install("-");
717
    minusSymbol = install("-");
718
    timesSymbol = install("*");
718
    timesSymbol = install("*");
719
    slashSymbol = install("/");
719
    slashSymbol = install("/");
720
    colonSymbol = install(":");
720
    colonSymbol = install(":");
721
    powerSymbol = install("^");
721
    powerSymbol = install("^");
722
    dotSymbol   = install(".");
722
    dotSymbol   = install(".");
723
    parenSymbol = install("(");
723
    parenSymbol = install("(");
724
    inSymbol = install("%in%");
724
    inSymbol = install("%in%");
725
    /* identSymbol = install("I"); */
725
    /* identSymbol = install("I"); */
726
 
726
 
727
    /* Do we have a model formula? */
727
    /* Do we have a model formula? */
728
    /* Check for unary or binary ~ */
728
    /* Check for unary or binary ~ */
729
 
729
 
730
    if (!isLanguage(CAR(args)) ||
730
    if (!isLanguage(CAR(args)) ||
731
	CAR(CAR(args)) != tildeSymbol ||
731
	CAR(CAR(args)) != tildeSymbol ||
732
	(length(CAR(args)) != 2 && length(CAR(args)) != 3))
732
	(length(CAR(args)) != 2 && length(CAR(args)) != 3))
733
	error("argument is not a valid model");
733
	error("argument is not a valid model");
734
 
734
 
735
    haveDot = FALSE;
735
    haveDot = FALSE;
736
    
736
    
737
    PROTECT(ans = duplicate(CAR(args)));
737
    PROTECT(ans = duplicate(CAR(args)));
738
 
738
 
739
    /* The formula will be returned, modified if haveDot becomes TRUE */
739
    /* The formula will be returned, modified if haveDot becomes TRUE */
740
 
740
 
741
    specials = CADR(args);
741
    specials = CADR(args);
742
    a = CDDR(args);
742
    a = CDDR(args);
743
 
743
 
744
    /* We use data to get the value to */
744
    /* We use data to get the value to */
745
    /* substitute for "." in formulae */
745
    /* substitute for "." in formulae */
746
 
746
 
747
    data = CAR(a);
747
    data = CAR(a);
748
    a = CDR(a);
748
    a = CDR(a);
749
    if (isNull(data) || isEnvironment(data))
749
    if (isNull(data) || isEnvironment(data))
750
	framenames = R_NilValue;
750
	framenames = R_NilValue;
751
    else if (isFrame(data))
751
    else if (isFrame(data))
752
	framenames = getAttrib(data, R_NamesSymbol);
752
	framenames = getAttrib(data, R_NamesSymbol);
753
    else
753
    else
754
	errorcall(call,"data argument is of the wrong type");
754
	errorcall(call,"data argument is of the wrong type");
755
 
755
 
756
    if (framenames != R_NilValue)
756
    if (framenames != R_NilValue)
757
	if (length(CAR(args))== 3)
757
	if (length(CAR(args))== 3)
758
	    CheckRHS(CADR(CAR(args)));
758
	    CheckRHS(CADR(CAR(args)));
759
 
759
 
760
    /* Preserve term order? */
760
    /* Preserve term order? */
761
 
761
 
762
    keepOrder = asLogical(CAR(a));
762
    keepOrder = asLogical(CAR(a));
763
    if (keepOrder == NA_LOGICAL)
763
    if (keepOrder == NA_LOGICAL)
764
	keepOrder = 0;
764
	keepOrder = 0;
765
 
765
 
766
    if (specials == R_NilValue) {
766
    if (specials == R_NilValue) {
767
	a = allocList(8);
767
	a = allocList(8);
768
	SET_ATTRIB(ans, a);
768
	SET_ATTRIB(ans, a);
769
    }
769
    }
770
    else {
770
    else {
771
	a = allocList(9);
771
	a = allocList(9);
772
	SET_ATTRIB(ans, a);
772
	SET_ATTRIB(ans, a);
773
    }
773
    }
774
 
774
 
775
    /* Step 1: Determine the ``variables'' in the model */
775
    /* Step 1: Determine the ``variables'' in the model */
776
    /* Here we create an expression of the form */
776
    /* Here we create an expression of the form */
777
    /* list(...).  You can evaluate it to get */
777
    /* list(...).  You can evaluate it to get */
778
    /* the model variables or use substitute and then */
778
    /* the model variables or use substitute and then */
779
    /* pull the result apart to get the variable names. */
779
    /* pull the result apart to get the variable names. */
780
 
780
 
781
    intercept = 1;
781
    intercept = 1;
782
    parity = 1;
782
    parity = 1;
783
    response = 0;
783
    response = 0;
784
    PROTECT(varlist = lcons(install("list"), R_NilValue));
784
    PROTECT(varlist = lcons(install("list"), R_NilValue));
785
    ExtractVars(CAR(args), 1);
785
    ExtractVars(CAR(args), 1);
786
    UNPROTECT(1);
786
    UNPROTECT(1);
787
    SETCAR(a, varlist);
787
    SETCAR(a, varlist);
788
    SET_TAG(a, install("variables"));
788
    SET_TAG(a, install("variables"));
789
    a = CDR(a);
789
    a = CDR(a);
790
 
790
 
791
    nvar = length(varlist) - 1;
791
    nvar = length(varlist) - 1;
792
    nwords = (nvar - 1) / WORDSIZE + 1;
792
    nwords = (nvar - 1) / WORDSIZE + 1;
793
 
793
 
794
    /* Step 2: Recode the model terms in binary form */
794
    /* Step 2: Recode the model terms in binary form */
795
    /* and at the same time, expand the model formula. */
795
    /* and at the same time, expand the model formula. */
796
 
796
 
797
    /* FIXME: this includes specials in the model */
797
    /* FIXME: this includes specials in the model */
798
    /* There perhaps needs to be a an extra pass */
798
    /* There perhaps needs to be a an extra pass */
799
    /* through the model to delete any terms which */
799
    /* through the model to delete any terms which */
800
    /* contain specials.  Actually, specials should */
800
    /* contain specials.  Actually, specials should */
801
    /* only enter additively so this should also be */
801
    /* only enter additively so this should also be */
802
    /* checked and abort forced if not. */
802
    /* checked and abort forced if not. */
803
 
803
 
804
    /* BDR 2002-01-29: S does include specials, so code may rely on this */
804
    /* BDR 2002-01-29: S does include specials, so code may rely on this */
805
 
805
 
806
    /* FIXME: this is also the point where nesting */
806
    /* FIXME: this is also the point where nesting */
807
    /* needs to be taken care of. */
807
    /* needs to be taken care of. */
808
 
808
 
809
    PROTECT(formula = EncodeVars(CAR(args)));
809
    PROTECT(formula = EncodeVars(CAR(args)));
810
 
810
 
811
    nvar = length(varlist) - 1; /* need to recompute, in case
811
    nvar = length(varlist) - 1; /* need to recompute, in case
812
                                   EncodeVars stretched it */
812
                                   EncodeVars stretched it */
813
 
813
 
814
    /* Step 2a: Compute variable names */
814
    /* Step 2a: Compute variable names */
815
 
815
 
816
    PROTECT(varnames = allocVector(STRSXP, nvar));
816
    PROTECT(varnames = allocVector(STRSXP, nvar));
817
    for (v = CDR(varlist), i = 0; v != R_NilValue; v = CDR(v))
817
    for (v = CDR(varlist), i = 0; v != R_NilValue; v = CDR(v))
818
	SET_STRING_ELT(varnames, i++, STRING_ELT(deparse1line(CAR(v), 0), 0));
818
	SET_STRING_ELT(varnames, i++, STRING_ELT(deparse1line(CAR(v), 0), 0));
819
    
819
    
820
    /* Step 2b: Remove any offset(s) */
820
    /* Step 2b: Remove any offset(s) */
821
 
821
 
822
    for (l = response, k = 0; l < nvar; l++)
822
    for (l = response, k = 0; l < nvar; l++)
823
	if (!strncmp(CHAR(STRING_ELT(varnames, l)), "offset(", 7)) k++;
823
	if (!strncmp(CHAR(STRING_ELT(varnames, l)), "offset(", 7)) k++;
824
    SETCAR(a, v = allocVector(INTSXP, k));
824
    SETCAR(a, v = allocVector(INTSXP, k));
825
    if (k > 0) {
825
    if (k > 0) {
826
	for (l = response, k = 0; l < nvar; l++)
826
	for (l = response, k = 0; l < nvar; l++)
827
	    if (!strncmp(CHAR(STRING_ELT(varnames, l)), "offset(", 7))
827
	    if (!strncmp(CHAR(STRING_ELT(varnames, l)), "offset(", 7))
828
		INTEGER(v)[k++] = l + 1;
828
		INTEGER(v)[k++] = l + 1;
829
	call = formula; /* call is to be the previous value */
829
	call = formula; /* call is to be the previous value */
830
	for (l = response, k = 0; l < length(formula)+response; l++) {
830
	for (l = response, k = 0; l < length(formula)+response; l++) {
831
	    SEXP thisterm;
831
	    SEXP thisterm;
832
	    Rboolean have_offset = FALSE;
832
	    Rboolean have_offset = FALSE;
833
	    thisterm = (l > response) ? CDR(call): call;
833
	    thisterm = (l > response) ? CDR(call): call;
834
	    for (i = 1; i <= nvar; i++) {
834
	    for (i = 1; i <= nvar; i++) {
835
		if (GetBit(CAR(thisterm), i) &&
835
		if (GetBit(CAR(thisterm), i) &&
836
		    !strncmp(CHAR(STRING_ELT(varnames, i-1)), "offset(", 7)) {
836
		    !strncmp(CHAR(STRING_ELT(varnames, i-1)), "offset(", 7)) {
837
		    have_offset = TRUE;
837
		    have_offset = TRUE;
838
		    break;
838
		    break;
839
		}
839
		}
840
	    }
840
	    }
841
	    if (have_offset) {
841
	    if (have_offset) {
842
		if (l == response) call = formula = CDR(formula);
842
		if (l == response) call = formula = CDR(formula);
843
		else SETCDR(call, CDR(CDR(call)));
843
		else SETCDR(call, CDR(CDR(call)));
844
	    } else if (l > response) call = CDR(call);
844
	    } else if (l > response) call = CDR(call);
845
	}
845
	}
846
	SET_TAG(a, install("offset"));
846
	SET_TAG(a, install("offset"));
847
	a = CDR(a);
847
	a = CDR(a);
848
    }
848
    }
849
    nterm = length(formula);
849
    nterm = length(formula);
850
 
850
 
851
    /* Step 3: Reorder the model terms by BitCount, otherwise
851
    /* Step 3: Reorder the model terms by BitCount, otherwise
852
       preserving their order. */
852
       preserving their order. */
853
 
853
 
854
    if (!keepOrder) {
854
    if (!keepOrder) {
855
	SEXP sCounts;
855
	SEXP sCounts;
856
	int *counts, bitmax = 0;
856
	int *counts, bitmax = 0;
857
 
857
 
858
	PROTECT(pattern = allocVector(VECSXP, nterm));
858
	PROTECT(pattern = allocVector(VECSXP, nterm));
859
	PROTECT(sCounts = allocVector(INTSXP, nterm));
859
	PROTECT(sCounts = allocVector(INTSXP, nterm));
860
	counts = INTEGER(sCounts);
860
	counts = INTEGER(sCounts);
861
	for (call = formula, n = 0; call != R_NilValue; call = CDR(call)) {
861
	for (call = formula, n = 0; call != R_NilValue; call = CDR(call)) {
862
	    SET_VECTOR_ELT(pattern, n, CAR(call));
862
	    SET_VECTOR_ELT(pattern, n, CAR(call));
863
	    counts[n++] = BitCount(CAR(call));
863
	    counts[n++] = BitCount(CAR(call));
864
	}
864
	}
865
	for (n = 0; n < nterm; n++) 
865
	for (n = 0; n < nterm; n++) 
866
	    if(counts[n] > bitmax) bitmax = counts[n];
866
	    if(counts[n] > bitmax) bitmax = counts[n];
867
	call = formula;
867
	call = formula;
868
	for (i = 0; i <= bitmax; i++) /* can order 0 occur? */
868
	for (i = 0; i <= bitmax; i++) /* can order 0 occur? */
869
	    for (n = 0; n < nterm; n++)
869
	    for (n = 0; n < nterm; n++)
870
		if (counts[n] == i) {
870
		if (counts[n] == i) {
871
		    SETCAR(call, VECTOR_ELT(pattern, n));
871
		    SETCAR(call, VECTOR_ELT(pattern, n));
872
		    SETLEVELS(CAR(call), i);
872
		    SETLEVELS(CAR(call), i);
873
		    call = CDR(call);
873
		    call = CDR(call);
874
		}
874
		}
875
	UNPROTECT(2);
875
	UNPROTECT(2);
876
    }
876
    }
877
    
877
    
878
 
878
 
879
    /* Step 4: Compute the factor pattern for the model. */
879
    /* Step 4: Compute the factor pattern for the model. */
880
    /* 0 - the variable does not appear in this term. */
880
    /* 0 - the variable does not appear in this term. */
881
    /* 1 - code the variable by contrasts in this term. */
881
    /* 1 - code the variable by contrasts in this term. */
882
    /* 2 - code the variable by indicators in this term. */
882
    /* 2 - code the variable by indicators in this term. */
883
 
883
 
884
    if (nterm > 0) {
884
    if (nterm > 0) {
885
	SETCAR(a, pattern = allocMatrix(INTSXP, nvar, nterm));
885
	SETCAR(a, pattern = allocMatrix(INTSXP, nvar, nterm));
886
	SET_TAG(a, install("factors"));
886
	SET_TAG(a, install("factors"));
887
	a = CDR(a);
887
	a = CDR(a);
888
	for (i = 0; i < nterm * nvar; i++)
888
	for (i = 0; i < nterm * nvar; i++)
889
	    INTEGER(pattern)[i] = 0;
889
	    INTEGER(pattern)[i] = 0;
890
	PROTECT(term = AllocTerm());
890
	PROTECT(term = AllocTerm());
891
	n = 0;
891
	n = 0;
892
	for (call = formula; call != R_NilValue; call = CDR(call)) {
892
	for (call = formula; call != R_NilValue; call = CDR(call)) {
893
	    for (i = 1; i <= nvar; i++) {
893
	    for (i = 1; i <= nvar; i++) {
894
		if (GetBit(CAR(call), i))
894
		if (GetBit(CAR(call), i))
895
		    INTEGER(pattern)[i-1+n*nvar] =
895
		    INTEGER(pattern)[i-1+n*nvar] =
896
			TermCode(formula, call, i, term);
896
			TermCode(formula, call, i, term);
897
	    }
897
	    }
898
	    n++;
898
	    n++;
899
	}
899
	}
900
	UNPROTECT(1);
900
	UNPROTECT(1);
901
    }
901
    }
902
    else {
902
    else {
903
	SETCAR(a, pattern = allocVector(INTSXP,0));
903
	SETCAR(a, pattern = allocVector(INTSXP,0));
904
	SET_TAG(a, install("factors"));
904
	SET_TAG(a, install("factors"));
905
	a = CDR(a);
905
	a = CDR(a);
906
    }
906
    }
907
 
907
 
908
    /* Step 5: Compute term labels */
908
    /* Step 5: Compute term labels */
909
 
909
 
910
    PROTECT(termlabs = allocVector(STRSXP, nterm));
910
    PROTECT(termlabs = allocVector(STRSXP, nterm));
911
    n = 0;
911
    n = 0;
912
    for (call = formula; call != R_NilValue; call = CDR(call)) {
912
    for (call = formula; call != R_NilValue; call = CDR(call)) {
913
	l = 0;
913
	l = 0;
914
	for (i = 1; i <= nvar; i++) {
914
	for (i = 1; i <= nvar; i++) {
915
	    if (GetBit(CAR(call), i)) {
915
	    if (GetBit(CAR(call), i)) {
916
		if (l > 0)
916
		if (l > 0)
917
		    l += 1;
917
		    l += 1;
918
		l += strlen(CHAR(STRING_ELT(varnames, i - 1)));
918
		l += strlen(CHAR(STRING_ELT(varnames, i - 1)));
919
	    }
919
	    }
920
	}
920
	}
921
	SET_STRING_ELT(termlabs, n, allocString(l));
921
	SET_STRING_ELT(termlabs, n, allocString(l));
922
	CHAR(STRING_ELT(termlabs, n))[0] = '\0';
922
	CHAR(STRING_ELT(termlabs, n))[0] = '\0';
923
	l = 0;
923
	l = 0;
924
	for (i = 1; i <= nvar; i++) {
924
	for (i = 1; i <= nvar; i++) {
925
	    if (GetBit(CAR(call), i)) {
925
	    if (GetBit(CAR(call), i)) {
926
		if (l > 0)
926
		if (l > 0)
927
		    strcat(CHAR(STRING_ELT(termlabs, n)), ":");
927
		    strcat(CHAR(STRING_ELT(termlabs, n)), ":");
928
		strcat(CHAR(STRING_ELT(termlabs, n)), 
928
		strcat(CHAR(STRING_ELT(termlabs, n)), 
929
		       CHAR(STRING_ELT(varnames, i - 1)));
929
		       CHAR(STRING_ELT(varnames, i - 1)));
930
		l++;
930
		l++;
931
	    }
931
	    }
932
	}
932
	}
933
	n++;
933
	n++;
934
    }
934
    }
935
    PROTECT(v = allocVector(VECSXP, 2));
935
    PROTECT(v = allocVector(VECSXP, 2));
936
    SET_VECTOR_ELT(v, 0, varnames);
936
    SET_VECTOR_ELT(v, 0, varnames);
937
    SET_VECTOR_ELT(v, 1, termlabs);
937
    SET_VECTOR_ELT(v, 1, termlabs);
938
    if (nterm > 0)
938
    if (nterm > 0)
939
	setAttrib(pattern, R_DimNamesSymbol, v);
939
	setAttrib(pattern, R_DimNamesSymbol, v);
940
 
940
 
941
    SETCAR(a, termlabs);
941
    SETCAR(a, termlabs);
942
    SET_TAG(a, install("term.labels"));
942
    SET_TAG(a, install("term.labels"));
943
    a = CDR(a);
943
    a = CDR(a);
944
 
944
 
945
    /* If there are specials stick them in here */
945
    /* If there are specials stick them in here */
946
 
946
 
947
    if (specials != R_NilValue) {
947
    if (specials != R_NilValue) {
948
	i = length(specials);
948
	i = length(specials);
949
	PROTECT(v = allocList(i));
949
	PROTECT(v = allocList(i));
950
	for (j = 0, t = v; j < i; j++, t = CDR(t)) {
950
	for (j = 0, t = v; j < i; j++, t = CDR(t)) {
951
	    SET_TAG(t, install(CHAR(STRING_ELT(specials, j))));
951
	    SET_TAG(t, install(CHAR(STRING_ELT(specials, j))));
952
	    n = strlen(CHAR(STRING_ELT(specials, j)));
952
	    n = strlen(CHAR(STRING_ELT(specials, j)));
953
	    SETCAR(t, allocVector(INTSXP, 0));
953
	    SETCAR(t, allocVector(INTSXP, 0));
954
	    k = 0;
954
	    k = 0;
955
	    for (l = 0; l < nvar; l++) {
955
	    for (l = 0; l < nvar; l++) {
956
		if (!strncmp(CHAR(STRING_ELT(varnames, l)),
956
		if (!strncmp(CHAR(STRING_ELT(varnames, l)),
957
			    CHAR(STRING_ELT(specials, j)), n))
957
			    CHAR(STRING_ELT(specials, j)), n))
958
		    if (CHAR(STRING_ELT(varnames, l))[n] == '(')
958
		    if (CHAR(STRING_ELT(varnames, l))[n] == '(')
959
			k++;
959
			k++;
960
	    }
960
	    }
961
	    if (k > 0) {
961
	    if (k > 0) {
962
		SETCAR(t, allocVector(INTSXP, k));
962
		SETCAR(t, allocVector(INTSXP, k));
963
		k = 0;
963
		k = 0;
964
		for (l = 0; l < nvar; l++) {
964
		for (l = 0; l < nvar; l++) {
965
		    if (!strncmp(CHAR(STRING_ELT(varnames, l)),
965
		    if (!strncmp(CHAR(STRING_ELT(varnames, l)),
966
				CHAR(STRING_ELT(specials, j)), n))
966
				CHAR(STRING_ELT(specials, j)), n))
967
			if (CHAR(STRING_ELT(varnames, l))[n] == '('){
967
			if (CHAR(STRING_ELT(varnames, l))[n] == '('){
968
			    INTEGER(CAR(t))[k++] = l+1;
968
			    INTEGER(CAR(t))[k++] = l+1;
969
			}
969
			}
970
		}
970
		}
971
	    }
971
	    }
972
	    else SETCAR(t, R_NilValue);
972
	    else SETCAR(t, R_NilValue);
973
	}
973
	}
974
	SETCAR(a, v);
974
	SETCAR(a, v);
975
	SET_TAG(a, install("specials"));
975
	SET_TAG(a, install("specials"));
976
	a = CDR(a);
976
	a = CDR(a);
977
	UNPROTECT(1);
977
	UNPROTECT(1);
978
    }
978
    }
979
 
979
 
980
    UNPROTECT(3);	/* keep termlabs until here */
980
    UNPROTECT(3);	/* keep termlabs until here */
981
 
981
 
982
    /* Step 6: Fix up the formula by substituting for dot, which should be 
982
    /* Step 6: Fix up the formula by substituting for dot, which should be 
983
       the framenames joined by + */
983
       the framenames joined by + */
984
 
984
 
985
    if (haveDot && LENGTH(framenames)) {
985
    if (haveDot && LENGTH(framenames)) {
-
 
986
	PROTECT_INDEX ind;
986
	PROTECT(rhs = install(CHAR(STRING_ELT(framenames, 0))));
987
	PROTECT_WITH_INDEX(rhs = install(CHAR(STRING_ELT(framenames, 0))), 
-
 
988
			   &ind);
987
	for (i = 1; i < LENGTH(framenames); i++) {
989
	for (i = 1; i < LENGTH(framenames); i++) {
988
	    UNPROTECT(1);
-
 
989
	    PROTECT(rhs = lang3(plusSymbol, rhs, 
990
	    REPROTECT(rhs = lang3(plusSymbol, rhs, 
990
				install(CHAR(STRING_ELT(framenames, i)))));
991
				  install(CHAR(STRING_ELT(framenames, i)))),
-
 
992
		      ind);
991
	}
993
	}
992
	if (!isNull(CADDR(ans)))
994
	if (!isNull(CADDR(ans)))
993
	    SETCADDR(ans, ExpandDots(CADDR(ans), rhs));
995
	    SETCADDR(ans, ExpandDots(CADDR(ans), rhs));
994
	else
996
	else
995
	    SETCADR(ans, ExpandDots(CADR(ans), rhs));
997
	    SETCADR(ans, ExpandDots(CADR(ans), rhs));
996
	UNPROTECT(1);
998
	UNPROTECT(1);
997
    }
999
    }
998
 
1000
 
999
    SETCAR(a, allocVector(INTSXP, nterm));
1001
    SETCAR(a, allocVector(INTSXP, nterm));
1000
    n = 0;
1002
    n = 0;
1001
    for (call = formula; call != R_NilValue; call = CDR(call))
1003
    for (call = formula; call != R_NilValue; call = CDR(call))
1002
	INTEGER(CAR(a))[n++] = LEVELS(CAR(call));
1004
	INTEGER(CAR(a))[n++] = LEVELS(CAR(call));
1003
    SET_TAG(a, install("order"));
1005
    SET_TAG(a, install("order"));
1004
    a = CDR(a);
1006
    a = CDR(a);
1005
 
1007
 
1006
    SETCAR(a, allocVector(INTSXP, 1));
1008
    SETCAR(a, allocVector(INTSXP, 1));
1007
    INTEGER(CAR(a))[0] = (intercept != 0);
1009
    INTEGER(CAR(a))[0] = (intercept != 0);
1008
    SET_TAG(a, install("intercept"));
1010
    SET_TAG(a, install("intercept"));
1009
    a = CDR(a);
1011
    a = CDR(a);
1010
 
1012
 
1011
    SETCAR(a, allocVector(INTSXP, 1));
1013
    SETCAR(a, allocVector(INTSXP, 1));
1012
    INTEGER(CAR(a))[0] = (response != 0);
1014
    INTEGER(CAR(a))[0] = (response != 0);
1013
    SET_TAG(a, install("response"));
1015
    SET_TAG(a, install("response"));
1014
    a = CDR(a);
1016
    a = CDR(a);
1015
 
1017
 
1016
    SETCAR(a, mkString("terms"));
1018
    SETCAR(a, mkString("terms"));
1017
    SET_TAG(a, install("class"));
1019
    SET_TAG(a, install("class"));
1018
    SETCDR(a, R_NilValue);  /* truncate if necessary */
1020
    SETCDR(a, R_NilValue);  /* truncate if necessary */
1019
    SET_OBJECT(ans, 1);
1021
    SET_OBJECT(ans, 1);
1020
 
1022
 
1021
    UNPROTECT(2);
1023
    UNPROTECT(2);
1022
    return ans;
1024
    return ans;
1023
}
1025
}
1024
 
1026
 
1025
/* Update a model formula by the replacement of "." templates. */
1027
/* Update a model formula by the replacement of "." templates. */
1026
 
1028
 
1027
static SEXP ExpandDots(SEXP object, SEXP value)
1029
static SEXP ExpandDots(SEXP object, SEXP value)
1028
{
1030
{
1029
    SEXP op;
1031
    SEXP op;
1030
 
1032
 
1031
    if (TYPEOF(object) == SYMSXP) {
1033
    if (TYPEOF(object) == SYMSXP) {
1032
	if (object == dotSymbol)
1034
	if (object == dotSymbol)
1033
	    object = duplicate(value);
1035
	    object = duplicate(value);
1034
	return object;
1036
	return object;
1035
    }
1037
    }
1036
 
1038
 
1037
    if (TYPEOF(object) == LANGSXP) {
1039
    if (TYPEOF(object) == LANGSXP) {
1038
	if (TYPEOF(value) == LANGSXP) op = CAR(value);
1040
	if (TYPEOF(value) == LANGSXP) op = CAR(value);
1039
	else op = NULL;
1041
	else op = NULL;
1040
	PROTECT(object);
1042
	PROTECT(object);
1041
	if (CAR(object) == plusSymbol) {
1043
	if (CAR(object) == plusSymbol) {
1042
	    if (length(object) == 2) {
1044
	    if (length(object) == 2) {
1043
		SETCADR(object, ExpandDots(CADR(object), value));
1045
		SETCADR(object, ExpandDots(CADR(object), value));
1044
	    }
1046
	    }
1045
	    else if (length(object) == 3) {
1047
	    else if (length(object) == 3) {
1046
		SETCADR(object, ExpandDots(CADR(object), value));
1048
		SETCADR(object, ExpandDots(CADR(object), value));
1047
		SETCADDR(object, ExpandDots(CADDR(object), value));
1049
		SETCADDR(object, ExpandDots(CADDR(object), value));
1048
	    }
1050
	    }
1049
	    else goto badformula;
1051
	    else goto badformula;
1050
	}
1052
	}
1051
	else if (CAR(object) == minusSymbol) {
1053
	else if (CAR(object) == minusSymbol) {
1052
	    if (length(object) == 2) {
1054
	    if (length(object) == 2) {
1053
		if (CADR(object) == dotSymbol &&
1055
		if (CADR(object) == dotSymbol &&
1054
		   (op == plusSymbol || op == minusSymbol))
1056
		   (op == plusSymbol || op == minusSymbol))
1055
		    SETCADR(object, lang2(parenSymbol,
1057
		    SETCADR(object, lang2(parenSymbol,
1056
					  ExpandDots(CADR(object), value)));
1058
					  ExpandDots(CADR(object), value)));
1057
		else
1059
		else
1058
		    SETCADR(object, ExpandDots(CADR(object), value));
1060
		    SETCADR(object, ExpandDots(CADR(object), value));
1059
	    }
1061
	    }
1060
	    else if (length(object) == 3) {
1062
	    else if (length(object) == 3) {
1061
		if (CADR(object) == dotSymbol &&
1063
		if (CADR(object) == dotSymbol &&
1062
		   (op == plusSymbol || op == minusSymbol))
1064
		   (op == plusSymbol || op == minusSymbol))
1063
		    SETCADR(object, lang2(parenSymbol,
1065
		    SETCADR(object, lang2(parenSymbol,
1064
					  ExpandDots(CADR(object), value)));
1066
					  ExpandDots(CADR(object), value)));
1065
		else
1067
		else
1066
		    SETCADR(object, ExpandDots(CADR(object), value));
1068
		    SETCADR(object, ExpandDots(CADR(object), value));
1067
		if (CADDR(object) == dotSymbol &&
1069
		if (CADDR(object) == dotSymbol &&
1068
		   (op == plusSymbol || op == minusSymbol))
1070
		   (op == plusSymbol || op == minusSymbol))
1069
		    SETCADDR(object, lang2(parenSymbol,
1071
		    SETCADDR(object, lang2(parenSymbol,
1070
					   ExpandDots(CADDR(object), value)));
1072
					   ExpandDots(CADDR(object), value)));
1071
		else
1073
		else
1072
		    SETCADDR(object, ExpandDots(CADDR(object), value));
1074
		    SETCADDR(object, ExpandDots(CADDR(object), value));
1073
	    }
1075
	    }
1074
	    else goto badformula;
1076
	    else goto badformula;
1075
	}
1077
	}
1076
	else if (CAR(object) == timesSymbol || CAR(object) == slashSymbol) {
1078
	else if (CAR(object) == timesSymbol || CAR(object) == slashSymbol) {
1077
	    if (length(object) != 3)
1079
	    if (length(object) != 3)
1078
		goto badformula;
1080
		goto badformula;
1079
	    if (CADR(object) == dotSymbol &&
1081
	    if (CADR(object) == dotSymbol &&
1080
	       (op == plusSymbol || op == minusSymbol))
1082
	       (op == plusSymbol || op == minusSymbol))
1081
		SETCADR(object, lang2(parenSymbol,
1083
		SETCADR(object, lang2(parenSymbol,
1082
				      ExpandDots(CADR(object), value)));
1084
				      ExpandDots(CADR(object), value)));
1083
	    else
1085
	    else
1084
		SETCADR(object, ExpandDots(CADR(object), value));
1086
		SETCADR(object, ExpandDots(CADR(object), value));
1085
	    if (CADDR(object) == dotSymbol &&
1087
	    if (CADDR(object) == dotSymbol &&
1086
	       (op == plusSymbol || op == minusSymbol))
1088
	       (op == plusSymbol || op == minusSymbol))
1087
		SETCADDR(object, lang2(parenSymbol,
1089
		SETCADDR(object, lang2(parenSymbol,
1088
				       ExpandDots(CADDR(object), value)));
1090
				       ExpandDots(CADDR(object), value)));
1089
	    else
1091
	    else
1090
		SETCADDR(object, ExpandDots(CADDR(object), value));
1092
		SETCADDR(object, ExpandDots(CADDR(object), value));
1091
	}
1093
	}
1092
	else if (CAR(object) == colonSymbol) {
1094
	else if (CAR(object) == colonSymbol) {
1093
	    if (length(object) != 3)
1095
	    if (length(object) != 3)
1094
		goto badformula;
1096
		goto badformula;
1095
	    if (CADR(object) == dotSymbol &&
1097
	    if (CADR(object) == dotSymbol &&
1096
	       (op == plusSymbol || op == minusSymbol ||
1098
	       (op == plusSymbol || op == minusSymbol ||
1097
		op == timesSymbol || op == slashSymbol))
1099
		op == timesSymbol || op == slashSymbol))
1098
		SETCADR(object, lang2(parenSymbol,
1100
		SETCADR(object, lang2(parenSymbol,
1099
				      ExpandDots(CADR(object), value)));
1101
				      ExpandDots(CADR(object), value)));
1100
	    else
1102
	    else
1101
		SETCADR(object, ExpandDots(CADR(object), value));
1103
		SETCADR(object, ExpandDots(CADR(object), value));
1102
	    if (CADDR(object) == dotSymbol &&
1104
	    if (CADDR(object) == dotSymbol &&
1103
	       (op == plusSymbol || op == minusSymbol))
1105
	       (op == plusSymbol || op == minusSymbol))
1104
		SETCADDR(object, lang2(parenSymbol,
1106
		SETCADDR(object, lang2(parenSymbol,
1105
				       ExpandDots(CADDR(object), value)));
1107
				       ExpandDots(CADDR(object), value)));
1106
	    else
1108
	    else
1107
		SETCADDR(object, ExpandDots(CADDR(object), value));
1109
		SETCADDR(object, ExpandDots(CADDR(object), value));
1108
	}
1110
	}
1109
	else if (CAR(object) == powerSymbol) {
1111
	else if (CAR(object) == powerSymbol) {
1110
	    if (length(object) != 3)
1112
	    if (length(object) != 3)
1111
		goto badformula;
1113
		goto badformula;
1112
	    if (CADR(object) == dotSymbol &&
1114
	    if (CADR(object) == dotSymbol &&
1113
	       (op == plusSymbol || op == minusSymbol ||
1115
	       (op == plusSymbol || op == minusSymbol ||
1114
		op == timesSymbol || op == slashSymbol ||
1116
		op == timesSymbol || op == slashSymbol ||
1115
		op == colonSymbol))
1117
		op == colonSymbol))
1116
		SETCADR(object, lang2(parenSymbol,
1118
		SETCADR(object, lang2(parenSymbol,
1117
				      ExpandDots(CADR(object), value)));
1119
				      ExpandDots(CADR(object), value)));
1118
	    else
1120
	    else
1119
		SETCADR(object, ExpandDots(CADR(object), value));
1121
		SETCADR(object, ExpandDots(CADR(object), value));
1120
	    if (CADDR(object) == dotSymbol &&
1122
	    if (CADDR(object) == dotSymbol &&
1121
	       (op == plusSymbol || op == minusSymbol))
1123
	       (op == plusSymbol || op == minusSymbol))
1122
		SETCADDR(object, lang2(parenSymbol,
1124
		SETCADDR(object, lang2(parenSymbol,
1123
				       ExpandDots(CADDR(object), value)));
1125
				       ExpandDots(CADDR(object), value)));
1124
	    else
1126
	    else
1125
		SETCADDR(object, ExpandDots(CADDR(object), value));
1127
		SETCADDR(object, ExpandDots(CADDR(object), value));
1126
	}
1128
	}
1127
	else {
1129
	else {
1128
	    op = object;
1130
	    op = object;
1129
	    while(op != R_NilValue) {
1131
	    while(op != R_NilValue) {
1130
		SETCAR(op, ExpandDots(CAR(op), value));
1132
		SETCAR(op, ExpandDots(CAR(op), value));
1131
		op = CDR(op);
1133
		op = CDR(op);
1132
	    }
1134
	    }
1133
	}
1135
	}
1134
	UNPROTECT(1);
1136
	UNPROTECT(1);
1135
	return object;
1137
	return object;
1136
    }
1138
    }
1137
    else return object;
1139
    else return object;
1138
 
1140
 
1139
 badformula:
1141
 badformula:
1140
    error("invalid formula in update");
1142
    error("invalid formula in update");
1141
    return R_NilValue; /*NOTREACHED*/
1143
    return R_NilValue; /*NOTREACHED*/
1142
}
1144
}
1143
 
1145
 
1144
SEXP do_updateform(SEXP call, SEXP op, SEXP args, SEXP rho)
1146
SEXP do_updateform(SEXP call, SEXP op, SEXP args, SEXP rho)
1145
{
1147
{
1146
    SEXP new, old, lhs, rhs;
1148
    SEXP new, old, lhs, rhs;
1147
 
1149
 
1148
    checkArity(op, args);
1150
    checkArity(op, args);
1149
 
1151
 
1150
    /* Always fetch these values rather than trying */
1152
    /* Always fetch these values rather than trying */
1151
    /* to remember them between calls.  The overhead */
1153
    /* to remember them between calls.  The overhead */
1152
    /* is minimal and we don't have to worry about */
1154
    /* is minimal and we don't have to worry about */
1153
    /* intervening dump/restore problems. */
1155
    /* intervening dump/restore problems. */
1154
 
1156
 
1155
    tildeSymbol = install("~");
1157
    tildeSymbol = install("~");
1156
    plusSymbol  = install("+");
1158
    plusSymbol  = install("+");
1157
    minusSymbol = install("-");
1159
    minusSymbol = install("-");
1158
    timesSymbol = install("*");
1160
    timesSymbol = install("*");
1159
    slashSymbol = install("/");
1161
    slashSymbol = install("/");
1160
    colonSymbol = install(":");
1162
    colonSymbol = install(":");
1161
    powerSymbol = install("^");
1163
    powerSymbol = install("^");
1162
    dotSymbol   = install(".");
1164
    dotSymbol   = install(".");
1163
    parenSymbol = install("(");
1165
    parenSymbol = install("(");
1164
    inSymbol = install("%in%");
1166
    inSymbol = install("%in%");
1165
    /* identSymbol = install("I"); */
1167
    /* identSymbol = install("I"); */
1166
 
1168
 
1167
    /* We must duplicate here because the */
1169
    /* We must duplicate here because the */
1168
    /* formulae may be part of the parse tree */
1170
    /* formulae may be part of the parse tree */
1169
    /* and we don't want to modify it. */
1171
    /* and we don't want to modify it. */
1170
 
1172
 
1171
    old = CAR(args);
1173
    old = CAR(args);
1172
    new = SETCADR(args, duplicate(CADR(args)));
1174
    new = SETCADR(args, duplicate(CADR(args)));
1173
 
1175
 
1174
    /* Check of new and old formulae. */
1176
    /* Check of new and old formulae. */
1175
    if (TYPEOF(old) != LANGSXP ||
1177
    if (TYPEOF(old) != LANGSXP ||
1176
       (TYPEOF(new) != LANGSXP && CAR(old) != tildeSymbol) ||
1178
       (TYPEOF(new) != LANGSXP && CAR(old) != tildeSymbol) ||
1177
       CAR(new) != tildeSymbol)
1179
       CAR(new) != tildeSymbol)
1178
	errorcall(call, "formula expected");
1180
	errorcall(call, "formula expected");
1179
 
1181
 
1180
    if (length(old) == 3) {
1182
    if (length(old) == 3) {
1181
	lhs = CADR(old);
1183
	lhs = CADR(old);
1182
	rhs = CADDR(old);
1184
	rhs = CADDR(old);
1183
	/* We now check that new formula has a valid lhs.
1185
	/* We now check that new formula has a valid lhs.
1184
	   If it doesn't, we add one and set it to the rhs of the old
1186
	   If it doesn't, we add one and set it to the rhs of the old
1185
	   formula. */
1187
	   formula. */
1186
	if (length(new) == 2)
1188
	if (length(new) == 2)
1187
	    SETCDR(new, CONS(lhs, CDR(new)));
1189
	    SETCDR(new, CONS(lhs, CDR(new)));
1188
	/* Now we check the left and right sides of the new formula
1190
	/* Now we check the left and right sides of the new formula
1189
	   and substitute the correct value for any "." templates.
1191
	   and substitute the correct value for any "." templates.
1190
	   We must parenthesize the rhs or we might upset arity and
1192
	   We must parenthesize the rhs or we might upset arity and
1191
	   precedence. */
1193
	   precedence. */
1192
	PROTECT(rhs);
1194
	PROTECT(rhs);
1193
	SETCADR(new, ExpandDots(CADR(new), lhs));
1195
	SETCADR(new, ExpandDots(CADR(new), lhs));
1194
	SETCADDR(new, ExpandDots(CADDR(new), rhs));
1196
	SETCADDR(new, ExpandDots(CADDR(new), rhs));
1195
	UNPROTECT(1);
1197
	UNPROTECT(1);
1196
    }
1198
    }
1197
    else {
1199
    else {
1198
	/* The old formula had no lhs, so we only expand the rhs of the
1200
	/* The old formula had no lhs, so we only expand the rhs of the
1199
	   new formula. */
1201
	   new formula. */
1200
	rhs = CADR(old);
1202
	rhs = CADR(old);
1201
	if (length(new) == 3)
1203
	if (length(new) == 3)
1202
	    SETCADDR(new, ExpandDots(CADDR(new), rhs));
1204
	    SETCADDR(new, ExpandDots(CADDR(new), rhs));
1203
	else
1205
	else
1204
	    SETCADR(new, ExpandDots(CADR(new), rhs));
1206
	    SETCADR(new, ExpandDots(CADR(new), rhs));
1205
    }
1207
    }
1206
 
1208
 
1207
    /* It might be overkill to zero the */
1209
    /* It might be overkill to zero the */
1208
    /* the attribute list of the returned */
1210
    /* the attribute list of the returned */
1209
    /* value, but it can't hurt. */
1211
    /* value, but it can't hurt. */
1210
 
1212
 
1211
    SET_ATTRIB(new, R_NilValue);
1213
    SET_ATTRIB(new, R_NilValue);
1212
    return new;
1214
    return new;
1213
}
1215
}
1214

1216

1215
 
1217
 
1216
/*
1218
/*
1217
 *  model.frame
1219
 *  model.frame
1218
 *
1220
 *
1219
 *  The argument "terms" contains the terms object generated from the
1221
 *  The argument "terms" contains the terms object generated from the
1220
 *  model formula.  We first evaluate the "variables" attribute of
1222
 *  model formula.  We first evaluate the "variables" attribute of
1221
 *  "terms" in the "data" environment.  This gives us a list of basic
1223
 *  "terms" in the "data" environment.  This gives us a list of basic
1222
 *  variables to be in the model frame.  We do some basic sanity
1224
 *  variables to be in the model frame.  We do some basic sanity
1223
 *  checks on these to ensure that resulting object make sense.
1225
 *  checks on these to ensure that resulting object make sense.
1224
 *
1226
 *
1225
 *  The argument "dots" gives additional things like "weights", "offsets"
1227
 *  The argument "dots" gives additional things like "weights", "offsets"
1226
 *  and "subset" which will also go into the model frame so that they can
1228
 *  and "subset" which will also go into the model frame so that they can
1227
 *  be treated in parallel.
1229
 *  be treated in parallel.
1228
 *
1230
 *
1229
 *  Next we subset the data frame according to "subset" and finally apply
1231
 *  Next we subset the data frame according to "subset" and finally apply
1230
 *  "na.action" to get the final data frame.
1232
 *  "na.action" to get the final data frame.
1231
 *
1233
 *
1232
 *  Note that the "terms" argument is glued to the model frame as an
1234
 *  Note that the "terms" argument is glued to the model frame as an
1233
 *  attribute.  Code downstream appears to need this.
1235
 *  attribute.  Code downstream appears to need this.
1234
 *
1236
 *
1235
 *  Q: Is this really needed, or can we get by with less info?
1237
 *  Q: Is this really needed, or can we get by with less info?
1236
 */
1238
 */
1237
 
1239
 
1238
/* time to move more functionality back into compiled
1240
/* time to move more functionality back into compiled
1239
   code (cycle of reincarnation) */
1241
   code (cycle of reincarnation) */
1240
 
1242
 
1241
/* .Internal(model.frame(terms, rownames, variables, varnames, */
1243
/* .Internal(model.frame(terms, rownames, variables, varnames, */
1242
/*           dots, dotnames, subset, na.action)) */
1244
/*           dots, dotnames, subset, na.action)) */
1243
 
1245
 
1244
SEXP do_modelframe(SEXP call, SEXP op, SEXP args, SEXP rho)
1246
SEXP do_modelframe(SEXP call, SEXP op, SEXP args, SEXP rho)
1245
{
1247
{
1246
    SEXP terms, data, names, variables, varnames, dots, dotnames, na_action;
1248
    SEXP terms, data, names, variables, varnames, dots, dotnames, na_action;
1247
    SEXP ans, row_names, subset, tmp;
1249
    SEXP ans, row_names, subset, tmp;
1248
    char buf[256];
1250
    char buf[256];
1249
    int i, j, nr, nc;
1251
    int i, j, nr, nc;
1250
    int nvars, ndots, nactualdots;
1252
    int nvars, ndots, nactualdots;
1251
 
1253
 
1252
    checkArity(op, args);
1254
    checkArity(op, args);
1253
    terms = CAR(args); args = CDR(args);
1255
    terms = CAR(args); args = CDR(args);
1254
    row_names = CAR(args); args = CDR(args);
1256
    row_names = CAR(args); args = CDR(args);
1255
    variables = CAR(args); args = CDR(args);
1257
    variables = CAR(args); args = CDR(args);
1256
    varnames = CAR(args); args = CDR(args);
1258
    varnames = CAR(args); args = CDR(args);
1257
    dots = CAR(args); args = CDR(args);
1259
    dots = CAR(args); args = CDR(args);
1258
    dotnames = CAR(args); args = CDR(args);
1260
    dotnames = CAR(args); args = CDR(args);
1259
    subset = CAR(args); args = CDR(args);
1261
    subset = CAR(args); args = CDR(args);
1260
    na_action = CAR(args); args = CDR(args);
1262
    na_action = CAR(args); args = CDR(args);
1261
 
1263
 
1262
    /* Argument Sanity Checks */
1264
    /* Argument Sanity Checks */
1263
 
1265
 
1264
    if (!isNewList(variables))
1266
    if (!isNewList(variables))
1265
	errorcall(call, "invalid variables");
1267
	errorcall(call, "invalid variables");
1266
    if (!isString(varnames))
1268
    if (!isString(varnames))
1267
	errorcall(call, "invalid variable names");
1269
	errorcall(call, "invalid variable names");
1268
    if ((nvars = length(variables)) != length(varnames))
1270
    if ((nvars = length(variables)) != length(varnames))
1269
	errorcall(call, "number of variables != number of variable names");
1271
	errorcall(call, "number of variables != number of variable names");
1270
 
1272
 
1271
    if (!isNewList(dots))
1273
    if (!isNewList(dots))
1272
	errorcall(call, "invalid extra variables");
1274
	errorcall(call, "invalid extra variables");
1273
    if ((ndots = length(dots)) != length(dotnames))
1275
    if ((ndots = length(dots)) != length(dotnames))
1274
	errorcall(call, "number of variables != number of variable names");
1276
	errorcall(call, "number of variables != number of variable names");
1275
    if ( ndots && !isString(dotnames))
1277
    if ( ndots && !isString(dotnames))
1276
	errorcall(call, "invalid extra variable names");
1278
	errorcall(call, "invalid extra variable names");
1277
 
1279
 
1278
    /*  check for NULL extra arguments -- moved from interpreted code */
1280
    /*  check for NULL extra arguments -- moved from interpreted code */
1279
 
1281
 
1280
    nactualdots = 0;
1282
    nactualdots = 0;
1281
    for (i = 0; i < ndots; i++){
1283
    for (i = 0; i < ndots; i++){
1282
	if (VECTOR_ELT(dots, i) != R_NilValue)
1284
	if (VECTOR_ELT(dots, i) != R_NilValue)
1283
	    nactualdots++;
1285
	    nactualdots++;
1284
    }
1286
    }
1285
 
1287
 
1286
    /* Assemble the base data frame. */
1288
    /* Assemble the base data frame. */
1287
 
1289
 
1288
    PROTECT(data = allocVector(VECSXP, nvars + nactualdots));
1290
    PROTECT(data = allocVector(VECSXP, nvars + nactualdots));
1289
    PROTECT(names = allocVector(STRSXP, nvars + nactualdots));
1291
    PROTECT(names = allocVector(STRSXP, nvars + nactualdots));
1290
 
1292
 
1291
    for (i = 0; i < nvars; i++) {
1293
    for (i = 0; i < nvars; i++) {
1292
	SET_VECTOR_ELT(data, i, VECTOR_ELT(variables, i));
1294
	SET_VECTOR_ELT(data, i, VECTOR_ELT(variables, i));
1293
	SET_STRING_ELT(names, i, STRING_ELT(varnames, i));
1295
	SET_STRING_ELT(names, i, STRING_ELT(varnames, i));
1294
    }
1296
    }
1295
    for (i = 0,j = 0; i < ndots; i++) {
1297
    for (i = 0,j = 0; i < ndots; i++) {
1296
	if (VECTOR_ELT(dots, i) == R_NilValue)
1298
	if (VECTOR_ELT(dots, i) == R_NilValue)
1297
	    continue;
1299
	    continue;
1298
	if(strlen(CHAR(STRING_ELT(dotnames, i))) + 3 > 256)
1300
	if(strlen(CHAR(STRING_ELT(dotnames, i))) + 3 > 256)
1299
	    error("overlong names in %s", CHAR(STRING_ELT(dotnames, i)));
1301
	    error("overlong names in %s", CHAR(STRING_ELT(dotnames, i)));
1300
	sprintf(buf, "(%s)", CHAR(STRING_ELT(dotnames, i)));
1302
	sprintf(buf, "(%s)", CHAR(STRING_ELT(dotnames, i)));
1301
	SET_VECTOR_ELT(data, nvars + j, VECTOR_ELT(dots, i));
1303
	SET_VECTOR_ELT(data, nvars + j, VECTOR_ELT(dots, i));
1302
	SET_STRING_ELT(names, nvars + j,  mkChar(buf));
1304
	SET_STRING_ELT(names, nvars + j,  mkChar(buf));
1303
	j++;
1305
	j++;
1304
    }
1306
    }
1305
    setAttrib(data, R_NamesSymbol, names);
1307
    setAttrib(data, R_NamesSymbol, names);
1306
    UNPROTECT(2);
1308
    UNPROTECT(2);
1307
 
1309
 
1308
    /* Sanity checks to ensure that the the answer can become */
1310
    /* Sanity checks to ensure that the the answer can become */
1309
    /* a data frame.  Be deeply suspicious here! */
1311
    /* a data frame.  Be deeply suspicious here! */
1310
 
1312
 
1311
    nc = length(data);
1313
    nc = length(data);
1312
    nr = 0;			/* -Wall */
1314
    nr = 0;			/* -Wall */
1313
    if (nc > 0) {
1315
    if (nc > 0) {
1314
	nr = nrows(VECTOR_ELT(data, 0));
1316
	nr = nrows(VECTOR_ELT(data, 0));
1315
	for (i = 0; i < nc; i++) {
1317
	for (i = 0; i < nc; i++) {
1316
	    ans = VECTOR_ELT(data, i);
1318
	    ans = VECTOR_ELT(data, i);
1317
	    if (TYPEOF(ans) < LGLSXP ||
1319
	    if (TYPEOF(ans) < LGLSXP ||
1318
		TYPEOF(ans) > REALSXP)
1320
		TYPEOF(ans) > REALSXP)
1319
		errorcall(call, "invalid variable type");
1321
		errorcall(call, "invalid variable type");
1320
	    if (nrows(ans) != nr)
1322
	    if (nrows(ans) != nr)
1321
		errorcall(call, "variable lengths differ");
1323
		errorcall(call, "variable lengths differ");
1322
	}
1324
	}
1323
    } else nr = length(row_names);
1325
    } else nr = length(row_names);
1324
 
1326
 
1325
    PROTECT(data);
1327
    PROTECT(data);
1326
    PROTECT(subset);
1328
    PROTECT(subset);
1327
 
1329
 
1328
    /* Turn the data "list" into a "data.frame" */
1330
    /* Turn the data "list" into a "data.frame" */
1329
    /* so that subsetting methods will work. */
1331
    /* so that subsetting methods will work. */
1330
    /* To do this we must attach "class"  and */
1332
    /* To do this we must attach "class"  and */
1331
    /* "row.names" attributes */
1333
    /* "row.names" attributes */
1332
 
1334
 
1333
    PROTECT(tmp = mkString("data.frame"));
1335
    PROTECT(tmp = mkString("data.frame"));
1334
    setAttrib(data, R_ClassSymbol, tmp);
1336
    setAttrib(data, R_ClassSymbol, tmp);
1335
    UNPROTECT(1);
1337
    UNPROTECT(1);
1336
    if (length(row_names) == nr) {
1338
    if (length(row_names) == nr) {
1337
	setAttrib(data, R_RowNamesSymbol, row_names);
1339
	setAttrib(data, R_RowNamesSymbol, row_names);
1338
    }
1340
    }
1339
    else {
1341
    else {
1340
	PROTECT(row_names = allocVector(STRSXP, nr));
1342
	PROTECT(row_names = allocVector(STRSXP, nr));
1341
	for (i=0; i<nr; i++) {
1343
	for (i=0; i<nr; i++) {
1342
	    sprintf(buf, "%d", i+1);
1344
	    sprintf(buf, "%d", i+1);
1343
	    SET_STRING_ELT(row_names, i, mkChar(buf));
1345
	    SET_STRING_ELT(row_names, i, mkChar(buf));
1344
	}
1346
	}
1345
	setAttrib(data, R_RowNamesSymbol, row_names);
1347
	setAttrib(data, R_RowNamesSymbol, row_names);
1346
	UNPROTECT(1);
1348
	UNPROTECT(1);
1347
    }
1349
    }
1348
 
1350
 
1349
    /* Do the subsetting, if required. */
1351
    /* Do the subsetting, if required. */
1350
    /* Need to save and restore 'most' attributes */
1352
    /* Need to save and restore 'most' attributes */
1351
 
1353
 
1352
    if (subset != R_NilValue) {
1354
    if (subset != R_NilValue) {
1353
	PROTECT(tmp=install("[.data.frame"));
1355
	PROTECT(tmp=install("[.data.frame"));
1354
	PROTECT(tmp=LCONS(tmp,list4(data,subset,R_MissingArg,mkFalse())));
1356
	PROTECT(tmp=LCONS(tmp,list4(data,subset,R_MissingArg,mkFalse())));
1355
	data = eval(tmp, rho);
1357
	data = eval(tmp, rho);
1356
	UNPROTECT(2);
1358
	UNPROTECT(2);
1357
    }
1359
    }
1358
    UNPROTECT(2);
1360
    UNPROTECT(2);
1359
    PROTECT(data);
1361
    PROTECT(data);
1360
 
1362
 
1361
    /* finally, we run na.action on the data frame */
1363
    /* finally, we run na.action on the data frame */
1362
    /* usually, this will be na.omit */
1364
    /* usually, this will be na.omit */
1363
 
1365
 
1364
    if (na_action != R_NilValue) {
1366
    if (na_action != R_NilValue) {
1365
	/* some na.actions need this to distinguish responses from
1367
	/* some na.actions need this to distinguish responses from
1366
	   explanatory variables */
1368
	   explanatory variables */
1367
	setAttrib(data, install("terms"), terms);
1369
	setAttrib(data, install("terms"), terms);
1368
	if (isString(na_action) && length(na_action) > 0)
1370
	if (isString(na_action) && length(na_action) > 0)
1369
	    na_action = install(CHAR(STRING_ELT(na_action, 0)));
1371
	    na_action = install(CHAR(STRING_ELT(na_action, 0)));
1370
	PROTECT(na_action);
1372
	PROTECT(na_action);
1371
	PROTECT(tmp = lang2(na_action, data));
1373
	PROTECT(tmp = lang2(na_action, data));
1372
	PROTECT(ans = eval(tmp, rho));
1374
	PROTECT(ans = eval(tmp, rho));
1373
	if (!isNewList(ans) || length(ans) != length(data))
1375
	if (!isNewList(ans) || length(ans) != length(data))
1374
	    errorcall(call, "invalid result from na.action");
1376
	    errorcall(call, "invalid result from na.action");
1375
	/* need to transfer _all but dim_ attributes, possibly lost
1377
	/* need to transfer _all but dim_ attributes, possibly lost
1376
	   by subsetting in na.action.  */
1378
	   by subsetting in na.action.  */
1377
	for ( i = length(ans) ; i-- ; )
1379
	for ( i = length(ans) ; i-- ; )
1378
	  	copyMostAttrib(VECTOR_ELT(data, i),VECTOR_ELT(ans, i));
1380
	  	copyMostAttrib(VECTOR_ELT(data, i),VECTOR_ELT(ans, i));
1379
 
1381
 
1380
	UNPROTECT(3);
1382
	UNPROTECT(3);
1381
    }
1383
    }
1382
    else ans = data;
1384
    else ans = data;
1383
    UNPROTECT(1);
1385
    UNPROTECT(1);
1384
    PROTECT(ans);
1386
    PROTECT(ans);
1385
 
1387
 
1386
    /* Finally, tack on a terms attribute
1388
    /* Finally, tack on a terms attribute
1387
       Now done at R level.
1389
       Now done at R level.
1388
       setAttrib(ans, install("terms"), terms); */
1390
       setAttrib(ans, install("terms"), terms); */
1389
    UNPROTECT(1);
1391
    UNPROTECT(1);
1390
    return ans;
1392
    return ans;
1391
}
1393
}
1392
 
1394
 
1393
	/* Internal code for the ~ operator */
1395
	/* Internal code for the ~ operator */
1394
	/* Just returns the unevaluated call */
1396
	/* Just returns the unevaluated call */
1395
	/* No longer needed??? */
1397
	/* No longer needed??? */
1396
 
1398
 
1397
SEXP do_tilde(SEXP call, SEXP op, SEXP args, SEXP rho)
1399
SEXP do_tilde(SEXP call, SEXP op, SEXP args, SEXP rho)
1398
{
1400
{
1399
    if (isObject(call))
1401
    if (isObject(call))
1400
        return duplicate(call);
1402
        return duplicate(call);
1401
    else {
1403
    else {
1402
        SEXP class;
1404
        SEXP class;
1403
        PROTECT(call = duplicate(call));
1405
        PROTECT(call = duplicate(call));
1404
        PROTECT(class = allocVector(STRSXP, 1));
1406
        PROTECT(class = allocVector(STRSXP, 1));
1405
        SET_STRING_ELT(class, 0, mkChar("formula"));
1407
        SET_STRING_ELT(class, 0, mkChar("formula"));
1406
        setAttrib(call, R_ClassSymbol, class);
1408
        setAttrib(call, R_ClassSymbol, class);
1407
        setAttrib(call, R_DotEnvSymbol, rho);
1409
        setAttrib(call, R_DotEnvSymbol, rho);
1408
        UNPROTECT(2);
1410
        UNPROTECT(2);
1409
        return call;
1411
        return call;
1410
    }
1412
    }
1411
}
1413
}
1412
 
1414
 
1413
 
1415
 
1414
	/* The code below is related to model expansion */
1416
	/* The code below is related to model expansion */
1415
	/* and is ultimately called by do_modelmatrix. */
1417
	/* and is ultimately called by do_modelmatrix. */
1416
 
1418
 
1417
static void firstfactor(double *x, int nrx, int ncx,
1419
static void firstfactor(double *x, int nrx, int ncx,
1418
			double *c, int nrc, int ncc, int *v)
1420
			double *c, int nrc, int ncc, int *v)
1419
{
1421
{
1420
    double *cj, *xj;
1422
    double *cj, *xj;
1421
    int i, j;
1423
    int i, j;
1422
 
1424
 
1423
    for (j = 0; j < ncc; j++) {
1425
    for (j = 0; j < ncc; j++) {
1424
	xj = &x[j*nrx];
1426
	xj = &x[j*nrx];
1425
	cj = &c[j*nrc];
1427
	cj = &c[j*nrc];
1426
	for (i = 0; i < nrx; i++)
1428
	for (i = 0; i < nrx; i++)
1427
	    if(v[i] == NA_INTEGER) xj[i] = NA_REAL;
1429
	    if(v[i] == NA_INTEGER) xj[i] = NA_REAL;
1428
	    else xj[i] = cj[v[i]-1];
1430
	    else xj[i] = cj[v[i]-1];
1429
    }
1431
    }
1430
}
1432
}
1431
 
1433
 
1432
static void addfactor(double *x, int nrx, int ncx,
1434
static void addfactor(double *x, int nrx, int ncx,
1433
		      double *c, int nrc, int ncc, int *v)
1435
		      double *c, int nrc, int ncc, int *v)
1434
{
1436
{
1435
    int i, j, k;
1437
    int i, j, k;
1436
    double *ck, *xj, *yj;
1438
    double *ck, *xj, *yj;
1437
 
1439
 
1438
    for (k = ncc - 1; k >= 0; k--) {
1440
    for (k = ncc - 1; k >= 0; k--) {
1439
	for (j = 0; j < ncx; j++) {
1441
	for (j = 0; j < ncx; j++) {
1440
	    xj = &x[j*nrx];
1442
	    xj = &x[j*nrx];
1441
	    yj = &x[(k*ncx+j)*nrx];
1443
	    yj = &x[(k*ncx+j)*nrx];
1442
	    ck = &c[k*nrc];
1444
	    ck = &c[k*nrc];
1443
	    for (i = 0; i < nrx; i++)
1445
	    for (i = 0; i < nrx; i++)
1444
	    if(v[i] == NA_INTEGER) yj[i] = NA_REAL;
1446
	    if(v[i] == NA_INTEGER) yj[i] = NA_REAL;
1445
	    else yj[i] = ck[v[i]-1] * xj[i];
1447
	    else yj[i] = ck[v[i]-1] * xj[i];
1446
	}
1448
	}
1447
    }
1449
    }
1448
}
1450
}
1449
 
1451
 
1450
static void firstvar(double *x, int nrx, int ncx, double *c, int nrc, int ncc)
1452
static void firstvar(double *x, int nrx, int ncx, double *c, int nrc, int ncc)
1451
{
1453
{
1452
    double *cj, *xj;
1454
    double *cj, *xj;
1453
    int i, j;
1455
    int i, j;
1454
 
1456
 
1455
    for (j = 0; j < ncc; j++) {
1457
    for (j = 0; j < ncc; j++) {
1456
	xj = &x[j*nrx];
1458
	xj = &x[j*nrx];
1457
	cj = &c[j*nrc];
1459
	cj = &c[j*nrc];
1458
	for (i = 0; i < nrx; i++)
1460
	for (i = 0; i < nrx; i++)
1459
	    xj[i] = cj[i];
1461
	    xj[i] = cj[i];
1460
    }
1462
    }
1461
}
1463
}
1462
 
1464
 
1463
static void addvar(double *x, int nrx, int ncx, double *c, int nrc, int ncc)
1465
static void addvar(double *x, int nrx, int ncx, double *c, int nrc, int ncc)
1464
{
1466
{
1465
    int i, j, k;
1467
    int i, j, k;
1466
    double *ck, *xj, *yj;
1468
    double *ck, *xj, *yj;
1467
 
1469
 
1468
    for (k = ncc - 1; k >= 0; k--) {
1470
    for (k = ncc - 1; k >= 0; k--) {
1469
	for (j = 0; j < ncx; j++) {
1471
	for (j = 0; j < ncx; j++) {
1470
	    xj = &x[j*nrx];
1472
	    xj = &x[j*nrx];
1471
	    yj = &x[(k*ncx+j)*nrx];
1473
	    yj = &x[(k*ncx+j)*nrx];
1472
	    ck = &c[k*nrc];
1474
	    ck = &c[k*nrc];
1473
	    for (i = 0; i < nrx; i++)
1475
	    for (i = 0; i < nrx; i++)
1474
		yj[i] = ck[i] * xj[i];
1476
		yj[i] = ck[i] * xj[i];
1475
	}
1477
	}
1476
    }
1478
    }
1477
}
1479
}
1478
 
1480
 
1479
#define BUFSIZE 4096
1481
#define BUFSIZE 4096
1480
 
1482
 
1481
static char *AppendString(char *buf, char *str)
1483
static char *AppendString(char *buf, char *str)
1482
{
1484
{
1483
    while (*str)
1485
    while (*str)
1484
	*buf++ = *str++;
1486
	*buf++ = *str++;
1485
    *buf = '\0';
1487
    *buf = '\0';
1486
    return buf;
1488
    return buf;
1487
}
1489
}
1488
 
1490
 
1489
static char *AppendInteger(char *buf, int i)
1491
static char *AppendInteger(char *buf, int i)
1490
{
1492
{
1491
    sprintf(buf, "%d", i);
1493
    sprintf(buf, "%d", i);
1492
    while(*buf) buf++;
1494
    while(*buf) buf++;
1493
    return buf;
1495
    return buf;
1494
}
1496
}
1495
 
1497
 
1496
static SEXP ColumnNames(SEXP x)
1498
static SEXP ColumnNames(SEXP x)
1497
{
1499
{
1498
    SEXP dn = getAttrib(x, R_DimNamesSymbol);
1500
    SEXP dn = getAttrib(x, R_DimNamesSymbol);
1499
    if (dn == R_NilValue)
1501
    if (dn == R_NilValue)
1500
	return R_NilValue;
1502
	return R_NilValue;
1501
    else
1503
    else
1502
	return VECTOR_ELT(dn, 1);
1504
	return VECTOR_ELT(dn, 1);
1503
}
1505
}
1504
 
1506
 
1505
SEXP do_modelmatrix(SEXP call, SEXP op, SEXP args, SEXP rho)
1507
SEXP do_modelmatrix(SEXP call, SEXP op, SEXP args, SEXP rho)
1506
{
1508
{
1507
    SEXP expr, factors, terms, vars, vnames, assign;
1509
    SEXP expr, factors, terms, vars, vnames, assign;
1508
    SEXP xnames, tnames, rnames;
1510
    SEXP xnames, tnames, rnames;
1509
    SEXP count, contrast, contr1, contr2, nlevs, ordered, columns, x;
1511
    SEXP count, contrast, contr1, contr2, nlevs, ordered, columns, x;
1510
    SEXP variable, var_i;
1512
    SEXP variable, var_i;
1511
    int fik, first, i, j, k, kk, ll, n, nc, nterms, nVar;
1513
    int fik, first, i, j, k, kk, ll, n, nc, nterms, nVar;
1512
    int intrcept, jstart, jnext, risponse, indx, rhs_response;
1514
    int intrcept, jstart, jnext, risponse, indx, rhs_response;
1513
    char buf[BUFSIZE]="\0", *bufp, *addp;
1515
    char buf[BUFSIZE]="\0", *bufp, *addp;
1514
    
1516
    
1515
 
1517
 
1516
    checkArity(op, args);
1518
    checkArity(op, args);
1517
 
1519
 
1518
    /* Get the "terms" structure and extract */
1520
    /* Get the "terms" structure and extract */
1519
    /* the intercept and response attributes. */
1521
    /* the intercept and response attributes. */
1520
 
1522
 
1521
    terms = CAR(args);
1523
    terms = CAR(args);
1522
 
1524
 
1523
    intrcept = asLogical(getAttrib(terms, install("intercept")));
1525
    intrcept = asLogical(getAttrib(terms, install("intercept")));
1524
    if (intrcept == NA_INTEGER)
1526
    if (intrcept == NA_INTEGER)
1525
	intrcept = 0;
1527
	intrcept = 0;
1526
 
1528
 
1527
    risponse = asLogical(getAttrib(terms, install("response")));
1529
    risponse = asLogical(getAttrib(terms, install("response")));
1528
    if (risponse == NA_INTEGER)
1530
    if (risponse == NA_INTEGER)
1529
	risponse = 0;
1531
	risponse = 0;
1530
 
1532
 
1531
    /* Get the factor pattern matrix.  We duplicate this because */
1533
    /* Get the factor pattern matrix.  We duplicate this because */
1532
    /* we may want to alter it if we are in the no-intercept case. */
1534
    /* we may want to alter it if we are in the no-intercept case. */
1533
    /* Note: the values of "nVar" and "nterms" are the REAL number of */
1535
    /* Note: the values of "nVar" and "nterms" are the REAL number of */
1534
    /* variables in the model data frame and the number of model terms. */
1536
    /* variables in the model data frame and the number of model terms. */
1535
 
1537
 
1536
    nVar = nterms = 0;		/* -Wall */
1538
    nVar = nterms = 0;		/* -Wall */
1537
    PROTECT(factors = duplicate(getAttrib(terms, install("factors"))));
1539
    PROTECT(factors = duplicate(getAttrib(terms, install("factors"))));
1538
    if (length(factors) == 0) {
1540
    if (length(factors) == 0) {
1539
	/* if (intrcept == 0)
1541
	/* if (intrcept == 0)
1540
	   errorcall(call, "illegal model (zero parameters).");*/
1542
	   errorcall(call, "illegal model (zero parameters).");*/
1541
	nVar = 1;
1543
	nVar = 1;
1542
	nterms = 0;
1544
	nterms = 0;
1543
    }
1545
    }
1544
    else if (isInteger(factors) && isMatrix(factors)) {
1546
    else if (isInteger(factors) && isMatrix(factors)) {
1545
	nVar = nrows(factors);
1547
	nVar = nrows(factors);
1546
	nterms = ncols(factors);
1548
	nterms = ncols(factors);
1547
    }
1549
    }
1548
    else errorcall(call, "invalid terms argument");
1550
    else errorcall(call, "invalid terms argument");
1549
 
1551
 
1550
    /* Get the variable names from the factor matrix */
1552
    /* Get the variable names from the factor matrix */
1551
 
1553
 
1552
    vnames = getAttrib(factors, R_DimNamesSymbol);
1554
    vnames = getAttrib(factors, R_DimNamesSymbol);
1553
    if (length(factors) > 0) {
1555
    if (length(factors) > 0) {
1554
	if (length(vnames) < 1 ||
1556
	if (length(vnames) < 1 ||
1555
	    (nVar - intrcept > 0 && !isString(VECTOR_ELT(vnames, 0))))
1557
	    (nVar - intrcept > 0 && !isString(VECTOR_ELT(vnames, 0))))
1556
	    errorcall(call, "invalid terms argument");
1558
	    errorcall(call, "invalid terms argument");
1557
	vnames = VECTOR_ELT(vnames, 0);
1559
	vnames = VECTOR_ELT(vnames, 0);
1558
    }
1560
    }
1559
 
1561
 
1560
    /* Get the variables from the model frame.  First perform */
1562
    /* Get the variables from the model frame.  First perform */
1561
    /* elementary sanity checks.  Notes:  1) We need at least */
1563
    /* elementary sanity checks.  Notes:  1) We need at least */
1562
    /* one variable (lhs or rhs) to compute the number of cases. */
1564
    /* one variable (lhs or rhs) to compute the number of cases. */
1563
    /* 2) We don't type-check the response. */
1565
    /* 2) We don't type-check the response. */
1564
 
1566
 
1565
    vars = CADR(args);
1567
    vars = CADR(args);
1566
    if (!isNewList(vars) || length(vars) < nVar)
1568
    if (!isNewList(vars) || length(vars) < nVar)
1567
	errorcall(call, "invalid model frame");
1569
	errorcall(call, "invalid model frame");
1568
    if (length(vars) == 0)
1570
    if (length(vars) == 0)
1569
	errorcall(call, "don't know how many cases");
1571
	errorcall(call, "don't know how many cases");
1570
    n = nrows(VECTOR_ELT(vars, 0));
1572
    n = nrows(VECTOR_ELT(vars, 0));
1571
    rnames = getAttrib(vars, R_RowNamesSymbol);
1573
    rnames = getAttrib(vars, R_RowNamesSymbol);
1572
 
1574
 
1573
    /* This section of the code checks the types of the variables */
1575
    /* This section of the code checks the types of the variables */
1574
    /* in the model frame.  Note that it should really only check */
1576
    /* in the model frame.  Note that it should really only check */
1575
    /* the variables if they appear in a term in the model. */
1577
    /* the variables if they appear in a term in the model. */
1576
 
1578
 
1577
    PROTECT(variable = allocVector(VECSXP, nVar));
1579
    PROTECT(variable = allocVector(VECSXP, nVar));
1578
    PROTECT(nlevs = allocVector(INTSXP, nVar));
1580
    PROTECT(nlevs = allocVector(INTSXP, nVar));
1579
    PROTECT(ordered = allocVector(LGLSXP, nVar));
1581
    PROTECT(ordered = allocVector(LGLSXP, nVar));
1580
    PROTECT(columns = allocVector(INTSXP, nVar));
1582
    PROTECT(columns = allocVector(INTSXP, nVar));
1581
 
1583
 
1582
    for (i = 0; i < nVar; i++) {
1584
    for (i = 0; i < nVar; i++) {
1583
	var_i = SET_VECTOR_ELT(variable, i, VECTOR_ELT(vars, i));
1585
	var_i = SET_VECTOR_ELT(variable, i, VECTOR_ELT(vars, i));
1584
	if (nrows(var_i) != n)
1586
	if (nrows(var_i) != n)
1585
	    errorcall(call, "variable lengths differ");
1587
	    errorcall(call, "variable lengths differ");
1586
	/*if (i == risponse - 1) {
1588
	/*if (i == risponse - 1) {
1587
	    LOGICAL(ordered)[0] = 0;
1589
	    LOGICAL(ordered)[0] = 0;
1588
	    INTEGER(nlevs)[0] = 0;
1590
	    INTEGER(nlevs)[0] = 0;
1589
	    INTEGER(columns)[0] = 0;
1591
	    INTEGER(columns)[0] = 0;
1590
	}
1592
	}
1591
	else */
1593
	else */
1592
	if (isOrdered(var_i)) {
1594
	if (isOrdered(var_i)) {
1593
	    LOGICAL(ordered)[i] = 1;
1595
	    LOGICAL(ordered)[i] = 1;
1594
	    if((INTEGER(nlevs)[i] = nlevels(var_i)) < 1)
1596
	    if((INTEGER(nlevs)[i] = nlevels(var_i)) < 1)
1595
		errorcall(call, "variable %d has no levels", i+1);
1597
		errorcall(call, "variable %d has no levels", i+1);
1596
	    /* will get updated later when contrasts are set */
1598
	    /* will get updated later when contrasts are set */
1597
	    INTEGER(columns)[i] = ncols(var_i);
1599
	    INTEGER(columns)[i] = ncols(var_i);
1598
	}
1600
	}
1599
	else if (isUnordered(var_i)) {
1601
	else if (isUnordered(var_i)) {
1600
	    LOGICAL(ordered)[i] = 0;
1602
	    LOGICAL(ordered)[i] = 0;
1601
	    if((INTEGER(nlevs)[i] = nlevels(var_i)) < 1)
1603
	    if((INTEGER(nlevs)[i] = nlevels(var_i)) < 1)
1602
		errorcall(call, "variable %d has no levels", i+1);
1604
		errorcall(call, "variable %d has no levels", i+1);
1603
	    /* will get updated later when contrasts are set */
1605
	    /* will get updated later when contrasts are set */
1604
	    INTEGER(columns)[i] = ncols(var_i);
1606
	    INTEGER(columns)[i] = ncols(var_i);
1605
	}
1607
	}
1606
	else if (isLogical(var_i)) {
1608
	else if (isLogical(var_i)) {
1607
	    /* currently this cannot happen as R code turns 
1609
	    /* currently this cannot happen as R code turns 
1608
	       logical into factor when setting contrasts */ 
1610
	       logical into factor when setting contrasts */ 
1609
	    LOGICAL(ordered)[i] = 0;
1611
	    LOGICAL(ordered)[i] = 0;
1610
	    INTEGER(nlevs)[i] = 2;
1612
	    INTEGER(nlevs)[i] = 2;
1611
	    INTEGER(columns)[i] = ncols(var_i);
1613
	    INTEGER(columns)[i] = ncols(var_i);
1612
	}
1614
	}
1613
	else if (isNumeric(var_i)) {
1615
	else if (isNumeric(var_i)) {
1614
	    SET_VECTOR_ELT(variable, i, coerceVector(var_i, REALSXP));
1616
	    SET_VECTOR_ELT(variable, i, coerceVector(var_i, REALSXP));
1615
	    var_i = VECTOR_ELT(variable, i);
1617
	    var_i = VECTOR_ELT(variable, i);
1616
	    LOGICAL(ordered)[i] = 0;
1618
	    LOGICAL(ordered)[i] = 0;
1617
	    INTEGER(nlevs)[i] = 0;
1619
	    INTEGER(nlevs)[i] = 0;
1618
	    INTEGER(columns)[i] = ncols(var_i);
1620
	    INTEGER(columns)[i] = ncols(var_i);
1619
	}
1621
	}
1620
	else
1622
	else
1621
	    errorcall(call, "invalid variable type");
1623
	    errorcall(call, "invalid variable type");
1622
    }
1624
    }
1623
 
1625
 
1624
    /* If there is no intercept we look through the factor pattern */
1626
    /* If there is no intercept we look through the factor pattern */
1625
    /* matrix and adjust the code for the first factor found so that */
1627
    /* matrix and adjust the code for the first factor found so that */
1626
    /* it will be coded by dummy variables rather than contrasts. */
1628
    /* it will be coded by dummy variables rather than contrasts. */
1627
 
1629
 
1628
    if (!intrcept) {
1630
    if (!intrcept) {
1629
	for (j = 0; j < nterms; j++) {
1631
	for (j = 0; j < nterms; j++) {
1630
	    for (i = risponse; i < nVar; i++) {
1632
	    for (i = risponse; i < nVar; i++) {
1631
		if (INTEGER(nlevs)[i] > 1
1633
		if (INTEGER(nlevs)[i] > 1
1632
		    && INTEGER(factors)[i + j * nVar] > 0) {
1634
		    && INTEGER(factors)[i + j * nVar] > 0) {
1633
		    INTEGER(factors)[i + j * nVar] = 2;
1635
		    INTEGER(factors)[i + j * nVar] = 2;
1634
		    goto alldone;
1636
		    goto alldone;
1635
		}
1637
		}
1636
	    }
1638
	    }
1637
	}
1639
	}
1638
    }
1640
    }
1639
 alldone:
1641
 alldone:
1640
    ;
1642
    ;
1641
 
1643
 
1642
    /* Compute the required contrast or dummy variable matrices. */
1644
    /* Compute the required contrast or dummy variable matrices. */
1643
    /* We set up a symbolic expression to evaluate these, substituting */
1645
    /* We set up a symbolic expression to evaluate these, substituting */
1644
    /* the required arguments at call time.  The calls have the following */
1646
    /* the required arguments at call time.  The calls have the following */
1645
    /* form: (contrast.type nlevs contrasts) */
1647
    /* form: (contrast.type nlevs contrasts) */
1646
 
1648
 
1647
    PROTECT(contr1 = allocVector(VECSXP, nVar));
1649
    PROTECT(contr1 = allocVector(VECSXP, nVar));
1648
    PROTECT(contr2 = allocVector(VECSXP, nVar));
1650
    PROTECT(contr2 = allocVector(VECSXP, nVar));
1649
 
1651
 
1650
    PROTECT(expr = allocList(3));
1652
    PROTECT(expr = allocList(3));
1651
    SET_TYPEOF(expr, LANGSXP);
1653
    SET_TYPEOF(expr, LANGSXP);
1652
    SETCAR(expr, install("contrasts"));
1654
    SETCAR(expr, install("contrasts"));
1653
    SETCADDR(expr, allocVector(LGLSXP, 1));
1655
    SETCADDR(expr, allocVector(LGLSXP, 1));
1654
 
1656
 
1655
    /* FIXME: We need to allow a third argument to this function */
1657
    /* FIXME: We need to allow a third argument to this function */
1656
    /* which allows us to specify contrasts directly.  That argument */
1658
    /* which allows us to specify contrasts directly.  That argument */
1657
    /* would be used here in exactly the same way as the below. */
1659
    /* would be used here in exactly the same way as the below. */
1658
    /* I.e. we would search the list of constrast specs before */
1660
    /* I.e. we would search the list of constrast specs before */
1659
    /* we try the evaluation below. */
1661
    /* we try the evaluation below. */
1660
 
1662
 
1661
    for (i = 0; i < nVar; i++) {
1663
    for (i = 0; i < nVar; i++) {
1662
	if (INTEGER(nlevs)[i]) {
1664
	if (INTEGER(nlevs)[i]) {
1663
	    k = 0;
1665
	    k = 0;
1664
	    for (j = 0; j < nterms; j++) {
1666
	    for (j = 0; j < nterms; j++) {
1665
		if (INTEGER(factors)[i + j * nVar] == 1)
1667
		if (INTEGER(factors)[i + j * nVar] == 1)
1666
		    k |= 1;
1668
		    k |= 1;
1667
		else if (INTEGER(factors)[i + j * nVar] == 2)
1669
		else if (INTEGER(factors)[i + j * nVar] == 2)
1668
		    k |= 2;
1670
		    k |= 2;
1669
	    }
1671
	    }
1670
	    SETCADR(expr, VECTOR_ELT(variable, i));
1672
	    SETCADR(expr, VECTOR_ELT(variable, i));
1671
	    if (k & 1) {
1673
	    if (k & 1) {
1672
		LOGICAL(CADDR(expr))[0] = 1;
1674
		LOGICAL(CADDR(expr))[0] = 1;
1673
		SET_VECTOR_ELT(contr1, i, eval(expr, rho));
1675
		SET_VECTOR_ELT(contr1, i, eval(expr, rho));
1674
	    }
1676
	    }
1675
	    if (k & 2) {
1677
	    if (k & 2) {
1676
		LOGICAL(CADDR(expr))[0] = 0;
1678
		LOGICAL(CADDR(expr))[0] = 0;
1677
		SET_VECTOR_ELT(contr2, i, eval(expr, rho));
1679
		SET_VECTOR_ELT(contr2, i, eval(expr, rho));
1678
	    }
1680
	    }
1679
	}
1681
	}
1680
    }
1682
    }
1681
 
1683
 
1682
    /* By convention, an rhs term identical to the response generates nothing
1684
    /* By convention, an rhs term identical to the response generates nothing
1683
       in the model matrix (but interactions involving the response do). */
1685
       in the model matrix (but interactions involving the response do). */
1684
 
1686
 
1685
    rhs_response = -1;
1687
    rhs_response = -1;
1686
    if (risponse > 0) /* there is a response specified */
1688
    if (risponse > 0) /* there is a response specified */
1687
	for (j = 0; j < nterms; j++)
1689
	for (j = 0; j < nterms; j++)
1688
	    if (INTEGER(factors)[risponse - 1 + j * nVar]) {
1690
	    if (INTEGER(factors)[risponse - 1 + j * nVar]) {
1689
		for (i = 0, k = 0; i < nVar; i++)
1691
		for (i = 0, k = 0; i < nVar; i++)
1690
		    k += INTEGER(factors)[i + j * nVar] > 0;
1692
		    k += INTEGER(factors)[i + j * nVar] > 0;
1691
		if (k == 1) {
1693
		if (k == 1) {
1692
		    rhs_response = j;
1694
		    rhs_response = j;
1693
		    break;
1695
		    break;
1694
		}
1696
		}
1695
	    }
1697
	    }
1696
 
1698
 
1697
 
1699
 
1698
    /* We now have everything needed to build the design matrix. */
1700
    /* We now have everything needed to build the design matrix. */
1699
    /* The first step is to compute the matrix size and to allocate it. */
1701
    /* The first step is to compute the matrix size and to allocate it. */
1700
    /* Note that "count" holds a count of how many columns there are */
1702
    /* Note that "count" holds a count of how many columns there are */
1701
    /* for each term in the model and "nc" gives the total column count. */
1703
    /* for each term in the model and "nc" gives the total column count. */
1702
 
1704
 
1703
    PROTECT(count = allocVector(INTSXP, nterms));
1705
    PROTECT(count = allocVector(INTSXP, nterms));
1704
    if (intrcept)
1706
    if (intrcept)
1705
	nc = 1;
1707
	nc = 1;
1706
    else
1708
    else
1707
	nc = 0;
1709
	nc = 0;
1708
    for (j = 0; j < nterms; j++) {
1710
    for (j = 0; j < nterms; j++) {
1709
	if (j == rhs_response) {
1711
	if (j == rhs_response) {
1710
	    warning("the response appeared on the rhs and was dropped");
1712
	    warning("the response appeared on the rhs and was dropped");
1711
	    INTEGER(count)[j] = 0;  /* need this initialised */
1713
	    INTEGER(count)[j] = 0;  /* need this initialised */
1712
	    continue;
1714
	    continue;
1713
	}
1715
	}
1714
	k = 1;
1716
	k = 1;
1715
	for (i = 0; i < nVar; i++) {
1717
	for (i = 0; i < nVar; i++) {
1716
	    if (INTEGER(factors)[i + j * nVar]) {
1718
	    if (INTEGER(factors)[i + j * nVar]) {
1717
		if (INTEGER(nlevs)[i]) {
1719
		if (INTEGER(nlevs)[i]) {
1718
		    switch(INTEGER(factors)[i + j * nVar]) {
1720
		    switch(INTEGER(factors)[i + j * nVar]) {
1719
		    case 1:
1721
		    case 1:
1720
			k *= ncols(VECTOR_ELT(contr1, i));
1722
			k *= ncols(VECTOR_ELT(contr1, i));
1721
			break;
1723
			break;
1722
		    case 2:
1724
		    case 2:
1723
			k *= ncols(VECTOR_ELT(contr2, i));
1725
			k *= ncols(VECTOR_ELT(contr2, i));
1724
			break;
1726
			break;
1725
		    }
1727
		    }
1726
		}
1728
		}
1727
		else k *= INTEGER(columns)[i];
1729
		else k *= INTEGER(columns)[i];
1728
	    }
1730
	    }
1729
	}
1731
	}
1730
	INTEGER(count)[j] = k;
1732
	INTEGER(count)[j] = k;
1731
	nc = nc + k;
1733
	nc = nc + k;
1732
    }
1734
    }
1733
 
1735
 
1734
    /* Record which columns of the design matrix are associated */
1736
    /* Record which columns of the design matrix are associated */
1735
    /* with which model terms. */
1737
    /* with which model terms. */
1736
 
1738
 
1737
    PROTECT(assign = allocVector(INTSXP, nc));
1739
    PROTECT(assign = allocVector(INTSXP, nc));
1738
    k = 0;
1740
    k = 0;
1739
    if (intrcept) INTEGER(assign)[k++] = 0;
1741
    if (intrcept) INTEGER(assign)[k++] = 0;
1740
    for (j = 0; j < nterms; j++)
1742
    for (j = 0; j < nterms; j++)
1741
	for (i = 0; i < INTEGER(count)[j]; i++)
1743
	for (i = 0; i < INTEGER(count)[j]; i++)
1742
	    INTEGER(assign)[k++] = j+1;
1744
	    INTEGER(assign)[k++] = j+1;
1743
 
1745
 
1744
 
1746
 
1745
    /* Create column labels for the matrix columns. */
1747
    /* Create column labels for the matrix columns. */
1746
 
1748
 
1747
    PROTECT(xnames = allocVector(STRSXP, nc));
1749
    PROTECT(xnames = allocVector(STRSXP, nc));
1748
 
1750
 
1749
    /* Here we loop over the terms in the model and, within each */
1751
    /* Here we loop over the terms in the model and, within each */
1750
    /* term, loop over the corresponding columns of the design */
1752
    /* term, loop over the corresponding columns of the design */
1751
    /* matrix, assembling the names. */
1753
    /* matrix, assembling the names. */
1752
 
1754
 
1753
    /* FIXME : The body within these two loops should be embedded */
1755
    /* FIXME : The body within these two loops should be embedded */
1754
    /* in its own function. */
1756
    /* in its own function. */
1755
 
1757
 
1756
    k = 0;
1758
    k = 0;
1757
    if (intrcept)
1759
    if (intrcept)
1758
	SET_STRING_ELT(xnames, k++, mkChar("(Intercept)"));
1760
	SET_STRING_ELT(xnames, k++, mkChar("(Intercept)"));
1759
 
1761
 
1760
    for (j = 0; j < nterms; j++) {
1762
    for (j = 0; j < nterms; j++) {
1761
	if (j == rhs_response) continue;
1763
	if (j == rhs_response) continue;
1762
	for (kk = 0; kk < INTEGER(count)[j]; kk++) {
1764
	for (kk = 0; kk < INTEGER(count)[j]; kk++) {
1763
	    first = 1;
1765
	    first = 1;
1764
	    indx = kk;
1766
	    indx = kk;
1765
	    bufp = &buf[0];
1767
	    bufp = &buf[0];
1766
	    for (i = 0; i < nVar; i++) {
1768
	    for (i = 0; i < nVar; i++) {
1767
		ll = INTEGER(factors)[i + j * nVar];
1769
		ll = INTEGER(factors)[i + j * nVar];
1768
		if (ll) {
1770
		if (ll) {
1769
		    var_i = VECTOR_ELT(variable, i);
1771
		    var_i = VECTOR_ELT(variable, i);
1770
		    if (!first)
1772
		    if (!first)
1771
			bufp = AppendString(bufp, ":");
1773
			bufp = AppendString(bufp, ":");
1772
		    first = 0;
1774
		    first = 0;
1773
		    if (isFactor(var_i) || isLogical(var_i)) {
1775
		    if (isFactor(var_i) || isLogical(var_i)) {
1774
			if (ll == 1) {
1776
			if (ll == 1) {
1775
			    x = ColumnNames(VECTOR_ELT(contr1, i));
1777
			    x = ColumnNames(VECTOR_ELT(contr1, i));
1776
			    ll = ncols(VECTOR_ELT(contr1, i));
1778
			    ll = ncols(VECTOR_ELT(contr1, i));
1777
			}
1779
			}
1778
			else {
1780
			else {
1779
			    x = ColumnNames(VECTOR_ELT(contr2, i));
1781
			    x = ColumnNames(VECTOR_ELT(contr2, i));
1780
			    ll = ncols(VECTOR_ELT(contr2, i));
1782
			    ll = ncols(VECTOR_ELT(contr2, i));
1781
			}
1783
			}
1782
			addp = CHAR(STRING_ELT(vnames, i));
1784
			addp = CHAR(STRING_ELT(vnames, i));
1783
			if(strlen(buf) + strlen(addp) < BUFSIZE)
1785
			if(strlen(buf) + strlen(addp) < BUFSIZE)
1784
			    bufp = AppendString(bufp, addp);
1786
			    bufp = AppendString(bufp, addp);
1785
			else
1787
			else
1786
			    warningcall(call, "term names will be truncated");
1788
			    warningcall(call, "term names will be truncated");
1787
			if (x == R_NilValue) {
1789
			if (x == R_NilValue) {
1788
			    if(strlen(buf) + 10 < BUFSIZE)
1790
			    if(strlen(buf) + 10 < BUFSIZE)
1789
				bufp = AppendInteger(bufp, indx % ll + 1);
1791
				bufp = AppendInteger(bufp, indx % ll + 1);
1790
			    else
1792
			    else
1791
				warningcall(call, "term names will be truncated");
1793
				warningcall(call, "term names will be truncated");
1792
			} else {
1794
			} else {
1793
			    addp = CHAR(STRING_ELT(x, indx % ll));
1795
			    addp = CHAR(STRING_ELT(x, indx % ll));
1794
			    if(strlen(buf) + strlen(addp) < BUFSIZE)
1796
			    if(strlen(buf) + strlen(addp) < BUFSIZE)
1795
				bufp = AppendString(bufp, addp);
1797
				bufp = AppendString(bufp, addp);
1796
			    else
1798
			    else
1797
				warningcall(call, "term names will be truncated");
1799
				warningcall(call, "term names will be truncated");
1798
			}
1800
			}
1799
		    }
1801
		    }
1800
		    else {
1802
		    else {
1801
			x = ColumnNames(var_i);
1803
			x = ColumnNames(var_i);
1802
			ll = ncols(var_i);
1804
			ll = ncols(var_i);
1803
			addp = CHAR(STRING_ELT(vnames, i));
1805
			addp = CHAR(STRING_ELT(vnames, i));
1804
			if(strlen(buf) + strlen(addp) < BUFSIZE)
1806
			if(strlen(buf) + strlen(addp) < BUFSIZE)
1805
			    bufp = AppendString(bufp, addp);
1807
			    bufp = AppendString(bufp, addp);
1806
			else
1808
			else
1807
			    warningcall(call, "term names will be truncated");
1809
			    warningcall(call, "term names will be truncated");
1808
			if (ll > 1) {
1810
			if (ll > 1) {
1809
			    if (x == R_NilValue) {
1811
			    if (x == R_NilValue) {
1810
				if(strlen(buf) + 10 < BUFSIZE)
1812
				if(strlen(buf) + 10 < BUFSIZE)
1811
				    bufp = AppendInteger(bufp, indx % ll + 1);
1813
				    bufp = AppendInteger(bufp, indx % ll + 1);
1812
				else
1814
				else
1813
				    warningcall(call, "term names will be truncated");
1815
				    warningcall(call, "term names will be truncated");
1814
			    } else {
1816
			    } else {
1815
				addp = CHAR(STRING_ELT(x, indx % ll));
1817
				addp = CHAR(STRING_ELT(x, indx % ll));
1816
				if(strlen(buf) + strlen(addp) < BUFSIZE)
1818
				if(strlen(buf) + strlen(addp) < BUFSIZE)
1817
				    bufp = AppendString(bufp, addp);
1819
				    bufp = AppendString(bufp, addp);
1818
				else
1820
				else
1819
				    warningcall(call, "term names will be truncated");
1821
				    warningcall(call, "term names will be truncated");
1820
			    }
1822
			    }
1821
			}
1823
			}
1822
		    }
1824
		    }
1823
		    indx /= ll;
1825
		    indx /= ll;
1824
		}
1826
		}
1825
	    }
1827
	    }
1826
	    SET_STRING_ELT(xnames, k++, mkChar(buf));
1828
	    SET_STRING_ELT(xnames, k++, mkChar(buf));
1827
	}
1829
	}
1828
    }
1830
    }
1829
 
1831
 
1830
    /* Allocate and compute the design matrix. */
1832
    /* Allocate and compute the design matrix. */
1831
 
1833
 
1832
    PROTECT(x = allocMatrix(REALSXP, n, nc));
1834
    PROTECT(x = allocMatrix(REALSXP, n, nc));
1833
 
1835
 
1834
    /* a) Begin with a column of 1s for the intercept. */
1836
    /* a) Begin with a column of 1s for the intercept. */
1835
 
1837
 
1836
    if ((jnext = jstart = intrcept) != 0) {
1838
    if ((jnext = jstart = intrcept) != 0) {
1837
	for (i = 0; i < n; i++) {
1839
	for (i = 0; i < n; i++) {
1838
	    REAL(x)[i] = 1.0;
1840
	    REAL(x)[i] = 1.0;
1839
	}
1841
	}
1840
    }
1842
    }
1841
 
1843
 
1842
    /* b) Now loop over the model terms */
1844
    /* b) Now loop over the model terms */
1843
 
1845
 
1844
    contrast = R_NilValue;	/* -Wall */
1846
    contrast = R_NilValue;	/* -Wall */
1845
    for (k = 0; k < nterms; k++) {
1847
    for (k = 0; k < nterms; k++) {
1846
	if (k == rhs_response) continue;
1848
	if (k == rhs_response) continue;
1847
	for (i = 0; i < nVar; i++) {
1849
	for (i = 0; i < nVar; i++) {
1848
	    if (INTEGER(columns)[i] == 0)
1850
	    if (INTEGER(columns)[i] == 0)
1849
		continue;
1851
		continue;
1850
	    var_i = VECTOR_ELT(variable, i);
1852
	    var_i = VECTOR_ELT(variable, i);
1851
	    fik = INTEGER(factors)[i + k * nVar];
1853
	    fik = INTEGER(factors)[i + k * nVar];
1852
	    if (fik) {
1854
	    if (fik) {
1853
		switch(fik) {
1855
		switch(fik) {
1854
		case 1:
1856
		case 1:
1855
		    contrast = VECTOR_ELT(contr1, i);
1857
		    contrast = VECTOR_ELT(contr1, i);
1856
		    break;
1858
		    break;
1857
		case 2:
1859
		case 2:
1858
		    contrast = VECTOR_ELT(contr2, i);
1860
		    contrast = VECTOR_ELT(contr2, i);
1859
		    break;
1861
		    break;
1860
		}
1862
		}
1861
		if (jnext == jstart) {
1863
		if (jnext == jstart) {
1862
		    if (INTEGER(nlevs)[i] > 0) {
1864
		    if (INTEGER(nlevs)[i] > 0) {
1863
			int adj = isLogical(var_i)?1:0;
1865
			int adj = isLogical(var_i)?1:0;
1864
			firstfactor(&REAL(x)[jstart * n], n, jnext - jstart,
1866
			firstfactor(&REAL(x)[jstart * n], n, jnext - jstart,
1865
				    REAL(contrast), nrows(contrast),
1867
				    REAL(contrast), nrows(contrast),
1866
				    ncols(contrast), INTEGER(var_i)+adj);
1868
				    ncols(contrast), INTEGER(var_i)+adj);
1867
			jnext = jnext + ncols(contrast);
1869
			jnext = jnext + ncols(contrast);
1868
		    }
1870
		    }
1869
		    else {
1871
		    else {
1870
			firstvar(&REAL(x)[jstart * n], n, jnext - jstart,
1872
			firstvar(&REAL(x)[jstart * n], n, jnext - jstart,
1871
				 REAL(var_i), n, ncols(var_i));
1873
				 REAL(var_i), n, ncols(var_i));
1872
			jnext = jnext + ncols(var_i);
1874
			jnext = jnext + ncols(var_i);
1873
		    }
1875
		    }
1874
		}
1876
		}
1875
		else {
1877
		else {
1876
		    if (INTEGER(nlevs)[i] > 0) {
1878
		    if (INTEGER(nlevs)[i] > 0) {
1877
			int adj = isLogical(var_i)?1:0;
1879
			int adj = isLogical(var_i)?1:0;
1878
			addfactor(&REAL(x)[jstart * n], n, jnext - jstart,
1880
			addfactor(&REAL(x)[jstart * n], n, jnext - jstart,
1879
				  REAL(contrast), nrows(contrast),
1881
				  REAL(contrast), nrows(contrast),
1880
				  ncols(contrast), INTEGER(var_i)+adj);
1882
				  ncols(contrast), INTEGER(var_i)+adj);
1881
			jnext = jnext + (jnext - jstart)*(ncols(contrast) - 1);
1883
			jnext = jnext + (jnext - jstart)*(ncols(contrast) - 1);
1882
		    }
1884
		    }
1883
		    else {
1885
		    else {
1884
			addvar(&REAL(x)[jstart * n], n, jnext - jstart,
1886
			addvar(&REAL(x)[jstart * n], n, jnext - jstart,
1885
			       REAL(var_i), n, ncols(var_i));
1887
			       REAL(var_i), n, ncols(var_i));
1886
			jnext = jnext + (jnext - jstart) * (ncols(var_i) - 1);
1888
			jnext = jnext + (jnext - jstart) * (ncols(var_i) - 1);
1887
		    }
1889
		    }
1888
		}
1890
		}
1889
	    }
1891
	    }
1890
	}
1892
	}
1891
	jstart = jnext;
1893
	jstart = jnext;
1892
    }
1894
    }
1893
    PROTECT(tnames = allocVector(VECSXP, 2));
1895
    PROTECT(tnames = allocVector(VECSXP, 2));
1894
    SET_VECTOR_ELT(tnames, 0, rnames);
1896
    SET_VECTOR_ELT(tnames, 0, rnames);
1895
    SET_VECTOR_ELT(tnames, 1, xnames);
1897
    SET_VECTOR_ELT(tnames, 1, xnames);
1896
    setAttrib(x, R_DimNamesSymbol, tnames);
1898
    setAttrib(x, R_DimNamesSymbol, tnames);
1897
    setAttrib(x, install("assign"), assign);
1899
    setAttrib(x, install("assign"), assign);
1898
    UNPROTECT(13);
1900
    UNPROTECT(13);
1899
    return x;
1901
    return x;
1900
}
1902
}