void Ephemeris<Frame>::WriteToMessage( not_null<serialization::Ephemeris*> const message) const { LOG(INFO) << __FUNCTION__; // The bodies are serialized in the order in which they were given at // construction. for (auto const& unowned_body : unowned_bodies_) { unowned_body->WriteToMessage(message->add_body()); } // The trajectories are serialized in the order resulting from the separation // between oblate and spherical bodies. if (checkpoints_.empty()) { for (auto const& trajectory : trajectories_) { trajectory->WriteToMessage(message->add_trajectory()); } last_state_.WriteToMessage(message->mutable_last_state()); } else { auto const& checkpoints = checkpoints_.front().checkpoints; CHECK_EQ(trajectories_.size(), checkpoints.size()); for (int i = 0; i < trajectories_.size(); ++i) { trajectories_[i]->WriteToMessage(message->add_trajectory(), checkpoints[i]); } checkpoints_.front().system_state.WriteToMessage( message->mutable_last_state()); t_max().WriteToMessage(message->mutable_t_max()); } parameters_.WriteToMessage(message->mutable_fixed_step_parameters()); fitting_tolerance_.WriteToMessage(message->mutable_fitting_tolerance()); LOG(INFO) << NAMED(message->SpaceUsed()); LOG(INFO) << NAMED(message->ByteSize()); }

SEXP add_xtsCoreAttributes(SEXP _x, SEXP _index, SEXP _indexClass, SEXP _tzone, SEXP _tclass, SEXP _class, SEXP _indexFormat) { int P=0; if(NAMED(_index) == 2) { PROTECT(_index = duplicate(_index)); P++; } /* add tzone and tclass to index */ setAttrib(_index, install("tclass"), _tclass); setAttrib(_index, install("tzone"), _tzone); if(NAMED(_x) == 2) { PROTECT(_x = duplicate(_x)); P++; //_x = duplicate(_x); } setAttrib(_x, xts_IndexSymbol, _index); /* index */ setAttrib(_x, xts_IndexClassSymbol, _indexClass); /* .indexClass */ setAttrib(_x, xts_IndexTZSymbol, _tzone); /* .indexTZ */ setAttrib(_x, install("tclass"), _tclass); /* tclass */ setAttrib(_x, install("tzone"), _tzone); /* tzone */ setAttrib(_x, R_ClassSymbol, _class); /* class */ /* .indexFormat is only here because it's set in Ops.xts * This should go away once this attribute is on the index */ if(_indexFormat != R_NilValue) setAttrib(_x, xts_IndexFormatSymbol, _indexFormat); UNPROTECT(P); return(_x); }

void Plugin::UpdateCelestialHierarchy(Index const celestial_index, Index const parent_index) const { VLOG(1) << __FUNCTION__ << '\n' << NAMED(celestial_index) << '\n' << NAMED(parent_index); CHECK(!initializing_); FindOrDie(celestials_, celestial_index)->set_parent( FindOrDie(celestials_, parent_index).get()); }

static R_INLINE SEXP VECTOR_ELT_FIX_NAMED(SEXP y, R_xlen_t i) { /* if RHS (container or element) has NAMED > 0 set NAMED = 2. Duplicating might be safer/more consistent (fix bug reported by Radford Neal; similar to PR15098) */ SEXP val = VECTOR_ELT(y, i); if ((NAMED(y) || NAMED(val))) if (NAMED(val) < 2) SET_NAMED(val, 2); return val; }

void Ephemeris<Frame>::FlowWithFixedStep( std::vector<not_null<DiscreteTrajectory<Frame>*>> const& trajectories, std::vector<IntrinsicAcceleration> const& intrinsic_accelerations, Instant const& t, FixedStepParameters const& parameters) { VLOG(1) << __FUNCTION__ << " " << NAMED(parameters.step_) << " " << NAMED(t); if (empty() || t > t_max()) { Prolong(t); } std::vector<typename ContinuousTrajectory<Frame>::Hint> hints(bodies_.size()); NewtonianMotionEquation massless_body_equation; massless_body_equation.compute_acceleration = std::bind(&Ephemeris::ComputeMasslessBodiesTotalAccelerations, this, std::cref(intrinsic_accelerations), _1, _2, _3, &hints); typename NewtonianMotionEquation::SystemState initial_state; for (auto const& trajectory : trajectories) { auto const trajectory_last = trajectory->last(); auto const last_degrees_of_freedom = trajectory_last.degrees_of_freedom(); // TODO(phl): why do we keep rewriting this? Should we check consistency? initial_state.time = trajectory_last.time(); initial_state.positions.push_back(last_degrees_of_freedom.position()); initial_state.velocities.push_back(last_degrees_of_freedom.velocity()); } IntegrationProblem<NewtonianMotionEquation> problem; problem.equation = massless_body_equation; #if defined(WE_LOVE_228) typename NewtonianMotionEquation::SystemState last_state; problem.append_state = [&last_state]( typename NewtonianMotionEquation::SystemState const& state) { last_state = state; }; #else problem.append_state = std::bind(&Ephemeris::AppendMasslessBodiesState, _1, std::cref(trajectories)); #endif problem.t_final = t; problem.initial_state = &initial_state; parameters.integrator_->Solve(problem, parameters.step_); #if defined(WE_LOVE_228) // The |positions| are empty if and only if |append_state| was never called; // in that case there was not enough room to advance the |trajectories|. if (!last_state.positions.empty()) { AppendMasslessBodiesState(last_state, trajectories); } #endif }

void principia__AddVesselToNextPhysicsBubble(Plugin* const plugin, char const* const vessel_guid, KSPPart const* const parts, int count) { journal::Method<journal::AddVesselToNextPhysicsBubble> m({plugin, vessel_guid, parts, count}); VLOG(1) << __FUNCTION__ << '\n' << NAMED(count); CHECK_NOTNULL(plugin); std::vector<principia::ksp_plugin::IdAndOwnedPart> vessel_parts; vessel_parts.reserve(count); for (KSPPart const* part = parts; part < parts + count; ++part) { vessel_parts.push_back( std::make_pair( part->id, make_not_null_unique<Part<World>>( DegreesOfFreedom<World>( World::origin + Displacement<World>( FromXYZ(part->world_position) * Metre), Velocity<World>( FromXYZ(part->world_velocity) * (Metre / Second))), part->mass_in_tonnes * Tonne, Vector<Acceleration, World>( FromXYZ( part->gravitational_acceleration_to_be_applied_by_ksp) * (Metre / Pow<2>(Second)))))); } plugin->AddVesselToNextPhysicsBubble(vessel_guid, std::move(vessel_parts)); return m.Return(); }

SEXP attribute_hidden do_makelist(SEXP call, SEXP op, SEXP args, SEXP rho) { SEXP list, names, next; int i, n, havenames; /* compute number of args and check for names */ for (next = args, n = 0, havenames = FALSE; next != R_NilValue; next = CDR(next)) { if (TAG(next) != R_NilValue) havenames = TRUE; n++; } PROTECT(list = allocVector(VECSXP, n)); PROTECT(names = havenames ? allocVector(STRSXP, n) : R_NilValue); for (i = 0; i < n; i++) { if (havenames) { if (TAG(args) != R_NilValue) SET_STRING_ELT(names, i, PRINTNAME(TAG(args))); else SET_STRING_ELT(names, i, R_BlankString); } if (NAMED(CAR(args))) INCREMENT_NAMED(CAR(args)); SET_VECTOR_ELT(list, i, CAR(args)); args = CDR(args); } if (havenames) { setAttrib(list, R_NamesSymbol, names); } UNPROTECT(2); return list; }

/* Return -1 on failure */ int Sexp_named(const SEXP sexp) { if (! RINTERF_ISREADY()) { return -1; } int res = NAMED(sexp); return res; }

SEXP attribute_hidden do_commentgets(SEXP call, SEXP op, SEXP args, SEXP env) { checkArity(op, args); if (NAMED(CAR(args)) == 2) SETCAR(args, duplicate(CAR(args))); if (length(CADR(args)) == 0) SETCADR(args, R_NilValue); setAttrib(CAR(args), R_CommentSymbol, CADR(args)); SET_NAMED(CAR(args), 0); return CAR(args); }

void DiscreteTrajectory<Frame>::WriteToMessage( not_null<serialization::Trajectory*> const message, std::vector<DiscreteTrajectory<Frame>*> const& forks) const { LOG(INFO) << __FUNCTION__; CHECK(this->is_root()); std::vector<DiscreteTrajectory<Frame>*> mutable_forks = forks; WriteSubTreeToMessage(message, mutable_forks); CHECK(std::all_of(mutable_forks.begin(), mutable_forks.end(), [](DiscreteTrajectory<Frame>* const fork) { return fork == nullptr; })); LOG(INFO) << NAMED(this); LOG(INFO) << NAMED(message->SpaceUsed()); LOG(INFO) << NAMED(message->ByteSize()); }

/* This is a special .Internal, so has unevaluated arguments. It is called from a closure wrapper, so X and FUN are promises. */ SEXP attribute_hidden do_lapply(SEXP call, SEXP op, SEXP args, SEXP rho) { SEXP R_fcall, ans, names, X, XX, FUN; R_xlen_t i, n; PROTECT_INDEX px; checkArity(op, args); PROTECT_WITH_INDEX(X = CAR(args), &px); PROTECT(XX = eval(CAR(args), rho)); FUN = CADR(args); /* must be unevaluated for use in e.g. bquote */ n = xlength(XX); if (n == NA_INTEGER) error(_("invalid length")); Rboolean realIndx = CXXRCONSTRUCT(Rboolean, n > INT_MAX); PROTECT(ans = allocVector(VECSXP, n)); names = getAttrib(XX, R_NamesSymbol); if(!isNull(names)) setAttrib(ans, R_NamesSymbol, names); /* The R level code has ensured that XX is a vector. If it is atomic we can speed things up slightly by using the evaluated version. */ { SEXP ind, tmp; /* Build call: FUN(XX[[<ind>]], ...) */ /* Notice that it is OK to have one arg to LCONS do memory allocation and not PROTECT the result (LCONS does memory protection of its args internally), but not both of them, since the computation of one may destroy the other */ PROTECT(ind = allocVector(realIndx ? REALSXP : INTSXP, 1)); if(isVectorAtomic(XX)) PROTECT(tmp = LCONS(R_Bracket2Symbol, CONS(XX, CONS(ind, R_NilValue)))); else PROTECT(tmp = LCONS(R_Bracket2Symbol, CONS(X, CONS(ind, R_NilValue)))); PROTECT(R_fcall = LCONS(FUN, CONS(tmp, CONS(R_DotsSymbol, R_NilValue)))); for(i = 0; i < n; i++) { if (realIndx) REAL(ind)[0] = double(i + 1); else INTEGER(ind)[0] = int(i + 1); tmp = eval(R_fcall, rho); if (NAMED(tmp)) tmp = duplicate(tmp); SET_VECTOR_ELT(ans, i, tmp); } UNPROTECT(3); } UNPROTECT(3); /* X, XX, ans */ return ans; }

SEXP attribute_hidden do_mvfft(SEXP call, SEXP op, SEXP args, SEXP env) { SEXP z, d; int i, inv, maxf, maxp, n, p; double *work; int *iwork; checkArity(op, args); z = CAR(args); d = getAttrib(z, R_DimSymbol); if (d == R_NilValue || length(d) > 2) error(_("vector-valued (multivariate) series required")); n = INTEGER(d)[0]; p = INTEGER(d)[1]; switch(TYPEOF(z)) { case INTSXP: case LGLSXP: case REALSXP: z = coerceVector(z, CPLXSXP); break; case CPLXSXP: if (NAMED(z)) z = duplicate(z); break; default: error(_("non-numeric argument")); } PROTECT(z); /* -2 for forward transform, complex values */ /* +2 for backward transform, complex values */ inv = asLogical(CADR(args)); if (inv == NA_INTEGER || inv == 0) inv = -2; else inv = 2; if (n > 1) { fft_factor(n, &maxf, &maxp); if (maxf == 0) error(_("fft factorization error")); work = (double*)R_alloc(4 * maxf, sizeof(double)); iwork = (int*)R_alloc(maxp, sizeof(int)); for (i = 0; i < p; i++) { fft_factor(n, &maxf, &maxp); fft_work(&(COMPLEX(z)[i*n].r), &(COMPLEX(z)[i*n].i), 1, n, 1, inv, work, iwork); } } UNPROTECT(1); return z; }

SEXP setattrib(SEXP x, SEXP name, SEXP value) { if (TYPEOF(name) != STRSXP) error("Attribute name must be of type character"); if ( !isNewList(x) && strcmp(CHAR(STRING_ELT(name, 0)), "class") == 0 && isString(value) && (strcmp(CHAR(STRING_ELT(value, 0)), "data.table") == 0 || strcmp(CHAR(STRING_ELT(value, 0)), "data.frame") == 0) ) error("Internal structure doesn't seem to be a list. Can't set class to be 'data.table' or 'data.frame'. Use 'as.data.table()' or 'as.data.frame()' methods instead."); if (isLogical(x) && x == ScalarLogical(TRUE)) { x = PROTECT(duplicate(x)); setAttrib(x, name, NAMED(value) ? duplicate(value) : value); UNPROTECT(1); return(x); } setAttrib(x, name, NAMED(value) ? duplicate(value) : value); // duplicate is temp fix to restore R behaviour prior to R-devel change on 10 Jan 2014 (r64724). // TO DO: revisit. Enough to reproduce is: DT=data.table(a=1:3); DT[2]; DT[,b:=2] // ... Error: selfrefnames is ok but tl names [1] != tl [100] return(R_NilValue); }

void Plugin::InsertCelestialJacobiKeplerian( Index const celestial_index, std::experimental::optional<Index> const& parent_index, std::experimental::optional<KeplerianElements<Barycentric>> const& keplerian_elements, not_null<std::unique_ptr<MassiveBody>> body) { LOG(INFO) << __FUNCTION__ << "\n" << NAMED(celestial_index) << "\n" << NAMED(parent_index) << "\n" << NAMED(keplerian_elements) << "\n" << NAMED(body); CHECK(initializing_) << "Celestial bodies should be inserted before the end " << "of initialization"; CHECK(!absolute_initialization_); CHECK_EQ((bool)parent_index, (bool)keplerian_elements); CHECK_EQ((bool)parent_index, (bool)hierarchical_initialization_); MassiveBody* const unowned_body = body.get(); if (hierarchical_initialization_) { hierarchical_initialization_->system.Add( std::move(body), hierarchical_initialization_->indices_to_bodies[*parent_index], *keplerian_elements); } else { hierarchical_initialization_.emplace(std::move(body)); } bool inserted = hierarchical_initialization_->parents.emplace(celestial_index, parent_index).second; inserted &= hierarchical_initialization_-> indices_to_bodies.emplace(celestial_index, unowned_body).second; CHECK(inserted); // Record the fingerprints of the parameters to detect if we are in KSP stock. CHECK(celestial_jacobi_keplerian_fingerprints_.insert( FingerprintCelestialJacobiKeplerian(celestial_index, parent_index, keplerian_elements, *unowned_body)).second); }

/* oldClass<-(), primitive */ SEXP attribute_hidden do_classgets(SEXP call, SEXP op, SEXP args, SEXP env) { checkArity(op, args); check1arg(args, call, "x"); if (NAMED(CAR(args)) == 2) SETCAR(args, duplicate(CAR(args))); if (length(CADR(args)) == 0) SETCADR(args, R_NilValue); if(IS_S4_OBJECT(CAR(args))) UNSET_S4_OBJECT(CAR(args)); setAttrib(CAR(args), R_ClassSymbol, CADR(args)); SET_NAMED(CAR(args), 0); return CAR(args); }

/* duplicate RHS value of complex assignment if necessary to prevent cycles */ INLINE_FUN SEXP R_FixupRHS(SEXP x, SEXP y) { if( y != R_NilValue && MAYBE_REFERENCED(y) ) { if (R_cycle_detected(x, y)) { #ifdef WARNING_ON_CYCLE_DETECT warning("cycle detected"); R_cycle_detected(x, y); #endif y = duplicate(y); } else if (NAMED(y) < 2) SET_NAMED(y, 2); } return y; }

/* 'name' should be 1-element STRSXP or SYMSXP */ SEXP setAttrib(SEXP vec, SEXP name, SEXP val) { PROTECT(vec); PROTECT(name); if (isString(name)) name = install(translateChar(STRING_ELT(name, 0))); if (val == R_NilValue) { UNPROTECT(2); return removeAttrib(vec, name); } /* We allow attempting to remove names from NULL */ if (vec == R_NilValue) error(_("attempt to set an attribute on NULL")); if (NAMED(val)) val = duplicate(val); SET_NAMED(val, NAMED(val) | NAMED(vec)); UNPROTECT(2); if (name == R_NamesSymbol) return namesgets(vec, val); else if (name == R_DimSymbol) return dimgets(vec, val); else if (name == R_DimNamesSymbol) return dimnamesgets(vec, val); else if (name == R_ClassSymbol) return classgets(vec, val); else if (name == R_TspSymbol) return tspgets(vec, val); else if (name == R_CommentSymbol) return commentgets(vec, val); else if (name == R_RowNamesSymbol) return row_names_gets(vec, val); else return installAttrib(vec, name, val); }

static PyObject* Sexp_named_get(PyObject *self) { SEXP sexp = RPY_SEXP(((PySexpObject*)self)); if (! sexp) { PyErr_Format(PyExc_ValueError, "NULL SEXP."); return NULL;; } unsigned int res = NAMED(sexp); #if (PY_VERSION_HEX < 0x03010000) return PyInt_FromLong((long)res); #else return PyLong_FromLong((long)res); #endif }

/* The $ subset operator. We need to be sure to only evaluate the first argument. The second will be a symbol that needs to be matched, not evaluated. */ SEXP attribute_hidden do_subset3(SEXP call, SEXP op, SEXP args, SEXP env) { SEXP input, nlist, ans; checkArity(op, args); /* first translate CADR of args into a string so that we can pass it down to DispatchorEval and have it behave correctly */ input = PROTECT(allocVector(STRSXP, 1)); nlist = CADR(args); if (TYPEOF(nlist) == PROMSXP) nlist = eval(nlist, env); if(isSymbol(nlist) ) SET_STRING_ELT(input, 0, PRINTNAME(nlist)); else if(isString(nlist) ) SET_STRING_ELT(input, 0, STRING_ELT(nlist, 0)); else { errorcall(call,_("invalid subscript type '%s'"), type2char(TYPEOF(nlist))); } /* replace the second argument with a string */ /* Previously this was SETCADR(args, input); */ /* which could cause problems when nlist was */ /* ..., as in PR#8718 */ PROTECT(args = CONS(CAR(args), CONS(input, R_NilValue))); /* If the first argument is an object and there is */ /* an approriate method, we dispatch to that method, */ /* otherwise we evaluate the arguments and fall */ /* through to the generic code below. Note that */ /* evaluation retains any missing argument indicators. */ if(R_DispatchOrEvalSP(call, op, "$", args, env, &ans)) { UNPROTECT(2); /* input, args */ if (NAMED(ans)) SET_NAMED(ans, 2); return(ans); } UNPROTECT(2); /* input, args */ return R_subset3_dflt(CAR(ans), STRING_ELT(input, 0), call); }

/* This is used for [[ and [[<- with a vector of indices of length > 1 . x is a list or pairlist, and it is indexed recusively from level start to level stop-1. ( 0...len-1 or 0..len-2 then len-1). For [[<- it needs to duplicate if substructure might be shared. */ SEXP attribute_hidden vectorIndex(SEXP x, SEXP thesub, int start, int stop, int pok, SEXP call, Rboolean dup) { int i; R_xlen_t offset; SEXP cx; /* sanity check */ if (dup && MAYBE_SHARED(x)) error("should only be called in an assignment context."); for(i = start; i < stop; i++) { if(!isVectorList(x) && !isPairList(x)) { if (i) errorcall(call, _("recursive indexing failed at level %d\n"), i+1); else errorcall(call, _("attempt to select more than one element")); } PROTECT(x); SEXP names = PROTECT(getAttrib(x, R_NamesSymbol)); offset = get1index(thesub, names, xlength(x), pok, i, call); UNPROTECT(2); /* x, names */ if(offset < 0 || offset >= xlength(x)) errorcall(call, _("no such index at level %d\n"), i+1); if(isPairList(x)) { #ifdef LONG_VECTOR_SUPPORT if (offset > R_SHORT_LEN_MAX) error("invalid subscript for pairlist"); #endif cx = nthcdr(x, (int) offset); if (NAMED(x) > NAMED(CAR(cx))) SET_NAMED(CAR(x), NAMED(x)); x = CAR(cx); if (dup && MAYBE_SHARED(x)) { x = shallow_duplicate(x); SETCAR(cx, x); } } else { cx = x; x = VECTOR_ELT(x, offset); if (NAMED(cx) > NAMED(x)) SET_NAMED(x, NAMED(cx)); if (dup && MAYBE_SHARED(x)) { x = shallow_duplicate(x); SET_VECTOR_ELT(cx, offset, x); } } } return x; }

SEXP copyNamedInList(SEXP x) { // As from R 3.1.0 list() no longer copies NAMED inputs // Since data.table allows subassignment by reference, we need a way to copy NAMED inputs, still. // But for many other applications (such as in j and elsewhere internally) the new non-copying list() in R 3.1.0 is very welcome. // This is intended to be called just after list(...) in data.table(). It isn't for use on a single data.table, as // member columns of a list aren't marked as NAMED when the VECSXP is. // For now, this makes the old behaviour of list() in R<3.1.0 available for use, where we need it. if (TYPEOF(x) != VECSXP) error("x isn't a VECSXP"); for (int i=0; i<LENGTH(x); i++) { if (NAMED(VECTOR_ELT(x, i))) { SET_VECTOR_ELT(x, i, duplicate(VECTOR_ELT(x,i))); } } return R_NilValue; }

static SEXP do_one(SEXP X, SEXP FUN, SEXP classes, SEXP deflt, Rboolean replace, SEXP rho) { SEXP ans, names, klass, R_fcall; int i, j, n; Rboolean matched = FALSE; /* if X is a list, recurse. Otherwise if it matches classes call f */ if(isNewList(X)) { n = length(X); PROTECT(ans = allocVector(VECSXP, n)); names = getAttrib(X, R_NamesSymbol); /* or copy attributes if replace = TRUE? */ if(!isNull(names)) setAttrib(ans, R_NamesSymbol, names); for(i = 0; i < n; i++) SET_VECTOR_ELT(ans, i, do_one(VECTOR_ELT(X, i), FUN, classes, deflt, replace, rho)); UNPROTECT(1); return ans; } if(strcmp(CHAR(STRING_ELT(classes, 0)), "ANY") == 0) /* ASCII */ matched = TRUE; else { PROTECT(klass = R_data_class(X, FALSE)); for(i = 0; i < LENGTH(klass); i++) for(j = 0; j < length(classes); j++) if(Seql(STRING_ELT(klass, i), STRING_ELT(classes, j))) matched = TRUE; UNPROTECT(1); } if(matched) { /* PROTECT(R_fcall = lang2(FUN, X)); */ PROTECT(R_fcall = lang3(FUN, X, R_DotsSymbol)); ans = eval(R_fcall, rho); if (NAMED(ans)) ans = duplicate(ans); UNPROTECT(1); return(ans); } else if(replace) return duplicate(X); else return duplicate(deflt); }

SEXP attribute_hidden do_subset(SEXP call, SEXP op, SEXP args, SEXP rho) { SEXP ans; /* If the first argument is an object and there is an */ /* approriate method, we dispatch to that method, */ /* otherwise we evaluate the arguments and fall through */ /* to the generic code below. Note that evaluation */ /* retains any missing argument indicators. */ if(DispatchOrEval(call, op, "[", args, rho, &ans, 0, 0)) { /* if(DispatchAnyOrEval(call, op, "[", args, rho, &ans, 0, 0)) */ if (NAMED(ans)) SET_NAMED(ans, 2); return(ans); } /* Method dispatch has failed, we now */ /* run the generic internal code. */ return do_subset_dflt(call, op, ans, rho); }

SEXP attribute_hidden do_subset2(SEXP call, SEXP op, SEXP args, SEXP rho) { SEXP ans; /* If the first argument is an object and there is */ /* an approriate method, we dispatch to that method, */ /* otherwise we evaluate the arguments and fall */ /* through to the generic code below. Note that */ /* evaluation retains any missing argument indicators. */ if(R_DispatchOrEvalSP(call, op, "[[", args, rho, &ans)) { if (NAMED(ans)) SET_NAMED(ans, 2); return(ans); } /* Method dispatch has failed. */ /* We now run the generic internal code. */ return do_subset2_dflt(call, op, ans, rho); }

SEXP attribute_hidden do_subset2_dflt(SEXP call, SEXP op, SEXP args, SEXP rho) { SEXP ans, dims, dimnames, indx, subs, x; int i, ndims, nsubs; int drop = 1, pok, exact = -1; int named_x; R_xlen_t offset = 0; PROTECT(args); ExtractDropArg(args, &drop); /* Is partial matching ok? When the exact arg is NA, a warning is issued if partial matching occurs. */ exact = ExtractExactArg(args); if (exact == -1) pok = exact; else pok = !exact; x = CAR(args); /* This code was intended for compatibility with S, */ /* but in fact S does not do this. Will anyone notice? */ if (x == R_NilValue) { UNPROTECT(1); /* args */ return x; } /* Get the subscripting and dimensioning information */ /* and check that any array subscripting is compatible. */ subs = CDR(args); if(0 == (nsubs = length(subs))) errorcall(call, _("no index specified")); dims = getAttrib(x, R_DimSymbol); ndims = length(dims); if(nsubs > 1 && nsubs != ndims) errorcall(call, _("incorrect number of subscripts")); /* code to allow classes to extend environment */ if(TYPEOF(x) == S4SXP) { x = R_getS4DataSlot(x, ANYSXP); if(x == R_NilValue) errorcall(call, _("this S4 class is not subsettable")); } PROTECT(x); /* split out ENVSXP for now */ if( TYPEOF(x) == ENVSXP ) { if( nsubs != 1 || !isString(CAR(subs)) || length(CAR(subs)) != 1 ) errorcall(call, _("wrong arguments for subsetting an environment")); ans = findVarInFrame(x, installTrChar(STRING_ELT(CAR(subs), 0))); if( TYPEOF(ans) == PROMSXP ) { PROTECT(ans); ans = eval(ans, R_GlobalEnv); UNPROTECT(1); /* ans */ } else SET_NAMED(ans, 2); UNPROTECT(2); /* args, x */ if(ans == R_UnboundValue) return(R_NilValue); if (NAMED(ans)) SET_NAMED(ans, 2); return ans; } /* back to the regular program */ if (!(isVector(x) || isList(x) || isLanguage(x))) errorcall(call, R_MSG_ob_nonsub, type2char(TYPEOF(x))); named_x = NAMED(x); /* x may change below; save this now. See PR#13411 */ if(nsubs == 1) { /* vector indexing */ SEXP thesub = CAR(subs); int len = length(thesub); if (len > 1) { #ifdef SWITCH_TO_REFCNT if (IS_GETTER_CALL(call)) { /* this is (most likely) a getter call in a complex assighment so we duplicate as needed. The original x should have been duplicated if it might be shared */ if (MAYBE_SHARED(x)) error("getter call used outside of a complex assignment."); x = vectorIndex(x, thesub, 0, len-1, pok, call, TRUE); } else x = vectorIndex(x, thesub, 0, len-1, pok, call, FALSE); #else x = vectorIndex(x, thesub, 0, len-1, pok, call, FALSE); #endif named_x = NAMED(x); UNPROTECT(1); /* x */ PROTECT(x); } SEXP xnames = PROTECT(getAttrib(x, R_NamesSymbol)); offset = get1index(thesub, xnames, xlength(x), pok, len > 1 ? len-1 : -1, call); UNPROTECT(1); /* xnames */ if (offset < 0 || offset >= xlength(x)) { /* a bold attempt to get the same behaviour for $ and [[ */ if (offset < 0 && (isNewList(x) || isExpression(x) || isList(x) || isLanguage(x))) { UNPROTECT(2); /* args, x */ return R_NilValue; } else errorcall(call, R_MSG_subs_o_b); } } else { /* matrix indexing */ /* Here we use the fact that: */ /* CAR(R_NilValue) = R_NilValue */ /* CDR(R_NilValue) = R_NilValue */ int ndn; /* Number of dimnames. Unlikely to be anything but 0 or nsubs, but just in case... */ PROTECT(indx = allocVector(INTSXP, nsubs)); dimnames = getAttrib(x, R_DimNamesSymbol); ndn = length(dimnames); for (i = 0; i < nsubs; i++) { INTEGER(indx)[i] = (int) get1index(CAR(subs), (i < ndn) ? VECTOR_ELT(dimnames, i) : R_NilValue, INTEGER(indx)[i], pok, -1, call); subs = CDR(subs); if (INTEGER(indx)[i] < 0 || INTEGER(indx)[i] >= INTEGER(dims)[i]) errorcall(call, R_MSG_subs_o_b); } offset = 0; for (i = (nsubs - 1); i > 0; i--) offset = (offset + INTEGER(indx)[i]) * INTEGER(dims)[i - 1]; offset += INTEGER(indx)[0]; UNPROTECT(1); /* indx */ } if(isPairList(x)) { #ifdef LONG_VECTOR_SUPPORT if (offset > R_SHORT_LEN_MAX) error("invalid subscript for pairlist"); #endif ans = CAR(nthcdr(x, (int) offset)); if (named_x > NAMED(ans)) SET_NAMED(ans, named_x); } else if(isVectorList(x)) { /* did unconditional duplication before 2.4.0 */ ans = VECTOR_ELT(x, offset); if (named_x > NAMED(ans)) SET_NAMED(ans, named_x); } else { ans = allocVector(TYPEOF(x), 1); switch (TYPEOF(x)) { case LGLSXP: case INTSXP: INTEGER(ans)[0] = INTEGER(x)[offset]; break; case REALSXP: REAL(ans)[0] = REAL(x)[offset]; break; case CPLXSXP: COMPLEX(ans)[0] = COMPLEX(x)[offset]; break; case STRSXP: SET_STRING_ELT(ans, 0, STRING_ELT(x, offset)); break; case RAWSXP: RAW(ans)[0] = RAW(x)[offset]; break; default: UNIMPLEMENTED_TYPE("do_subset2", x); } } UNPROTECT(2); /* args, x */ return ans; }

SEXP attribute_hidden do_subset_dflt(SEXP call, SEXP op, SEXP args, SEXP rho) { SEXP ans, ax, px, x, subs; int drop, i, nsubs, type; /* By default we drop extents of length 1 */ /* Handle cases of extracting a single element from a simple vector or matrix directly to improve speed for these simple cases. */ SEXP cdrArgs = CDR(args); SEXP cddrArgs = CDR(cdrArgs); if (cdrArgs != R_NilValue && cddrArgs == R_NilValue && TAG(cdrArgs) == R_NilValue) { /* one index, not named */ SEXP x = CAR(args); if (ATTRIB(x) == R_NilValue) { SEXP s = CAR(cdrArgs); R_xlen_t i = scalarIndex(s); switch (TYPEOF(x)) { case REALSXP: if (i >= 1 && i <= XLENGTH(x)) return ScalarReal( REAL(x)[i-1] ); break; case INTSXP: if (i >= 1 && i <= XLENGTH(x)) return ScalarInteger( INTEGER(x)[i-1] ); break; case LGLSXP: if (i >= 1 && i <= XLENGTH(x)) return ScalarLogical( LOGICAL(x)[i-1] ); break; // do the more rare cases as well, since we've already prepared everything: case CPLXSXP: if (i >= 1 && i <= XLENGTH(x)) return ScalarComplex( COMPLEX(x)[i-1] ); break; case RAWSXP: if (i >= 1 && i <= XLENGTH(x)) return ScalarRaw( RAW(x)[i-1] ); break; default: break; } } } else if (cddrArgs != R_NilValue && CDR(cddrArgs) == R_NilValue && TAG(cdrArgs) == R_NilValue && TAG(cddrArgs) == R_NilValue) { /* two indices, not named */ SEXP x = CAR(args); SEXP attr = ATTRIB(x); if (TAG(attr) == R_DimSymbol && CDR(attr) == R_NilValue) { /* only attribute of x is 'dim' */ SEXP dim = CAR(attr); if (TYPEOF(dim) == INTSXP && LENGTH(dim) == 2) { /* x is a matrix */ SEXP si = CAR(cdrArgs); SEXP sj = CAR(cddrArgs); R_xlen_t i = scalarIndex(si); R_xlen_t j = scalarIndex(sj); int nrow = INTEGER(dim)[0]; int ncol = INTEGER(dim)[1]; if (i > 0 && j > 0 && i <= nrow && j <= ncol) { /* indices are legal scalars */ R_xlen_t k = i - 1 + nrow * (j - 1); switch (TYPEOF(x)) { case REALSXP: if (k < LENGTH(x)) return ScalarReal( REAL(x)[k] ); break; case INTSXP: if (k < LENGTH(x)) return ScalarInteger( INTEGER(x)[k] ); break; case LGLSXP: if (k < LENGTH(x)) return ScalarLogical( LOGICAL(x)[k] ); break; case CPLXSXP: if (k < LENGTH(x)) return ScalarComplex( COMPLEX(x)[k] ); break; case RAWSXP: if (k < LENGTH(x)) return ScalarRaw( RAW(x)[k] ); break; default: break; } } } } } PROTECT(args); drop = 1; ExtractDropArg(args, &drop); x = CAR(args); /* This was intended for compatibility with S, */ /* but in fact S does not do this. */ /* FIXME: replace the test by isNull ... ? */ if (x == R_NilValue) { UNPROTECT(1); return x; } subs = CDR(args); nsubs = length(subs); /* Will be short */ type = TYPEOF(x); /* Here coerce pair-based objects into generic vectors. */ /* All subsetting takes place on the generic vector form. */ ax = x; if (isVector(x)) PROTECT(ax); else if (isPairList(x)) { SEXP dim = getAttrib(x, R_DimSymbol); int ndim = length(dim); if (ndim > 1) { PROTECT(ax = allocArray(VECSXP, dim)); setAttrib(ax, R_DimNamesSymbol, getAttrib(x, R_DimNamesSymbol)); setAttrib(ax, R_NamesSymbol, getAttrib(x, R_DimNamesSymbol)); } else { PROTECT(ax = allocVector(VECSXP, length(x))); setAttrib(ax, R_NamesSymbol, getAttrib(x, R_NamesSymbol)); } for(px = x, i = 0 ; px != R_NilValue ; px = CDR(px)) SET_VECTOR_ELT(ax, i++, CAR(px)); } else errorcall(call, R_MSG_ob_nonsub, type2char(TYPEOF(x))); /* This is the actual subsetting code. */ /* The separation of arrays and matrices is purely an optimization. */ if(nsubs < 2) { SEXP dim = getAttrib(x, R_DimSymbol); int ndim = length(dim); PROTECT(ans = VectorSubset(ax, (nsubs == 1 ? CAR(subs) : R_MissingArg), call)); /* one-dimensional arrays went through here, and they should have their dimensions dropped only if the result has length one and drop == TRUE */ if(ndim == 1) { SEXP attr, attrib, nattrib; int len = length(ans); if(!drop || len > 1) { // must grab these before the dim is set. SEXP nm = PROTECT(getAttrib(ans, R_NamesSymbol)); PROTECT(attr = allocVector(INTSXP, 1)); INTEGER(attr)[0] = length(ans); setAttrib(ans, R_DimSymbol, attr); if((attrib = getAttrib(x, R_DimNamesSymbol)) != R_NilValue) { /* reinstate dimnames, include names of dimnames */ PROTECT(nattrib = duplicate(attrib)); SET_VECTOR_ELT(nattrib, 0, nm); setAttrib(ans, R_DimNamesSymbol, nattrib); setAttrib(ans, R_NamesSymbol, R_NilValue); UNPROTECT(1); } UNPROTECT(2); } } } else { if (nsubs != length(getAttrib(x, R_DimSymbol))) errorcall(call, _("incorrect number of dimensions")); if (nsubs == 2) ans = MatrixSubset(ax, subs, call, drop); else ans = ArraySubset(ax, subs, call, drop); PROTECT(ans); } /* Note: we do not coerce back to pair-based lists. */ /* They are "defunct" in this version of R. */ if (type == LANGSXP) { ax = ans; PROTECT(ans = allocList(LENGTH(ax))); if ( LENGTH(ax) > 0 ) SET_TYPEOF(ans, LANGSXP); for(px = ans, i = 0 ; px != R_NilValue ; px = CDR(px)) SETCAR(px, VECTOR_ELT(ax, i++)); setAttrib(ans, R_DimSymbol, getAttrib(ax, R_DimSymbol)); setAttrib(ans, R_DimNamesSymbol, getAttrib(ax, R_DimNamesSymbol)); setAttrib(ans, R_NamesSymbol, getAttrib(ax, R_NamesSymbol)); SET_NAMED(ans, NAMED(ax)); /* PR#7924 */ } else { PROTECT(ans); } if (ATTRIB(ans) != R_NilValue) { /* remove probably erroneous attr's */ setAttrib(ans, R_TspSymbol, R_NilValue); #ifdef _S4_subsettable if(!IS_S4_OBJECT(x)) #endif setAttrib(ans, R_ClassSymbol, R_NilValue); } UNPROTECT(4); return ans; }

/* This is a special .Internal */ SEXP attribute_hidden do_vapply(SEXP call, SEXP op, SEXP args, SEXP rho) { SEXP R_fcall, ans, names = R_NilValue, rowNames = R_NilValue, X, XX, FUN, value, dim_v; R_xlen_t i, n; int commonLen; int useNames, rnk_v = -1; // = array_rank(value) := length(dim(value)) Rboolean array_value; SEXPTYPE commonType; PROTECT_INDEX index = 0; // -Wall checkArity(op, args); PROTECT(X = CAR(args)); PROTECT(XX = eval(CAR(args), rho)); FUN = CADR(args); /* must be unevaluated for use in e.g. bquote */ PROTECT(value = eval(CADDR(args), rho)); if (!isVector(value)) error(_("'FUN.VALUE' must be a vector")); useNames = asLogical(eval(CADDDR(args), rho)); if (useNames == NA_LOGICAL) error(_("invalid '%s' value"), "USE.NAMES"); n = xlength(XX); if (n == NA_INTEGER) error(_("invalid length")); Rboolean realIndx = CXXRCONSTRUCT(Rboolean, n > INT_MAX); commonLen = length(value); if (commonLen > 1 && n > INT_MAX) error(_("long vectors are not supported for matrix/array results")); commonType = TYPEOF(value); dim_v = getAttrib(value, R_DimSymbol); array_value = CXXRCONSTRUCT(Rboolean, (TYPEOF(dim_v) == INTSXP && LENGTH(dim_v) >= 1)); PROTECT(ans = allocVector(commonType, n*commonLen)); if (useNames) { PROTECT(names = getAttrib(XX, R_NamesSymbol)); if (isNull(names) && TYPEOF(XX) == STRSXP) { UNPROTECT(1); PROTECT(names = XX); } PROTECT_WITH_INDEX(rowNames = getAttrib(value, array_value ? R_DimNamesSymbol : R_NamesSymbol), &index); } /* The R level code has ensured that XX is a vector. If it is atomic we can speed things up slightly by using the evaluated version. */ { SEXP ind, tmp; /* Build call: FUN(XX[[<ind>]], ...) */ /* Notice that it is OK to have one arg to LCONS do memory allocation and not PROTECT the result (LCONS does memory protection of its args internally), but not both of them, since the computation of one may destroy the other */ PROTECT(ind = allocVector(INTSXP, 1)); if(isVectorAtomic(XX)) PROTECT(tmp = LCONS(R_Bracket2Symbol, CONS(XX, CONS(ind, R_NilValue)))); else PROTECT(tmp = LCONS(R_Bracket2Symbol, CONS(X, CONS(ind, R_NilValue)))); PROTECT(R_fcall = LCONS(FUN, CONS(tmp, CONS(R_DotsSymbol, R_NilValue)))); for(i = 0; i < n; i++) { SEXP val; SEXPTYPE valType; PROTECT_INDEX indx; if (realIndx) REAL(ind)[0] = double(i + 1); else INTEGER(ind)[0] = int(i + 1); val = eval(R_fcall, rho); if (NAMED(val)) val = duplicate(val); PROTECT_WITH_INDEX(val, &indx); if (length(val) != commonLen) error(_("values must be length %d,\n but FUN(X[[%d]]) result is length %d"), commonLen, i+1, length(val)); valType = TYPEOF(val); if (valType != commonType) { bool okay = FALSE; switch (commonType) { case CPLXSXP: okay = (valType == REALSXP) || (valType == INTSXP) || (valType == LGLSXP); break; case REALSXP: okay = (valType == INTSXP) || (valType == LGLSXP); break; case INTSXP: okay = (valType == LGLSXP); break; default: Rf_error(_("Internal error: unexpected SEXPTYPE")); } if (!okay) error(_("values must be type '%s',\n but FUN(X[[%d]]) result is type '%s'"), type2char(commonType), i+1, type2char(valType)); REPROTECT(val = coerceVector(val, commonType), indx); } /* Take row names from the first result only */ if (i == 0 && useNames && isNull(rowNames)) REPROTECT(rowNames = getAttrib(val, array_value ? R_DimNamesSymbol : R_NamesSymbol), index); for (int j = 0; j < commonLen; j++) { switch (commonType) { case CPLXSXP: COMPLEX(ans)[i*commonLen + j] = COMPLEX(val)[j]; break; case REALSXP: REAL(ans)[i*commonLen + j] = REAL(val)[j]; break; case INTSXP: INTEGER(ans)[i*commonLen + j] = INTEGER(val)[j]; break; case LGLSXP: LOGICAL(ans)[i*commonLen + j] = LOGICAL(val)[j]; break; case RAWSXP: RAW(ans)[i*commonLen + j] = RAW(val)[j]; break; case STRSXP: SET_STRING_ELT(ans, i*commonLen + j, STRING_ELT(val, j)); break; case VECSXP: SET_VECTOR_ELT(ans, i*commonLen + j, VECTOR_ELT(val, j)); break; default: error(_("type '%s' is not supported"), type2char(commonType)); } } UNPROTECT(1); } UNPROTECT(3); } if (commonLen != 1) { SEXP dim; rnk_v = array_value ? LENGTH(dim_v) : 1; PROTECT(dim = allocVector(INTSXP, rnk_v+1)); if(array_value) for(int j = 0; j < rnk_v; j++) INTEGER(dim)[j] = INTEGER(dim_v)[j]; else INTEGER(dim)[0] = commonLen; INTEGER(dim)[rnk_v] = int( n); // checked above setAttrib(ans, R_DimSymbol, dim); UNPROTECT(1); } if (useNames) { if (commonLen == 1) { if(!isNull(names)) setAttrib(ans, R_NamesSymbol, names); } else { if (!isNull(names) || !isNull(rowNames)) { SEXP dimnames; PROTECT(dimnames = allocVector(VECSXP, rnk_v+1)); if(array_value && !isNull(rowNames)) { if(TYPEOF(rowNames) != VECSXP || LENGTH(rowNames) != rnk_v) // should never happen .. error(_("dimnames(<value>) is neither NULL nor list of length %d"), rnk_v); for(int j = 0; j < rnk_v; j++) SET_VECTOR_ELT(dimnames, j, VECTOR_ELT(rowNames, j)); } else SET_VECTOR_ELT(dimnames, 0, rowNames); SET_VECTOR_ELT(dimnames, rnk_v, names); setAttrib(ans, R_DimNamesSymbol, dimnames); UNPROTECT(1); } } } UNPROTECT(useNames ? 6 : 4); /* X, XX, value, ans, and maybe names and rowNames */ return ans; }

/* used in eval.c */ SEXP attribute_hidden R_subset3_dflt(SEXP x, SEXP input, SEXP call) { SEXP y, nlist; size_t slen; PROTECT(input); PROTECT(x); /* Optimisation to prevent repeated recalculation */ slen = strlen(translateChar(input)); /* The mechanism to allow a class extending "environment" */ if( IS_S4_OBJECT(x) && TYPEOF(x) == S4SXP ){ x = R_getS4DataSlot(x, ANYSXP); if(x == R_NilValue) errorcall(call, "$ operator not defined for this S4 class"); } UNPROTECT(1); /* x */ PROTECT(x); /* If this is not a list object we return NULL. */ if (isPairList(x)) { SEXP xmatch = R_NilValue; int havematch; UNPROTECT(2); /* input, x */ havematch = 0; for (y = x ; y != R_NilValue ; y = CDR(y)) { switch(pstrmatch(TAG(y), input, slen)) { case EXACT_MATCH: y = CAR(y); if (NAMED(x) > NAMED(y)) SET_NAMED(y, NAMED(x)); return y; case PARTIAL_MATCH: havematch++; xmatch = y; break; case NO_MATCH: break; } } if (havematch == 1) { /* unique partial match */ if(R_warn_partial_match_dollar) { const char *st = ""; SEXP target = TAG(xmatch); switch (TYPEOF(target)) { case SYMSXP: st = CHAR(PRINTNAME(target)); break; case CHARSXP: st = translateChar(target); break; } warningcall(call, _("partial match of '%s' to '%s'"), translateChar(input), st); } y = CAR(xmatch); if (NAMED(x) > NAMED(y)) SET_NAMED(y, NAMED(x)); return y; } return R_NilValue; } else if (isVectorList(x)) { R_xlen_t i, n, imatch = -1; int havematch; nlist = getAttrib(x, R_NamesSymbol); UNPROTECT(2); /* input, x */ n = xlength(nlist); havematch = 0; for (i = 0 ; i < n ; i = i + 1) { switch(pstrmatch(STRING_ELT(nlist, i), input, slen)) { case EXACT_MATCH: y = VECTOR_ELT(x, i); if (NAMED(x) > NAMED(y)) SET_NAMED(y, NAMED(x)); return y; case PARTIAL_MATCH: havematch++; if (havematch == 1) { /* partial matches can cause aliasing in eval.c:evalseq This is overkill, but alternative ways to prevent the aliasing appear to be even worse */ y = VECTOR_ELT(x,i); SET_NAMED(y,2); SET_VECTOR_ELT(x,i,y); } imatch = i; break; case NO_MATCH: break; } } if(havematch == 1) { /* unique partial match */ if(R_warn_partial_match_dollar) { const char *st = ""; SEXP target = STRING_ELT(nlist, imatch); switch (TYPEOF(target)) { case SYMSXP: st = CHAR(PRINTNAME(target)); break; case CHARSXP: st = translateChar(target); break; } warningcall(call, _("partial match of '%s' to '%s'"), translateChar(input), st); } y = VECTOR_ELT(x, imatch); if (NAMED(x) > NAMED(y)) SET_NAMED(y, NAMED(x)); return y; } return R_NilValue; } else if( isEnvironment(x) ){ y = findVarInFrame(x, installTrChar(input)); if( TYPEOF(y) == PROMSXP ) { PROTECT(y); y = eval(y, R_GlobalEnv); UNPROTECT(1); /* y */ } UNPROTECT(2); /* input, x */ if( y != R_UnboundValue ) { if (NAMED(y)) SET_NAMED(y, 2); else if (NAMED(x) > NAMED(y)) SET_NAMED(y, NAMED(x)); return(y); } return R_NilValue; } else if( isVectorAtomic(x) ){ errorcall(call, "$ operator is invalid for atomic vectors"); } else /* e.g. a function */ errorcall(call, R_MSG_ob_nonsub, type2char(TYPEOF(x))); UNPROTECT(2); /* input, x */ return R_NilValue; }

SEXP coxfit6(SEXP maxiter2, SEXP time2, SEXP status2, SEXP covar2, SEXP offset2, SEXP weights2, SEXP strata2, SEXP method2, SEXP eps2, SEXP toler2, SEXP ibeta, SEXP doscale2) { int i,j,k, person; double **covar, **cmat, **imat; /*ragged arrays */ double wtave; double *a, *newbeta; double *a2, **cmat2; double *scale; double denom=0, zbeta, risk; double temp, temp2; int ndead; /* actually, the sum of their weights */ double newlk=0; double dtime, d2; double deadwt; /*sum of case weights for the deaths*/ double efronwt; /* sum of weighted risk scores for the deaths*/ int halving; /*are we doing step halving at the moment? */ int nrisk; /* number of subjects in the current risk set */ /* copies of scalar input arguments */ int nused, nvar, maxiter; int method; double eps, toler; int doscale; /* vector inputs */ double *time, *weights, *offset; int *status, *strata; /* returned objects */ SEXP imat2, means2, beta2, u2, loglik2; double *beta, *u, *loglik, *means; SEXP sctest2, flag2, iter2; double *sctest; int *flag, *iter; SEXP rlist, rlistnames; int nprotect; /* number of protect calls I have issued */ /* get local copies of some input args */ nused = LENGTH(offset2); nvar = ncols(covar2); method = asInteger(method2); maxiter = asInteger(maxiter2); eps = asReal(eps2); /* convergence criteria */ toler = asReal(toler2); /* tolerance for cholesky */ doscale = asInteger(doscale2); time = REAL(time2); weights = REAL(weights2); offset= REAL(offset2); status = INTEGER(status2); strata = INTEGER(strata2); /* ** Set up the ragged arrays and scratch space ** Normally covar2 does not need to be duplicated, even though ** we are going to modify it, due to the way this routine was ** was called. In this case NAMED(covar2) will =0 */ nprotect =0; if (NAMED(covar2)>0) { PROTECT(covar2 = duplicate(covar2)); nprotect++; } covar= dmatrix(REAL(covar2), nused, nvar); PROTECT(imat2 = allocVector(REALSXP, nvar*nvar)); nprotect++; imat = dmatrix(REAL(imat2), nvar, nvar); a = (double *) R_alloc(2*nvar*nvar + 4*nvar, sizeof(double)); newbeta = a + nvar; a2 = newbeta + nvar; scale = a2 + nvar; cmat = dmatrix(scale + nvar, nvar, nvar); cmat2= dmatrix(scale + nvar +nvar*nvar, nvar, nvar); /* ** create output variables */ PROTECT(beta2 = duplicate(ibeta)); beta = REAL(beta2); PROTECT(means2 = allocVector(REALSXP, nvar)); means = REAL(means2); PROTECT(u2 = allocVector(REALSXP, nvar)); u = REAL(u2); PROTECT(loglik2 = allocVector(REALSXP, 2)); loglik = REAL(loglik2); PROTECT(sctest2 = allocVector(REALSXP, 1)); sctest = REAL(sctest2); PROTECT(flag2 = allocVector(INTSXP, 1)); flag = INTEGER(flag2); PROTECT(iter2 = allocVector(INTSXP, 1)); iter = INTEGER(iter2); nprotect += 7; /* ** Subtract the mean from each covar, as this makes the regression ** much more stable. */ for (i=0; i<nvar; i++) { temp=0; for (person=0; person<nused; person++) temp += covar[i][person]; temp /= nused; means[i] = temp; for (person=0; person<nused; person++) covar[i][person] -=temp; if (doscale==1) { /* and also scale it */ temp =0; for (person=0; person<nused; person++) { temp += fabs(covar[i][person]); } if (temp > 0) temp = nused/temp; /* scaling */ else temp=1.0; /* rare case of a constant covariate */ scale[i] = temp; for (person=0; person<nused; person++) covar[i][person] *= temp; } } if (doscale==1) { for (i=0; i<nvar; i++) beta[i] /= scale[i]; /*rescale initial betas */ } else { for (i=0; i<nvar; i++) scale[i] = 1.0; } /* ** do the initial iteration step */ strata[nused-1] =1; loglik[1] =0; for (i=0; i<nvar; i++) { u[i] =0; a2[i] =0; for (j=0; j<nvar; j++) { imat[i][j] =0 ; cmat2[i][j] =0; } } for (person=nused-1; person>=0; ) { if (strata[person] == 1) { nrisk =0 ; denom = 0; for (i=0; i<nvar; i++) { a[i] = 0; for (j=0; j<nvar; j++) cmat[i][j] = 0; } } dtime = time[person]; ndead =0; /*number of deaths at this time point */ deadwt =0; /* sum of weights for the deaths */ efronwt=0; /* sum of weighted risks for the deaths */ while(person >=0 &&time[person]==dtime) { /* walk through the this set of tied times */ nrisk++; zbeta = offset[person]; /* form the term beta*z (vector mult) */ for (i=0; i<nvar; i++) zbeta += beta[i]*covar[i][person]; zbeta = coxsafe(zbeta); risk = exp(zbeta) * weights[person]; denom += risk; /* a is the vector of weighted sums of x, cmat sums of squares */ for (i=0; i<nvar; i++) { a[i] += risk*covar[i][person]; for (j=0; j<=i; j++) cmat[i][j] += risk*covar[i][person]*covar[j][person]; } if (status[person]==1) { ndead++; deadwt += weights[person]; efronwt += risk; loglik[1] += weights[person]*zbeta; for (i=0; i<nvar; i++) u[i] += weights[person]*covar[i][person]; if (method==1) { /* Efron */ for (i=0; i<nvar; i++) { a2[i] += risk*covar[i][person]; for (j=0; j<=i; j++) cmat2[i][j] += risk*covar[i][person]*covar[j][person]; } } } person--; if (strata[person]==1) break; /*ties don't cross strata */ } if (ndead >0) { /* we need to add to the main terms */ if (method==0) { /* Breslow */ loglik[1] -= deadwt* log(denom); for (i=0; i<nvar; i++) { temp2= a[i]/ denom; /* mean */ u[i] -= deadwt* temp2; for (j=0; j<=i; j++) imat[j][i] += deadwt*(cmat[i][j] - temp2*a[j])/denom; } } else { /* Efron */ /* ** If there are 3 deaths we have 3 terms: in the first the ** three deaths are all in, in the second they are 2/3 ** in the sums, and in the last 1/3 in the sum. Let k go ** from 0 to (ndead -1), then we will sequentially use ** denom - (k/ndead)*efronwt as the denominator ** a - (k/ndead)*a2 as the "a" term ** cmat - (k/ndead)*cmat2 as the "cmat" term ** and reprise the equations just above. */ for (k=0; k<ndead; k++) { temp = (double)k/ ndead; wtave = deadwt/ndead; d2 = denom - temp*efronwt; loglik[1] -= wtave* log(d2); for (i=0; i<nvar; i++) { temp2 = (a[i] - temp*a2[i])/ d2; u[i] -= wtave *temp2; for (j=0; j<=i; j++) imat[j][i] += (wtave/d2) * ((cmat[i][j] - temp*cmat2[i][j]) - temp2*(a[j]-temp*a2[j])); } } for (i=0; i<nvar; i++) { a2[i]=0; for (j=0; j<nvar; j++) cmat2[i][j]=0; } } } } /* end of accumulation loop */ loglik[0] = loglik[1]; /* save the loglik for iter 0 */ /* am I done? ** update the betas and test for convergence */ for (i=0; i<nvar; i++) /*use 'a' as a temp to save u0, for the score test*/ a[i] = u[i]; *flag= cholesky2(imat, nvar, toler); chsolve2(imat,nvar,a); /* a replaced by a *inverse(i) */ temp=0; for (i=0; i<nvar; i++) temp += u[i]*a[i]; *sctest = temp; /* score test */ /* ** Never, never complain about convergence on the first step. That way, ** if someone HAS to they can force one iter at a time. */ for (i=0; i<nvar; i++) { newbeta[i] = beta[i] + a[i]; } if (maxiter==0) { chinv2(imat,nvar); for (i=0; i<nvar; i++) { beta[i] *= scale[i]; /*return to original scale */ u[i] /= scale[i]; imat[i][i] *= scale[i]*scale[i]; for (j=0; j<i; j++) { imat[j][i] *= scale[i]*scale[j]; imat[i][j] = imat[j][i]; } } goto finish; } /* ** here is the main loop */ halving =0 ; /* =1 when in the midst of "step halving" */ for (*iter=1; *iter<= maxiter; (*iter)++) { newlk =0; for (i=0; i<nvar; i++) { u[i] =0; for (j=0; j<nvar; j++) imat[i][j] =0; } /* ** The data is sorted from smallest time to largest ** Start at the largest time, accumulating the risk set 1 by 1 */ for (person=nused-1; person>=0; ) { if (strata[person] == 1) { /* rezero temps for each strata */ denom = 0; nrisk =0; for (i=0; i<nvar; i++) { a[i] = 0; for (j=0; j<nvar; j++) cmat[i][j] = 0; } } dtime = time[person]; deadwt =0; ndead =0; efronwt =0; while(person>=0 && time[person]==dtime) { nrisk++; zbeta = offset[person]; for (i=0; i<nvar; i++) zbeta += newbeta[i]*covar[i][person]; zbeta = coxsafe(zbeta); risk = exp(zbeta) * weights[person]; denom += risk; for (i=0; i<nvar; i++) { a[i] += risk*covar[i][person]; for (j=0; j<=i; j++) cmat[i][j] += risk*covar[i][person]*covar[j][person]; } if (status[person]==1) { ndead++; deadwt += weights[person]; newlk += weights[person] *zbeta; for (i=0; i<nvar; i++) u[i] += weights[person] *covar[i][person]; if (method==1) { /* Efron */ efronwt += risk; for (i=0; i<nvar; i++) { a2[i] += risk*covar[i][person]; for (j=0; j<=i; j++) cmat2[i][j] += risk*covar[i][person]*covar[j][person]; } } } person--; if (strata[person]==1) break; /*tied times don't cross strata*/ } if (ndead >0) { /* add up terms*/ if (method==0) { /* Breslow */ newlk -= deadwt* log(denom); for (i=0; i<nvar; i++) { temp2= a[i]/ denom; /* mean */ u[i] -= deadwt* temp2; for (j=0; j<=i; j++) imat[j][i] += (deadwt/denom)* (cmat[i][j] - temp2*a[j]); } } else { /* Efron */ for (k=0; k<ndead; k++) { temp = (double)k / ndead; wtave= deadwt/ ndead; d2= denom - temp* efronwt; newlk -= wtave* log(d2); for (i=0; i<nvar; i++) { temp2 = (a[i] - temp*a2[i])/ d2; u[i] -= wtave*temp2; for (j=0; j<=i; j++) imat[j][i] += (wtave/d2)* ((cmat[i][j] - temp*cmat2[i][j]) - temp2*(a[j]-temp*a2[j])); } } for (i=0; i<nvar; i++) { /*in anticipation */ a2[i] =0; for (j=0; j<nvar; j++) cmat2[i][j] =0; } } } } /* end of accumulation loop */ /* am I done? ** update the betas and test for convergence */ *flag = cholesky2(imat, nvar, toler); if (fabs(1-(loglik[1]/newlk))<= eps && halving==0) { /* all done */ loglik[1] = newlk; chinv2(imat, nvar); /* invert the information matrix */ for (i=0; i<nvar; i++) { beta[i] = newbeta[i]*scale[i]; u[i] /= scale[i]; imat[i][i] *= scale[i]*scale[i]; for (j=0; j<i; j++) { imat[j][i] *= scale[i]*scale[j]; imat[i][j] = imat[j][i]; } } goto finish; } if (*iter== maxiter) break; /*skip the step halving calc*/ if (newlk < loglik[1]) { /*it is not converging ! */ halving =1; for (i=0; i<nvar; i++) newbeta[i] = (newbeta[i] + beta[i]) /2; /*half of old increment */ } else { halving=0; loglik[1] = newlk; chsolve2(imat,nvar,u); j=0; for (i=0; i<nvar; i++) { beta[i] = newbeta[i]; newbeta[i] = newbeta[i] + u[i]; } } } /* return for another iteration */ /* ** We end up here only if we ran out of iterations */ loglik[1] = newlk; chinv2(imat, nvar); for (i=0; i<nvar; i++) { beta[i] = newbeta[i]*scale[i]; u[i] /= scale[i]; imat[i][i] *= scale[i]*scale[i]; for (j=0; j<i; j++) { imat[j][i] *= scale[i]*scale[j]; imat[i][j] = imat[j][i]; } } *flag = 1000; finish: /* ** create the output list */ PROTECT(rlist= allocVector(VECSXP, 8)); SET_VECTOR_ELT(rlist, 0, beta2); SET_VECTOR_ELT(rlist, 1, means2); SET_VECTOR_ELT(rlist, 2, u2); SET_VECTOR_ELT(rlist, 3, imat2); SET_VECTOR_ELT(rlist, 4, loglik2); SET_VECTOR_ELT(rlist, 5, sctest2); SET_VECTOR_ELT(rlist, 6, iter2); SET_VECTOR_ELT(rlist, 7, flag2); /* add names to the objects */ PROTECT(rlistnames = allocVector(STRSXP, 8)); SET_STRING_ELT(rlistnames, 0, mkChar("coef")); SET_STRING_ELT(rlistnames, 1, mkChar("means")); SET_STRING_ELT(rlistnames, 2, mkChar("u")); SET_STRING_ELT(rlistnames, 3, mkChar("imat")); SET_STRING_ELT(rlistnames, 4, mkChar("loglik")); SET_STRING_ELT(rlistnames, 5, mkChar("sctest")); SET_STRING_ELT(rlistnames, 6, mkChar("iter")); SET_STRING_ELT(rlistnames, 7, mkChar("flag")); setAttrib(rlist, R_NamesSymbol, rlistnames); unprotect(nprotect+2); return(rlist); }

SEXP attribute_hidden do_fft(SEXP call, SEXP op, SEXP args, SEXP env) { SEXP z, d; int i, inv, maxf, maxmaxf, maxmaxp, maxp, n, ndims, nseg, nspn; double *work; int *iwork; checkArity(op, args); z = CAR(args); switch (TYPEOF(z)) { case INTSXP: case LGLSXP: case REALSXP: z = coerceVector(z, CPLXSXP); break; case CPLXSXP: if (NAMED(z)) z = duplicate(z); break; default: error(_("non-numeric argument")); } PROTECT(z); /* -2 for forward transform, complex values */ /* +2 for backward transform, complex values */ inv = asLogical(CADR(args)); if (inv == NA_INTEGER || inv == 0) inv = -2; else inv = 2; if (LENGTH(z) > 1) { if (isNull(d = getAttrib(z, R_DimSymbol))) { /* temporal transform */ n = length(z); fft_factor(n, &maxf, &maxp); if (maxf == 0) error(_("fft factorization error")); work = (double*)R_alloc(4 * maxf, sizeof(double)); iwork = (int*)R_alloc(maxp, sizeof(int)); fft_work(&(COMPLEX(z)[0].r), &(COMPLEX(z)[0].i), 1, n, 1, inv, work, iwork); } else { /* spatial transform */ maxmaxf = 1; maxmaxp = 1; ndims = LENGTH(d); /* do whole loop just for error checking and maxmax[fp] .. */ for (i = 0; i < ndims; i++) { if (INTEGER(d)[i] > 1) { fft_factor(INTEGER(d)[i], &maxf, &maxp); if (maxf == 0) error(_("fft factorization error")); if (maxf > maxmaxf) maxmaxf = maxf; if (maxp > maxmaxp) maxmaxp = maxp; } } work = (double*)R_alloc(4 * maxmaxf, sizeof(double)); iwork = (int*)R_alloc(maxmaxp, sizeof(int)); nseg = LENGTH(z); n = 1; nspn = 1; for (i = 0; i < ndims; i++) { if (INTEGER(d)[i] > 1) { nspn *= n; n = INTEGER(d)[i]; nseg /= n; fft_factor(n, &maxf, &maxp); fft_work(&(COMPLEX(z)[0].r), &(COMPLEX(z)[0].i), nseg, n, nspn, inv, work, iwork); } } } } UNPROTECT(1); return z; }