I am trying to use the very recent capability of the RcppArmadillo package (version 0.3.910.0 with R 3.0.1 and evrerything up to date) for conversion of a sparse matrix from the Matrix package (class "dgCMatrix") to the sp_mat type of armadillo. I am using the "as" and "wrap" functions from the file "RcppArmadilloExtensions/spmat.h". Unfortunately, I am experiencing a compilation error while trying to create the shared library .so when invoking "R CMD INSTALL myRpackage".
Here is a minimal example to reproduce the error:
I created an empty package with RcppArmadillo.package.skeleton()
I defined 2 .cpp files with their corresponding headers .h to perform sum and product of sparse matrices imported from R, as follows :
file "arma_sp_sum.h"
#ifndef _anRpackage_ARMA_SP_SUM_H
#define _anRpackage_ARMA_SP_SUM_H
#include <RcppArmadilloExtensions/spmat.h>
RcppExport SEXP arma_sp_prod(SEXP SPMAT) ;
#endif
file "arma_sp_sum.cpp"
#include "arma_sp_sum.h"
using namespace Rcpp ;
SEXP arma_sp_sum(SEXP SPMAT){
arma::sp_mat m1 = Rcpp::as<arma::sp_mat>(SPMAT) ;
arma::sp_mat m2 = Rcpp::as<arma::sp_mat>(SPMAT) ;
arma::sp_mat res = m1 + m2;
return Rcpp::wrap(res) ;
}
file "arma_sp_prod.h"
#ifndef _anRpackage_ARMA_SP_PROD_H
#define _anRpackage_ARMA_SP_PROD_H
#include <RcppArmadilloExtensions/spmat.h>
RcppExport SEXP arma_sp_prod(SEXP SPMAT) ;
#endif
file "arma_sp_prod.cpp"
#include "arma_sp_prod.h"
using namespace Rcpp ;
SEXP arma_sp_prod(SEXP SPMAT){
arma::sp_mat m1 = Rcpp::as<arma::sp_mat>(SPMAT) ;
arma::sp_mat m2 = Rcpp::as<arma::sp_mat>(SPMAT) ;
arma::sp_mat res = m1 * m2;
return Rcpp::wrap(res) ;
}
Then, when running $ R CMD INSTALL anRpackage $, the compiler successively creates the ".o" files but I get the following ld error :
ld: duplicate symbol arma::SpMat<double> Rcpp::as<arma::SpMat<double> >(SEXPREC*)in arma_sp_sum.o and arma_sp_prod.o for architecture x86_64
collect2: ld returned 1 exit status
make: *** [anRpackage.so] Error 1
ERROR: compilation failed for package ‘anRpackage’
So what am I doing wrong? Sorry if it is a silly question... Anyway, thanks to all the guys doing such a good job with armadilllo/RcppArmadillo, and for your help.
J.
I have made a few changes to RcppArmadillo to clean this. Now as and wrap are correctly templated for sparse matrix types from armadillo (arma::SpMat<T>).
Can you try again using the RcppArmadillo from svn ?
Also, now, you should only need
#include <RcppArmadillo.h>
With the updated code, I'm able to compile your package as well as something like this :
#include <RcppArmadillo.h>
// [[Rcpp::depends("RcppArmadillo")]]
using namespace Rcpp ;
// [[Rcpp::export]]
arma::sp_mat sparse( arma::sp_mat A ){
A(0,0) = 1;
A(1,0) = 2;
return A ;
}
/*** R
require(Matrix)
m <- Matrix(c(0,0,2:0), 3,5)
sparse(m)
*/
Related
I tried to use eigen in mac. After I installing it I run a demo from its' main page in Xcode.The code is as follows:
#include <iostream>
#include <Eigen/Dense>
using Eigen::MatrixXd;
int main()
{
MatrixXd m(2,2);
m(0,0) = 3;
m(1,0) = 2.5;
m(0,1) = -1;
m(1,1) = m(1,0) + m(0,1);
std::cout << m << std::endl;
}
But it shows "Eigen/Dense' file not found". I try the ways as followed:
Change include line to:#include <Eigen/Core>
try to place the "Eigen" into the "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/" which includes header file like .
3.use the command line"g++ -I /usr/local/include/eigen3 aaa.cpp -o aaa -O1 ". The third one is from
fatal error: 'eigen3/Eigen/Dense' file not found
But I don't know why use this command line. Can someone tell me why? What's more, It also doesn't work for me.
Some people said "/usr/local/include" is the default folders, but there is no "/usr/local/include" in my Mac. So I make a file folder named "include" in 'usr/local'and put the Eigen into it. But it doesn't work. I can't run this code in Xcode.
Can someone help me to solve this problem? Thanks!
I am creating an R package 'lapacker' to provide the C interface for internal LAPACK library provided and used by R (with double precision and double complex only) using the R API header file "R_ext/Lapack.h". The source code:
https://github.com/ypan1988/lapacker/
And the project structure:
/lapacker
/inst
/include
/lapacke.h
/someother header files
/R
/zzz.R
/src
/lapacke_dgetrf.c
/lapacke_dgetrf_work.c
/loads of other utility functions provided by LAPACKE
/rcpp_hello.cpp
DESCRIPTION
NAMESPACE
Inside the project, I tried a test function in rcpp_hello.cpp file (Note this example is coming from https://www.netlib.org/lapack/lapacke.html#_calling_code_dgels_code):
//'#export
// [[Rcpp::export]]
void example_lapacke_dgels()
{
double a[5][3] = {{1,1,1},{2,3,4},{3,5,2},{4,2,5},{5,4,3}};
double b[5][2] = {{-10,-3},{12,14},{14,12},{16,16},{18,16}};
lapack_int info,m,n,lda,ldb,nrhs;
int i,j;
m = 5;
n = 3;
nrhs = 2;
lda = 3;
ldb = 2;
info = LAPACKE_dgels(LAPACK_ROW_MAJOR,'N',m,n,nrhs,*a,lda,*b,ldb);
for(i=0;i<n;i++)
{
for(j=0;j<nrhs;j++)
{
printf("%lf ",b[i][j]);
}
printf("\n");
}
}
The whole package can compile properly with no errors, and in R it gives the right answer(indicating symbol LAPACKE_dgels can be found):
> example_lapacke_dgels()
2.000000 1.000000
1.000000 1.000000
1.000000 2.000000
However, when I create a separate C++ file, say demo3.cpp with exactly the same function,
#include <Rcpp.h>
#include <lapacke.h>
// [[Rcpp::depends(lapacker)]]
// [[Rcpp::export]]
void lapacke_dgels_test()
{
double a[5][3] = {{1,1,1},{2,3,4},{3,5,2},{4,2,5},{5,4,3}};
double b[5][2] = {{-10,-3},{12,14},{14,12},{16,16},{18,16}};
lapack_int info,m,n,lda,ldb,nrhs;
int i,j;
m = 5;
n = 3;
nrhs = 2;
lda = 3;
ldb = 2;
info = LAPACKE_dgels(LAPACK_ROW_MAJOR,'N',m,n,nrhs,*a,lda,*b,ldb);
for(i=0;i<n;i++)
{
for(j=0;j<nrhs;j++)
{
printf("%lf ",b[i][j]);
}
printf("\n");
}
}
it no longer compiles properly (actually I tried under both macOS and ubuntu, same linking problem), and gives linking error messages (Cannot find symbol LAPACKE_dgels):
> Rcpp::sourceCpp("~/Desktop/demo3.cpp", showOutput = TRUE)
/usr/lib/R/bin/R CMD SHLIB -o 'sourceCpp_6.so' 'demo3.cpp'
g++ -I/usr/share/R/include -DNDEBUG -I"/home/yipan/R/x86_64-pc-linux-gnu-library/3.4/Rcpp/include" -I"/home/yipan/R/x86_64-pc-linux-gnu-library/3.4/lapacker/include" -I"/home/yipan/Desktop" -fpic -g -O2 -fdebug-prefix-map=/build/r-base-AitvI6/r-base-3.4.4=. -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -g -c demo3.cpp -o demo3.o
g++ -shared -L/usr/lib/R/lib -Wl,-Bsymbolic-functions -Wl,-z,relro -o sourceCpp_6.so demo3.o -L/usr/lib/R/lib -lR
Error in dyn.load("/tmp/RtmpUsASwK/sourceCpp-x86_64-pc-linux-gnu-1.0.0/sourcecpp_159e6145591d/sourceCpp_6.so") :
unable to load shared object '/tmp/RtmpUsASwK/sourceCpp-x86_64-pc-linux-gnu-1.0.0/sourcecpp_159e6145591d/sourceCpp_6.so':
/tmp/RtmpUsASwK/sourceCpp-x86_64-pc-linux-gnu-1.0.0/sourcecpp_159e6145591d/sourceCpp_6.so: undefined symbol: LAPACKE_dgels
I have also checked the lapacker.so under /R/x86_64-pc-linux-gnu-library/3.4/lapacker/libs and found:
000000000000c6b0 g DF .text 00000000000001bf Base LAPACKE_dgels
Do I miss something to get the demo3.cpp compile correctly? Thanks very much for your patience and time!
You are facing a difficult problem here. The Symbol you are trying to resolve LAPACKE_dgels is part of lapacker.so, build during package installation. Problem is, that the libraries for R packages are not meant for linking. Instead, they are loaded by R dynamically at run-time. Basically, I see four possibilities:
Convert lapacke into a header only library and install that in inst/include (c.f. RcppArmadillo).
Link with a system installation of lapacke (easy on Linux ...)
Register all functions with R and use the methods provided by R to link to them (c.f. WRE and nloptr).
Compile a library meant for linking and install it with the R package. You will still need a plugin for that to work, since you have to add -L<path/to/lib> -l<libname> .... to PKG_LIBS.
I am sure there are examples on CRAN that use method 4, but none comes to mind right now. However, as a "code kata" I have converted a recent test package of mine to use this structure, c.f. https://github.com/rstub/levmaR/tree/static.
(Original incomplete answer.)
In src/Makevars you have
PKG_LIBS = $(LAPACK_LIBS) $(BLAS_LIBS) $(FLIBS)
You need an analogue setting when compiling a cpp file via Rcpp attributes. The best way achieve this is by using an Rcpp plugin, c.f. RcppArmadillo's solution (adjustments are untested!):
inlineCxxPlugin <- function(...) {
plugin <-
Rcpp::Rcpp.plugin.maker(
include.before = "#include <lapacke.h>",
libs = "$(LAPACK_LIBS) $(BLAS_LIBS) $(FLIBS)",
package = "lapacker"
)
settings <- plugin()
settings$env$PKG_CPPFLAGS <- "-I../inst/include"
settings
}
BTW, why do you want to interface with LAPACK directly, when RcppArmadillo does so already?
I created a bpsk flowgraph in gnuradio companion (grc) and it is working fine. At the moment Im writing a C++ equivalent of the same program using gnuradio classes. First I read the I/Q data from a file and I was able to get all the bpsk-modulated AX.25 frames. Now im trying to replace the file source block with a UHD one in order to be able to read the I/Q data in real time. make reports an error "reference to ‘uhd’ is ambiguous". The full make output is shown below
$ make
[ 50%] Building CXX object CMakeFiles/bpsk.dir/bpsk.cc.o
/home/mbkitine/Dropbox/Lulea/GRC/SSC/PSK/bpsk/RX_C++/bpsk.cc: In function ‘int main(int, char**)’:
/home/mbkitine/Dropbox/Lulea/GRC/SSC/PSK/bpsk/RX_C++/bpsk.cc:85:78: error: reference to ‘uhd’ is ambiguous
gr::uhd::usrp_source::sptr uhd_source = gr::uhd::usrp_source::make(address,uhd::stream_args_t("fc32"));
^
In file included from /usr/local/include/uhd/types/metadata.hpp:22:0,
from /usr/local/include/uhd/stream.hpp:22,
from /usr/local/include/uhd/device.hpp:22,
from /usr/local/include/uhd/usrp/multi_usrp.hpp:37,
from /usr/local/include/gnuradio/uhd/usrp_block.h:28,
from /usr/local/include/gnuradio/uhd/usrp_source.h:26,
from /home/mbkitine/Dropbox/Lulea/GRC/SSC/PSK/bpsk/RX_C++/bpsk.cc:56:
/usr/local/include/uhd/types/time_spec.hpp:25:14: note: candidates are: namespace uhd { }
namespace uhd{
^
In file included from /usr/local/include/gnuradio/uhd/usrp_source.h:26:0,
from /home/mbkitine/Dropbox/Lulea/GRC/SSC/PSK/bpsk/RX_C++/bpsk.cc:56:
/usr/local/include/gnuradio/uhd/usrp_block.h:31:17: note: namespace gr::uhd { }
namespace uhd {
^
CMakeFiles/bpsk.dir/build.make:62: recipe for target 'CMakeFiles/bpsk.dir/bpsk.cc.o' failed
make[2]: *** [CMakeFiles/bpsk.dir/bpsk.cc.o] Error 1
CMakeFiles/Makefile2:67: recipe for target 'CMakeFiles/bpsk.dir/all' failed
make[1]: *** [CMakeFiles/bpsk.dir/all] Error 2
Makefile:83: recipe for target 'all' failed
make: *** [all] Error 2
Here is my bpsk.cc code
// Include header files for each block used in flowgraph
#include <gnuradio/top_block.h>
#include <gnuradio/analog/sig_source_f.h>
#include <gnuradio/analog/agc2_cc.h>
#include <gnuradio/digital/fll_band_edge_cc.h>
#include <gnuradio/digital/pfb_clock_sync_ccf.h>
#include <gnuradio/filter/firdes.h>
#include <gnuradio/digital/cma_equalizer_cc.h>
#include <gnuradio/digital/costas_loop_cc.h>
#include <gnuradio/blocks/api.h>
#include <gnuradio/sync_block.h>
#include <gnuradio/digital/binary_slicer_fb.h>
#include <gnuradio/digital/diff_decoder_bb.h>
#include <gnuradio/digital/hdlc_deframer_bp.h>
#include <gnuradio/blocks/message_debug.h>
#include <gnuradio/audio/sink.h>
#include <gnuradio/blocks/file_source.h>
#include <gnuradio/uhd/usrp_source.h>
#include <ais/invert.h>
#include <gnuradio/blocks/complex_to_real.h>
#include <iostream>
#include <string>
using namespace gr;
int main(int argc, char **argv)
{
//Extracting variables from the menu
char* filename = argv[1];
//UHD Default parameters
double samp_rate = 1000000;
double baud_rate = 250000;
double fc = 100e6;
int sps = int(samp_rate/baud_rate);
//Receiver parameters
int dec = 10;
float loop_bw = 2 * 3.14/100;
// Construct a top block that will contain flowgraph blocks. Alternatively,
// one may create a derived class from top_block and hold instantiated blocks
// as member data for later manipulation.
top_block_sptr tb = make_top_block("bpsk");
//UHD block
std::string address = "192.168.10.2";
gr::uhd::usrp_source::sptr uhd_source = gr::uhd::usrp_source::make(address,uhd::stream_args_t("fc32"));
uhd_source->set_samp_rate(samp_rate);
uhd_source->set_center_freq(fc);
//Reading bpsk signal from file
//blocks::file_source::sptr file = blocks::file_source::make(sizeof(gr_complex),filename,false);
//Automatic gain controller
analog::agc2_cc::sptr agc = analog::agc2_cc::make(1e-1, 1e-2, 1.0, 1.0);
//FLL band edge filter
digital::fll_band_edge_cc::sptr fll = digital::fll_band_edge_cc::make(sps, 0.5, 44, loop_bw);
//PFB symbol time recovery
const int nfilts = 32;
std::vector<float> rrc_taps = filter::firdes::root_raised_cosine(nfilts, nfilts, 1.0/float(sps), 0.35, 11*sps*nfilts);
digital::pfb_clock_sync_ccf::sptr pfb = digital::pfb_clock_sync_ccf::make(sps,loop_bw,rrc_taps,nfilts,0,1.5,2);
//CMA equalization
digital::cma_equalizer_cc::sptr cma = digital::cma_equalizer_cc::make(15,1,0.01,2);
//Costas loop
digital::costas_loop_cc::sptr costas = digital::costas_loop_cc::make(loop_bw,2);
//Taking the real part
gr::blocks::complex_to_real::sptr comp_to_real = blocks::complex_to_real::make(1);
//Binary slicer
digital::binary_slicer_fb::sptr slicer = digital::binary_slicer_fb::make();
//Differential decoder
digital::diff_decoder_bb::sptr differential_decoder = digital::diff_decoder_bb::make(2);
//Inverting bit values
//invert::sptr inverter = ais::invert::make();
//HDLC Deframer
digital::hdlc_deframer_bp::sptr deframer = digital::hdlc_deframer_bp::make(32,500);
//Output data
gr::blocks::message_debug::sptr msg = gr::blocks::message_debug::make();
std::cout << "Blocks declared successfully " << std::endl;
//Connections
tb->connect(uhd_source,0,agc,0);
tb->connect(agc,0,fll,0);
tb->connect(fll,0,pfb,0);
tb->connect(pfb,0,cma,0);
tb->connect(cma,0,costas,0);
tb->connect(costas,0,comp_to_real,0);
tb->connect(comp_to_real,0,slicer,0);
tb->connect(slicer,0,differential_decoder,0);
tb->connect(differential_decoder,0,deframer,0);
//tb->connect(inverter,0,deframer,0);
tb->msg_connect(deframer,"out",msg,"print_pdu");
tb->run();
std::cout << "The GNU Radio Thread is Running " << std::endl;
// Exit normally.
return 0;
}
And finally my CMakelists.txt file. I basically modified this file from the original dialtone C++ example which can be found in {YOUR_GNURADIO_DIRECTORY}/gr-audio/examples/c++
cmake_minimum_required(VERSION 2.6)
project(bpsk CXX)
find_package(Boost "1.35" COMPONENTS system)
set(GR_REQUIRED_COMPONENTS RUNTIME ANALOG AUDIO BLOCKS FILTER DIGITAL UHD)
find_package(Gnuradio "3.7.2" REQUIRED)
include_directories(${GNURADIO_ALL_INCLUDE_DIRS})
add_executable(bpsk bpsk.cc)
target_link_libraries(bpsk ${Boost_LIBRARIES} ${GNURADIO_ALL_LIBRARIES})
Any help will be highly appreciated.
Regards
Moses.
The error says what's wrong right there:
since you're doing
using namespace gr;
you compiler can't know whether you mean gr::uhd or just uhd.
I'd just recommend dropping the using namespace gr directive. Or, using ::uhd when you really mean the non-gr:: namespace.
I hope I dont get downvoted, but I have search online and the Eigen wiki and I cant find instructions on how to install Eigen3 to use it on Xcode5.
I downloaded the tar file and untar it, but then I dont know where to go.
I managed to do it.
Because in Eigen3 there is no library to link to. What you have to do is to untar the downloaded file and then copy the Eigen folder into
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include
After that you can create any project and just add the headers of Eigen3
To try it, you can run a the following example given in the "Getting started" guide:
#include <iostream>
#include <Eigen/Dense>
using Eigen::MatrixXd;
int main()
{
MatrixXd m(2,2);
m(0,0) = 3;
m(1,0) = 2.5;
m(0,1) = -1;
m(1,1) = m(1,0) + m(0,1);
std::cout << m << std::endl;
}
That has the following output:
3 -1
2.5 1.5
I am trying run a code of "Seamless R and C++ Integration with Rcpp" (Page 32, Listing 2.10) but It´s giving a error. Could someone explain to me why is not working? Thanks
Code <- '
#include <gsL/gsl_const_mksa.h> // decl of constants
std::vector<double> volumes() {
std::vector<double> v(5);
v[0] = GSL_CONST_MKSA_US_GALLON; // 1 US gallon
v[1] = GSL_CONST_MKSA_CANADIAN_GALLON; // 1 Canadian gallon
v[2] = GSL_CONST_MKSA_UK_GALLON; // 1 UK gallon
v[3] = GSL_CONST_MKSA_QUART; // 1 quart
v[4] = GSL_CONST_MKSA_PINT; // 1 pint
return v;
}'
gslVolumes <- cppFunction(code, depends="RcppGSL")
This is the message error:
file16e2b6cb966.cpp: In function ‘SEXPREC* sourceCpp_52966_volumes()’:
file16e2b6cb966.cpp:30: error: ‘__result’ was not declared in this scope
make: *** [file16e2b6cb966.o] Error 1
llvm-g++-4.2 -arch x86_64 -I/Library/Frameworks/R.framework/Resources/include -DNDEBUG -I/usr/local/include -I/Library/Frameworks/R.framework/Versions/3.0/Resources/library/Rcpp/include -I/usr/local/include -I"/Library/Frameworks/R.framework/Versions/3.0/Resources/library/Rcpp/include" -I"/Library/Frameworks/R.framework/Versions/3.0/Resources/library/RcppGSL/include" -fPIC -mtune=core2 -g -O2 -c file16e2b6cb966.cpp -o file16e2b6cb966.o
Erro em sourceCpp(code = code, env = env, rebuild = rebuild, showOutput = showOutput, :
Error 1 occurred building shared library.
It looks like you have typos:
Code <- '
#include <gsL/gsl_const_mksa.h> // decl of constants
That should be code <- with lower-case c, and then #include <gsl/gsl_const_mksa.h> with a lower-case 'ell'.
In general, I recomment to switch on verbose mode:
gslVolumes <- cppFunction(code, depends="RcppGSL", verbose=TRUE)
which would have told you about
object code not found from the first error, and
file....cpp:10:63: fatal error: gsL/gsl_const_mksa.h: No such file or directory
about the missing header.
But I do see now that with the current versions, I also get __result not declared. Will
investigate.
Edit: It's a bug / change. It worked when I wrote the chapter, now you need to
remove the line with the #include <gsl/gsl_const_mksa.h> from the code assignment
add a new includes=... argument to the cppFunction() call as below:
Corrected call:
gslVolumes <- cppFunction(code, depends="RcppGSL",
includes="#include <gsl/gsl_const_mksa.h>")
In addition to what Dirk said, I recommend that you promote the code to a .cpp file.
// [[Rcpp::depends(RcppGSL)]]
#include <Rcpp.h>
#include <gsl/gsl_const_mksa.h> // decl of constants
// [[Rcpp::export]]
std::vector<double> volumes() {
std::vector<double> v(5);
v[0] = GSL_CONST_MKSA_US_GALLON; // 1 US gallon
v[1] = GSL_CONST_MKSA_CANADIAN_GALLON; // 1 Canadian gallon
v[2] = GSL_CONST_MKSA_UK_GALLON; // 1 UK gallon
v[3] = GSL_CONST_MKSA_QUART; // 1 quart
v[4] = GSL_CONST_MKSA_PINT; // 1 pint
return v;
}
Then, you can sourceCpp that file.