BOOST_AUTO_TEST_CASE_TEMPLATE(agrees_with_noninterpolated_for_negative_real_wave_number,
                              ValueType, kernel_types)
{
    typedef Fiber::ModifiedHelmholtz3dDoubleLayerPotentialKernelFunctor<ValueType>
            NoninterpolatedFunctor;
    typedef Fiber::ModifiedHelmholtz3dDoubleLayerPotentialKernelInterpolatedFunctor<ValueType>
            InterpolatedFunctor;
    typedef Fiber::DefaultCollectionOfKernels<NoninterpolatedFunctor>
            NoninterpolatedKernels;
    typedef Fiber::DefaultCollectionOfKernels<InterpolatedFunctor>
            InterpolatedKernels;
    typedef typename Fiber::ScalarTraits<ValueType>::RealType CoordinateType;
    const ValueType waveNumber = -1;
    const CoordinateType wavelength = 2. * M_PI / std::abs(waveNumber);
    const double maxDist = 20.;
    auto parameterList = GlobalParameters::parameterList();
    const int interpPtsPerWavelength = parameterList.template get<int>("options.assembly.interpolationPointsPerWavelength");

    NoninterpolatedKernels noninterpKernels((NoninterpolatedFunctor(waveNumber)));
    InterpolatedKernels interpKernels((InterpolatedFunctor(waveNumber, maxDist,
                                                          interpPtsPerWavelength)));

    Fiber::GeometricalData<CoordinateType> testGeomData, trialGeomData;
    const int worldDim = 3;
    const int testPointCount = 3, trialPointCount = 50;
    testGeomData.globals.resize(worldDim, testPointCount);
    testGeomData.globals.fill(0.);
    testGeomData.globals(0, 0) = wavelength / (2 * interpPtsPerWavelength);
    testGeomData.globals(1, 1) = wavelength / (2 * interpPtsPerWavelength);
    testGeomData.globals(2, 2) = wavelength / (2 * interpPtsPerWavelength);

    trialGeomData.globals = 0.5 * maxDist *
            generateRandomMatrix<CoordinateType>(worldDim, trialPointCount);
    trialGeomData.globals.col(0).fill(0.);
    trialGeomData.globals.block(0, 1, trialGeomData.globals.rows(), 10) *= 0.01; // to test well the area near origin
    trialGeomData.globals.block(0, 11, trialGeomData.globals.rows(), 10) *= 0.1;

    trialGeomData.normals.resize(worldDim, trialPointCount);
    trialGeomData.normals.fill(0.);
    trialGeomData.normals.row(0).fill(0.5);
    trialGeomData.normals.row(1).fill(0.5);
    trialGeomData.normals.row(2).fill(1. / sqrt(2.)); // just to make them nonzero and nonequal

    Fiber::CollectionOf4dArrays<ValueType> noninterpResult, interpResult;
    noninterpKernels.evaluateOnGrid(testGeomData, trialGeomData, noninterpResult);
    interpKernels.evaluateOnGrid(testGeomData, trialGeomData, interpResult);

    CoordinateType tol = 50 * std::numeric_limits<CoordinateType>::epsilon();
    BOOST_CHECK(check_arrays_are_close<ValueType>(interpResult[0],
                                                  noninterpResult[0], tol));
}
BOOST_AUTO_TEST_CASE_TEMPLATE(agrees_with_noninterpolated_for_complex_wave_number,
                              ValueType, complex_kernel_types)
{
    typedef Fiber::ModifiedHelmholtz3dDoubleLayerPotentialKernelFunctor<ValueType>
            NoninterpolatedFunctor;
    typedef Fiber::ModifiedHelmholtz3dDoubleLayerPotentialKernelInterpolatedFunctor<ValueType>
            InterpolatedFunctor;
    typedef Fiber::DefaultCollectionOfKernels<NoninterpolatedFunctor>
            NoninterpolatedKernels;
    typedef Fiber::DefaultCollectionOfKernels<InterpolatedFunctor>
            InterpolatedKernels;
    typedef typename Fiber::ScalarTraits<ValueType>::RealType CoordinateType;
    const ValueType waveNumber(1., 1.);
    const CoordinateType wavelength = 2. * M_PI / std::abs(waveNumber);
    const double maxDist = 20.;
    const int interpPtsPerWavelength = Bempp::DEFAULT_HELMHOLTZ_INTERPOLATION_DENSITY;
    NoninterpolatedKernels noninterpKernels((NoninterpolatedFunctor(waveNumber)));
    InterpolatedKernels interpKernels((InterpolatedFunctor(waveNumber, maxDist,
                                                          interpPtsPerWavelength)));

    Fiber::GeometricalData<CoordinateType> testGeomData, trialGeomData;
    const int worldDim = 3;
    const int testPointCount = 3, trialPointCount = 30;
    testGeomData.globals.set_size(worldDim, testPointCount);
    testGeomData.globals.fill(0.);
    testGeomData.globals(0, 0) = wavelength / (2 * interpPtsPerWavelength);
    testGeomData.globals(1, 1) = wavelength / (2 * interpPtsPerWavelength);
    testGeomData.globals(2, 2) = wavelength / (2 * interpPtsPerWavelength);

    trialGeomData.globals = 0.5 * maxDist *
            generateRandomMatrix<CoordinateType>(worldDim, trialPointCount);
    trialGeomData.globals.col(0).fill(0.);
    trialGeomData.globals.cols(1, 10) *= 0.01; // to test well the area near origin
    trialGeomData.globals.cols(11, 20) *= 0.1;

    trialGeomData.normals.set_size(worldDim, trialPointCount);
    trialGeomData.normals.fill(0.);
    trialGeomData.normals.row(0).fill(0.5);
    trialGeomData.normals.row(1).fill(0.5);
    trialGeomData.normals.row(2).fill(1. / sqrt(2.)); // just to make them nonzero and nonequal

    Fiber::CollectionOf4dArrays<ValueType> noninterpResult, interpResult;
    noninterpKernels.evaluateOnGrid(testGeomData, trialGeomData, noninterpResult);
    interpKernels.evaluateOnGrid(testGeomData, trialGeomData, interpResult);

    CoordinateType tol = 50 * std::numeric_limits<CoordinateType>::epsilon();
    BOOST_CHECK(check_arrays_are_close<ValueType>(interpResult[0],
                                                  noninterpResult[0], tol));
}