2013-12-09 5 views
12

में अन्य पैकेज से सी फ़ंक्शन का उपयोग करके मैं बहु-आयामी एकीकरण करने के लिए एक C++ फ़ंक्शन में क्यूबचर पैकेज से सी सी रूटीन कॉल करने का प्रयास कर रहा हूं।आरसीपी

बुनियादी अनुसंधान उदाहरण मैं पुन: पेश करने की कोशिश कर रहा हूँ

library(cubature) 
integrand <- function(x) sin(x) 
adaptIntegrate(integrand, 0, pi) 

है मैं सिर्फ निम्नलिखित this recipe from the gallery Rcpp से आर समारोह कह सकते हैं, लेकिन आगे और पीछे से सी/सी स्विच करने में कुछ प्रदर्शन जुर्माना होगा ++ आर के लिए सी सी + से सीधे सी समारोह को कॉल करने के लिए यह अधिक समझदार लगता है।

सी दिनचर्या adapt_integrate

// R_RegisterCCallable("cubature", "adapt_integrate", (DL_FUNC) adapt_integrate); 

साथ cubature से निर्यात किया जाता है मुझे समझ नहीं आता कि यह कैसे सी ++ से कॉल करने के लिए हालांकि,। यहां मेरा लंगड़ा प्रयास है,

sourceCpp(code = ' 
#include <Rcpp.h> 
using namespace Rcpp; 

// [[Rcpp::export]] 
double integrand(double x){ 
return(sin(x)); 
} 

// [[Rcpp::depends(cubature)]] 
// [[Rcpp::export]] 
Rcpp::List integratecpp(double llim, double ulim) 
{ 
    Rcpp::Function p_cubature = R_GetCCallable("cubature", "adapt_integrate"); 

    Rcpp::List result = p_cubature(integrand, llim, ulim); 
    return(result); 
} 
' 
) 

integratecpp(0, pi) 

यह संकलित करने में विफल रहता है; स्पष्ट रूप से मैं कुछ बहुत मूर्खतापूर्ण कर रहा हूं और R_GetCCallable के आउटपुट को Rcpp::Function में परिवर्तित करने के लिए कुछ महत्वपूर्ण कदम उठा रहा हूं (या इसे सीधे कॉल करें?)। मैंने फ़ंक्शन पॉइंटर्स से निपटने वाली कई संबंधित पोस्ट पढ़ी हैं, लेकिन बाहरी सी फ़ंक्शन का उपयोग करके कोई उदाहरण नहीं देखा है।

उत्तर

6

दुर्भाग्य cubatureinst/include में हेडर शिप नहीं करता है, तो आप उन लोगों से उधार ले कि और अपने कोड में कुछ इस तरह करना है:

typedef void (*integrand) (unsigned ndim, const double *x, void *, 
      unsigned fdim, double *fval); 

int adapt_integrate(
    unsigned fdim, integrand f, void *fdata, 
    unsigned dim, const double *xmin, const double *xmax, 
    unsigned maxEval, double reqAbsError, double reqRelError, 
    double *val, double *err) 
{ 
    typedef int (*Fun)(unsigned,integrand,void*,unsigned, 
     const double*,const double*, unsigned, double, double, double*, double*) ; 
    Fun fun = (Fun) R_GetCCallable("cubature", "adapt_integrate") ;   
    return fun(fdim,f,fdata,dim,xmin,xmax,maxEval,reqAbsError, reqRelError,val,err); 
} 

यह एक अच्छा विचार के मेंटेनर साथ negociate हो सकता है cubature कि वह inst/include में घोषणाएं भेजता है ताकि आपको केवल LinkingTo का उपयोग करना पड़े।

+0

इन लापता टुकड़ों को इकट्ठा करने के लिए बहुत धन्यवाद। दुर्भाग्यवश, मुझे समस्या पर पुनर्विचार करना होगा, क्योंकि मैं जो देखता हूं उससे 'adapt_integrate' आसानी से एक एकीकृतता स्वीकार नहीं करेगा जिसे मैंने आर्मडिलो के डेटा संरचनाओं का उपयोग करके परिभाषित किया है। पूर्णता के लिए, क्या आप उपयोग का एक न्यूनतम उदाहरण जोड़ पाएंगे? – baptiste

+0

यह आपको फ़ंक्शन पॉइंटर तक पहुंच प्रदान करता है जो 'क्यूबचर' पंजीकृत है। मुझे नहीं पता कि आपको सी फ़ंक्शन के साथ क्या करना है ... –

+0

वास्तव में, [उपयोग के उदाहरण पर विचार करना] (http://ab-initio.mit.edu/wiki/index.php/Cubature# उदाहरण) मुझे आगे की परेशानी दिखाई देती है: 'adapt_integrate_v' पॉइंटर्स को '* fdata' जैसी ऑब्जेक्ट्स की अपेक्षा करता है, एकीकृत और' * fval' जैसे पॉइंटर्स की अपेक्षा करता है, जबकि तर्क जो मैं वास्तव में पास करना चाहता हूं, उदाहरण के लिए हैं 'arma :: colvec' वस्तुओं। मुझे नहीं लगता कि मैं दोनों के बीच एक पुल बनाने में सक्षम हो जाऊंगा। मुझे आर-स्तरीय इंटरफेस के साथ रहना पड़ सकता है, या सी ++ में अपना 2 डी क्वाड्रैचर लागू करना पड़ सकता है। – baptiste

2

पहले इस प्रश्न को नहीं देखा था, और ऐसा लगता है कि @Romain ने इसे संबोधित किया।

पूर्णता के लिए, यह सुनिश्चित करने के लिए एक कार्य उदाहरण है कि जब सभी पार्टियां खेलती हैं तो xts और RcppXts पैकेज द्वारा प्रदान की जाती है। R_registerRoutines और R_RegisterCCallable के सामान्य व्यापार के साथ साथ

SEXP attribute_hidden xtsLag(SEXP x, SEXP k, SEXP pad) {  
    static SEXP(*fun)(SEXP,SEXP,SEXP) = NULL;   
    if (fun == NULL)         
     fun = (SEXP(*)(SEXP,SEXP,SEXP)) R_GetCCallable("xts","lagXts"); 
    return fun(x, k, pad);        
} 

: xts में, हम ऐसा करते हैं (स्रोत) में (लगभग दस कार्यों के लिए) फ़ाइल inst/include/xtsAPI.h

RcppXts में इस रूप में

function("xtsLag", 
     &xtsLag,  
     List::create(Named("x"), Named("k"), Named("pad")), 
     "Extract the coredata from xts object"); 

जो बहुत अच्छी तरह से काम करता है (एक Rcpp मॉड्यूल में) उठाया है। किसी ने मुझे xts पक्ष को अधिक कॉम्पैक्टली लिखने के लिए झगड़ा दिया (जैसा कि if NULL नकली है) जो मैं ... अंततः प्राप्त करूंगा।

+0

पॉइंटर्स के लिए धन्यवाद, दुर्भाग्यवश यह एक ऐसा मामला है जहां कोड के दो टुकड़ों के बीच उचित गोंद को काम करने से मुझे धीरे-धीरे आर कार्यान्वयन के साथ गणना करने की तुलना में अधिक समय और पीड़ा मिल जाएगी। मैं अन्यथा आर पैकेज के बजाय मूल क्यूबचर कोड से सीधे लिंक करने पर विचार करता हूं, जो पुराने संस्करण का उपयोग कर रहा है। पॉइंटर के लिए – baptiste

0

यह सवाल तीन साल अब पुरानी है, लेकिन मैं बाहर बात करने के लिए अब Rcpp साथ बहुआयामी एकीकरण आसान हो सकता है कि कि RcppNumerical पुस्तकालय उपलब्ध है चाहता हूँ: https://github.com/yixuan/RcppNumerical

कंप्यूटिंग अभिन्न के लिए दिनचर्या थॉमस हैन के क्यूबा पर आधारित होते हैं पैकेज और सीआरएएन पर आर 2 सी क्यूबा लाइब्रेरी में भी उपलब्ध हैं, इसलिए यदि आप क्यूबचर से adaptIntegrate() फ़ंक्शन पर क्यूबा रूटीन का उपयोग कर स्वीकार कर सकते हैं, तो यह पैकेज ब्याज का हो सकता है।

+0

धन्यवाद। हालांकि, इसे एक टिप्पणी के रूप में रखना सबसे अच्छा है, क्योंकि सवाल विशेष रूप से एकीकरण के बारे में नहीं था, बल्कि किसी अन्य पैकेज से सी फ़ंक्शन तक पहुंचने के बारे में था। हालांकि मैं लिंक की सराहना करता हूं, हालांकि, मैंने क्यूबचर की अपनी प्रति का उपयोग करके समाप्त किया, लेकिन यह एक योग्य विकल्प की तरह दिखता है (विशेष रूप से यदि कोई पहले से ही ईजिन का उपयोग कर रहा है, लेकिन मुझे आर्मडिलो में उपयोग किया जाता है)। क्यूबचर का एक फायदा हालांकि वेक्टर-मूल्यवान इंटीग्रैंड्स से निपटने की क्षमता है। – baptiste

संबंधित मुद्दे