Ruby C API - From ruby array to C array - c

I am passing an array (matrix) from Ruby to a C function. At the moment I am using the following code
VALUE matmat_mul(VALUE self, VALUE matrixA, VALUE matrixB)
{
int rowsA = RARRAY_LEN(matrixA);
VALUE firstElement = rb_ary_entry(matrixA, 0);
int colsA = RARRAY_LEN(firstElement);
int rowsB = RARRAY_LEN(matrixB);
firstElement = rb_ary_entry(matrixB, 0);
int colsB = RARRAY_LEN(firstElement);
int i,j;
double *matA = (double *)malloc(rowsA * colsA * sizeof(double));
double *matB = (double *)malloc(rowsB * colsB * sizeof(double));
VALUE rowA;
for (i=0; i<rowsA; i++)
{
rowA = rb_ary_entry(matrixA, i);
for (j=0; j<colsA; j++)
{
matA[i * colsA + j] = NUM2DBL(rb_ary_entry( rowA, j));
}
}
// same for matrix B
....
....
// Perform operation C = A x B
VALUE matrixC = rb_ary_new2(rowsC);
VALUE rowC;
for (i=0; i<rowsC; i++) {
rowC = rb_ary_new2(colsC);
for (j=0; j<colsC; j++) {
rb_ary_store(rowC, j, DBL2NUM(matC[i * colsC + j]));
}
rb_ary_store(matrixC, i, rowC);
}
return matrixC
}
Is there a better/quicker way to convert a Ruby array to a C array and viceversa?

No there is not a quicker way to convert Ruby Array to a C structure. That's because the Ruby Array could contain a mixture of any other kind of Ruby object, many of which could not be converted to a C double
There is another option though - NArray. This is a very efficient way of dealing with numerical multi-dimensional arrays in Ruby. There is a lot less procedure converting from an NArray to C, but it is entirely different way of doing things.
Some of it is a little complex. In summary . . .
Load the narray.h library in extconf.rb
Original version of this was from fftw3 gem (I have simplified a little):
require "mkmf"
require "narray"
narray_dir = File.dirname(Gem.find_files("narray.h").first) rescue $sitearchdir
dir_config('narray', narray_dir, narray_dir)
if ( ! ( have_header("narray.h") && have_header("narray_config.h") ) )
puts "Header narray.h or narray_config.h is not found."
exit(-1)
end
create_makefile( 'my_lib_name/my_lib_name' )
Cast input NArray objects to the data type you want to work with
Here's an example instance method that can access the NArray
VALUE example_narray_param( VALUE self, VALUE rv_narray ) {
// Cast the input to the data type you want - here 32-bit ints
volatile VALUE new_narray = na_cast_object(rv_narray, NA_LINT);
// NARRAY is the C struct interface to NArray data
struct NARRAY *na_items;
// This macro is NArray's equivalent of NUM2DBL, pointing na_items
// at the data
GetNArray( new_narray, na_items );
// row now points natively to the data
int * row = (int*) na_items->ptr;
For multi-dimensional arrays like your matrix, NArray uses a single pointer with multiplier offsets, similar to your matA[i * colsA + j] - going into full detail on this would be too long, but hopefully this is enough of a start to help you decide if this is the right solution for you.
I actually use this approach a lot in some personal projects. They are MIT licensed, so feel free to look through them and copy or re-use anything. This neural network layer class might contain some useful reference code.

Related

How to perform computational operation on 2D array which has been returned from a function in C?

I have written a function for FIR Filter which has an array as input and another array as output.This is my FIR Filter function here:
float * filter(float PATIENTSIGNAL[],float FILTERCOEF[])
I can use it without any problem, like the way hereunder:
float *FILTEROUT;
float FIROUT[8000];
FILTEROUT = filter(PATIENTSIGNAL, FILTERCOEF);
/* */
for (k = 0; k <= 1000; k++){
FIR[k] = 10 + FILTEROUT[k];
}
As you see I added number 10 to each element of my output array to evaluate that can I use this array for future computation,
But Here is my problem when I want use 2D array, This my function which return a 2D array correctly;
float(*Windowing(float SIGNAL[], int WINDOWSIZE));
I have used the Windowing function by this code in appropriate way:
patientwindow = Windowing(FILTEROUT, WINDOWSIZE);
and the all numbers in "patientwindow" array is correct but when I want to perform some simple operation like summation as here:
float evaluate[WINDOWSIZE][OVERLAP/4];
for (j = 0; j <= NUMBEROFWINDOWS; j++){
for (i = 0; i < WINDOWSIZE; i++){
evaluate[i][j] = 2+ (patientwindow[i][j]);
}
}
all elements of "evaluate" array are 0;
Would you please help me?
use
float** patientwindow;
float* is a pointer to array whereas float** is a pointer to matrix (for why is that the case see this answer https://stackoverflow.com/a/17953693/4996826 ).
If you want to use float* , then use following snippet of code:
evaluate[i][j] = 2 + (patientwindow[(i * NUMBEROFWINDOWS) + j]);

Best solution to represent Data[i,j] in c?

There is a pseudocode that I want to implement in C. But I am in doubt on how to implement a part of it. The psuedocode is:
for every pair of states qi, and qj, i<j, do
D[i,j] := 0
S[i,j] := notzero
end for
i and j, in qi and qj are subscripts.
how do I represent D[i,J] or S[i,j]. which data structure to use so that its simple and fast.
You can use something like
int length= 10;
int i =0, j= 0;
int res1[10][10] = {0, }; //index is based on "length" value
int res2[10][10] = {0, }; //index is based on "length" value
and then
for (i =0; i < length; i++)
{
for (j =0; j < length; j++)
{
res1[i][j] = 0;
res2[i][j] = 1;//notzero
}
}
Here D[i,j] and S[i,j] are represented by res1[10][10] and res2[10][10], respectively. These are called two-dimentional array.
I guess struct will be your friend here depending on what you actually want to work with.
Struct would be fine if, say, pair of states creates some kind of entity.
Otherwise You could use two-dimensional array.
After accept answer.
Depending on coding goals and platform, to get "simple and fast" using a pointer to pointer to a number may be faster then a 2-D array in C.
// 2-D array
double x[MAX_ROW][MAX_COL];
// Code computes the address in `x`, often involving a i*MAX_COL, if not in a loop.
// Slower when multiplication is expensive and random array access occurs.
x[i][j] = f();
// pointer to pointer of double
double **y = calloc(MAX_ROW, sizeof *y);
for (i=0; i<MAX_ROW; i++) y[i] = calloc(MAX_COL, sizeof *(y[i]));
// Code computes the address in `y` by a lookup of y[i]
y[i][j] = f();
Flexibility
The first data type is easy print(x), when the array size is fixed, but becomes challenging otherwise.
The 2nd data type is easy print(y, rows, columns), when the array size is variable and of course works well with fixed.
The 2nd data type also row swapping simply by swapping pointers.
So if code is using a fixed array size, use double x[MAX_ROW][MAX_COL], otherwise recommend double **y. YMMV

Indexing slice from 3D Rcpp NumericVector

Hi I have what I think must be a really simple Rcpp question regarding treating NumericVector objects as multidimensional arrays. I can't find an answer to what might be obvious. Apologies up front if this is the case -- my inexperience with C++ is to blame...
If I use the answer posted here a (Constructing 3D array in Rcpp) as an example
library("Rcpp")
cppFunction(code='
NumericVector arrayC(NumericVector input, IntegerVector dim) {
input.attr("dim") = dim;
return input;
}
')
How do I extract/access an single slice / row / column out of the "intput" object?
I.e. Do something like
NumericMatrix X = input(_,_,i)
// FYI -- I know this doesn't work! Simply trying to convey the point...
And yes I know RcppArmadillo could be used. I have my reasons, for doing things this way but no need to bore folks with them.
Thanks.
Rcpp11 has Array for this, templated with both the dimension depth and the R type.
For example, you could do:
#include <Rcpp.h>
using namespace Rcpp ;
typedef Array<3,REALSXP> Numeric3D ;
// [[Rcpp::export]]
Numeric3D test(){
Numeric3D res(2,3,4) ;
for( int i=0; i<2; i++)
for( int j=0; j<3; j++)
for( int k=0; k<4; k++)
res(i,j,k) = i+j+k ;
return res ;
}
/*** R
test()
*/
All the relevant indexing logic is in the Index class template. The implementation uses C++11 variadic templates.
Everything I wrote in the previous answer you cite still holds: doable, but possibly painful as you may need to write converters. Contributions would still be welcome.
For what it is worth, I use the (Rcpp)Armadillo containers for three-dimensional data as they do have the slicing operators. Note that you can't easily convert them to something R likes ,ie I think we still automated converters for cube to lists of matrices.
Edit: For what it is worth, here is a short loop from a recent GitHub project of mine:
for (unsigned int j=k-1-1; j>0; j--) {
arma::mat Ppred = AA.slice(j) * P.slice(j) * AA.slice(j).t() + QQ.slice(j);
arma::mat lhs = (P.slice(j) * AA.slice(j).t());
arma::mat rhs = Ppred;
D.slice(j) = arma::solve(rhs.t(), lhs.t()).t();
M.col(j) = M.col(j) + D.slice(j) * (M.col(j+1) - AA.slice(j) * M.col(j));
P.slice(j) = P.slice(j) + D.slice(j) *
(P.slice(j+1) - Ppred) * D.slice(j).t();
}
This uses Armadillo slicing on both the left and right-hand sides. And this works rather well from R thanks to RcppArmadillo (modulo the aforementioned issue that because a R has no real native 3-d structure, so we can't pass a 3-d matrix back easily).

Postgresql SPI: Manipulating type "Datum" to create a double array

I am using SPI_getbinval to pull a column of type double precision[] from my cursor. How can I reconstruct this as a double * in C so I can work with the values?
Most of the examples I've seen in the documentation make reference to obscure helper functions (i.e. construct_md_array()) and I cannot find a listing of these functions or how to use them appropriately for my situation.
Basically, I need to know the most efficient way to construct a double array from Datum containing double precision[].
(See prior question Achieving high-performance transactions when extending PostgreSQL with C-functions).
...
bool is_null = true;
Datum raw_array = SPI_getbinval(heap_tuple, tuple_desc, column_of_array, &is_null);
if ( !is_null ) {
ArrayType *pg_array = DatumGetArrayTypeP(raw_array);
int array_dimensionality = ARR_NDIM(pg_array);
// Not prepared for multi-dimension array
if ( array_dimensionality == 1 ) {
double *c_array = VARDATA(pg_array); // Pointer to the array data
int array_size = ARR_DIMS(pg_array)[0]; // Element count of array at [dimension]
// Cycle through a single dimension array
for (int i = 0 ; i < array_size ; ++i) {
elog(INFO, "Double value at element %d: %lf\n", i, c_array[i]);
}
}
}
...
P.S. elog() is PostgreSQL version of the printf() function (with additional functionality) - use it.

manage array of memory directions

I have several variables inside a struct.
struct my_struct{
float variable_2_x[2],variable_2_y[2],variable_2_z[2];
float coef_2_xyz[3];
float variable_3_x[3],variable_3_y[3],variable_3_z[3];
float coef_3_xyz[3];
float variable_4_x[4],variable_4_y[4],variable_4_z[4];
float coef_4_xyz[3];
};
This struct its going to contain Lagrange polynomial (en.wikipedia.org/wiki/Lagrange_polynomial) coefficients, for several polynomial lenght: 2, 3, 4. The value of this coefficients its easy to calculate but the problem is, that i have to repeat the same code to create every single polynomial. for example
// T_space is a cube with {[-1:1][-1:1][-1:1]} dimension,
// its call transformed space.
// distance is the distance between two points of T_space
// point_1 its the point where the function has value 1
p = 2;
step = distance / p;
polinoms.coef_2_xyz[0] = 1.0:
polinoms.coef_2_xyz[1] = 1.0:
polinoms.coef_2_xyz[2] = 1.0:
for( i = 0; i < p ; ++i)
{
polinoms.pol_2_x[i] = (T_space.xi[point_1] + step) + (i * step);
polinoms.pol_2_y[i] = (T_space.eta[point_1] + step) + (i * step);
polinoms.pol_2_z[i] = (T_space.sigma[point_1] + step) + (i * step);
polinoms.coef_2_xyz[0]*= (T_space.eta[point_1] - polinoms.pol_2_x[i]);
polinoms.coef_2_xyz[1]*= (T_space.eta[point_1] - polinoms.pol_2_y[i]);
polinoms.coef_2_xyz[2]*= (T_space.eta[point_1] - polinoms.pol_2_z[i]);
}
As i don't want to repeat the same loop several times in the code. And what is more important next step in the code i need to integrate the product of the gradient of the polynomial, to every point in the cube.
It will very useful beening able to call every array of the struct independently.
As i know that, variables can't be dynamically called on runtime. I think of making an array which contains the memory directions of the struct. something like this.
// declare variable to store memory directions
float mem_array[12];
// some code
mem_array[0] = &variable_2_x;
mem_array[1] = &variable_2_y;
mem_array[2] = &variable_2_z;
mem_array[3] = &coef_2_xyz;
mem_array[4] = &variable_3_x;
mem_array[11] = &variable_4_z;
mem_array[12] = &coef_4_xyz;
// work calling mem_array.
But i don't know if this is possible or if it will work. If you think this is not the proper way to face the problem, i'm open to advice. Because i'm really stuck with this.
I have edited the question to be more clear, hope it will help.
You'd be better to allocate the memory you need dynamically. You can have a struct that represents a single Lagrange polynomial (of any order), and then have an array of these, one for each order.
You could also store the order of the polynomial as a member of the struct if you wish. You should be able to factor out code that deals with these into functions that take a LagrangePolynomial*, determine the order, and do whatever computation is required.
The key benefit of all of this is that you don't need to have special code for each order, you can use the same code (and the same struct) for any size of polynomial.
Example below:
struct LagrangePolynomial {
float *x;
float *y;
float *z;
};
For p=2:
LagrangePolynomial p;
p.x = malloc(sizeof(float)*2);
p.y = malloc(sizeof(float)*2);
p.z = malloc(sizeof(float)*2);
for (size_t i=0; i<2; i++) {
p.x[i] = ...;
p.y[i] = ...;
p.z[i] = ...;
}
When you've finished with the structure you can free all the memory you've allocated.
free(p.x);
free(p.y);
free(p.z);
As mentioned before you can have an array of these.
LagrangePolynomial ps[4];
for (size_t i=0; i<4; i++) {
p[i].x = malloc(sizeof(float)*2);
p[i].y = malloc(sizeof(float)*2);
p[i].z = malloc(sizeof(float)*2);
for (size_t j=0; j<2; j++) {
p[i].x[j] = ...;
p[i].y[j] = ...;
p[i].z[j] = ...;
}
}

Resources