I am attempting to use some code in root (through typing ‘.L RCARRY.cpp’ in the root interpreter) that has been working fine with g++. I can load, but when I try to instantiate my class
RCARRY *rc = new RCARRY
CINT doesn’t like my use of vectors. The error
The vectors in this class were initially defined like this:
vector xn;
I saw a post on this forum where someone was instructed to do it formally using pointer syntax.
vector *xn=new vector
So I tried it, then CINT told me to use xn->assign(num1,num2) instead of xn.assign(num1,num2). OK, did that. Now back to original error message.
This also happens directly in the interpreter:
What does CINT want from me? It’s a scoping problem? It works with g++.
But root tells me (rightly, it’s included in RCARRY.h) that vector is already included. I did some more messing around, and manually loaded the vector using xn.pushy_back(0) in a loop, instead of xn.assign(num1,num2). Root accepted this, but then throws a bus error later. the vector xn has size==24, and it acts mainly as a fifo, but needs to be a vector (or something like it) because I need random access as well. So root throws this bus error after the first 24 numbers get pushed through the fifo, which means that my push and pop routine is now broken (it uses an xn.erase(iterator) then an xn.push_back(newNumber) to move the fifo along). Besides, the interpreter version of using std::vector->assign(num1,num2) should work if the vector class is not broken in terms of CINT being able to deal with it. There must be something particular to root that I don’t know about.
OK, so I tried including vector before loading my class, still doesn’t work. Maybe I should build root from scratch? That seems to fix weird problems with binary software distributions sometimes.
/*
* RCARRY.h
* RCARRY
*
*
*/
#include <iostream>
#include <cstdlib>
#include <math.h>
#include <time.h>
#include <vector>
using namespace std;
class RCARRY
{
public:
RCARRY(int seed, int luxury); // use a specified seed and luxury
RCARRY::RCARRY(int luxury); // use time(0) for seed, and specified luxury
// 0: skip 0
// 1: skip 48
// 2: skip 97
// 3: skip 223
// 4: skip 389
RCARRY(); // use time(0) for seed and luxury level 3
// (223 steps skiped every 24 numbers)
int randRC(); // return the 'random' number, from 0 to 2^24-1
int randRC(int a, int b); // return an int in [a,b]
float randRCf(); // return float from (0,1)
double randRCd(); // return double from (0,1)
// --NOTE: division of the int
// by B-1(=2^24-1) should give
// a float without losing any information
// but a double probably does lose
// information. Advice: use randRCf().
double randRCn(); // retrun normal(0,1)
double randRCn(double sigma); // retrun normal(0,sigma)
// where width is sigma,
// P(x)=exp(-x^2/sigma^2)
void seedRC(int seed); // reseed the generator with arg: seed.
int randRC_MAX(); // return max value of randRC()
void luxury(int l); // redefine luxury value
private:
void InitGlobal();
void seedRC();
vector <int> xn;
vector <int> cn;
int B,s,r;
int mySeed, myLuxury, nEnd;
int skip,randNumsInBatch;
int randRC_l_is_not_zero();
int randRC_l_is_zero();
int (RCARRY::*randRCpointer)();
};
The class deff:
/*
*
* RCARRY
*
*
*/
#include "RCARRY.h"
using namespace std;
/*********************************************************************/
/* */
/* RCARRY */
/* */
/*********************************************************************/
/*********************************************************************/
/* */
/* Public functions: */
/* */
/*********************************************************************/
RCARRY::RCARRY(int seed, int lux)
{
InitGlobal();
luxury(lux);
mySeed = seed;
seedRC();
}
RCARRY::RCARRY(int lux) // seed from time(0)
{
InitGlobal();
mySeed=time(0);
luxury(lux);
seedRC();
randNumsInBatch=0;
}
RCARRY::RCARRY() // seed from time(0), luxury = level3 (skip 223)
{
luxury(3);
InitGlobal();
mySeed=time(0);
seedRC();
}
void RCARRY::seedRC(int seed)
{
mySeed=seed;
seedRC();
}
int RCARRY::randRC()
{
return ((this->*randRCpointer)());
}
int RCARRY::randRC(int a, int b)
{
return (randRC()%(b+1)+a);
}
float RCARRY::randRCf()
{
int x;
float y;
x=randRC();
y=((float)x/((float)(B-1)));
return y;
}
double RCARRY::randRCd()
{
int x;
double y;
x=randRC();
y=((double)x/((double)(B-1)));
return y;
}
double RCARRY::randRCn()
{
double r1,r2;
r1=randRCd();
r2=randRCd();
return sqrt(-2*log(r2))*cos(2*M_PI*r1);
}
double RCARRY::randRCn(double sigma)
{
double r1,r2;
r1=randRCd();
r2=randRCd();
return sigma*sqrt(-2*log(r2))*cos(2*M_PI*r1);
}
int RCARRY::randRC_MAX()
{
return (B-1);
}
void RCARRY::luxury(int l)
{
myLuxury=l;
switch (myLuxury)
{
case 0:
skip=0;
randRCpointer=&RCARRY::randRC_l_is_zero; // don't waste
// checking if
// we need to skip
// when we are not
// skipping...
break;
case 1:
skip=48;
randRCpointer=&RCARRY::randRC_l_is_not_zero;
break;
case 2:
skip=97;
randRCpointer=&RCARRY::randRC_l_is_not_zero;
break;
case 3:
skip=223;
randRCpointer=&RCARRY::randRC_l_is_not_zero;
break;
case 4:
skip=389;
randRCpointer=&RCARRY::randRC_l_is_not_zero;
break;
default :
cout<<"bad luxury value\n";
exit(1);
}
}
/*********************************************************************/
/* */
/* Private functions: */
/* */
/*********************************************************************/
void RCARRY::InitGlobal()
{
B=16777216;// 2^24
s=10;
r=24;
xn.assign(24,0);
cn.assign(24,0);
nEnd=xn.size()-1;
randNumsInBatch=0;
}
// seed the vectors xn (INT) and cn (1,0) with 'random' values from system rand();
void RCARRY::seedRC()
{
srand(mySeed);
for (int i = 0;i<xn.size();i++)
{
xn[i]=(int)((double)rand()/((double)RAND_MAX)*(double)(B-1)); // seed xn from math.h::rand();
if ( ((double)rand())/((double)RAND_MAX)<0.5)
cn[i]=0;
else
cn[i]=1;
}
}
int RCARRY::randRC_l_is_zero()
{
vector < int>::iterator xnIter=xn.begin();
vector <int>::iterator cnIter=cn.begin();
int y;
y=xn[nEnd-s]-xn[0]-cn[nEnd];
if(y>=0)
{
xn.erase(xnIter);
xn.push_back(y);
cn.erase(cnIter);
cn.push_back(0);
}
else
{
xn.erase(xnIter);
xn.push_back(y+B);
cn.erase(cnIter);
cn.push_back(1);
}
randNumsInBatch++;
return (xn[nEnd]);
}
int RCARRY::randRC_l_is_not_zero()
{
vector < int>::iterator xnIter=xn.begin();
vector <int>::iterator cnIter=cn.begin();
int y;
// if batch isn't up to 24, return the next xn in sequence.
if (randNumsInBatch<24)
{
y=xn[nEnd-s]-xn[0]-cn[nEnd];
if(y>=0)
{
xn.erase(xnIter);
xn.push_back(y);
cn.erase(cnIter);
cn.push_back(0);
}
else
{
xn.erase(xnIter);
xn.push_back(y+B);
cn.erase(cnIter);
cn.push_back(1);
}
randNumsInBatch++;
}
else // skip over the next number defined by luxury
{
randNumsInBatch=0;
for(int i=0;i<skip;i++)
{
randNumsInBatch=0;
randRC();
}
}
return (xn[nEnd]);
}
It’s just the unmodified source I use to build a dylib (or an .so in linux speak). Works in g++, no warnings or errors.
We are not yet generating the dictionary for ‘assign’.
Using the following code:[code]void assign(std::vector &vec,int len,int what)
{
vec.erase(vec.begin(),vec.end());
for(int i=0; i<len; ++i) {
vec.push_back(0);
}
}
void RCARRY::InitGlobal()
{
B=16777216;// 2^24
s=10;
r=24;
assign(xn,24,0);
assign(cn,24,0);
nEnd=xn.size()-1;
randNumsInBatch=0;
}[/code]seems to work for me (aka the loading and the execution of c = new RCARRY complete sucessfully).
Alternatively, you can simply compile your code using ACLiC:root [] .L RCARRY.C+