[Rcpp-devel] Looping over the parameters of a function

Petre Caraiani petre.caraiani at gmail.com
Tue Apr 8 15:41:22 CEST 2014


Hello everybody,
I have a code in C which computes the root of a function using the Brent
algorithm. The code is attached below. I provided the full code but you can
focus on the function definition and the main program. I can call this
program from R. What I am interested in is looping over the parameters of
the defined function. For example, passing an array a to the C program and
computing the root of the function: (x*x-a[i]/2) for each entry in vector a.


#include <Rcpp.h>
using namespace Rcpp;

#include <stdio.h>
#include <math.h>

#define FALSE  0
#define TRUE   1


//Test function for Brent method
double AFunction(double x) {
  return (x*x-1/2);
}

// TRUE if x1*x2 negative
int RootBracketed(double x1,double x2) {
  int result;
  if ((x1 > 0 && x2 > 0) || (x1 < 0 && x2 < 0))
    result = FALSE;
  else
    result = TRUE;
  return result;
}

// returns the minimum of two real numbers
double Minimum(double x1,double x2) {
  double result;
  if (x1 < x2) result = x1;
  else result = x2;
  return result;
}

/****************************************************
*              Brent Method Function                *
* ------------------------------------------------- *
* The purpose is to find a real root of a real      *
* function f(x) using Brent's method.               *
*                                                   *
* INPUTS:  x1,x2     : interval of root             *
*          Tolerance : desired accuracy for root    *
*          maxIter   : maximum number of iterations *
*                                                   *
* OUTPUTS: The function returns the root value      *
*          ValueAtRoot : value of f(root)           *
*          niter    : number of done iterations     *
*          error    : =0, all OK                    *
*                   : =1, no root found in interval *
*                   : =2, no more iterations !      *
****************************************************/
double BrentRoots( double x1, double x2, double Tolerance,
                   int maxIterations,
               double *valueAtRoot,
                   int *niter, double *error )  {

  double FPP = 1e-11, nearzero = 1e-20;

  double result, AA, BB, CC, DD, EE, FA, FB, FC, Tol1, PP, QQ, RR, SS, xm;
  int i, done;

  i = 0; done = FALSE;   error = 0;
  AA = x1;  BB = x2;  FA = AFunction(AA); FB = AFunction(BB);
  if (!(RootBracketed(FA,FB)))
    *error = 1;
  else {
    FC = FB;
    do {
      if (!(RootBracketed(FC,FB))) {
        CC = AA; FC = FA; DD = BB - AA; EE = DD;
      }
      if (fabs(FC) < fabs(FB)) {
        AA = BB; BB = CC; CC = AA;
        FA = FB; FB = FC; FC = FA;
      }
      Tol1 = 2.0 * FPP * fabs(BB) + 0.5 * Tolerance;
      xm = 0.5 * (CC-BB);
      if ((fabs(xm) <= Tol1) || (fabs(FA) < nearzero)) {
        result = BB;
        done = TRUE;
        *valueAtRoot = AFunction(result);
      } // A root has been found
      else {
        if ((fabs(EE) >= Tol1) && (fabs(FA) > fabs(FB))) {
          SS = FB/ FA;
          if (fabs(AA - CC) < nearzero) {
            PP = 2.0 * xm * SS;
            QQ = 1.0 - SS;
          }
          else {
            QQ = FA/FC;
            RR = FB /FC;
            PP = SS * (2.0 * xm * QQ * (QQ - RR) - (BB-AA) * (RR - 1.0));
            QQ = (QQ - 1.0) * (RR - 1.0) * (SS - 1.0);
          }
          if (PP > nearzero) QQ = -QQ;
          PP = fabs(PP);
          if ((2.0 * PP) < Minimum(3.0*xm *QQ-fabs(Tol1 * QQ), fabs(EE *
QQ))) {
            EE = DD;  DD = PP/QQ;
          }
          else {
            DD = xm;   EE = DD;
          }
        }
        else {
          DD = xm;
          EE = DD;
        }
        AA = BB;
        FA = FB;
        if (fabs(DD) > Tol1)
          BB = BB + DD;
        else {
          if (xm > 0) BB = BB + fabs(Tol1);
          else BB = BB - fabs(Tol1);
        }
        FB = AFunction(BB);
        i++;
      }
  }  while ((!done) && (i < maxIterations));
    if (i >= maxIterations) *error = 2;
  }
  *niter = i;
  return result;
} // BrentRoots()
// End of file zbrent.cpp



// Below is a simple example of exporting a C++ function to R. You can
// source this function into an R session using the Rcpp::sourceCpp
// function (or via the Source button on the editor toolbar)

// For more on using Rcpp click the Help button on the editor toolbar

// [[Rcpp::export]]

 NumericVector fun560 (NumericVector a){
//int n=a.size();

double   e,x1,x2,err,yr,r;
int      maxiter,k;

x1=0.0;
x2=1.0;
e =1e-10;
maxiter = 10;



a[1] = BrentRoots(x1,x2,e,maxiter,&yr,&k,&err);
a[2] = BrentRoots(x1,x2,e,maxiter,&yr,&k,&err);

//for (int ii = 0; ii <= nrow-1; ii++) {

//          Am(ii,0)= a[ii]*(1.0+B(ii,0));

//     for (int jj = 0; jj<= ncol-2; jj++){

//        Am(ii,jj+1) = Am(ii,jj)*(1.0+B(ii,jj+1));

return a;
 }
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.r-forge.r-project.org/pipermail/rcpp-devel/attachments/20140408/09262f8b/attachment.html>


More information about the Rcpp-devel mailing list