
ADD_LIBRARY(JFJochGeomRefinement STATIC
        BeamCenterFromBackground.cpp
        BeamCenterFromBackground.h
        BeamCenterFFT.cpp
        BeamCenterFFT.h
        BeamCenterFFTEngine.h
        BeamCenterFFTCPU.cpp
        BeamCenterFFTCPU.h
        RingOptimizer.cpp
        RingOptimizer.h
        AssignSpotsToRings.cpp
        AssignSpotsToRings.h
        Calibrants.cpp
        Calibrants.h
        RingsFromProfile.cpp
        RingsFromProfile.h
        PowderCalibration.cpp
        PowderCalibration.h
        PowderAutoSeed.cpp
        PowderAutoSeed.h
        XtalOptimizer.cpp
        XtalOptimizer.h
        XtalResidual.h
        XtalRefine.cpp
        XtalRefine.h
        LMSolver.cpp
        LMSolver.h
        Dual.h
        BackgroundBand.h
        PostRefine.cpp
        PostRefine.h
        GeometryRefiner.cpp
        GeometryRefiner.h
        LatticeReduction.cpp
        LatticeReduction.h
        CellEsd.cpp
        CellEsd.h
)

# fftw3f: BeamCenterFFT scores every candidate centre with one transform set (always fetched,
# same target the CPU FFT indexer links), and is the fallback wherever there is no GPU.
TARGET_LINK_LIBRARIES(JFJochGeomRefinement Ceres::ceres Eigen3::Eigen JFJochCommon fftw3f)

IF (JFJOCH_CUDA_AVAILABLE)
    TARGET_SOURCES(JFJochGeomRefinement PRIVATE BeamCenterFFTGPU.cu BeamCenterFFTGPU.h
            BeamCenterBackgroundGPU.cu BeamCenterBackgroundGPU.h)
    # Same static/dynamic cuFFT choice as the FFT indexer, and for the same reasons - see the long
    # note in image_analysis/indexing/CMakeLists.txt.
    IF (JFJOCH_PORTABLE_ONLY AND TARGET CUDA::cufft_static)
        TARGET_LINK_LIBRARIES(JFJochGeomRefinement CUDA::cufft_static)
    ELSE()
        TARGET_LINK_LIBRARIES(JFJochGeomRefinement CUDA::cufft)
    ENDIF()
ENDIF()

# The background beam-centre fit bins every pixel with BackgroundBand.h on the host and on the device
# and must get the same bits on both (see there). That needs no multiply-add contracted on either side:
# GCC and Clang contract by default and nvcc does too, while MSVC does not without /fp:contract.
IF (JFJOCH_CUDA_AVAILABLE)
    SET_SOURCE_FILES_PROPERTIES(BeamCenterBackgroundGPU.cu PROPERTIES COMPILE_OPTIONS "--fmad=false")
ENDIF()
IF (CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
    SET_SOURCE_FILES_PROPERTIES(BeamCenterFromBackground.cpp PROPERTIES COMPILE_OPTIONS "-ffp-contract=off")
ENDIF()
