My problem is that I want to pass a 3 dimensional array as output to matlab and work with it in a seperate C void function.. But when I try my Matlab Crashes. I have almost just started working with mex functions and have created others that works with no problems, but they have only been outputting arrays and single values.
Here is my Code.:
First file is my entry file called pm_motion_entry.c .:
#include <mex.h>
#include <matrix.h>
/* The gateway function */
void mexFunction(int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[])
{
/* Variable declarations here */
double sigma;
double L;
double radius;
int N;
int M;
double *outMatrixOne;
mwSignedIndex *outMatrixTwo;
mxArray *Array;
/* Dimensions for cell array */
mwSize dim[2] = {M,N};
/* checks for right type*/
if(nrhs != 5) {
mexErrMsgIdAndTxt("MyToolbox:arrayProduct:nrhs","Inputs: sigma, L, radius, N, NumberOfParticles");
}
if(nlhs != 2) {
mexErrMsgIdAndTxt("MyToolbox:arrayProduct:nrhs","Too Few output argumetns, Output is I and Particle");
}
sigma = mxGetScalar(prhs[0]);
L = mxGetScalar(prhs[1]);
radius = mxGetScalar(prhs[2]);
N = mxGetScalar(prhs[3]);
M = mxGetScalar(prhs[4]);
if( !mxIsDouble(prhs[0]) || !mxIsDouble(prhs[1]) || !mxIsDouble(prhs[2]) || !mxIsDouble(prhs[3]) || !mxIsDouble(prhs[4])) {
mexErrMsgIdAndTxt("MyToolBox:arrayProduct:notScalar","Input 1,2 and 3 should be of type double, and 4 and 5 should be of type Integer.");
}
/* create output matrix */
plhs[0] = mxCreateDoubleMatrix(N,1,mxREAL);
Array = mxCreateNumericArray(2,dim,mxDOUBLE_CLASS,mxREAL); /* Two cell arrays one for x positions and one for y positions*/
/* assign pointer to output*/
outMatrixOne = mxGetPr(plhs[0]);
outMatrixTwo = (mwSignedIndex*)mxGetData(Array);
/* run function */
pBm_motion(sigma,L,radius,N,M,outMatrixOne,outMatrixTwo);
}
And my main function for calculations called pm_motion.c .:
#define _USE_MATH_DEFINES
#include <math.h>
#define UNIFORM ((rand()+0.5)/(RAND_MAX+1.0)) /* uniform inside [0,1] */
#include "mex.h"
/* Function for the calculation of the Intensity spectra of pure Brownian motion in FSC data */
void pBm_motion(double sigma, double L, double radius, int N, int M, double *In, double ***Particle)
{
/* Inputs/Outputs: D is the diffusion coefficient, tau is the size of timesteps, L is the length of on side of the system, radius is the radius of the focal volume, N is the number of time steps and M is the number of particles */
/* Initialization of Parameters */
int n = 1;
int i;
double pos_x,pos_y;
/* The random walk and advancement in time */
/* First place all particles randomly, this is t=0 */
for(i = 0; i <= M; i++){
Particle[i][0][0] = (-1.0)*UNIFORM + 0.5;
Particle[i][0][1] = (-1.0)*UNIFORM + 0.5;
In[0] += exp(-((Particle[i][0][0]*Particle[i][0][0])+(Particle[i][0][1]*Particle[i][0][1]))/(2.0*radius*radius));
}
/* Then we let time flow in the system */
while(N >= n){
for(i = 0; i <= M; i++){
/* Using the Box-Muller Method to generate random normal distrubuted number to find the new position */
pos_x = Particle[i][n][0] + sigma*sqrt(-2.0*log(UNIFORM))*sin(2.0*M_PI*UNIFORM);
pos_y = Particle[i][n][1] + sigma*sqrt(-2.0*log(UNIFORM))*sin(2.0*M_PI*UNIFORM);
/* Double Periodic violation */
if(pos_x > (L/2.0) && pos_y > (L/2.0)){
pos_x = -(L/2.0)+(pos_x - (L/2.0));
pos_y = -(L/2.0)+(pos_y - (L/2.0));
}
if(pos_x < -(L/2.0) && pos_y > (L/2.0)){
pos_y = -(L/2.0)+(pos_y - (L/2.0));
pos_x = (L/2.0)+((L/2.0) + pos_x);
}
if(pos_x < (L/2.0) && pos_y < -(L/2.0)){
pos_x = -(L/2.0)+(pos_x - (L/2.0));
pos_y = (L/2.0)+((L/2.0) + pos_y);
}
if(pos_x < -(L/2.0) && pos_y < -(L/2.0)){
pos_y = (L/2.0)+((L/2.0) + pos_y);
pos_x = (L/2.0)+((L/2.0) + pos_x);
}
/* Periodic Boundary condition invoked, maybe.. */
if(pos_x > (L/2.0)){
pos_x = -(L/2.0)+(pos_x - (L/2.0));
}
if(pos_y > (L/2.0)){
pos_y = -(L/2.0)+(pos_y - (L/2.0));
}
if(pos_x < -(L/2.0)){
pos_x = (L/2.0)+((L/2.0) + pos_x);
}
if(pos_y < -(L/2.0)){
pos_y = (L/2.0)+((L/2.0) + pos_y);
}
/* Update position. */
Particle[i][n][0] = pos_x;
Particle[i][n][1] = pos_y;
/* Calculate Intensity */
In[n] += exp(-((Particle[i][n][0]*Particle[i][n][0])+(Particle[i][n][1]*Particle[i][n][1]))/(2.0*radius*radius));
}
n++;
}
}
I have I feeling that it is the way i access the 3D Matrix in the Entry file, But I don't know enough about mex yet to be really sure about it.
Related
I program in C and I am testing my program and I don't understand why I get the error -1073741819 (0xC0000005). Here is the Code:
#include <stdio.h>
#include <stdlib.h>
double interpol(double x0, double y0, double x1, double y1, double h) {
double ergebnis = (y1 - y0) / (x1 - x0) * h;
printf("%.2f\n", ergebnis);
return ergebnis;
}
void interpol_array(double *x_org, double *y_org, int dim_org,
double *x_int, double *y_int, int dim_int,
int n) {
int j, i;
double h;
i = 0;
y_org[0] = y_int[0];
for (j = 1; j < dim_int; j++) {
if (j % (n + 1) == 0 && j != 0) {
i++;
x_int[j] = x_org[i];
y_int[j] = x_org[i];
continue;
}
printf("%.2f ", y_org[0]);
}
}
int main() {
/* Pointer erzeugen auf null setzen */
double *xArrayOriginal = NULL;
double *yArrayOriginal = NULL;
double *xArrayInterpol = NULL;
double *yArrayInterpol = NULL;
/**/
int dimOriginal = 2;
int n = 3;
int dimInterpol = (n + 1) * (dimOriginal + 1) - n; /*+1 wegen der null*/
int i, j;
double h;
/* Array für die Originalwerte erzeugen */
xArrayOriginal = (double *)malloc(dimOriginal * sizeof(double));
yArrayOriginal = (double *)malloc(dimOriginal * sizeof(double));
/*Array für das Interpolierte Array erzeugen*/
xArrayInterpol = (double *)malloc(dimInterpol * sizeof(double));
yArrayInterpol = (double *)malloc(dimInterpol * sizeof(double));
xArrayOriginal[0] = 0;
xArrayOriginal[1] = 1;
xArrayOriginal[2] = 2;
yArrayOriginal[0] = 2;
yArrayOriginal[1] = 4;
yArrayOriginal[2] = 8;
interpol_array(xArrayOriginal, yArrayOriginal, dimOriginal, xArrayInterpol,
yArrayInterpol, dimInterpol, n);
return 0;
}
In my program I have 4 dynamic arrays. 2 dynamic arrays for origin x and y values and 2 dynamic arrays for interpolated x and y values. I don't program the full interpolation because I got an error. Therefore I searched the error and found out that when I use
printf("%.2f ", y_org[0]);
I get the error that you can see above. Only when I change it to
printf("test");
it works fine. So why do I get this error. what is wrong with my array list?
In the function main, the lines
int dimOriginal = 2;
...
xArrayOriginal =(double *)malloc(dimOriginal*sizeof(double));
yArrayOriginal =(double *)malloc(dimOriginal*sizeof(double));
allocate arrays for 2 double elements each. However, the lines
xArrayOriginal[2] =2;
...
yArrayOriginal[2] =8;
write out of bounds of these arrays, as the only valid elements numbers are 0 and 1. This causes undefined behavior.
Also, in the function interpol_array, the following line causes undefined behavior:
y_org[0] = y_int[0];
This is because y_int has been assigned the value of yArrayInterpol in main, but the contents of yArrayInterpol has not been initialized.
I am trying to adapt a secuential function writen for CPU to an OpenCL kernel for GPU.
The function is the well known im2col used in many deep learning applications.
I have found some code on the OpenCV repository implementing this im2col function written in OpenCL but the one that I have to adapt uses a batch that confuses me and seems to be a bit different.
What should I change on the OpenCL kernel to make it work the same on GPU as it does on the CPU function?
CPU code
int fn_im2col_cpu(int I, int WI, int HI, int B, int KW, int KH, int WO, int HO, int PW, int PH, int SW, int SH, type *in_ptr, type *out_ptr) {
PROFILING_HEADER_EXTERN(im2col);
PROFILING_DEVICE(im2col, DEV_CPU);
int i; // scrolls input channels
int w; // scrolls channel columns (width)
int h; // scrolls channel rows (height)
int kw; // scrolls filter columns (width)
int kh; // scrolls filter rows (height)
// we sweep all output pixels, and for each pixel we compute the associated input pixel
#pragma omp parallel for private (kh, kw, h, w)
for (i = 0; i < I; i++) {
size_t out_addr = ((size_t)B * (size_t)WO * (size_t)HO * (size_t)KW * (size_t)KH * (size_t)i);
size_t in_addr1 = (size_t)i * (size_t)B * (size_t)WI * (size_t)HI;
for (kh = 0; kh < KH; kh++) {
for (kw = 0; kw < KW; kw++) {
for (h = 0; h < HO; h++) {
int hi = h * SH - PH + kh;
size_t in_addr2 = in_addr1 + ((size_t)hi * (size_t)B * (size_t)WI);
for (w = 0; w < WO; w++) {
int wi = w * SW - PW + kw;
int force_padding = (wi < 0) || (wi >= WI) || (hi < 0) || (hi >= HI);
if (force_padding) {
bzero(&out_ptr[out_addr], B*sizeof(type));
} else {
int in_addr = in_addr2 + (wi * B);
memcpy(&out_ptr[out_addr], &in_ptr[in_addr], B*sizeof(type));
}
out_addr+=B;
}
}
}
}
}
return 1;
}
OpenCL kernel from https://github.com/opencv/opencv/blob/master/modules/dnn/src/opencl/im2col.cl
__kernel void im2col(__global const float *im_src, int im_src_offset,
int channels, int height_inp, int width_inp,
int kernel_h, int kernel_w, int pad_h, int pad_w,
int stride_h, int stride_w,
int height_out, int width_out,
__global float *im_col, int im_col_offset
)
{
int index = get_global_id(0);
if (index >= height_out * width_out * channels)
return;
int j_out = index % width_out;
int i_out = (index / width_out) % height_out;
int c_inp = (index / width_out) / height_out;
int c_out = c_inp * kernel_h * kernel_w;
int i_inp = i_out * stride_h - pad_h;
int j_inp = j_out * stride_w - pad_w;
im_src += (c_inp * height_inp + i_inp) * width_inp + j_inp + im_src_offset;
im_col += (c_out * height_out + i_out) * width_out + j_out + im_col_offset;
for (int ki = 0; ki < kernel_h; ++ki)
for (int kj = 0; kj < kernel_w; ++kj) {
int i = i_inp + ki;
int j = j_inp + kj;
*im_col = (i >= 0 && j >= 0 && i < height_inp && j < width_inp) ?
im_src[ki * width_inp + kj] : 0;
im_col += height_out * width_out;
}
}
Your C version folds the batch into the lowest dimension. The opencl version isn't even using batch.
You need to pass in the batch size "B", and change this copy to a block copy (or just do a loop over) by the batch size:
for (int b=0; b<B; b++) *(im_col*B+b) = (i >= 0 && j >= 0 && i < height_inp && j < width_inp) ? im_src[(ki * width_inp + kj)*B + b] : 0;
to emulate the memcpy(..., B*sizeof(type)).
And then just stride B times more:
im_col += height_out * width_out * B;
I'm working on some code that initialises a couple of blocks of memory with random values. I will use these blocks of memory as matrices for the weights and biases in a neural net later on but that is not the point of this question.
I have two pieces off code (Code A & Code B) which does essentially the same thing, namely initialising a block of memory with random values. Both pieces of code compile just fine, however when I execute Code B I get a segmentation fault 11 error and the code stops executing. Code B works with a structure of variable member length and I believe this creates the problem. However i don't know how to fix this.
My question: Does someone know what the problem causes and how to fix it? I would really love to have Code B working since this is convenient in the code later on. I have pasted both pieces of code below. The system where I have this code tested is macOS.
Any help would be greatly appreciated!
Code A:
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#define DEBUG
/*
Function prototypes
*/
void init_rand(float *p, int size);
int main(int argc, char const *argv[])
{
int neurons [] = {10,10,10}; // use this array to define the neuralnet
int layers = sizeof(neurons)/sizeof(int); // this calculates the amount of layers in the neuralnet (i.e. the amount of members in the array 'neurons')
// array of pointers for the memory given by malloc
float *pwl[layers];
float *pbl[layers];
float *pzl[layers];
float *pal[layers];
for (int i = 1; i < layers; i++) // create memory for the matrices and assign the start adress of each matrix to the pointers
{
pwl[i] = (float *)malloc(neurons[i]*neurons[(i-1)]*sizeof(float));
pbl[i] = (float *)malloc(neurons[i]*sizeof(float));
pzl[i] = (float *)malloc(neurons[i]*sizeof(float));
pal[i] = (float *)malloc(neurons[i]*sizeof(float));
}
for (int i = 1; i < layers; i++) // initialize the weights and the biases with random values
{
init_rand(pwl[i], neurons[i]*neurons[i-1]);
init_rand(pbl[i], neurons[i]);
}
return 0;
}
/*
Random generator with a gaussian distribution. Mean = 0, Variance = 1
*/
double gaussrand()
{
static double V1, V2, S;
static int phase = 0;
double X;
if(phase == 0)
{
do
{
double U1 = (double)rand() / RAND_MAX;
double U2 = (double)rand() / RAND_MAX;
V1 = 2 * U1 - 1;
V2 = 2 * U2 - 1;
S = V1 * V1 + V2 * V2;
} while(S >= 1 || S == 0);
X = V1 * sqrt(-2 * log(S) / S);
} else
X = V2 * sqrt(-2 * log(S) / S);
phase = 1 - phase;
return X;
}
/*
This function initializes a float array with random gaussian distributed numbers
*/
void init_rand(float *p, int size)
{
for (int i = 0; i < size; i++, p++)
{
*p = (float)gaussrand();
#ifdef DEBUG
printf("%d:*p = %f\n", i, *p); //
#endif
}
}
Code B:
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#define DEBUG
struct neuralnet
{
int struct_size;
float *pwl[0];
float *pbl[0];
float *pzl[0];
float *pal[0];
};
/*
Function prototypes
*/
void init_rand(float *p, int size);
struct neuralnet* create_neuralnet(struct neuralnet* pnet, int layers);
int main(int argc, char const *argv[])
{
int neurons [] = {10,10,10}; // use this array to define the neuralnet
int layers = sizeof(neurons)/sizeof(int); // this calculates the amount of layers in the neuralnet
struct neuralnet *pnet; // create a struct neuralnet pointer
pnet = create_neuralnet(pnet, layers); // this function will create a neuralnet structure with variable size members
for (int i = 1; i < layers; i++) // create memory for the matrices and assign the start adress of each matrix to the pointers
{
pnet->pwl[i] = (float *)malloc(neurons[i]*neurons[(i-1)]*sizeof(float));
pnet->pbl[i] = (float *)malloc(neurons[i]*sizeof(float));
pnet->pzl[i] = (float *)malloc(neurons[i]*sizeof(float));
pnet->pal[i] = (float *)malloc(neurons[i]*sizeof(float));
}
for (int i = 1; i < layers; i++) // initialize the weights and the biases with random values
{
init_rand(pnet->pwl[i], neurons[i]*neurons[i-1]);
init_rand(pnet->pbl[i], neurons[i]);
}
return 0;
}
/*
Random generator with a gaussian distribution. Mean = 0, Variance = 1
*/
double gaussrand()
{
static double V1, V2, S;
static int phase = 0;
double X;
if(phase == 0)
{
do
{
double U1 = (double)rand() / RAND_MAX;
double U2 = (double)rand() / RAND_MAX;
V1 = 2 * U1 - 1;
V2 = 2 * U2 - 1;
S = V1 * V1 + V2 * V2;
} while(S >= 1 || S == 0);
X = V1 * sqrt(-2 * log(S) / S);
} else
X = V2 * sqrt(-2 * log(S) / S);
phase = 1 - phase;
return X;
}
/*
This function initializes a float array with random gaussian distributed numbers
*/
void init_rand(float *p, int size)
{
for (int i = 0; i < size; i++, p++)
{
*p = (float)gaussrand();
#ifdef DEBUG
printf("%d:*p = %f\n", i, *p); //
#endif
}
}
/*
This function creates the structure with members of variable length
*/
struct neuralnet* create_neuralnet(struct neuralnet *pnet, int layers)
{
pnet = (struct neuralnet *)malloc(sizeof(*pnet) + sizeof(float *) * layers * 4);
return pnet;
}
I am trying to compile an MPI program with mpicc. The compiler complains only that there is no reference to MPI_RECIVE and MPI_SEND, and ends the compile error. I have #include in the .c file.
Can someone tell me how I can fix this?
Here ist the Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <mpi.h>
#include "random.h"
#include "md5tool.h"
/* horizontal size of the configuration */
#define XSIZE 1024
/* "ADT" State and line of states (plus border) */
typedef char State;
typedef State Line[XSIZE + 2];
/* determine random integer between 0 and n-1 */
#define randInt(n) ((int)(nextRandomLEcuyer() * n))
/* random starting configuration */
static void initConfig(Line *buf, int lines){
int x, y;
initRandomLEcuyer(424243);
for (y = 1; y <= lines; y++) {
for (x = 1; x <= XSIZE; x++) {
buf[y][x] = randInt(100) >= 50;
}
}
}
/* annealing rule from ChoDro96 page 34
* the table is used to map the number of nonzero
* states in the neighborhood to the new state
*/
static State anneal[10] = {0, 0, 0, 0, 1, 0, 1, 1, 1, 1};
/* a: pointer to array; x,y: coordinates; result: n-th element of anneal,
where n is the number of neighbors */
#define transition(a, x, y) \
(anneal[(a)[(y)-1][(x)-1] + (a)[(y)][(x)-1] + (a)[(y)+1][(x)-1] +\
(a)[(y)-1][(x) ] + (a)[(y)][(x) ] + (a)[(y)+1][(x) ] +\
(a)[(y)-1][(x)+1] + (a)[(y)][(x)+1] + (a)[(y)+1][(x)+1]])
/* treat torus like boundary conditions */
static void boundary(Line *buf, int lines){
int x,y;
for (y = 0; y <= lines+1; y++) {
/* copy rightmost column to the buffer column 0 */
buf[y][0 ] = buf[y][XSIZE];
/* copy leftmost column to the buffer column XSIZE + 1 */
buf[y][1+1] = buf[y][1 ];
}
for (x = 0; x <= XSIZE+1; x++) {
/* copy bottommost row to buffer row 0 */
buf[0][x ] = buf[lines][x];
/* copy topmost row to buffer row lines + 1 */
buf[lines+1][x] = buf[1][x ];
}
}
/* make one simulation iteration with lines lines.
* old configuration is in from, new one is written to to.
*/
//umschreiben
/**
static void simulate(Line *from, Line *to, int lines){
boundary(from, lines);
for (y = 1; y <= lines; y++) {
for (x = 1; x <= XSIZE; x++) {
to[y][x ] = transition(from, x , y);
}
}
}
*/
/* --------------------- measurement ---------------------------------- */
int main(int argc, char** argv){
int lines, its;
int i;
Line *from, *to, *temp, *next;
char* hash;
assert(argc == 3);
lines = atoi(argv[1]);
its = atoi(argv[2]);
from = malloc((lines + 2) * sizeof(Line));
to = malloc((lines + 2) * sizeof(Line));
MPI_Init(NULL, NULL);
// Get the number of processes
int world_size;
MPI_Comm_size(MPI_COMM_WORLD, &world_size);
// Get the rank of the process
int world_rank;
MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
if(world_rank == 0){
int y;
next = malloc((lines + 2) * sizeof(Line));
initConfig(from, lines);
for (i = 0; i < its; i++) {
boundary(from, lines);
int z;
for(z = 0; z < world_size;z++){
if(z !=world_rank ){
MPI_SEND(from,(lines + 2) * sizeof(Line),MPI_CHARACTER,z,0,MPI_COMM_WORLD);
}
}
MPI_Status status;
for(z = 0; z < world_size;z++){
if(z !=world_rank ){
MPI_RECIVE(next,(lines + 2) * sizeof(Line),MPI_CHARACTER,z,1,&status);
if(status.MPI_ERROR){
//TODO
MPI_Abort(MPI_COMM_WORLD,1);
}
for (y = 1; y <= (lines%world_size+lines/world_size); y++) {
stpcpy(to[y*z],next[y*z]);
}
}
}
temp = from;
from = to;
to = temp;
}
hash = getMD5DigestStr(from[1], sizeof(Line) * (lines));
printf("hash: %s\n", hash);
free(next);
}else{
int x,y;
MPI_Status status;
for(i = 0; i < its; i++){
MPI_RECIVE(from,(lines + 2) * sizeof(Line),MPI_CHARACTER,0,0,&status);
if(status.MPI_ERROR){
MPI_Abort(MPI_COMM_WORLD,2);
}
for (y = 1; y <= (lines%world_size+lines/world_size); y++) {
for (x = 1; x <= XSIZE; x++) {
to[y*world_rank][x ] = transition(from, x , y*world_rank);
}
}
MPI_SEND(to,(lines + 2) * sizeof(Line),MPI_CHARACTER,0,1,MPI_COMM_WORLD);
}
}
MPI_Finalize();
free(from);
free(to);
free(hash);
return 0;
}
This is a C a Sequence implementation which I wrote for the university as a homework assignment.
Are you talking about MPI_Send and MPI_Recv ?
Don't know about any MPI_SEND or MPI_RECIV function...
I think you just mispelled them.
BTW: here is a great tutorial about how to use them http://mpitutorial.com/tutorials/mpi-send-and-receive/
I am interested in precisely understanding C code for R packages. But I have come across code such as RANDIN, RANDOUT, UNIF, EPS etc (are they macros?) for which I don't know where to find the implementations/definitions.
Where can I find the code (and explanations if any) for these capitalised 'expressions'?
An example is the VR_onlineSOM function inside the 'class' R package. This function has the following code written in C:
void
VR_onlineSOM(double *data, double *codes, double *nhbrdist,
double *alpha, double *radii,
Sint *pn, Sint *pp, Sint *pncodes, Sint *rlen)
{
int n = *pn, p = *pp, ncodes = *pncodes;
int i, j, k, nearest = 0 /* -Wall */, nind;
double dm, dist, tmp;
unsigned int cd; /* avoid spurious warning from gcc pre-4.3.0 */
RANDIN;
for (k = 0; k < *rlen; k++) {
/* pick a random data point */
i = (int)(n * UNIF);
/* find the nearest code 'near' */
nind = 0; dm = DOUBLE_XMAX;
for (cd = 0; cd < ncodes; cd++) {
dist = 0.0;
for (j = 0; j < p; j++) {
tmp = data[i + j*n] - codes[cd + j*ncodes];
dist += tmp * tmp;
}
if (dist <= dm * (1 + EPS)) {
if (dist < dm * (1 - EPS)) {
nind = 0;
nearest = cd;
} else {
if(++nind * UNIF < 1.0) nearest = cd;
}
dm = dist;
}
/* update all codes within radii[k] of 'nearest' */
for (cd = 0; cd < ncodes; cd++) {
if(nhbrdist[cd + ncodes*nearest] > radii[k]) continue;
for(j = 0; j < p; j++)
codes[cd + j*ncodes] += alpha[k] *
(data[i + j*n] - codes[cd + j*ncodes]);
}
}
}
RANDOUT;
}
Yes they are some macros and constantes defined in the begining of the class.c.
#define EPS 1e-4 /* relative test of equality of distances */
#define RANDIN GetRNGstate()
#define RANDOUT PutRNGstate()
#define UNIF unif_rand()