Workaround for TMath::Max( RVec<double> , RVec<double> )

Dear experts,
We use RVec operations in our analysis and we let the JIT to interpret
Scalar (*,-,+,/) Vector operations or Vector to Vector
Everything works very nicely, however we have not been able to get a JITTED code working fine for

TMath::Max( Scalar * Vector , Scalar * Vector) 

columns .
I wonder if there is any inline thing we can declare to get this working fine or we should decouple the 2 elements in the comparison expression ad replace this with a set of 2Defines and one operator() which does a new RVec with the indexes.
I know this is not “general” enough as one can say the Vector columns are not equal sized, but in our analysis this is the case.
Any suggestion is welcome.

Renato


Please read tips for efficient and successful posting and posting code

_ROOT Version:_6.18
Platform: Not Provided
Compiler: Not Provided


Ideally i would be interested to understand as well, if i can declare actually a custom namespace with some inlined functions which can be jitted , that would be awesome, but i fail to understand what to add to LinkDef and how to actually declare that function (in case), something like this for example :

namespace TMath{ 
    inline ROOT::VecOps::RVec<double> Max( ROOT::VecOps::RVec<double> & a, ROOT::VecOps::RVec<double> & b ){
        ROOT::VecOps::RVec<double> vecOut; 
        for( int i = 0 ; i < a.size() ; ++i){
            if( a.at(i) > b.at(i)) vecOut.push_back( a.at(i));
            else vecOut.push_back( b.at(i));
        }
        return vecOut;
    };
    inline ROOT::VecOps::RVec<float> Max( ROOT::VecOps::RVec<float> & a, ROOT::VecOps::RVec<float> & b ){
        ROOT::VecOps::RVec<float> vecOut; 
        for( int i = 0 ; i < a.size() ; ++i){
            if( a.at(i) > b.at(i)) vecOut.push_back( a.at(i));
            else vecOut.push_back( b.at(i));
        }
        return vecOut;
    };
};

I tried to overload the TMath::Max with ROOT::VecOps return and arguments with no success ( maybe i am doing it wrong) .
I saw that

max( vector<double> , vector<double>) 

works as i expect on the ROOT prompt, however

max( RVec<double>, RVec<double> ) 

doesn’t.
…
Any help is very welcome.
Renato

Hi,
TMath::Max is only defined for scalars.
You can add an overload for RVecs, it should be enough to pass the code you mentioned to gInterpreter->Declare, although adding things to another library’s namespace is usually considered “unsafe” (as that library might then also define the same thing, creating conflicts. but ROOT will likely never define RVec-oriented overloads of TMath stuff).

max(vector<double>, vector<double>) is not a vectorized version of max: it returns either the first or the second vector depending on the value of vec1 < vec2 (which I’m surprised it’s defined).

Cheers,
Enrico

Thanks @eguiraud , so if i have a CMake project, it would be enough to add in my executable which i compile
gInterpreter->Declare("… c++ code for the function") ?
Cheers
Renato

That should be the case, I suggest you test this in a toy program first.

I am testing


        gInterpreter->Declare("ROOT::VecOps::RVec<double> MAXV( ROOT::VecOps::RVec<double> & a, ROOT::VecOps::RVec<double> & b ){ "
                            "     ROOT::VecOps::RVec<double> vecOut;                                                            "
                            "     for( int i = 0 ; i < a.size() ; ++i){                                                         "
                            "         if( a.at(i) > b.at(i)) vecOut.push_back( a.at(i));                                        "
                            "         else vecOut.push_back( b.at(i));                                                          "
                            "     }                                                                                             "
                            "     return vecOut;                                                                                "
                            "};");

is added in my code , when the Define using MAXV is called

input_line_180:13:57: error: no matching function for call to 'MAXV'
return RndPoisson2*(wiPIDCalib_Weight_BS*wTRKCalib_BS*((MAXV(E1_wfL0L_comb_Bp_effCL_BS*(E1_L0Calo_ECAL_realET>3000.000000),E2_wfL0L_comb_Bp_effCL_BS*(E2_L0Calo_ECAL_realET>3000.000000)))/(MAXV(E1_wfL0L_comb_Bp_effMC_BS*(E1...
                                                        ^~~~
input_line_105:1:28: note: candidate function not viable: expects an l-value for 1st argument
ROOT::VecOps::RVec<double> MAXV( ROOT::VecOps::RVec<double> & a, ROOT::VecOps::RVec<double> & b ){      ROOT::VecOps::RVec<double> vecOut;                                                                 for( int i = 0 ; i ...
                           ^

I wanted to pass references to avoid copying vectors…Will try defining the function without &

You need a const RVec<double>& to be able to pass r-values.

1 Like

Thanks again, this solved my issue :

    gInterpreter->Declare("ROOT::VecOps::RVec<double> MAXV( const ROOT::VecOps::RVec<double>  &a, const ROOT::VecOps::RVec<double>  & b ){     "
                            "     ROOT::VecOps::RVec<double> vecOut(a.size());                                                  "
                            "     for( int i = 0 ; i < a.size() ; ++i){                                                         "
                            "         vecOut[i] = a[i]>b[i] ? a[i] : b[i];                                                      "
                            "     }                                                                                             "
                            "     return vecOut;                                                                                "
                            "};");

adding this to the start of my main() executable solves the problem and the MAXV can be interpreted.
Renato

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