R function callback from C - r

I have the following C function callThisFromR.c which I want to call from the R language,
#include <stdio.h>
#include <stdint.h>
#include <string.h>
void callThisFromR (
// some integer
int32_t integerFromR, // this is the length of the double vector `vec` to be passed again to R
// This is the R function passed to C: `getFuncFromR(vecLen, vec)`
double (* getFuncFromR) (
int32_t ,
double []
),
char inputString[] ,
int32_t inputStringLen
) {
printf("This is the integer passed from R: %d\n", integerFromR);
printf("This is the string passed from R: %s\n", inputString);
printf("This is the string length passed from R: %d\n", inputStringLen);
// Generate some double data to pass to R
double *vec;
vec = (double *) malloc( integerFromR * sizeof(*vec) );
for( int i=0; i<integerFromR; i++ ) {
vec[i] = (double) (i+1);
}
double result = getFuncFromR(integerFromR,vec);
printf("This is the result of the R callback function passed from R: %f\n", result );
}
This C function is supposed to be called from within R and expects to receive an int32 integer integerFromR, a string inputString and its length inputStringLen, as well as a callback function getFuncFromR from R. For example, here is the main.c C-equivalent of what I need to have in R,
#include <stdio.h>
#include <stdint.h>
#include <string.h>
double getFuncFromR (
int32_t vecLen,
double vec[]
)
{
double vecSum = 0.;
for(int i = 0; i < vecLen; i++){
vecSum += vec[i];
}
return vecSum;
}
int main(int argc, char *argv[])
{
char inputString[] = "ThisIsTheStringPassedFromR2C";
int32_t inputStringLen = strlen(inputString);
int32_t integerFromR = 3;
callThisFromR( integerFromR
, &getFuncFromR
, inputString
, inputStringLen
);
return 0;
}
Easy in C. But to call callThisFromR() C-function from R and pass an R function getFuncFromR() has so far been like a nightmare. How can I write the C wrapper function? My exhaustive web search for an answer (including the Rcpp and R-Foreign-Language-Extension documentation) have led to nothing.

Related

Why does my RcppParallel implementation of a user-defined function crash unexpectedly?

I have developed a dual chain markov monte carlo model designed to forecast loan portfolios in the excellent package Rcpp but have run into an issue trying to implement a parallelised version of these functions with RcppParallel.
I have based my attempts this far on this vignette (https://gallery.rcpp.org/articles/parallel-distance-matrix/) and this stackoverflow thread (How to call user-defined function in RcppParallel?).
All of the UDFs underlying this logic are implemented using Armadillo type objects, which I understand are threadsafe, and the writing of data between functions and pre-allocated outputs should be working smoothly as I have this same logic implemented successfully in serial functions. It's also true that the function portfolio_simulation_rating_model_rs_ts works well with the inputs used outside of the RcppParallel wrapper and there are no compilation errors or warnings when I source this code and the underlying functions. However, once I get to running the dcmcmc_portfolio_rating_model_parallel function in R, my session crashes only saying that there has been a fatal error.
Clearly I am missing something in the parallelisation, so any help/suggestions would be greatly appreciated.
// [[Rcpp::depends(RcppArmadillo, RcppParallel)]]
#include <string>
#include <algorithm>
#include <vector>
#include <math.h>
#include <RcppArmadillo.h>
#include <RcppParallel.h>
using namespace arma;
using namespace RcppParallel;
using namespace Rcpp;
using namespace std;
struct dcmcmc_portfolio_rating_model_worker : public Worker {
// Input Values
const int n_loans ;
const int n_regime ;
const int n_matrix ;
const int n_amort ;
const RVector<double> loan_ids ;
const RVector<double> starting_balances ;
const RVector<double> starting_positions ;
const RVector<double> cprs ;
const RVector<double> sim_regime_indices ;
const RVector<double> loan_regime_indices ;
const RVector<double> starting_periods ;
const RVector<double> regime_matrix_indices ;
const RVector<double> matrix_indices ;
const RVector<double> matrix_elements ;
const int nrow ;
const int ncol ;
const RMatrix<double> amortisation_schedules ;
const int periods ;
const int iterations ;
// Output Matrix
RMatrix<double> output_mx ;
dcmcmc_portfolio_rating_model_worker(
const int& n_loans,
const int& n_regime,
const int& n_matrix,
const int& n_amort,
const NumericVector& loan_ids,
const NumericVector& starting_balances,
const NumericVector& starting_positions,
const NumericVector& cprs,
const NumericVector& sim_regime_indices,
const NumericVector& loan_regime_indices,
const NumericVector& starting_periods,
const NumericVector& regime_matrix_indices,
const NumericVector& matrix_indices,
const NumericVector& matrix_elements,
const int& nrow,
const int& ncol,
const NumericMatrix& amortisation_schedules,
const int& periods,
const int& iterations,
NumericMatrix& output_mx)
: n_loans(n_loans),
n_regime(n_regime),
n_matrix(n_matrix),
n_amort(n_amort),
loan_ids(loan_ids),
starting_balances(starting_balances),
starting_positions(starting_positions),
cprs(cprs),
sim_regime_indices(sim_regime_indices),
loan_regime_indices(loan_regime_indices),
starting_periods(starting_periods),
regime_matrix_indices(regime_matrix_indices),
matrix_indices(matrix_indices),
matrix_elements(matrix_elements),
nrow(nrow),
ncol(ncol),
amortisation_schedules(amortisation_schedules),
periods(periods),
iterations(iterations),
output_mx(output_mx) {}
// Setting up functions to convert inputs to arma
arma::vec convert_input_vector(RVector<double> input_vector, int length)
{RVector<double> tmp_input_vector = input_vector ;
arma::vec input_vector_ts(tmp_input_vector.begin(), length, false) ;
return input_vector_ts ;}
arma::mat convert_input_matrix(RMatrix<double> input_matrix, int rows, int cols)
{RMatrix<double> tmp_input_matrix = input_matrix ;
arma::mat input_matrix_ts(tmp_input_matrix.begin(), rows, cols, false) ;
return input_matrix_ts ;}
// Function to iterate
void operator()(std::size_t begin, std::size_t end){
arma::vec loan_ids_ts = convert_input_vector(loan_ids, n_loans) ;
arma::vec starting_balances_ts = convert_input_vector(starting_balances, n_loans) ;
arma::vec starting_positions_ts = convert_input_vector(starting_positions, n_loans) ;
arma::vec cprs_ts = convert_input_vector(cprs, n_loans) ;
arma::vec sim_regime_indices_ts = convert_input_vector(sim_regime_indices, n_regime);
arma::vec loan_regime_indices_ts = convert_input_vector(loan_regime_indices, n_regime) ;
arma::vec starting_periods_ts = convert_input_vector(starting_periods, n_regime) ;
arma::vec regime_matrix_indices_ts = convert_input_vector(regime_matrix_indices, n_regime);
arma::vec matrix_indices_ts = convert_input_vector(matrix_indices, n_matrix) ;
arma::vec matrix_elements_ts = convert_input_vector(matrix_elements, n_matrix) ;
arma::mat amortisation_schedules_ts = convert_input_matrix(amortisation_schedules, n_amort, 3) ;
for(unsigned int i = begin; i < end; i++){
arma::vec i_sim_regime_indices = allwhich_ts(sim_regime_indices_ts,
i) ;
int sim_begin = as_scalar(i_sim_regime_indices.head(1)) ;
int sim_end = as_scalar(i_sim_regime_indices.tail(1)) ;
arma::vec i_loan_regime_indices = loan_regime_indices_ts.subvec(sim_begin, sim_end) ;
arma::vec i_starting_periods = starting_periods_ts.subvec(sim_begin, sim_end) ;
arma::vec i_regime_matrix_indices = regime_matrix_indices_ts.subvec(sim_begin, sim_end) ;
arma::mat pf_simulation = portfolio_simulation_rating_model_rs_ts(
loan_ids_ts,
starting_balances_ts,
starting_positions_ts,
cprs_ts,
i_loan_regime_indices,
i_starting_periods,
i_regime_matrix_indices,
matrix_indices_ts,
matrix_elements_ts,
nrow,
ncol,
amortisation_schedules_ts,
periods
) ;
int sim_rows = pf_simulation.n_rows ;
int sim_cols = pf_simulation.n_cols ;
for(int c = 0; c < sim_cols; c++){
for(int r = 0; r < sim_rows; r++){
output_mx((n_loans*periods*i + r), c) = pf_simulation(r, c) ;
}
}
for(int r = 0; r < sim_rows; r++){
output_mx((n_loans*periods*i + r), 7) = (i + 1) ;
}
}
}
};
//[[Rcpp::export]]
NumericMatrix dcmcmc_portfolio_rating_model_parallel(
const NumericVector& loan_ids,
const NumericVector& starting_balances,
const NumericVector& starting_positions,
const NumericVector& cprs,
const NumericVector& sim_regime_indices,
const NumericVector& loan_regime_indices,
const NumericVector& starting_periods,
const NumericVector& regime_matrix_indices,
const NumericVector& matrix_indices,
const NumericVector& matrix_elements,
int nrow,
int ncol,
const NumericMatrix& amortisation_schedules,
int periods,
int iterations
){
int n_loans = loan_ids.size() ;
int n_regime = sim_regime_indices.size() ;
int n_matrix = matrix_indices.size() ;
int n_amort = amortisation_schedules.nrow() ;
NumericMatrix output_mx(n_loans*periods*iterations, 8) ;
// Creating Worker object
dcmcmc_portfolio_rating_model_worker DCMCMC(
n_loans,
n_regime,
n_matrix,
n_amort,
loan_ids,
starting_balances,
starting_positions,
cprs,
sim_regime_indices,
loan_regime_indices,
starting_periods,
regime_matrix_indices,
matrix_indices,
matrix_elements,
nrow,
ncol,
amortisation_schedules,
periods,
iterations,
output_mx
) ;
// Call parellised worker
parallelFor(0, iterations, DCMCMC) ;
return(output_mx) ;
}
EDIT:
I have produced a minimum reproducible example, trying to incorporate the helpful comments recieved on this post so far. The example sets up trivial functions designed to mimic the structure of my modelling functions. The final function causing a crash takes three vectors, vec1, vec2, and vec_ind. It applies a worker which attempts to take chunks of equal size (indentified by indices stored in vec_ind) of vec1 and vec2, add these subvector chunks, and store the results in the relevant portions of an output vector.
I have reproduced the example below using both arma::vec and std::vector types and experience the crashing behaviour in both. I present the std::vector code below, further to Dirk's suggestion that the RcppArmadillo types may be relying on R memory, and I have removed all namespace inclusions other than RcppParallel to avoid conflicts, as per onyambu's remark.
Here is the Rcpp
// [[Rcpp::depends(RcppArmadillo, RcppParallel)]]
#include <string>
#include <algorithm>
#include <vector>
#include <math.h>
#include <RcppArmadillo.h>
#include <RcppParallel.h>
using namespace RcppParallel;
//[[Rcpp::export]]
std::vector<double> allwhich_ts(std::vector<double> vector, double value){
int length = vector.size() ;
std::vector<double> values(0) ;
for(int i = 0; i < length; i++){
bool match = vector[i] == value;
if(match){
values.push_back(i);
}
}
return(values);
}
//[[Rcpp::export]]
std::vector<double> vector_addition(std::vector<double> vector1, std::vector<double> vector2){
int n_elements = vector1.size() ;
std::vector<double> output_vec = std::vector<double>(n_elements) ;
for(int i = 0; i < n_elements; i++){
output_vec[i] = vector1[i] + vector2[i] ;
}
return(output_vec) ;
}
struct vector_addition_worker : public Worker {
const RVector<double> vector1 ;
const RVector<double> vector2 ;
const RVector<double> vector_indices ;
const int vector_length ;
RVector<double> output_vec ;
vector_addition_worker(
const Rcpp::NumericVector& vector1,
const Rcpp::NumericVector& vector2,
const Rcpp::NumericVector& vector_indices,
const int& vector_length,
Rcpp::NumericVector& output_vec
) : vector1(vector1),
vector2(vector2),
vector_indices(vector_indices),
vector_length(vector_length),
output_vec(output_vec) {}
std::vector<double> convert_input_vec(RVector<double> input_vector, int vec_length){
RVector<double> tmp_vector = input_vector ;
std::vector<double> input_vector_ts(tmp_vector.begin(), tmp_vector.end()) ;
return(input_vector_ts) ;
}
void operator()(std::size_t begin, std::size_t end){
std::vector<double> vector1_ts = convert_input_vec(vector1, vector_length) ;
std::vector<double> vector2_ts = convert_input_vec(vector2, vector_length) ;
std::vector<double> vector_indices_ts = convert_input_vec(vector_indices, vector_length) ;
for(unsigned int i = begin; i < end; i++){
std::vector<double> indices = allwhich_ts(vector_indices_ts, i) ;
int values_begin = indices.at(1) ;
int values_end = indices.at(std::distance(indices.begin(), indices.end())) ;
std::vector<double> values1(vector1_ts.begin() + values_begin, vector1_ts.begin() + values_end) ;
std::vector<double> values2(vector2_ts.begin() + values_begin, vector2_ts.begin() + values_end) ;
std::vector<double> interim_op = vector_addition(values1, values2) ;
int op_size = interim_op.size() ;
for(int n = 0; n < op_size; n++){
output_vec[i*op_size + n] = interim_op[n] ;
}
}
}
};
//[[Rcpp::export]]
Rcpp::NumericVector vector_addition_parallel(Rcpp::NumericVector vec1,
Rcpp::NumericVector vec2,
Rcpp::NumericVector vec_ind){
int vec_length = vec1.size() ;
double n_indices = *std::max_element(vec_ind.begin(), vec_ind.end()) ;
Rcpp::NumericVector op_vec(vec_length);
vector_addition_worker vec_add_worker(
vec1,
vec2,
vec_ind,
vec_length,
op_vec
) ;
parallelFor(0, n_indices, vec_add_worker) ;
return(op_vec) ;
}
Here is the R code which tests for expected behaviour
library(Rcpp)
library(RcppParallel)
library(RcppArmadillo)
# Setting up dummy data
vec1 = rep(1, 500)
vec2 = rep(1, 500)
vec_inds = sort(rep(1:20, 25))
length(vec1);length(vec2);length(vec_inds)
## Checking that allwhich_ts is working as expected
allwhich_ts(vec_inds, 1)
# Checking that vector_addition is working as expected
vector_addition(vec1, vec2)
# Checking that the same logic can be applied serially (mainly to verify data handling method)
r_repro_function <- function(vec1, vec2, vec_inds){
op_vec = numeric(length(vec1))
for(i in unique(vec_inds)){
tmp1 = vec1[vec_inds == i]
tmp2 = vec2[vec_inds == i]
tmp_op = tmp1 + tmp2
for(n in 1:length(tmp1)){
op_vec[(i - 1)*length(tmp1) + n] = tmp_op[n]
}
}
op_vec
}
r_repro_function(vec1, vec2, vec_inds)
vector_addition_parallel(vec1 = vec1,
vec2 = vec2,
vec_ind = vec_inds)
So following Dirk's suggestion I am posting an answer with a pared back example to illustrate the problem I had and the solution I arrived at with his help.
The mistake I made was actually in how I treated the begin and end variables within my worker. In contrast to the articles in the RcppParallel gallery, I was not using begin/end to guide iterators to the relevant portions of the calculation, but rather trying to use them to index the relevant part of my input dataset for each portion.
This caused dimension errors, which on my machine simply crashed the R session.
The solution to this mistake would be to either (1) ensure any UDFs you are applying deal in iterators rather than vector values or (2) to bridge the begin/end variables correctly to the vectors you are trying to index.
Given that all of my modelling functions are already in the business of taking vector indices, I have applied the second approach and create a unique_indices vector within my function which the begin/end values can simply select values from. The current solution makes some assumptions about how the input indices will work (i.e. simply integer values from smallest to largest in the argument vector).
Apologies if this is still considered verbose, but I thought it worth keeping the data-handling logic as it was in the problem statement because that is where the problem arose. That is where a submatrix is identified by an index and used as the arguments to some calculation. The key differences to the example above are on lines 48-52 and 62-65
Where (1) each i between begin and end is used to select an index as so int index_value = unique_indices[i] ; which then identifies the relevant input data and (2) the unique_indices vector is defined by the characteristics of the vector of indices vec_ind
:
// [[Rcpp::depends(RcppArmadillo, RcppParallel)]]
#include <string>
#include <algorithm>
#include <vector>
#include <math.h>
#include <RcppArmadillo.h>
#include <RcppParallel.h>
using namespace RcppParallel;
//[[Rcpp::export]]
std::vector<double> allwhich_ts(std::vector<double> vector, double value){
int length = vector.size() ;
std::vector<double> values(length) ;
int matches = 0;
for(int i = 0; i < length; i++){
bool match = vector[i] == value;
if(match){values[matches] = i;
matches++ ;}}
std::vector<double> op(values.begin(), values.begin() + matches) ;
return(op);
}
struct vector_double_worker : public Worker {
// Defining worker arguments
const RVector<double> vector1 ;
const RVector<double> vector_indices ;
const RVector<double> unique_indices ;
const int vector_length ;
RVector<double> output_vec ;
// Initialising function argument values
vector_double_worker(
const Rcpp::NumericVector& vector1, const Rcpp::NumericVector& vector_indices,
const Rcpp::NumericVector& unique_indices, const int& vector_length, Rcpp::NumericVector& output_vec
) : vector1(vector1),vector_indices(vector_indices),unique_indices(unique_indices),
vector_length(vector_length),output_vec(output_vec) {}
// Setting up conversion function so that UDFs can deal in std:: types
std::vector<double> convert_input_vec(RVector<double> input_vector, int vec_length){
std::vector<double> input_vector_ts(input_vector.begin(), input_vector.end()) ;
return(input_vector_ts) ;}
// Defining operator ranges which will breakdown the task into partitions
void operator()(std::size_t begin, std::size_t end){
// Converting input vectors to std types
std::vector<double> vector1_ts = convert_input_vec(vector1, vector_length) ;
std::vector<double> vector_indices_ts = convert_input_vec(vector_indices, vector_length) ;
// For loop to perform calculations for each element in a given partition
for(unsigned int i = begin; i < end; i++){
int index_value = unique_indices[i] ; // begin and end now used to index the vector of input indices defined outside of the function
std::vector<double> indices = allwhich_ts(vector_indices_ts, index_value) ; // identifying sub-vector indices
int values_begin = indices.at(0) ;
int values_end = indices.at(std::distance(indices.begin(), indices.end()) - 1) ; // - 1 was added to avoid dimension error
std::vector<double> values1(vector1_ts.begin() + values_begin, vector1_ts.begin() + values_end + 1) ; // + 1 was added to avoid dimension error
int op_size = values1.size() ;
for(int n = 0; n < op_size; n++){output_vec[i*op_size + n] = values1[n] * 2 ;} // Trivial example calculation
}}};
//[[Rcpp::export]]
Rcpp::NumericVector vector_double_parallel(Rcpp::NumericVector vec1, Rcpp::NumericVector vec_ind){
int vec_length = vec1.size() ; // Setting up output vector
Rcpp::NumericVector op_vec(vec_length);
double n_indices = *std::max_element(vec_ind.begin(), vec_ind.end()) ; // Identifying unique index values
double min_indices = *std::min_element(vec_ind.begin(), vec_ind.end()) ;
Rcpp::NumericVector unique_indices(n_indices) ;
std::iota(unique_indices.begin(), unique_indices.end(), min_indices);
vector_double_worker vec_2_worker(vec1,vec_ind,unique_indices,vec_length,op_vec) ; // Setting up parallel worker
parallelFor(0, n_indices, vec_2_worker) ; // Populating output vector with results
return(op_vec) ;}

how to return a pointer in a function returning char *?

I'm implementing my own strrchr - it searches for the last occurrence of the character c (an unsigned char) in the string pointed to by the argument str.
example:
Input: f("abcabc" , "b")
Output: "bc"
the function should return char *. How can i return a pointer to the char array in the function?
#include <stdio.h>
#include <string.h>
char* my_strrchr(char* param_1, char param_2)
{
int len = strlen(param_1);
char res ;
for(int i = len; i >= 0 ;i-- ){
if (param_1[i] == param_2){
res = param_1[i];
return *(res);
//here i tried return (char) res, (char*) res; nothing works
}
}
return NULL;
}
int main(){
char *d = "abcabc";
char r = 'b';
my_strrchr(d, r);
return 0 ;
}
You're trying to return value, not a pointer. Operator * means to get value by a pointer, when res isn't a pointer. You should make it a pointer an then return:
char* my_strrchr(char* param_1, char param_2)
{
int len = strlen(param_1);
char *res ; //make it a pointer
for(int i = len; i >= 0 ;i-- ){
if (param_1[i] == param_2){
res = &param_1[i]; //store address of an element to a pointer
return res; //return a pointer
}
}
return NULL;
}
Your variable res is of type char. To get the reference use the reference operator & (See Meaning of "referencing" and "dereferencing" in C):
return &res
However this will result in the address of your variable res and not in the address within your param_1 array. Have a look at Alex' answer to get the correct reference address: https://stackoverflow.com/a/61930295/6669161

Passing data to nlopt in Rcpp?

This is a rather simple question, but I haven't been able to quite find the answer on the web yet.
Wishing my latest attempt, here is latest compiler output:
note: candidate function not viable: no known conversion from 'double (unsigned int, const double *, void *, void )' to 'nlopt_func' (aka 'double ()(unsigned int, const double *, double *, void *)') for 2nd argument
From this error I surmise that I am now wrapping or 'type casting' the data argument correctly and also the parameter vector. The discrepency between the third input, the gradient, confuses me. As I am calling a gradient free optimization routine.
Here is a simple linear regression with a constant and a variable:
#include "RcppArmadillo.h"
// [[Rcpp::depends(RcppArmadillo)]]
// [[Rcpp::depends(nloptr)]]
//#include <vector>
#include <nloptrAPI.h>
using namespace arma;
using namespace Rcpp;
typedef struct {
arma::mat data_in;
} *my_func_data;
typedef struct {
double a, b;
} my_theta;
double myfunc(unsigned n, const double *theta, void *grad, void *data){
my_func_data &temp = (my_func_data &) data;
arma::mat data_in = temp->data_in;
my_theta *theta_temp = (my_theta *) theta;
double a = theta_temp->a, b = theta_temp->b;
int Len = arma::size(data_in)[0];
arma::vec Y1 = data_in(span(0, Len-1), 1);
arma::vec Y2 = data_in(span(0, Len-1), 2);
arma::vec res = data_in(span(0, Len-1), 0) - a*Y1 - b*Y2 ;
return sum(res);
}
// [[Rcpp::export]]
void test_nlopt_c() {
arma::mat data_in(10,3);
data_in(span(0,9),0) = arma::regspace(40, 49);
data_in(span(0,9),1) = arma::ones(10);
data_in(span(0,9),2) = arma::regspace(10, 19);
my_func_data &temp = (my_func_data &) data_in;
double lb[2] = { 0, 0,}; /* lower bounds */
nlopt_opt opt;
opt = nlopt_create(NLOPT_LN_NELDERMEAD, 2); /* algorithm and dimensionality */
nlopt_set_lower_bounds(opt, lb);
nlopt_set_min_objective(opt, myfunc, &data_in );
nlopt_set_xtol_rel(opt, 1e-4);
double minf; /* the minimum objective value, upon return */
double x[2] = {0.5, 0.5}; /* some initial guess */
nlopt_result result = nlopt_optimize(opt, x, &minf);
Rcpp::Rcout << "result:" << result;
return;
}
Got it figured out, stupid answer turns out to be correct, just change 'void' to 'double', no clue why. Anyway, the example code needs some improving but it works.
#include "RcppArmadillo.h"
// [[Rcpp::depends(RcppArmadillo)]]
// [[Rcpp::depends(nloptr)]]
//#include <vector>
#include <nloptrAPI.h>
using namespace arma;
using namespace Rcpp;
typedef struct {
arma::mat data_in;
} *my_func_data;
typedef struct {
double a, b;
} my_theta;
double myfunc(unsigned n, const double *theta, double *grad, void *data){
my_func_data &temp = (my_func_data &) data;
arma::mat data_in = temp->data_in;
my_theta *theta_temp = (my_theta *) theta;
double a = theta_temp->a, b = theta_temp->b;
int Len = arma::size(data_in)[0];
arma::vec Y1 = data_in(span(0, Len-1), 1);
arma::vec Y2 = data_in(span(0, Len-1), 2);
arma::vec res = data_in(span(0, Len-1), 0) - a*Y1 - b*Y2 ;
return sum(res);
}
// [[Rcpp::export]]
void test_nlopt_c() {
arma::mat data_in(10,3);
data_in(span(0,9),0) = arma::regspace(40, 49);
data_in(span(0,9),1) = arma::ones(10);
data_in(span(0,9),2) = arma::regspace(10, 19);
my_func_data &temp = (my_func_data &) data_in;
double lb[2] = { 0, 0,}; /* lower bounds */
nlopt_opt opt;
opt = nlopt_create(NLOPT_LN_NELDERMEAD, 2); /* algorithm and dimensionality */
nlopt_set_lower_bounds(opt, lb);
nlopt_set_min_objective(opt, myfunc, &data_in );
nlopt_set_xtol_rel(opt, 1e-4);
double minf; /* the minimum objective value, upon return */
double x[2] = {0.5, 0.5}; /* some initial guess */
nlopt_result result = nlopt_optimize(opt, x, &minf);
Rcpp::Rcout << "result:" << result;
return;
}

C code translated to Qt crashes while executing

I´m a beginner on programming and Qt, but as liked the framework I´m trying to improve my skills and write my C++ codes on it. I got a task of writing a Ricker wavelet code and then plot it.
I divided it in two tasks, first make the ricker code works, and when it is running, then implement a way to plot it, I will use qcustomplot for it.
I got a code from C and I´m trying to adapt it to Qt. Although it doesn´t give any errors during compilation, when executing it crashes, with the following message:
Invalid parameter passed to C runtime function. C:/Users/Flavio/Documents/qtTest/build-ricker2-Desktop_Qt_5_11_0_MinGW_32bit-Debug/debug/ricker2.exe
exited with code 255
The code I´m supposed to translate is:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
float *rickerwavelet(float fpeak, float dt, int *nwricker);
int main(int argc, char **argv)
{
int i;
float dt;
float fpeak;
float *wricker=NULL;
int nwricker;
fpeak = atof(argv[1]);
dt = atof(argv[2]);
wricker = rickerwavelet(fpeak, dt, &nwricker);
/* show value of ricker wavelets */
for (i=0; i<nwricker; i++)
printf("%i. %3.5f \n", i, wricker[i]);
free(wricker);
return(1);
}
/* ricker wavelet function, return an array ricker wavelets */
float *rickerwavelet(float fpeak, float dt, int *nwricker)
{
int i, k;
int nw;
int nc;
float pi;
float nw1, alpha, beta;
float *wricker=NULL;
pi = 3.141592653589793;
nw1 = 2.2/fpeak/dt;
nw = 2*floor(nw1/2)+1;
nc = floor(nw/2);
wricker = (float*) calloc (nw, sizeof(float));
for (i=0; i<nw; i++)
{
k = i+1;
alpha = (nc-k+1)fpeakdtpi;
beta = pow(alpha, 2.0);
wricker[i] = (1 - (beta2)) * exp(-beta);
}
(*nwricker) = nw;
return(wricker);
}
The code i wrote on Qt is:
#include <QCoreApplication>
#include <qmath.h>
#include <stdio.h>
#include <stdlib.h>
#include <QDebug>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
int i,k,nw,nc;
double *wricker=NULL;
int nwricker = 60;
int wavelet_freq = 30;
int polarity=1;
int sampling_rate=0.004;
float nw1, alpha, beta;
const double pi = 3.141592653589793238460;
nw1 = 2.2/wavelet_freq/sampling_rate;
nw = 2*floor(nw1/2)+1;
nc = floor(nw/2);
wricker = (double*)calloc (nw, sizeof(double));
for (i=0; i<nw; i++)
{
k = i+1;
alpha = (nc-k+1)wavelet_freqsampling_ratepi;
beta = pow(alpha, 2.0);
wricker[i] = polarity((1 - (beta2)) * exp(-beta));
};
/* show value of ricker wavelets */
for (i=0; i<nwricker; i++)
{
qDebug()<<i<<wricker[i];
};
free(wricker);
return a.exec();
}
Analytic expression
The amplitude A of the Ricker wavelet with peak frequency f at time t is computed like so:
A = (1-2 pi^2 f^2* t^2) e^{-pi^2* f^2* t^2}
A py code for it would be:
import numpy as np
import matplotlib.pyplot as plt
def ricker(f, length=0.128, dt=0.001):
t = np.arange(-length/2, (length-dt)/2, dt)
y = (1.0 - 2.0*(np.pi2)(f2)(t2)) * np.exp(-(np.pi2)(f2)(t**2))
return t, y
f = 25 # A low wavelength of 25 Hz
t, w = ricker(f)
What seems quite simple.
Does anyone have any idea what is wrong in my code???
Doing a bit of Debugging I found the problem is when passing the vectors to qDebug, it give a message:
THE INFERIOR STOPPED BECAUSE IT RECEIVED A SIGNAL FROM THE OPERATING
SYSTEM . SIGNAL NAME: SIGSEGV SIGNAL MEANING: SEGMENTATION FAULT
I´ll search for more information on this signal meaning. I used qDebug only with the intention of showing the data on a terminal to make sure the calculation was working.
Thanks in advance.
C++ is much more like Python than C. Even though your C code was particularly convoluted, it still isn't as nice a C++ can be.
A complete example that even plots the data can be very, very simple. If that doesn't show the combined power of C++ and Qt, I hardly know what will :)
wavelet-plot-50690312.pro file
QT = charts
SOURCES = main.cpp
main.cpp
// https://github.com/KubaO/stackoverflown/tree/master/questions/wavelet-plot-50690312
#include <QtCharts>
#include <cmath>
const double pi = 3.14159265358979323846;
QVector<QPointF> ricker(double f, double length = 2.0, double dt = 0.001) {
size_t N = (length - dt/2.0)/dt;
QVector<QPointF> w(N);
for (size_t i = 0; i < N; ++i) {
double t = -length/2 + i*dt;
w[i].setX(t);
w[i].setY((1.0 - 2*pi*pi*f*f*t*t) * exp(-pi*pi*f*f*t*t));
}
return w;
}
QLineSeries *rickerSeries(double f) {
auto *series = new QLineSeries;
series->setName(QStringLiteral("Ricker Wavelet for f=%1").arg(f, 2));
series->replace(ricker(f));
return series;
}
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
QChartView view;
view.chart()->addSeries(rickerSeries(1.0));
view.chart()->addSeries(rickerSeries(2.0));
view.chart()->createDefaultAxes();
view.setMinimumSize(800, 600);
view.show();
return app.exec();
}
Of course, this looks nice in C++. How about C? Let's pretend we had some C binding for Qt. Then it might look as follows:
// https://github.com/KubaO/stackoverflown/tree/master/questions/wavelet-plot-50690312/c-binding
#include "qc_binding.h"
#include <math.h>
#include <stddef.h>
#include <stdio.h>
const double pi = 3.14159265358979323846;
CQVector *ricker(double f, double length, double dt) {
scope_enter();
size_t N = (length - dt/2.0)/dt;
CQVector *vector = CQVector_size_(CQ_, CQPointF_type(), N);
CQPointF *const points = CQPointF_(CQVector_data_at(vector, 0));
for (size_t i = 0; i < N; ++i) {
double t = -length/2 + i*dt;
points[i].x = t;
points[i].y = (1.0 - 2*pi*pi*f*f*t*t) * exp(-pi*pi*f*f*t*t);
}
return scope_leave_ptr(vector);
}
CQLineSeries *rickerSeries(double f) {
scope_enter();
CQLineSeries *series = CQLineSeries_(CQ_);
CQLineSeries_setName(series, CQString_asprintf(CQ_, "Ricker Wavelet for f=%.2f", f));
CQLineSeries_replaceVector(series, ricker(f, 2.0, 0.001));
return scope_leave_ptr(series);
}
int main(int argc, char *argv[]) {
scope_enter();
CQApplication *app = CQApplication_(CQ_, &argc, argv);
CQChartView *view = CQChartView_(CQ_);
CQChart *chart = CQChartView_getChart(view);
CQChart_addLineSeries(chart, rickerSeries(1.0));
CQChart_addLineSeries(chart, rickerSeries(2.0));
CQChart_createDefaultAxes(chart);
CQWidget *view_ = CQWidget_cast(view);
CQWidget_setMinimumSize(view_, 800, 600);
CQWidget_show(view_);
return scope_leave_int(CQApplication_exec(app));
}
With a little bit of work, a C binding can be made that is about as easy to use as C++: scopes are tracked, RAII works, destructors get called when needed, values about to be returned are not destructed, etc.
Such a minimum binding, implementing all that's needed to run the code above, is available at https://github.com/KubaO/stackoverflown/tree/master/questions/wavelet-plot-50690312/c-binding.

OpenCL distance between strings

I have this C++ code from the web that computes for distance between two strings. Can someone help me convert this to OpenCL for parallelism? I'm having hard time learning OpenCL.
#include <stdio.h>
#include <math.h>
#include <string.h>
#define MIN(x,y) ((x) < (y) ? (x) : (y))
int main()
{
int d[100][100];
int i,j,m,n,temp,tracker;
char s[] = "Sanfoundry";
char t[] = "Education";
m = strlen(s);
n = strlen(t);
for(i=0;i<=m;i++)
d[0][i] = i;
for(j=0;j<=n;j++)
d[j][0] = j;
for (j=1;j<=m;j++)
{
for(i=1;i<=n;i++)
{
if(s[i-1] == t[j-1])
{
tracker = 0;
} else {
tracker = 1;
}
temp = MIN((d[i-1][j]+1),(d[i][j-1]+1));
d[i][j] = MIN(temp,(d[i-1][j-1]+tracker));
}
}
printf("the Levinstein distance is %d\n",d[n][m]);
return 0;
}
Specifically, what part of the code must be put in a kernel? Also, what memory objects needed to be created?
Thanks

Resources