Hello!

I am working with a fortran project which uses fgsl (v1.2.0, together with gsl v2.3.0).

The code reports an arithmetic exception in an integration routine, when trying to integrate exp(-x^2) from x=19.3 to 20.0. I would expect the code to work without problems (maybe underflow or denormal). Trying to create a minimal working example i came up with the attached file (the cmake input i used for compilation is also attached, sorry I could not boil this further down). As a corresponding version for c++ works (also attached), this might relate to a bug in fgsl, but for me (a person without knowledge of the internals), that seems questionable according to what causes the problem and what not.


The output is as follows:

Program received signal SIGFPE: Floating-point exception - erroneous arithmetic operation.

Backtrace for this error:
#0  0x7fa39acc5d1d in ???
#1  0x7fa39acc4f7d in ???
#2  0x7fa39a1e405f in ???
#3  0x560ac54c9eff in ???
#4  0x560ac54860cf in neo2
    at /afs/itp.tugraz.at/user/buchholz/Programs/neo2-minimal/NEO-2-QL/neo2.f90:31
#5  0x560ac54861d8 in main
    at /afs/itp.tugraz.at/user/buchholz/Programs/neo2-minimal/NEO-2-QL/neo2.f90:4

It does not occur with the alternative integration routine commented in the code. This does not occur, if one reduces the lower bound to 19.2 or smaller (which is a reason why I suspect that this might be a gsl bug - a bug in the interface should have no influence on this).


With kind regards
Rico Buchholz


PS: I did also send the bug report to fgsl.

### Initialize CMake (some internal stuff)
cmake_minimum_required(VERSION 3.0)
set(CMAKE_DISABLE_IN_SOURCE_BUILD ON)

# Enable project
project(NEO-2-NTV)
enable_language(Fortran)

set(EXE_NAME "neo_2.x")

### Define paths to external libraries (load external file)
### Installation directory
set (CMAKE_INSTALL_PREFIX ${CMAKE_SOURCE_DIR})

### Path to the external libraries
set(PROJLIBS /proj/plasma/Libs/ CACHE STRING "Common library path")

set(GSL_PATH ${PROJLIBS}GSL_gcc-6.3/gsl-2.3/LIB)
set(GSL_LIB ${GSL_PATH}/lib/ CACHE STRING "GSL path")

set(FGSL_PATH /proj/plasma/Libs/FGSL_gcc-6.3/fgsl-1.2.0/LIB CACHE STRING "FGSL 
path")
set(FGSL_LIB ${FGSL_PATH}/lib/)
set(FGSL_INC ${FGSL_PATH}/include/fgsl/)

### Path to the ATLAS libraries
set(ATLASLIBS /usr/lib/atlas-base/)
set(LAPACK_LIB ${ATLASLIBS}/atlas/)
set(F77BLAS_LIB ${ATLASLIBS})
set(ATLASBLAS_LIB ${ATLASLIBS})

### Path to OpenBLAS
set(OPEN_BLAS_PATH /usr/lib/openblas-base/)
set(OPEN_BLAS_LAPACK_LIB ${OPEN_BLAS_PATH})
set(OPEN_BLAS_LIB ${OPEN_BLAS_PATH})

# Print the current compiler
message(STATUS "The Compiler ID is ${CMAKE_Fortran_COMPILER_ID}")

# Include directories for NEO-2
include_directories(${NEO2_Inc})
set(CMAKE_Fortran_FLAGS_DEBUG "-O0 -cpp -g -ffpe-trap=invalid,zero,overflow 
-fcheck=all -fbacktrace -Wall -Wno-unused-dummy-argument") 
set(CFLAGS "-O2 -DDOUBLE_APPEND_FORTRAN")

### Define container for *.o and *.mod files
set(CMAKE_Fortran_MODULE_DIRECTORY ${PROJECT_BINARY_DIR}/OBJS)

### Find libraries
# GSL
find_library(gsl_lib gsl ${GSL_LIB})
# FGSL
find_library(fgsl_lib fgsl ${FGSL_LIB} NO_DEFAULT_PATH)
include_directories(${FGSL_INC})

# LAPACK and BLAS
if (CMAKE_Fortran_COMPILER_ID MATCHES "GNU")
  find_library(lapack_lib lapack ${LAPACK_LIB} NO_DEFAULT_PATH)
  find_library(f77blas_lib f77blas ${F77BLAS_LIB} NO_DEFAULT_PATH)
  find_library(atlas_lib atlas ${ATLASBLAS_LIB} NO_DEFAULT_PATH)
  find_library(open_blas_lapack_lib lapack ${OPEN_BLAS_LAPACK_LIB} 
NO_DEFAULT_PATH)
  find_library(open_blas_lib blas ${OPEN_BLAS_LIB} NO_DEFAULT_PATH)
endif ()

### Source files
set(NEO2_SRC_FILES
        ./neo2.f90
)
set_source_files_properties(${NEO2_SRC_FILES} PROPERTIES COMPILE_FLAGS 
"${DEBUGFLAG} ${FFLAG_DEBUG} ${FFLAGS}")

### Define executable
add_executable(${EXE_NAME}
  ${NEO2_SRC_FILES}
)

if (CMAKE_Fortran_COMPILER_ID MATCHES "GNU")
  set(LINALG_LIBRARIES ${lapack_lib} ${f77blas_lib} ${atlas_lib})
endif ()

### Add libraries linked with executable
target_link_libraries(${EXE_NAME}
        ${fgsl_lib} ${gsl_lib}
        ${LINALG_LIBRARIES}
        )
program neo2

  use, intrinsic :: iso_c_binding
  use fgsl ! Fortran interface of the GSL Library

  implicit none

  real(fgsl_double), parameter :: x_low = 1.93d1
  real(fgsl_double), parameter :: x_up = 2.0d1
  ! absolute error
  real(fgsl_double), parameter :: epsabs = 1.0d-13
  ! relative error
  real(fgsl_double), parameter :: epsrel = 1.0d-13

  integer(fgsl_size_t), parameter :: n = 100_fgsl_size_t

  integer(fgsl_size_t) :: neval ! number of function evaluations
  real(fgsl_double) :: ra, rda ! result and absolute error
  integer(fgsl_int) :: statusval
  type(fgsl_function) :: stdfunc
  type(fgsl_integration_cquad_workspace) :: workspace
!~   type(fgsl_integration_workspace) :: workspace

  neval = 0

  stdfunc = fgsl_function_init(func_to_integrate, c_null_ptr)
  workspace = fgsl_integration_cquad_workspace_alloc(n)
!~   workspace = fgsl_integration_workspace_alloc(1000_fgsl_size_t)

  statusval = fgsl_integration_cquad(stdfunc, x_low, x_up, &
     & epsabs, epsrel, workspace, ra, rda, neval)
!~   statusval = fgsl_integration_qags(stdfunc, x_low, x_up, &
!~      & epsabs, epsrel, 1000_fgsl_size_t, workspace, ra, rda)

  call fgsl_function_free(stdfunc)
  call fgsl_integration_cquad_workspace_free(workspace)
!~   call fgsl_integration_workspace_free(workspace)

  write(*,*) ra, rda, neval

  stop

contains

  function func_to_integrate(x, params) bind(c)
    real(c_double), value :: x
    type(c_ptr), value :: params
    real(c_double) :: func_to_integrate

    func_to_integrate =  exp(-x**2)
  end function func_to_integrate

end program neo2

/**
 *
 * g++ main.cpp -o main.x -L`gsl-config --libs`
 *
 */

#include <iostream>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>

#include <gsl/gsl_integration.h>

double f(double x, void * params) {
  return std::exp(-x*x);
}

int main (void)
{
  size_t const n(100);
  double const a(19.3);
  double const b(20.0);
  double const epsabs(1.0e-13);
  double const epsrel(1.0e-13);
  double result(0.0);
  double abserr(0.0);
  size_t nevals(0);

  gsl_integration_cquad_workspace * workspace(NULL);
  gsl_function F;

  F.function = &f;
  F.params = NULL;

  workspace = gsl_integration_cquad_workspace_alloc(n);

  gsl_integration_cquad(&F, a, b, epsabs, epsrel, workspace, &result, &abserr, &nevals);

  std::cout<<"result: " << result << "\n";
  std::cout<<"abserr: " << abserr << "\n";
  std::cout<<"nevals: " << nevals << "\n";

  gsl_integration_cquad_workspace_free(workspace);

  return 0;
}

Reply via email to