undefined reference to 'd1mach_'

后端 未结 1 1663
悲&欢浪女
悲&欢浪女 2021-01-24 03:39

I\'m trying to link a fortran subroutine with c++, but can\'t quite figure out what exactly is wrong here: The fortran subroutine calls some functions eg. d1mach or xermsg, whic

相关标签:
1条回答
  • 2021-01-24 04:10

    The reason why the problem persists might be simply because your lib3j6j9j.a does not include necessary files (such as d1mach). Actually, we can compile necessary files rather directly, so I will summarize the procedure below:

    1) Download drc3jm.f (which calculates 3j-symbols) and dependencies from the Netlib/Slatec page (here or here). Unpack the archive file to get Fortran files (*.f).

    tar xvf netlibfiles.tgz
    

    2) Remove d1mach.f, i1mach.f, and r1mach.f (if any). Instead, download their alternative versions from Netlib/blas (*):

    rm -f i1mach.f r1mach.f d1mach.f
    wget http://www.netlib.org/blas/i1mach.f 
    wget http://www.netlib.org/blas/r1mach.f
    wget http://www.netlib.org/blas/d1mach.f 
    

    3) Compile all *.f files

    gfortran testf.f90 *.f
    

    together with a main program testf.f90 (in free-format), e.g.,

    program main
    implicit none
    integer, parameter :: N = 1000
    double precision coef( N ), M2min, M2max, M2
    integer ier
    ier = 0 ; coef(:) = 0.0d0
    
    call DRC3JM( 15.0d0, 30.0d0, 40.d0, 2.0d0,  M2min, M2max, coef, N, ier )
    print *, "M2min, M2max, ier = ", M2min, M2max, ier
    
    M2 = 2.0d0
    print "(a, f20.15)", "coef = ", coef( nint(M2 - M2min+1) )  !! -0.019081579799192
    end
    

    Then running the executable gives the desired result.


    3-a) We can also make these *.f as a library and link with C++ codes, e.g., as follows:

    gfortran -c *.f
    ar rv mylib.a *.o
    g++ testc.cpp mylib.a -lgfortran
    

    with a main program (testc.cpp)

    #include <cstdio>
    extern "C"
    double drc3jm_ (double*, double*, double*, 
                    double*, double*, double*, double*, int*, int*);
    
    int main()
    {
        double* coef;
        double L1, L2, L3, M1, M2min, M2max, M2;
        int ier, k, N = 1000;
    
        coef = new double [ N ];
        L1 = 15.0; L2 = 30.0; L3 = 40.0; M1 = 2.0;
    
        drc3jm_ ( &L1, &L2,    &L3,
                  &M1, &M2min, &M2max, coef, &N, &ier );  
        printf( "M2min, M2max, ierr = %10.5f%10.5f%d\n", M2min, M2max, ier );
    
        M2 = 2.0;   
        k = (int)(M2 - M2min + 1.0e-3);
        printf( "coef = %20.15f\n", coef[ k ] );  // -0.019081579799192
        return 0;
    }
    

    We can see that the two programs give the same coefficient (-0.019081579799192) for

    j1=15, j2=30, j3=40, m1=2, m2=2, m3=-4
    

    You can also get the same result with an online tool, e.g., here.


    But depending on cases, it may be simpler to use other libraries. One approach is to use the corresponding GSL routines (here) as

    #include <cstdio>
    extern "C"
    double gsl_sf_coupling_3j (int two_ja, int two_jb, int two_jc,
                               int two_ma, int two_mb, int two_mc);  
    int main()
    {
        double coef;
        coef = gsl_sf_coupling_3j( 30, 60, 80, 4, 4, -8 );  // -0.019081579799205
        // NOTE: all j's and m's need to be doubled.
    
        printf( "coef = %20.15f\n", coef );
        return 0;
    }
    

    Here you need to link necessary GSL libraries (e.g., g++ test.cpp -lgsl or g++ test.cpp /usr/lib64/libgsl.so.0 /usr/lib64/libgslcblas.so.0 etc).


    Yet another approach is to use a latest program WIGXJPF (the related paper is here). I tried this a bit and it seems extremely easy to install (only one make) and use. For example, enter the example/ directory and try gcc -I../inc csimple.c ../lib/libwigxjpf.a. According to the above paper, this program may offer some accuracy and performance advantage.


    (*) For more details, please see the Netlib/FAQ page (thanks to @VladimirF in the comment). We could utilize the original d1mach.f etc in Slatec, but we need to modify them so as to obtain correct machine-dependent constants. The above BLAS versions of d1mach.f etc handle this automatically, so they are more convenient.

    0 讨论(0)
提交回复
热议问题