Wrong array dimension between CINT and execution

Dear co-rooters,

I am facing this rather bizarre issue… I have the following code

#include <iostream>
#include <fstream>
#include <vector>
#include "TString.h"

using namespace std;

// Inputs :  	-name   = name of the ascii file to be read - two column file with x and y values, rescpectively assumed
//		-X_USER = array that contains the user defined energy binning
//		-output = if output = TRUE  exports the interpolation array
//			  if output = FALSE exports the index of the input values used in the interpolation
int linear_Interpolation(TString name, float* X_USER, float* Y_USER, int* index){
	float	x, y;
	
	// (1) Open the file to count its lines
	ifstream myfile;
	myfile.open(name);
  	if(!myfile){
		cout << "File not found" << endl;
  	}
  	int size_EVAL = 0;
  	while(1){
  		myfile >> x >> y;
  		if (!myfile.good()) break;
		size_EVAL++;
	}
	myfile.close();
	// (2) Re-open the file to store the information
	myfile.open(name);
	float X_EVAL[size_EVAL], Y_EVAL[size_EVAL];
	x = 0; y = 0;
	int i=0;
  	while(1){
		myfile >> x >> y;
		if (!myfile.good()) break;
		X_EVAL[i]    = x;
		Y_EVAL[i] = y;
		i++;
	}
    	myfile.close();
    	
    	// (3) Do the interpolation
	int   size_USER = (int) sizeof(X_USER)/sizeof(X_USER[0]);
	cout << "The USER size is : " << sizeof(X_USER) << endl;
	cout << "The USER size is : " << sizeof(X_USER[0]) << endl;
	//cout << "The USER size is : " << size_USER << endl;
	//float Y_USER[size_USER];
	//int   index[size_USER];
	float x1, x2,y1, y2, a, b;
	bool boo;
	x2=0.;
	y2=0.;
	a=0.;
	b=0.;
    	for(i=0; i<=size_USER; ++i){
		boo = true;
		for (int j=0; j<=size_EVAL; j++){
			if (boo==true){
				if(X_USER[i] == X_EVAL[j]){
					Y_USER[i] = Y_EVAL[j];
					index[i]= j;
					boo = false;
				}
				else if(X_USER[i]>X_EVAL[j]){
					x1 = X_EVAL[j];
					y1 = Y_EVAL[j];
				}
				else if( X_USER[i]<X_EVAL[j] && boo == true ){
					x2 = X_EVAL[j];
					y2 = Y_EVAL[j];
					a = (y2-y1)/(x2-x1);
					b = y2-a*x2;
					Y_USER[i] = a*X_USER[i]+b;
					index[i] = j;
					boo = false;
				}
			}
		}//end of loop over EVAL
	}//end of loop over USER
	
	//for(i=0; i<=size_USER; ++i){
	//	cout << Y_USER[i] << "\t" << index[i] << endl;
	//}
	  	
	return 0;
	
}

I compile and load it using

root [38] .L linear_interpolation.cc++

While in CINT, I define the following arrays (in order to check that the code is working properly)

root [35] float a[10] = {0.5, 0.6, 0.7, 0.8, 0.9, 1., 2., 3., 4., 5}; float y[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; int ind[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}

Then I do the following check about the array a[10]

root [36] sizeof(a)
(const int)40
root [37] sizeof(a[0])
(const int)4

However when parsing array a[10] in the code by running
root [39] linear_Interpolation("ENDF_B-VII_1.dat", a, y, ind)

the output about the size of a[10] seems to be different than the one from CINT

The USER size is : 8
The USER size is : 4

Any idea on why this is happening?

P.S.: A sample file can be found here

Hi,

do you observe the same behaviour with ROOT6?

Cheers,
D

if I am not mistaken, it boils down to the difference between:

float a[10];
float *p;

sizeof(a); // == 10 * sizeof(float)     ==> 40 on your machine
sizeof(p); // ==  1 * sizeof(uintptr_t) ==>  8 on your machine

(inside the linear_Interpolation function, the a array of 10 floats has decayed to a pointer to the first element of an array of floats. not the same thing.)

I am running root 5.32/64 on lxplus, so I haven’t tried it, on ROOT6.
Do you think it will be different?

I initially thought about that.
So I tried changing the function to

int linear_Interpolation(TString name, float X_USER[], float Y_USER[], int index[]){

but I get exactly the same output

root [3] linear_Interpolation("ENDF_B-VII_1.dat", a, y, ind)
The USER size is : 8
The USER size is : 4

I also wanted to check if it’s related to CINT so I tried this

#include "linear_interpolation.cc"

int test(){

	float a[10] = {0.5, 0.6, 0.7, 0.8, 0.9, 1., 2., 3., 4., 5};
	float y[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 
	int ind[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
	
	cout << "The size of a is " << sizeof(a) << endl;
	
	linear_Interpolation("ENDF_B-VII_1.dat", a, y, ind);

}

where linear_interpolation.cc is

//#include "/afs/cern.ch/user/a/astamato/public/lib_thanos/c_header.h"
//#include "/afs/cern.ch/user/a/astamato/public/lib_thanos/root_header.h"

#include <iostream>
#include <fstream>
#include <vector>
#include "TString.h"

using namespace std;

// Inputs :  	-name   = name of the ascii file to be read - two column file with x and y values, rescpectively assumed
//		-X_USER = array that contains the user defined energy binning
//		-output = if output = TRUE  exports the interpolation array
//			  if output = FALSE exports the index of the input values used in the interpolation
int linear_Interpolation(TString name, float X_USER[], float Y_USER[], int index[]){
	float	x, y;
	
	// (1) Open the file to count its lines
	ifstream myfile;
	myfile.open(name);
  	if(!myfile){
		cout << "File not found" << endl;
  	}
  	int size_EVAL = 0;
  	while(1){
  		myfile >> x >> y;
  		if (!myfile.good()) break;
		size_EVAL++;
	}
	myfile.close();
	// (2) Re-open the file to store the information
	myfile.open(name);
	float X_EVAL[size_EVAL], Y_EVAL[size_EVAL];
	x = 0; y = 0;
	int i=0;
  	while(1){
		myfile >> x >> y;
		if (!myfile.good()) break;
		X_EVAL[i]    = x;
		Y_EVAL[i] = y;
		i++;
	}
    	myfile.close();
    	
    	// (3) Do the interpolation
	int   size_USER = (int) sizeof(X_USER)/sizeof(X_USER[0]);
	cout << "The USER size is : " << sizeof(X_USER) << endl;
	cout << "The USER size is : " << sizeof(X_USER[0]) << endl;
	//cout << "The USER size is : " << size_USER << endl;
	//float Y_USER[size_USER];
	//int   index[size_USER];
	float x1, x2,y1, y2, a, b;
	bool boo;
	x2=0.;
	y2=0.;
	a=0.;
	b=0.;
    	for(i=0; i<=size_USER; ++i){
		boo = true;
		for (int j=0; j<=size_EVAL; j++){
			if (boo==true){
				if(X_USER[i] == X_EVAL[j]){
					Y_USER[i] = Y_EVAL[j];
					index[i]= j;
					boo = false;
				}
				else if(X_USER[i]>X_EVAL[j]){
					x1 = X_EVAL[j];
					y1 = Y_EVAL[j];
				}
				else if( X_USER[i]<X_EVAL[j] && boo == true ){
					x2 = X_EVAL[j];
					y2 = Y_EVAL[j];
					a = (y2-y1)/(x2-x1);
					b = y2-a*x2;
					Y_USER[i] = a*X_USER[i]+b;
					index[i] = j;
					boo = false;
				}
			}
		}//end of loop over EVAL
	}//end of loop over USER
	
	//for(i=0; i<=size_USER; ++i){
	//	cout << Y_USER[i] << "\t" << index[i] << endl;
	//}
	  	
	return 0;
	
}	

And the result is

root [7] test()
The size of a is 40
The USER size is : 8
The USER size is : 4
(int)0

So something weird is going on… Any idea?

Inside of your function, sizeof(X_USER) == sizeof(float*) and sizeof(X_USER[0]) == sizeof(float).

Hmmm…

I can understand about sizeof(X_USER[0]) == sizeof(float), but I would expect that sizeof(X_USER) == sizeof(X_USER[])

So here what I am trying to do, is assign the dimension of the input array to a variable, in order to loop over it and do the required calculations.

Any idea on how to do that?

You need to add another parameter to your function, which will provide the length of the array.
Or, instead of a C array, try a std::vector or another C++ sequence container (passed by reference).

I wanted to avoid passing as an argument…
about the other option you are right…
The thing is that this question is related to Using SMatrix for large matrices and I am not sure what is the most effective way of calling the linear_interpolation.cc since I will have to handle big arrays and matrices.

Hi,

I would not use ROOT5 if using ROOT6 is possible, in general. Central installations of each ROOT release are provided and can be used from lxplus (and anywhere where cvmfs is available).
See for example: https://root.cern.ch/content/release-61204

Cheers,
D

I tried root 6 on lxplus, but still I get the same…

Hi,

it seems your code is buggy. I was just trying to say that using ROOT5 these days means ignoring 4 years of developments and the usage of a real compiler to interpret our code.

Cheers,
D

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.