LCSL / GURLS

GURLS: a Least Squares Library for Supervised Learning
http://lcsl.mit.edu/#/downloads/gurls
63 stars 37 forks source link

Issue with gvec<T>::subvec(unsigned int len, unsigned int start=0) const; #13

Closed raffaello-camoriano closed 10 years ago

raffaello-camoriano commented 10 years ago

I have experienced problems at compile time with method gvec::subvec(unsigned int len, unsigned int start=0) const.

Here is a dummy program I have prepared for illustrating the issue. Its goal is to initialize matrices N and P starting from 100 x 100 matrix M, such that, in MATLAB syntax, P = M(1:100,51:100).

#include <iostream>
#include <string>

#include "gurls++/gvec.h"
#include "gurls++/gmat2d.h"

using namespace gurls;
using namespace std;
typedef double T;

int main()
{
    gMat2D<T> M(gMat2D<T>::zeros(100,100));
    gMat2D<T> P(gMat2D<T>::zeros(100,50));

    // Initialize P
    gVec<T> tmpCol(100);
    gVec<T> tmpCol1(50);
    for ( int i = 0 ; i < 50 ; ++i )
    {
        tmpCol = M(50 + i);
        tmpCol1 = tmpCol.subvec( (unsigned int) 50 ,  (unsigned int) 0 );
        P.setColumn(  tmpCol1 , (long unsigned int) i);
    }
    cout << "P initialized: " << P << endl;
}

The compiling error is the following:

[100%] Building CXX object gurls++/demo/CMakeFiles/subvecTest.dir/subvecTest.cpp.o
In file included from /home/kammo/Repos/gurlssandbox/gurls++/include/gurls++/gvec.h:333:0,
                 from /home/kammo/Repos/gurlssandbox/gurls++/demo/subvecTest.cpp:4:
/home/kammo/Repos/gurlssandbox/gurls++/include/gurls++/gvec.hpp: In instantiation of ‘gurls::gVec<T> gurls::gVec<T>::subvec(unsigned int, unsigned int) const [with T = double]’:
/home/kammo/Repos/gurlssandbox/gurls++/demo/subvecTest.cpp:36:72:   required from here
/home/kammo/Repos/gurlssandbox/gurls++/include/gurls++/gvec.hpp:145:25: error: expression cannot be used as a function
     v.set(&(this->data()[start]), len);
                         ^
make[2]: *** [gurls++/demo/CMakeFiles/subvecTest.dir/subvecTest.cpp.o] Error 1
make[1]: *** [gurls++/demo/CMakeFiles/subvecTest.dir/all] Error 2
make: *** [all] Error 2
*** Failure: Exit code 2 ***

At the moment I am using the following workaround based on the setColumn method to overcome the problem, but it's quite verbose and probably inefficient in large-scale.

#include <iostream>
#include <string>

#include "gurls++/gvec.h"
#include "gurls++/gmat2d.h"

using namespace gurls;
using namespace std;
typedef double T;

int main()
{
    gMat2D<T> M(gMat2D<T>::zeros(10,10)+1);
    cout << "M initialized: " <<endl<< M << endl;

    gMat2D<T> P(gMat2D<T>::zeros(10,5));

    // Initialize P
    gVec<T> tmpCol(10);
    for ( int i = 0 ; i < 5 ; ++i )
    {
        tmpCol = M(5 + i);
        gVec<T> locs(10);
        for (int j = 0 ; j < 10 ; ++j)
            locs[j] = j;
        gVec<T>& tmpCol2 = tmpCol.copyLocations(locs);
        P.setColumn(  tmpCol2 , (long unsigned int) i);
    }
    cout << "P initialized: " <<endl<< P << endl;    
}
andreaschiappacasse commented 10 years ago

I could replicate your problem. It seems that the method "subvec" tried to use a non existent method data(). In the latest commit the issue is fixed. Please care that in your first demo program, the size of P (100, 50), is not consistent with the size (50) of the columns you are trying to set. After changing the number of rows of P to 50 I get the expected output.

Andrea

raffaello-camoriano commented 10 years ago

I have modified my test program as follows, thanks for reporting that:

#include <iostream>
#include <string>

#include "gurls++/gvec.h"
#include "gurls++/gmat2d.h"

using namespace gurls;
using namespace std;
typedef double T;

int main()
{
    gMat2D<T> M(gMat2D<T>::zeros(10,10) + 1);
    cout << "M initialized: " << endl  << M << endl;

    gMat2D<T> P(gMat2D<T>::zeros(5,5));
    cout << "P initialized: " << endl  << P << endl;

    // Initialize P
    gVec<T> tmpCol(10);
    gVec<T> tmpCol1(5);
    for ( int i = 0 ; i < 5 ; ++i )
    {
        tmpCol = M(5 + i);
        tmpCol1 = tmpCol.subvec( (unsigned int) 5 ,  (unsigned int) 0 );
        P.setColumn(  tmpCol1 , (long unsigned int) i);
    }
    cout << "Modified P: " << endl  << P << endl;
}

After pulling your latest changes, the project compiles and the result is correct.

kammo@kammo-Latitude-E5540:~/Repos/gurlssandbox/build/bin$ ./subVecTest2 
M initialized: 
[ 1 1 1 1 1 1 1 1 1 1
  1 1 1 1 1 1 1 1 1 1
  1 1 1 1 1 1 1 1 1 1
  1 1 1 1 1 1 1 1 1 1
  1 1 1 1 1 1 1 1 1 1
  1 1 1 1 1 1 1 1 1 1
  1 1 1 1 1 1 1 1 1 1
  1 1 1 1 1 1 1 1 1 1
  1 1 1 1 1 1 1 1 1 1
  1 1 1 1 1 1 1 1 1 1 ]

P initialized: 
[ 0 0 0 0 0
  0 0 0 0 0
  0 0 0 0 0
  0 0 0 0 0
  0 0 0 0 0 ]

Modified P: 
[ 1 1 1 1 1
  1 1 1 1 1
  1 1 1 1 1
  1 1 1 1 1
  1 1 1 1 1 ]

Thanks a lot.