[Rcpp-commits] r2404 - pkg/RcppDE/src
noreply at r-forge.r-project.org
noreply at r-forge.r-project.org
Sat Nov 6 21:16:13 CET 2010
Author: edd
Date: 2010-11-06 21:16:12 +0100 (Sat, 06 Nov 2010)
New Revision: 2404
Modified:
pkg/RcppDE/src/evaluate.h
Log:
beginnings of support for compiled evaluate()
Modified: pkg/RcppDE/src/evaluate.h
===================================================================
--- pkg/RcppDE/src/evaluate.h 2010-11-06 20:14:57 UTC (rev 2403)
+++ pkg/RcppDE/src/evaluate.h 2010-11-06 20:16:12 UTC (rev 2404)
@@ -5,29 +5,145 @@
//
// DEoptim is Copyright (C) 2009 David Ardia and Katharine Mullen
-#ifndef USE_OPENMP
-#include <RcppArmadillo.h>
+#ifndef Rcpp_DE_evaluate_h_
+#define Rcpp_DE_evaluate_h_
-// Slighly accelerated version of evaluate to evaluate function fcall with parameters param in environment env
-// Uses externally allocated par() vector into which param are copied
+#include <Rcpp.h>
+
+namespace Rcpp {
+ namespace DE {
+ double genrose(SEXP xs) { // genrose function in C++
+ Rcpp::NumericVector x(xs);
+ int n = x.size();
+ double sum = 1.0;
+ for (int i=1; i<n; i++) {
+ sum += 100*( ::pow(x[i-1]*x[i-1] - x[i], 2)) + (x[i] - 1)*(x[i] - 1);
+ }
+ return(sum);
+ }
+
+ double wild(SEXP xs) { // wild function in C++
+ Rcpp::NumericVector x(xs);
+ int n = x.size();
+ double sum = 0.0;
+ for (int i=0; i<n; i++) {
+ sum += 10 * ::sin(0.3 * x[i]) * ::sin(1.3 * x[i]*x[i]) + 0.00001 * x[i]*x[i]*x[i]*x[i] + 0.2 * x[i] + 80;
+ }
+ sum /= n;
+ return(sum);
+ }
+
+ double rastrigin(SEXP xs) { // rastrigin function in C++
+ Rcpp::NumericVector x(xs);
+ int n = x.size();
+ double sum = 20.0;
+ for (int i=0; i<n; i++) {
+ sum += x[i]+2 - 10*::cos(2*M_PI*x[i]);
+ }
+ return(sum);
+ }
+
#if 0
-double evaluate(long &l_nfeval, const double *param, SEXP par, SEXP fcall, SEXP env) {
- memcpy(REAL(par), param, Rf_nrows(par) * sizeof(double)); // -- faster: direct access _assuming_ numeric vector
- SEXP fn = ::Rf_lang2(fcall, par); // this could be done with Rcpp
- SEXP sexp_fvec = ::Rf_eval(fn, env); // but is still a lot slower right now
- double f_result = REAL(sexp_fvec)[0];
- if (ISNAN(f_result))
- ::Rf_error("NaN value of objective function! \nPerhaps adjust the bounds.");
- l_nfeval++; // increment function evaluation count
- return(f_result);
+class Evaluator { // class to evaluate a given function at a parameter
+public:
+ typedef double (Evaluator::*FunctionPointer)(SEXP);
+ Evaluator( FunctionPointer funptr_ ) : funptr(funptr_) {};
+ Evaluator(SEXP fcall_, SEXP env_) {
+ if (TYPEOF(env_) == ENVSXP) { // standard mode: env_ is an env, fcall_ is a function
+ //REprintf("In env case, default\n");
+ fcall = fcall_;
+ env = env_;
+ funptr = &Evaluator::defaultfun;
+ } else {
+ REprintf("NOT in env case, trying something new -- does not work yet\n");
+ fcall = fcall_;
+ env = env_;
+ funptr = &Evaluator::defaultfun;
+ }
+ };
+ double eval(SEXP par) {
+ return ((*this).*(funptr))(par); // isn't the syntax to eval a function pointer easy :)
+ }
+ inline FunctionPointer get() { return funptr ; }
+private:
+ SEXP fcall, env;
+ double defaultfun(SEXP par) {
+ SEXP fn = ::Rf_lang2(fcall, par); // this could be done with Rcpp
+ SEXP sexp_fvec = ::Rf_eval(fn, env); // but is still a lot slower right now
+ double f_result = REAL(sexp_fvec)[0];
+ if (ISNAN(f_result))
+ ::Rf_error("NaN value of objective function! \nPerhaps adjust the bounds.");
+ return(f_result);
+ }
+ FunctionPointer funptr;
+};
+#endif
+
+ class Fun { // class to wrap an external pointer around eval. function
+ public:
+ typedef double (*FunctionPointer)(SEXP);
+ Fun( FunctionPointer ptr_ ) : ptr(ptr_) {};
+ inline FunctionPointer get() { return ptr ; }
+ private:
+ FunctionPointer ptr ;
+ };
+
+ class EvalBase {
+ public:
+ virtual double eval(SEXP par) = 0;
+ };
+
+ class EvalStandard : public EvalBase {
+ public:
+ //typedef double (EvalStandard::*FunctionPointer)(SEXP);
+ EvalStandard(SEXP fcall_, SEXP env_) : fcall(fcall_), env(env_) {
+ //funptr = &EvalStandard::defaultfun;
+ }
+ double eval(SEXP par) {
+ //return ((*this).*(funptr))(par); // isn't the syntax to eval a function pointer easy :)
+ return defaultfun(par);
+ }
+ private:
+ SEXP fcall, env;
+ double defaultfun(SEXP par) {
+ SEXP fn = ::Rf_lang2(fcall, par); // this could be done with Rcpp
+ SEXP sexp_fvec = ::Rf_eval(fn, env); // but is still a lot slower right now
+ double f_result = REAL(sexp_fvec)[0];
+ if (ISNAN(f_result))
+ ::Rf_error("NaN value of objective function! \nPerhaps adjust the bounds.");
+ return(f_result);
+ }
+ //FunctionPointer funptr;
+ };
+
+ class EvalCompiled : public EvalBase {
+ public:
+ EvalCompiled( Rcpp::XPtr<Fun> xptr ) {
+ funptr = xptr->get();
+ };
+ EvalCompiled( SEXP xps ) {
+ Rcpp::XPtr<Fun> xptr(xps);
+ funptr = xptr->get();
+ };
+ double eval(SEXP par) {
+ return funptr(par);
+ }
+ private:
+ Fun::FunctionPointer funptr;
+ };
+
+ RcppExport SEXP putFunPtrInXPtr(SEXP funname) {
+ std::string fstr = Rcpp::as<std::string>(funname);
+ if (fstr == "genrose")
+ return(Rcpp::XPtr<Fun>(new Fun(&genrose)));
+ else if (fstr == "wild")
+ return(Rcpp::XPtr<Fun>(new Fun(&wild)));
+ else
+ return(Rcpp::XPtr<Fun>(new Fun(&rastrigin)));
+ }
+
+ }
+
}
+
#endif
-double evaluate(SEXP par, SEXP fcall, SEXP env) {
- SEXP fn = ::Rf_lang2(fcall, par); // this could be done with Rcpp
- SEXP sexp_fvec = ::Rf_eval(fn, env); // but is still a lot slower right now
- double f_result = REAL(sexp_fvec)[0];
- if (ISNAN(f_result))
- ::Rf_error("NaN value of objective function! \nPerhaps adjust the bounds.");
- return(f_result);
-}
-#endif
More information about the Rcpp-commits
mailing list