aboutsummaryrefslogtreecommitdiff
path: root/Client/ThirdParty/fpm/CMakeLists.txt
blob: a5332eb51a21be14aa446a3a5878e8c872048ce0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
cmake_minimum_required(VERSION 3.9)

project(fpm)

set(CMAKE_CXX_STANDARD 11)

add_library(fpm INTERFACE)

target_include_directories(fpm INTERFACE include)

#
# Test suite
#
enable_testing()
include(GoogleTest)

add_executable(fpm-test
  tests/arithmetic.cpp
  tests/arithmetic_int.cpp
  tests/basic_math.cpp
  tests/constants.cpp
  tests/conversion.cpp
  tests/classification.cpp
  tests/customizations.cpp
  tests/detail.cpp
  tests/input.cpp
  tests/manip.cpp
  tests/nearest.cpp
  tests/output.cpp
  tests/power.cpp
  tests/trigonometry.cpp
)
set_target_properties(fpm-test PROPERTIES CXX_STANDARD 11)
target_link_libraries(fpm-test PRIVATE fpm gtest_main)
gtest_add_tests(TARGET fpm-test)

#
# libfixmath for alternative comparison
#
include(ExternalProject)

# Libfixmath uses a Makefile with hardcoded compiler (gcc).
# So we need to define our own build rules.
set(LIBFIXMATH_ROOT "${CMAKE_CURRENT_BINARY_DIR}/libfixmath")

ExternalProject_Add(libfixmath-external
  GIT_REPOSITORY "https://github.com/PetteriAimonen/libfixmath.git"
  GIT_TAG bada934981a5961569ad2cb6b9006ed94542cc9c
  PREFIX ${LIBFIXMATH_ROOT}
  CONFIGURE_COMMAND ""
  BUILD_COMMAND ""
  INSTALL_COMMAND ""
)

set(LIBFIXMATH_SOURCES
  ${LIBFIXMATH_ROOT}/src/libfixmath-external/libfixmath/fix16.c
  ${LIBFIXMATH_ROOT}/src/libfixmath-external/libfixmath/fix16_exp.c
  ${LIBFIXMATH_ROOT}/src/libfixmath-external/libfixmath/fix16_sqrt.c
  ${LIBFIXMATH_ROOT}/src/libfixmath-external/libfixmath/fix16_str.c
  ${LIBFIXMATH_ROOT}/src/libfixmath-external/libfixmath/fix16_trig.c
  ${LIBFIXMATH_ROOT}/src/libfixmath-external/libfixmath/fract32.c
  ${LIBFIXMATH_ROOT}/src/libfixmath-external/libfixmath/uint32.c
)
set_source_files_properties(${LIBFIXMATH_SOURCES} PROPERTIES GENERATED TRUE)
add_library(libfixmath ${LIBFIXMATH_SOURCES})

# Set libfixmath compile options to match fpm functionality
target_compile_definitions(libfixmath
  PUBLIC
    FIXMATH_NO_CACHE        # No caching of results

    #FIXMATH_NO_OVERFLOW    # We want no runtime-overflow detection, but it fails to compile
    #FIXMATH_NO_ROUNDING    # We do want rounding
    #FIXMATH_NO_64BIT       # We do want 64-bit integer support
    #FIXMATH_OPTIMIZE_8BIT  # No special 8-bit architecture optimizations
    #FIXMATH_SIN_LUT        # No lookup table for sin
    #FIXMATH_FAST_SIN       # Prefer accuracy over speed
)

target_include_directories(libfixmath PUBLIC ${LIBFIXMATH_ROOT}/src/libfixmath-external/libfixmath)
add_dependencies(libfixmath libfixmath-external)

#
# CNL for alternative comparison
#
set(LIBCNL_ROOT "${CMAKE_CURRENT_BINARY_DIR}/libcnl")

ExternalProject_Add(libcnl-external
  GIT_REPOSITORY "https://github.com/johnmcfarlane/cnl"
  GIT_TAG 4d445566fe7c6c8939fffc145a2f30fd587796a6
  PREFIX ${LIBCNL_ROOT}
  CONFIGURE_COMMAND ""
  BUILD_COMMAND ""
  INSTALL_COMMAND ""
)

add_library(libcnl INTERFACE)
target_include_directories(libcnl INTERFACE ${LIBCNL_ROOT}/src/libcnl-external/include)
add_dependencies(libcnl libcnl-external)

#
# Benchmark tool.
# Runs benchmarks of FPM operations and dumps results to standard output.
#
add_executable(fpm-benchmark
	benchmarks/arithmetic.cpp
	benchmarks/power.cpp
	benchmarks/trigonometry.cpp
)
target_link_libraries(fpm-benchmark PRIVATE fpm libfixmath libcnl benchmark benchmark_main)

#
# Accuracy tool.
# Dumps the accuracy of approximated FPM functions to JSON files.
#
add_executable(fpm-accuracy
	accuracy/accuracy.cpp
)
set_target_properties(fpm-accuracy PROPERTIES CXX_STANDARD 14)
target_link_libraries(fpm-accuracy PRIVATE fpm libfixmath)


include(FindGnuplot)
if (GNUPLOT_FOUND)
  # Create accuracy data
  set(DATA_DIR ${CMAKE_CURRENT_BINARY_DIR})

  set(DATA_FILES_ACCURACY "")
  set(IMG_FILES_ACCURACY "")
  foreach(DATA sin-trig cos-trig tan-trig asin-invtrig acos-invtrig atan-invtrig atan2-trig sqrt-auto cbrt-auto pow-auto exp-auto exp2-auto log-auto log2-auto log10-auto)
    string(REGEX MATCHALL "[^-]+" M ${DATA})
    list(GET M 0 SERIES)
    list(GET M 1 TYPE)

    set(IMG_FILE ${DATA_DIR}/accuracy-${SERIES}.png)
    list(APPEND DATA_FILES_ACCURACY ${DATA_DIR}/${SERIES}.csv)
    list(APPEND IMG_FILES_ACCURACY ${IMG_FILE})

    add_custom_command(
      OUTPUT ${IMG_FILE}
      COMMAND ${GNUPLOT_EXECUTABLE} -c ${PROJECT_SOURCE_DIR}/accuracy/accuracy.gnuplot ${SERIES} ${TYPE}
      DEPENDS ${DATA_DIR}/${SERIES}.csv accuracy/accuracy.gnuplot
      WORKING_DIRECTORY ${DATA_DIR}
      VERBATIM
      COMMENT "Plotting ${SERIES} accuracy data"
    )
  endforeach(DATA)

  add_custom_command(
    OUTPUT ${DATA_FILES_ACCURACY}
    COMMAND fpm-accuracy
    DEPENDS fpm-accuracy
    WORKING_DIRECTORY ${DATA_DIR}
    VERBATIM
    COMMENT "Generating accuracy data with fpm-accuracy"
  )

  add_custom_target(fpm-accuracy-images DEPENDS ${IMG_FILES_ACCURACY})
endif()

if (CMAKE_BUILD_TYPE STREQUAL "Release")
  # Enable the performance data-generation command only for Release builds.

  set(DATA_FILE_PERFORMANCE_JSON ${DATA_DIR}/performance.json)
  add_custom_command(
    OUTPUT ${DATA_FILE_PERFORMANCE_JSON}
    COMMAND fpm-benchmark --benchmark_out=${DATA_FILE_PERFORMANCE_JSON} --benchmark_out_format=json
    DEPENDS fpm-benchmark
    WORKING_DIRECTORY ${DATA_DIR}
    VERBATIM
    COMMENT "Generating performance data with fpm-benchmark"
  )

  set(DATA_FILE_PERFORMANCE_GNUPLOT ${DATA_DIR}/performance.csv)
  add_custom_command(
    OUTPUT ${DATA_FILE_PERFORMANCE_GNUPLOT}
    COMMAND python ${PROJECT_SOURCE_DIR}/benchmarks/benchmark.py ${DATA_FILE_PERFORMANCE_JSON} ${DATA_FILE_PERFORMANCE_GNUPLOT}
    DEPENDS ${DATA_FILE_PERFORMANCE_JSON} ${PROJECT_SOURCE_DIR}/benchmarks/benchmark.py
    WORKING_DIRECTORY ${DATA_DIR}
    VERBATIM
    COMMENT "Converting performance data for GnuPlot"
  )

  set(IMG_FILE_PERFORMANCE "{$DATA_DIR}/performance.png")
  add_custom_command(
    OUTPUT ${IMG_FILE_PERFORMANCE}
    COMMAND ${GNUPLOT_EXECUTABLE} ${PROJECT_SOURCE_DIR}/benchmarks/benchmark.gnuplot
    DEPENDS ${DATA_FILE_PERFORMANCE_GNUPLOT} ${PROJECT_SOURCE_DIR}/benchmarks/benchmark.gnuplot
    WORKING_DIRECTORY ${DATA_DIR}
    VERBATIM
    COMMENT "Plotting performance data"
  )

  add_custom_target(fpm-performance-images DEPENDS ${IMG_FILE_PERFORMANCE})
endif()

add_subdirectory(3rdparty/googlebench)
add_subdirectory(3rdparty/googletest)