Dismiss Notice
Join Physics Forums Today!
The friendliest, high quality science and math community on the planet! Everyone who loves science is here!

Cannot use simplest ifstream with LAPACK

  1. Jun 6, 2015 #1
    I have an official LAPACK example from here:

    https://software.intel.com/sites/pr.../mkl_sa/11/mkl_lapack_examples/dsyev_ex.c.htm

    It compiles and runs without errors or warnings after using

    ludi@ludi-M17xR4:~/Desktop/tests$ gcc -Ddsyev=dsyev_ -o sylapack sylapack.c -L/usr/local/lib -llapack -lblas && ./sylapack​

    Then, I have a very simple programme using ifstream for reading from a file into a vector. It, too, compiles flawlessly using

    ludi@ludi-M17xR4:~/Desktop/tests$ g++ -Wall -pedantic -o justread.x justread.cc && ./justread.x

    Here is the latter programme:
    #include <fstream>
    #include <vector>


    int read_covariance ()
    {
    std::vector<double> data;
    double tmp;

    std::ifstream fin("peano_covariance.data");

    while(fin >> tmp)
    {
    data.push_back(tmp);
    }

    return 0;
    }

    int main()
    {
    read_covariance();
    return 0;
    }​

    I just want to use read_covariance() from the small programme within the first programme. To that end I just modify the start of the LAPACK example, adding the function I want to use. Explicitly, I moddify just the start of the example to

    #include <stdlib.h>
    #include <stdio.h>
    #include <fstream>
    #include <vector>

    int read_covariance ()
    {
    std::vector<double> data;
    double tmp;

    std::ifstream fin("peano_covariance.data");

    while(fin >> tmp)
    {
    data.push_back(tmp);
    }

    return 0;
    }


    /* DSYEV prototype */
    extern void dsyev( char* jobz, char* uplo, int* n, double* a, int* lda,
    double* w, double* work, int* lwork, int* info );
    /* Auxiliary routines prototypes */
    extern void print_matrix( char* desc, int m, int n, double* a, int lda );

    /* Parameters */​

    Leaving it otherwise unmodified. I added some unmodified lines to make clear where I am. I immediately get a ton of errors:

    ludi@ludi-M17xR4:~/Desktop/tests$ gcc -Ddgeev=dgeev_ -o combo combo.cc -L/usr/local/lib -llapack -lblas && ./combo
    combo.cc: In function ‘int main()’:
    combo.cc:107:74: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
    dsyev( "Vectors", "Upper", &n, a, &lda, w, &wkopt, &lwork, &info );
    ^
    combo.cc:107:74: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
    combo.cc:111:72: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
    dsyev( "Vectors", "Upper", &n, a, &lda, w, work, &lwork, &info );
    ^
    combo.cc:111:72: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
    combo.cc:118:49: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
    print_matrix( "Eigenvalues", 1, n, w, 1 );
    ^
    combo.cc:120:72: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
    print_matrix( "Eigenvectors (stored columnwise)", n, n, a, lda );
    ^
    /tmp/ccZrNqc0.o: In function `read_covariance()':
    combo.cc:(.text+0x3f): undefined reference to `std::basic_ifstream<char, std::char_traits<char> >::basic_ifstream(char const*, std::_Ios_Openmode)'
    combo.cc:(.text+0x73): undefined reference to `std::istream::eek:perator>>(double&)'
    combo.cc:(.text+0x88): undefined reference to `std::basic_ios<char, std::char_traits<char> >::eek:perator void*() const'
    combo.cc:(.text+0xa6): undefined reference to `std::basic_ifstream<char, std::char_traits<char> >::~basic_ifstream()'
    combo.cc:(.text+0xda): undefined reference to `std::basic_ifstream<char, std::char_traits<char> >::~basic_ifstream()'
    /tmp/ccZrNqc0.o: In function `main':
    combo.cc:(.text+0x1af): undefined reference to `dsyev(char*, char*, int*, double*, int*, double*, double*, int*, int*)'
    combo.cc:(.text+0x236): undefined reference to `dsyev(char*, char*, int*, double*, int*, double*, double*, int*, int*)'
    /tmp/ccZrNqc0.o: In function `std::vector<double, std::allocator<double> >::_M_insert_aux(__gnu_cxx::__normal_iterator<double*, std::vector<double, std::allocator<double> > >, double const&)':
    combo.cc:(.text._ZNSt6vectorIdSaIdEE13_M_insert_auxEN9__gnu_cxx17__normal_iteratorIPdS1_EERKd[_ZNSt6vectorIdSaIdEE13_M_insert_auxEN9__gnu_cxx17__normal_iteratorIPdS1_EERKd]+0x263): undefined reference to `__cxa_end_catch'
    combo.cc:(.text._ZNSt6vectorIdSaIdEE13_M_insert_auxEN9__gnu_cxx17__normal_iteratorIPdS1_EERKd[_ZNSt6vectorIdSaIdEE13_M_insert_auxEN9__gnu_cxx17__normal_iteratorIPdS1_EERKd]+0x276): undefined reference to `__cxa_begin_catch'
    combo.cc:(.text._ZNSt6vectorIdSaIdEE13_M_insert_auxEN9__gnu_cxx17__normal_iteratorIPdS1_EERKd[_ZNSt6vectorIdSaIdEE13_M_insert_auxEN9__gnu_cxx17__normal_iteratorIPdS1_EERKd]+0x2df): undefined reference to `__cxa_rethrow'
    /tmp/ccZrNqc0.o: In function `std::vector<double, std::allocator<double> >::_M_check_len(unsigned long, char const*) const':
    combo.cc:(.text._ZNKSt6vectorIdSaIdEE12_M_check_lenEmPKc[_ZNKSt6vectorIdSaIdEE12_M_check_lenEmPKc]+0x4c): undefined reference to `std::__throw_length_error(char const*)'
    /tmp/ccZrNqc0.o: In function `__gnu_cxx::new_allocator<double>::deallocate(double*, unsigned long)':
    combo.cc:(.text._ZN9__gnu_cxx13new_allocatorIdE10deallocateEPdm[_ZN9__gnu_cxx13new_allocatorIdE10deallocateEPdm]+0x1c): undefined reference to `operator delete(void*)'
    /tmp/ccZrNqc0.o: In function `__gnu_cxx::new_allocator<double>::allocate(unsigned long, void const*)':
    combo.cc:(.text._ZN9__gnu_cxx13new_allocatorIdE8allocateEmPKv[_ZN9__gnu_cxx13new_allocatorIdE8allocateEmPKv]+0x2c): undefined reference to `std::__throw_bad_alloc()'
    combo.cc:(.text._ZN9__gnu_cxx13new_allocatorIdE8allocateEmPKv[_ZN9__gnu_cxx13new_allocatorIdE8allocateEmPKv]+0x3c): undefined reference to `operator new(unsigned long)'
    /tmp/ccZrNqc0.o:(.eh_frame+0x4b): undefined reference to `__gxx_personality_v0'
    collect2: error: ld returned 1 exit status
    ludi@ludi-M17xR4:~/Desktop/tests$

    Can anyone offer guidance??
     
    Last edited: Jun 6, 2015
  2. jcsd
  3. Jun 6, 2015 #2

    D H

    User Avatar
    Staff Emeritus
    Science Advisor

    Emphasis mine:
    That you are compiling and linking with gcc (rather than g++) explains a large number of your errors. The problem is that gcc doesn't know to use the standard library. g++ does. So use g++. After all, you are writing c++, not c.

    The remaining warnings will be just that, warnings. The C wrapper to the fortran function dsyev is ancient. Strictly speaking, it's illegal to pass something like "Vector" as a char*. The compiler is warning you about that.
     
  4. Jun 6, 2015 #3
    Thank you so much!! What you say is so logical and resolves many errors. But there are still some errors left:

    ludi@ludi-M17xR4:~/Desktop/tests$ g++ -Ddsyev=dsyev_ -o combo.x combo.cc -L/usr/local/lib -llapack -lblas && ./combo.x
    combo.cc: In function ‘int main()’:
    combo.cc:107:74: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
    dsyev( "Vectors", "Upper", &n, a, &lda, w, &wkopt, &lwork, &info );
    ^
    combo.cc:107:74: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
    combo.cc:111:72: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
    dsyev( "Vectors", "Upper", &n, a, &lda, w, work, &lwork, &info );
    ^
    combo.cc:111:72: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
    combo.cc:118:49: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
    print_matrix( "Eigenvalues", 1, n, w, 1 );
    ^
    combo.cc:120:72: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
    print_matrix( "Eigenvectors (stored columnwise)", n, n, a, lda );
    ^
    /tmp/cciDZkcq.o: In function `main':
    combo.cc:(.text+0x1af): undefined reference to `dsyev_(char*, char*, int*, double*, int*, double*, double*, int*, int*)'
    combo.cc:(.text+0x236): undefined reference to `dsyev_(char*, char*, int*, double*, int*, double*, double*, int*, int*)'
    collect2: error: ld returned 1 exit status
    ludi@ludi-M17xR4:~/Desktop/tests$​
     
  5. Jun 6, 2015 #4
    All errors disappeared by using C linkage. Every occurrence of

    extern void function
    {...}

    was replaced by

    extern "C"
    {
    void function
    {...}
    }

    Specifically, I now use:
    /* DSYEV prototype */
    extern "C"{
    void dsyev( char* jobz, char* uplo, int* n, double* a, int* lda,
    double* w, double* work, int* lwork, int* info );
    }
    /* Auxiliary routines prototypes */
    extern "C"{
    void print_matrix( char* desc, int m, int n, double* a, int lda );
    }
    I kind of understand what extern "C" does. Could someone explain what extern did? Was it spurious?

    The warnings I still get are all of the type.

    combo.cc:110:74: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
    dsyev( "Vectors", "Upper", &n, a, &lda, w, &wkopt, &lwork, &info );
    ^
    combo.cc:110:74: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
    I think they are no big deal, but if someone knows how to remedy them...
     
    Last edited: Jun 6, 2015
  6. Jun 7, 2015 #5

    Mark44

    Staff: Mentor

    According to some documentation I found for dsyev (http://www.math.utah.edu/software/lapack/lapack-d/dsyev.html), there is a mismatch between your actual arguments (in the call to dsyev()) and the parameters that are described in the documentation.

    Here's a comparison between the input formal parameters you show in the dsyev prototype above, and those described in the documentation:
    Code (Text):

    Parameter Your prototype.................Docs I found
    jobz (in)       char *            CHARACTER* 1 <--- This is a single character, not a pointer
    uplo (in)       char *            CHARACTER*1 <---- Ditto
    n (in)          int *             INTEGER  <--- In your prototype, n is a pointer; in the docs it's an integer, which is not the same.
    LDA (in)        int *             INTEGER  <--- Ditto
    LWORK (in)      int *             INTEGER <--- Ditto
    I didn't list the in/out or out parameters, which do need to be pointers when you're calling this routine from C or C++. The in parameters shouldn't be pointers (addresses) as you have them. Since the parameters you show in your prototype agree with the types you show in the call to dsyev, I don't believe that the compiler will issue a warning, but it seems likely to me that you'll get very inaccurate results. This business of the parameters is the same thing I said in the other thread you posted, so it doesn't seem to have stuck with you.

    The two warnings you show come from using string constants in your calls to dsyev (e.g., "Vectors" and "Upper") instead of character arrays. In other words, for these first two parameters, the prototype you show expects them to have been declared as char jobz[] = "Vectors" and char uplo[] = "Upper". What seems more problematic to me is that the LAPACK dsyev function (according to the docs in the link I show, and elsewhere) is expecting a single constant for jobz and uplo, 'V' and 'U', respectively.[/code]
     
  7. Jun 7, 2015 #6
    I don't know for your problem but please, test fin.isopen() before reading it.
    If the file doesn't exist you will have a hard to find segmentation fault.
     
  8. Jun 7, 2015 #7

    D H

    User Avatar
    Staff Emeritus
    Science Advisor

    You shouldn't be declaring the functions in the lapack library. You should instead be using a header file that comes with the library. If that header file was written for use in C but not C++ (i.e., it doesn't wrap function declarations within an extern "C" block, you can use
    Code (Text):

    extern "C" {
    #include "goofy_c_only_header.h"
    }


    It was not spurious.

    Consider the following:
    Code (Text):

    int foo () { return 42; }
    int foo (int num) { return num + 42; }
    double foo (double num1, int num2=42) { return num1 + num2; }
    The above code is perfectly legal C++ code. C++ has overloading. C doesn't; the above is illegal in C. Actually, it's worse than illegal in C; it falls in that terrible category of "illegal" called "undefined behavior". The compiler/linker is nice if it does detect that their are multiple definitions of foo. It doesn't have to.

    This possibility of overloading in C++ (but not in C) is the reason you absolutely need to use extern "C" to call a C function from C++ code. C++ compilers mangle function names so as to distinguish foo() from foo(int) and foo(double). For example, the C++ function double foo(double num1, int num2) becomes __Z3foodi on my computer with my compiler. When compiled as a C function, the same function becomes _foo with my compiler. These different linkage rules for C versus C++ means you need to tell the compiler that the C functions you are calling are indeed C functions, not C++ functions.

    In this case, those warnings are benign. Those warnings do however need to be there. You are (potentially) invoking undefined behavior. What if dysev changes the contents of that string? That's undefined behavior. The function dysev doesn't do that, but the prototype says that it might well do exactly that. A good compiler will warn you when you supply a const array to a function that takes a non-const array as an argument.
     
Know someone interested in this topic? Share this thread via Reddit, Google+, Twitter, or Facebook




Similar Discussions: Cannot use simplest ifstream with LAPACK
  1. Ifstream issues (Replies: 8)

Loading...