From 0fded00f89ba30214738292c909160cd1639e7d6 Mon Sep 17 00:00:00 2001 From: TB Schardl Date: Tue, 9 Mar 2021 19:27:52 +0000 Subject: [PATCH] Version 1.1 release candidate 2 --- CMakeLists.txt | 153 +- cmake/Modules/AddCheetah.cmake | 487 +++ cmake/Modules/CheetahDarwinUtils.cmake | 561 +++ cmake/Modules/CheetahUtils.cmake | 481 +++ cmake/Modules/HandleCheetahFlags.cmake | 20 +- cmake/Modules/HandleOutOfTreeLLVM.cmake | 140 - cmake/base-config-ix.cmake | 245 ++ cmake/config-ix.cmake | 285 +- config.mk | 11 +- handcomp_test/Makefile | 3 +- handcomp_test/cilksort.c | 54 +- handcomp_test/fib.c | 19 +- handcomp_test/mm_dac.c | 41 +- handcomp_test/nqueens.c | 19 +- include/CMakeLists.txt | 4 +- include/cilk/cilk.h | 1 + include/cilk/cilk_api.h | 3 +- include/cilk/cilk_stub.h | 1 + reducer_bench/.gitignore | 6 - reducer_bench/Makefile | 79 - reducer_bench/cppsum.cpp | 48 - reducer_bench/getoptions.c | 93 - reducer_bench/getoptions.h | 20 - reducer_bench/intlist.c | 71 - reducer_bench/intlist.h | 76 - reducer_bench/intsum.c | 64 - reducer_bench/ktiming.c | 102 - reducer_bench/ktiming.h | 39 - reducer_bench/multispawnsum.c | 60 - reducer_bench/nqueens/.gitignore | 12 - reducer_bench/nqueens/Makefile | 39 - reducer_bench/nqueens/board.c | 71 - reducer_bench/nqueens/board.h | 59 - reducer_bench/nqueens/fasttime.h | 94 - reducer_bench/nqueens/ktiming.c | 101 - reducer_bench/nqueens/ktiming.h | 38 - reducer_bench/nqueens/nqueens.c | 166 - reducer_bench/nqueens/nqueens_int.c | 118 - reducer_bench/quad_tree/.gitignore | 4 - reducer_bench/quad_tree/Makefile | 67 - reducer_bench/quad_tree/beta | 0 reducer_bench/quad_tree/bin.c | 516 --- reducer_bench/quad_tree/bin.h | 109 - reducer_bench/quad_tree/clint.py | 3373 ----------------- reducer_bench/quad_tree/collision_world.c | 396 -- reducer_bench/quad_tree/collision_world.h | 88 - reducer_bench/quad_tree/fasttime.h | 97 - reducer_bench/quad_tree/graphic_stuff.c | 252 -- reducer_bench/quad_tree/graphic_stuff.h | 35 - reducer_bench/quad_tree/input/apple.in | 536 --- reducer_bench/quad_tree/input/beaver.in | 294 -- reducer_bench/quad_tree/input/box.in | 401 -- reducer_bench/quad_tree/input/explosion.in | 601 --- reducer_bench/quad_tree/input/mit.in | 810 ---- reducer_bench/quad_tree/input/sin_wave.in | 1181 ------ reducer_bench/quad_tree/input/smalllines.in | 530 --- .../quad_tree/intersection_detection.c | 157 - .../quad_tree/intersection_detection.h | 58 - .../quad_tree/intersection_event_list.c | 107 - .../quad_tree/intersection_event_list.h | 69 - reducer_bench/quad_tree/line.h | 111 - reducer_bench/quad_tree/line_demo.c | 137 - reducer_bench/quad_tree/line_demo.h | 71 - reducer_bench/quad_tree/qtree.c | 232 -- reducer_bench/quad_tree/qtree.h | 62 - reducer_bench/quad_tree/reducer_defs.c | 23 - reducer_bench/quad_tree/reducer_defs.h | 41 - reducer_bench/quad_tree/screensaver.c | 132 - reducer_bench/quad_tree/vec.c | 102 - reducer_bench/quad_tree/vec.h | 82 - reducer_bench/repeatedintsum.c | 59 - reducer_bench/serialsum.c | 49 - reducer_bench/setup.sh | 29 - runtime/CMakeLists.txt | 704 ++-- runtime/Makefile | 18 +- runtime/TODOS.txt | 64 - runtime/cilk-internal.h | 51 +- runtime/cilk2c.c | 100 +- runtime/cilk2c.h | 94 +- runtime/cilk2c_inlined.c | 270 +- runtime/closure-type.h | 115 + runtime/closure.c | 421 -- runtime/closure.h | 550 ++- runtime/debug.h | 4 + runtime/fiber-pool.c | 1 + runtime/fiber.c | 180 +- runtime/fiber.h | 20 +- runtime/global.c | 23 +- runtime/global.h | 52 +- runtime/init.c | 322 +- runtime/init.h | 6 +- runtime/internal-malloc.c | 8 +- runtime/jmpbuf.h | 12 +- runtime/local.h | 2 + runtime/mutex.c | 58 - runtime/mutex.h | 56 +- runtime/personality.c | 12 +- runtime/readydeque.c | 184 - runtime/readydeque.h | 203 +- runtime/rts-config.h | 14 +- runtime/sched_stats.c | 148 +- runtime/sched_stats.h | 34 + runtime/scheduler.c | 738 +++- runtime/scheduler.h | 10 +- runtime/types.h | 3 + runtime/worker_coord.h | 451 +++ 106 files changed, 5389 insertions(+), 14234 deletions(-) create mode 100644 cmake/Modules/AddCheetah.cmake create mode 100644 cmake/Modules/CheetahDarwinUtils.cmake create mode 100644 cmake/Modules/CheetahUtils.cmake delete mode 100644 cmake/Modules/HandleOutOfTreeLLVM.cmake create mode 100644 cmake/base-config-ix.cmake delete mode 100644 reducer_bench/.gitignore delete mode 100644 reducer_bench/Makefile delete mode 100644 reducer_bench/cppsum.cpp delete mode 100644 reducer_bench/getoptions.c delete mode 100644 reducer_bench/getoptions.h delete mode 100644 reducer_bench/intlist.c delete mode 100644 reducer_bench/intlist.h delete mode 100644 reducer_bench/intsum.c delete mode 100644 reducer_bench/ktiming.c delete mode 100644 reducer_bench/ktiming.h delete mode 100644 reducer_bench/multispawnsum.c delete mode 100644 reducer_bench/nqueens/.gitignore delete mode 100644 reducer_bench/nqueens/Makefile delete mode 100644 reducer_bench/nqueens/board.c delete mode 100644 reducer_bench/nqueens/board.h delete mode 100644 reducer_bench/nqueens/fasttime.h delete mode 100644 reducer_bench/nqueens/ktiming.c delete mode 100644 reducer_bench/nqueens/ktiming.h delete mode 100644 reducer_bench/nqueens/nqueens.c delete mode 100644 reducer_bench/nqueens/nqueens_int.c delete mode 100644 reducer_bench/quad_tree/.gitignore delete mode 100644 reducer_bench/quad_tree/Makefile delete mode 100644 reducer_bench/quad_tree/beta delete mode 100644 reducer_bench/quad_tree/bin.c delete mode 100644 reducer_bench/quad_tree/bin.h delete mode 100644 reducer_bench/quad_tree/clint.py delete mode 100644 reducer_bench/quad_tree/collision_world.c delete mode 100644 reducer_bench/quad_tree/collision_world.h delete mode 100644 reducer_bench/quad_tree/fasttime.h delete mode 100644 reducer_bench/quad_tree/graphic_stuff.c delete mode 100644 reducer_bench/quad_tree/graphic_stuff.h delete mode 100644 reducer_bench/quad_tree/input/apple.in delete mode 100644 reducer_bench/quad_tree/input/beaver.in delete mode 100644 reducer_bench/quad_tree/input/box.in delete mode 100644 reducer_bench/quad_tree/input/explosion.in delete mode 100644 reducer_bench/quad_tree/input/mit.in delete mode 100644 reducer_bench/quad_tree/input/sin_wave.in delete mode 100644 reducer_bench/quad_tree/input/smalllines.in delete mode 100644 reducer_bench/quad_tree/intersection_detection.c delete mode 100644 reducer_bench/quad_tree/intersection_detection.h delete mode 100644 reducer_bench/quad_tree/intersection_event_list.c delete mode 100644 reducer_bench/quad_tree/intersection_event_list.h delete mode 100644 reducer_bench/quad_tree/line.h delete mode 100644 reducer_bench/quad_tree/line_demo.c delete mode 100644 reducer_bench/quad_tree/line_demo.h delete mode 100644 reducer_bench/quad_tree/qtree.c delete mode 100644 reducer_bench/quad_tree/qtree.h delete mode 100644 reducer_bench/quad_tree/reducer_defs.c delete mode 100644 reducer_bench/quad_tree/reducer_defs.h delete mode 100644 reducer_bench/quad_tree/screensaver.c delete mode 100644 reducer_bench/quad_tree/vec.c delete mode 100644 reducer_bench/quad_tree/vec.h delete mode 100644 reducer_bench/repeatedintsum.c delete mode 100644 reducer_bench/serialsum.c delete mode 100755 reducer_bench/setup.sh delete mode 100644 runtime/TODOS.txt create mode 100644 runtime/closure-type.h delete mode 100644 runtime/closure.c delete mode 100644 runtime/mutex.c delete mode 100644 runtime/readydeque.c create mode 100644 runtime/worker_coord.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 814e6357..bacc1ad5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,11 +2,6 @@ cmake_minimum_required(VERSION 3.9) -if(POLICY CMP0068) - cmake_policy(SET CMP0068 NEW) - set(CMAKE_BUILD_WITH_INSTALL_NAME_DIR ON) -endif() - # Add path for custom cheetah modules. set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" @@ -17,15 +12,13 @@ set(CMAKE_MODULE_PATH # Check if cheetah is built as a standalone project. if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR OR CHEETAH_STANDALONE_BUILD) project(Cheetah CXX C) + set(CHEETAH_STANDALONE_BUILD TRUE) set_property(GLOBAL PROPERTY USE_FOLDERS ON) set(PACKAGE_NAME Cheetah) - set(PACKAGE_VERSION 10.0.1) + set(PACKAGE_VERSION 12.0.0) set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}") set(PACKAGE_BUGREPORT "bugs@opencilk.org") - - # Find the LLVM sources and simulate LLVM CMake options. - include(HandleOutOfTreeLLVM) endif() # Require out of source build. @@ -35,6 +28,18 @@ MACRO_ENSURE_OUT_OF_SOURCE_BUILD( build directory and run 'cmake /path/to/${PROJECT_NAME} [options]' there." ) +# Option to build cheetah into separate directories per target. +# Defaults to true. +option(CHEETAH_DIRECTORY_PER_TARGET "Build cheetah into a separate directory per target." ON) +if (LLVM_ENABLE_PER_TARGET_RUNTIME_DIR) + set(CHEETAH_ENABLE_PER_TARGET_RUNTIME_DIR ${LLVM_ENABLE_PER_TARGET_RUNTIME_DIR}) +else() + set(CHEETAH_ENABLE_PER_TARGET_RUNTIME_DIR ${CHEETAH_DIRECTORY_PER_TARGET}) +endif() + +include(base-config-ix) +include(CheetahUtils) + #=============================================================================== # Setup CMake Options #=============================================================================== @@ -47,26 +52,11 @@ option(CHEETAH_ENABLE_WERROR "Fail and stop if a warning is triggered." OFF) option(CHEETAH_USE_COMPILER_RT "Use compiler-rt instead of libgcc" OFF) option(CHEETAH_INCLUDE_TESTS "Generate build targets for the cheetah unit tests." ${LLVM_INCLUDE_TESTS}) -set(CHEETAH_LIBDIR_SUFFIX "${LLVM_LIBDIR_SUFFIX}" CACHE STRING - "Define suffix of library directory name (32/64)") option(CHEETAH_INSTALL_LIBRARY "Install the cheetah library." ON) -set(CHEETAH_TARGET_TRIPLE "" CACHE STRING "Target triple for cross compiling.") -set(CHEETAH_GCC_TOOLCHAIN "" CACHE PATH "GCC toolchain for cross compiling.") -set(CHEETAH_SYSROOT "" CACHE PATH "Sysroot for cross compiling.") option(CHEETAH_ENABLE_SHARED "Build cheetah as a shared library." ON) option(CHEETAH_ENABLE_STATIC "Build cheetah as a static library." ON) -option(CHEETAH_ENABLE_BITCODE_ABI "Build cheetah ABI as LLVM bitcode." ON) - -cmake_dependent_option(CHEETAH_INSTALL_STATIC_LIBRARY - "Install the static cheetah library." ON - "CHEETAH_ENABLE_STATIC;CHEETAH_INSTALL_LIBRARY" OFF) -cmake_dependent_option(CHEETAH_INSTALL_SHARED_LIBRARY - "Install the shared cheetah library." ON - "CHEETAH_ENABLE_SHARED;CHEETAH_INSTALL_LIBRARY" OFF) -cmake_dependent_option(CHEETAH_INSTALL_BITCODE_ABI - "Install the cheetah ABI LLVM bitcode." ON - "CHEETAH_ENABLE_BITCODE_ABI;CHEETAH_INSTALL_LIBRARY" OFF) +option(CHEETAH_ENABLE_ASAN "Build cheetah with ASan support." ON) set(CHEETAH_ABI_VERSION "1" CACHE STRING "ABI version of cheetah. Defaults to 1.") @@ -78,67 +68,65 @@ endif() # Default minimum OSX version to support, if # CMAKE_OSX_DEPLOYMENT_TARGET is not specified -set(CHEETAH_MIN_OSX_VERSION 10.14) +set(DEFAULT_CHEETAH_MIN_OSX_VERSION 10.14) #=============================================================================== # Configure System #=============================================================================== -set(CHEETAH_COMPILER ${CMAKE_CXX_COMPILER}) -set(CHEETAH_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) -set(CHEETAH_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}) - -if (LLVM_LIBRARY_OUTPUT_INTDIR AND PACKAGE_VERSION) - string(REGEX MATCH "[0-9]+\\.[0-9]+(\\.[0-9]+)?" CLANG_VERSION - ${PACKAGE_VERSION}) - # Setup the paths where cheetah runtime and headers should be stored. - set(CHEETAH_OUTPUT_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR}/clang/${CLANG_VERSION}) - set(CHEETAH_INSTALL_PREFIX lib${LLVM_LIBDIR_SUFFIX}/clang/${CLANG_VERSION}) - - if (NOT APPLE) - set(CHEETAH_LIBRARY_DIR ${CHEETAH_OUTPUT_DIR}/lib/${LLVM_DEFAULT_TARGET_TRIPLE}) - set(CHEETAH_LIBRARY_INSTALL_DIR ${CHEETAH_INSTALL_PREFIX}/lib/${LLVM_DEFAULT_TARGET_TRIPLE}) - if (CHEETAH_LIBDIR_SUFFIX) - string(APPEND CHEETAH_LIBRARY_DIR /${CHEETAH_LIBDIR_SUFFIX}) - string(APPEND CHEETAH_LIBRARY_INSTALL_DIR /${CHEETAH_LIBDIR_SUFFIX}) - endif() - else() - if(NOT DEFINED CHEETAH_OS_DIR) - string(TOLOWER ${CMAKE_SYSTEM_NAME} CHEETAH_OS_DIR) +if (CHEETAH_STANDALONE_BUILD) + load_llvm_config() + if (TARGET intrinsics_gen) + # Loading the llvm config causes this target to be imported so place it + # under the appropriate folder in an IDE. + set_target_properties(intrinsics_gen PROPERTIES FOLDER "Cheetah Misc") + endif() + + find_package(Python3 COMPONENTS Interpreter) + if(NOT Python3_Interpreter_FOUND) + message(WARNING "Python3 not found, using python2 as a fallback") + find_package(Python2 COMPONENTS Interpreter REQUIRED) + if(Python2_VERSION VERSION_LESS 2.7) + message(SEND_ERROR "Python 2.7 or newer is required") endif() - set(CHEETAH_LIBRARY_DIR ${CHEETAH_OUTPUT_DIR}/lib/${CHEETAH_OS_DIR}) - set(CHEETAH_LIBRARY_INSTALL_DIR ${CHEETAH_INSTALL_PREFIX}/lib/${CHEETAH_OS_DIR}) + + # Treat python2 as python3 + add_executable(Python3::Interpreter IMPORTED) + set_target_properties(Python3::Interpreter PROPERTIES + IMPORTED_LOCATION ${Python2_EXECUTABLE}) + set(Python3_EXECUTABLE ${Python2_EXECUTABLE}) endif() - set(CHEETAH_HEADER_DIR ${CHEETAH_OUTPUT_DIR}/include) - set(CHEETAH_HEADER_INSTALL_DIR ${CHEETAH_INSTALL_PREFIX}/include) -else() - set(CHEETAH_OUTPUT_DIR ${CHEETAH_BINARY_DIR} CACHE PATH - "Path where built cheetah library should be stored.") - set(CHEETAH_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX} CACHE PATH - "Path where built cheetah library should be installed.") - set(CHEETAH_LIBRARY_DIR ${CHEETAH_OUTPUT_DIR}/lib${CHEETAH_LIBDIR_SUFFIX}) - set(CHEETAH_LIBRARY_INSTALL_DIR ${CHEETAH_INSTALL_PREFIX}/lib${CHEETAH_LIBDIR_SUFFIX}) - - set(CHEETAH_HEADER_DIR ${CHEETAH_OUTPUT_DIR}/include) - set(CHEETAH_HEADER_INSTALL_DIR ${CHEETAH_INSTALL_PREFIX}/include) + # Ensure that fat libraries are built correctly on Darwin + if(APPLE) + include(UseLibtool) + endif() + + # Define default arguments to lit. + set(LIT_ARGS_DEFAULT "-sv") + if (MSVC OR XCODE) + set(LIT_ARGS_DEFAULT "${LIT_ARGS_DEFAULT} --no-progress-bar") + endif() + set(LLVM_LIT_ARGS "${LIT_ARGS_DEFAULT}" CACHE STRING "Default options for lit") + set(LLVM_LIT_OUTPUT_DIR "${CHEETAH_EXEC_OUTPUT_DIR}") endif() -set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CHEETAH_LIBRARY_DIR}) -set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CHEETAH_LIBRARY_DIR}) -set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CHEETAH_LIBRARY_DIR}) +construct_cheetah_default_triple() +if ("${CHEETAH_DEFAULT_TARGET_TRIPLE}" MATCHES ".*hf$") + if (${CHEETAH_DEFAULT_TARGET_ARCH} MATCHES "^arm") + set(CHEETAH_DEFAULT_TARGET_ARCH "armhf") + endif() +endif() set(CHEETAH_C_FLAGS "") set(CHEETAH_CXX_FLAGS "") set(CHEETAH_COMPILE_FLAGS "") set(CHEETAH_COMPILE_DEFS "") set(CHEETAH_LINK_FLAGS "") -set(CHEETAH_LIBRARIES "") +set(CHEETAH_COMMON_LIBS "") -if (APPLE AND NOT CMAKE_OSX_DEPLOYMENT_TARGET) - list(APPEND CHEETAH_COMPILE_FLAGS -mmacosx-version-min=${CHEETAH_MIN_OSX_VERSION}) - list(APPEND CHEETAH_LINK_FLAGS -mmacosx-version-min=${CHEETAH_MIN_OSX_VERSION}) -endif() +option(CHEETAH_EXTERNALIZE_DEBUGINFO + "Generate dSYM files and strip executables and libraries (Darwin Only)" OFF) # Include macros for adding and removing cheetah flags. include(HandleCheetahFlags) @@ -147,34 +135,9 @@ include(HandleCheetahFlags) # Setup Compiler Flags #=============================================================================== -# Configure target flags -if(CHEETAH_TARGET_TRIPLE) - add_target_flags("--target=${CHEETAH_TARGET_TRIPLE}") -elseif(CMAKE_CXX_COMPILER_TARGET) - set(CHEETAH_TARGET_TRIPLE "${CMAKE_CXX_COMPILER_TARGET}") -endif() -if(CHEETAH_SYSROOT) - add_target_flags("--sysroot=${CHEETAH_SYSROOT}") -elseif(CMAKE_SYSROOT) - set(CHEETAH_SYSROOT "${CMAKE_SYSROOT}") -endif() -if(CHEETAH_GCC_TOOLCHAIN) - add_target_flags("--gcc-toolchain=${CHEETAH_GCC_TOOLCHAIN}") -elseif(CMAKE_CXX_COMPILER_EXTERNAL_TOOLCHAIN) - set(CHEETAH_GCC_TOOLCHAIN "${CMAKE_CXX_COMPILER_EXTERNAL_TOOLCHAIN}") -endif() - -if (CHEETAH_TARGET_TRIPLE) - set(TARGET_TRIPLE "${CHEETAH_TARGET_TRIPLE}") -endif() - # Configure compiler. include(config-ix) -if (APPLE AND CHEETAH_HAS_APP_EXTENSION) - list(APPEND CHEETAH_LINK_FLAGS "-fapplication-extension") -endif() - if (CHEETAH_USE_COMPILER_RT) list(APPEND CHEETAH_LINK_FLAGS "--rtlib=compiler-rt") endif() @@ -206,6 +169,8 @@ string(REPLACE ";" " " CHEETAH_CXX_FLAGS "${CHEETAH_CXX_FLAGS}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CHEETAH_CXX_FLAGS}") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${CHEETAH_C_FLAGS}") +include(AddCheetah) + #=============================================================================== # Setup Source Code #=============================================================================== diff --git a/cmake/Modules/AddCheetah.cmake b/cmake/Modules/AddCheetah.cmake new file mode 100644 index 00000000..34b95339 --- /dev/null +++ b/cmake/Modules/AddCheetah.cmake @@ -0,0 +1,487 @@ +include(ExternalProject) +include(CheetahUtils) + +function(set_target_output_directories target output_dir) + # For RUNTIME_OUTPUT_DIRECTORY variable, Multi-configuration generators + # append a per-configuration subdirectory to the specified directory. + # To avoid the appended folder, the configuration specific variable must be + # set 'RUNTIME_OUTPUT_DIRECTORY_${CONF}': + # RUNTIME_OUTPUT_DIRECTORY_DEBUG, RUNTIME_OUTPUT_DIRECTORY_RELEASE, ... + if(CMAKE_CONFIGURATION_TYPES) + foreach(build_mode ${CMAKE_CONFIGURATION_TYPES}) + string(TOUPPER "${build_mode}" CONFIG_SUFFIX) + set_target_properties("${target}" PROPERTIES + "ARCHIVE_OUTPUT_DIRECTORY_${CONFIG_SUFFIX}" ${output_dir} + "LIBRARY_OUTPUT_DIRECTORY_${CONFIG_SUFFIX}" ${output_dir} + "RUNTIME_OUTPUT_DIRECTORY_${CONFIG_SUFFIX}" ${output_dir}) + endforeach() + else() + set_target_properties("${target}" PROPERTIES + ARCHIVE_OUTPUT_DIRECTORY ${output_dir} + LIBRARY_OUTPUT_DIRECTORY ${output_dir} + RUNTIME_OUTPUT_DIRECTORY ${output_dir}) + endif() +endfunction() + +# Tries to add an "object library" target for a given list of OSs and/or +# architectures with name "." for non-Darwin platforms if +# architecture can be targeted, and "." for Darwin platforms. +# add_cheetah_object_libraries( +# OS +# ARCHS +# SOURCES +# CFLAGS +# DEFS +# DEPS +# ADDITIONAL_HEADERS
) +function(add_cheetah_object_libraries name) + cmake_parse_arguments(LIB "" "" "OS;ARCHS;SOURCES;CFLAGS;DEFS;DEPS;ADDITIONAL_HEADERS" + ${ARGN}) + set(libnames) + if(APPLE) + foreach(os ${LIB_OS}) + set(libname "${name}.${os}") + set(libnames ${libnames} ${libname}) + set(extra_cflags_${libname} ${DARWIN_${os}_CFLAGS}) + list_intersect(LIB_ARCHS_${libname} DARWIN_${os}_ARCHS LIB_ARCHS) + endforeach() + else() + foreach(arch ${LIB_ARCHS}) + set(libname "${name}.${arch}") + set(libnames ${libnames} ${libname}) + set(extra_cflags_${libname} ${TARGET_${arch}_CFLAGS}) + if(NOT CAN_TARGET_${arch}) + message(FATAL_ERROR "Architecture ${arch} can't be targeted") + return() + endif() + endforeach() + endif() + + # Add headers to LIB_SOURCES for IDEs + cheetah_process_sources(LIB_SOURCES + ${LIB_SOURCES} + ADDITIONAL_HEADERS + ${LIB_ADDITIONAL_HEADERS} + ) + + foreach(libname ${libnames}) + add_library(${libname} OBJECT ${LIB_SOURCES}) + if(LIB_DEPS) + add_dependencies(${libname} ${LIB_DEPS}) + endif() + + # Strip out -msse3 if this isn't macOS. + set(target_flags ${LIB_CFLAGS}) + if(APPLE AND NOT "${libname}" MATCHES ".*\.osx.*") + list(REMOVE_ITEM target_flags "-msse3") + endif() + + set_target_compile_flags(${libname} + ${extra_cflags_${libname}} ${target_flags}) + target_include_directories(${libname} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../include) + set_property(TARGET ${libname} APPEND PROPERTY + COMPILE_DEFINITIONS ${LIB_DEFS}) + set_target_properties(${libname} PROPERTIES FOLDER "Cheetah Libraries") + if(APPLE) + set_target_properties(${libname} PROPERTIES + OSX_ARCHITECTURES "${LIB_ARCHS_${libname}}") + endif() + endforeach() +endfunction() + +# Takes a list of object library targets, and a suffix and appends the proper +# TARGET_OBJECTS string to the output variable. +# format_object_libs( ...) +macro(format_object_libs output suffix) + foreach(lib ${ARGN}) + list(APPEND ${output} $) + endforeach() +endmacro() + +function(add_cheetah_component name) + add_custom_target(${name}) + set_target_properties(${name} PROPERTIES FOLDER "Cheetah Misc") + if(COMMAND runtime_register_component) + runtime_register_component(${name}) + endif() + add_dependencies(cheetah ${name}) +endfunction() + +macro(set_output_name output name arch) + if(CHEETAH_ENABLE_PER_TARGET_RUNTIME_DIR) + set(${output} ${name}) + else() + if(ANDROID AND ${arch} STREQUAL "i386") + set(${output} "${name}-i686${CHEETAH_OS_SUFFIX}") + else() + set(${output} "${name}-${arch}${CHEETAH_OS_SUFFIX}") + endif() + endif() +endmacro() + +# Adds static or shared runtime for a list of architectures and operating +# systems and puts it in the proper directory in the build and install trees. +# add_cheetah_runtime( +# {OBJECT|STATIC|SHARED} +# ARCHS +# OS +# SOURCES +# CFLAGS +# LINK_FLAGS +# DEFS +# LINK_LIBS (only for shared library) +# OBJECT_LIBS +# VERSION +# SOVERSION +# PARENT_TARGET +# ADDITIONAL_HEADERS
) +function(add_cheetah_runtime name type) + if(NOT type MATCHES "^(OBJECT|STATIC|SHARED)$") + message(FATAL_ERROR "type argument must be OBJECT, STATIC or SHARED") + return() + endif() + cmake_parse_arguments(LIB + "" + "PARENT_TARGET" + "OS;ARCHS;SOURCES;CFLAGS;LINK_FLAGS;DEFS;LINK_LIBS;OBJECT_LIBS;VERSION;SOVERSION;ADDITIONAL_HEADERS" + ${ARGN}) + set(libnames) + # Until we support this some other way, build cheetah runtime without LTO + # to allow non-LTO projects to link with it. + if(CHEETAH_HAS_FNO_LTO_FLAG) + set(NO_LTO_FLAGS "-fno-lto") + else() + set(NO_LTO_FLAGS "") + endif() + + list(LENGTH LIB_SOURCES LIB_SOURCES_LENGTH) + if (${LIB_SOURCES_LENGTH} GREATER 0) + # Add headers to LIB_SOURCES for IDEs. It doesn't make sense to + # do this for a runtime library that only consists of OBJECT + # libraries, so only add the headers when source files are present. + cheetah_process_sources(LIB_SOURCES + ${LIB_SOURCES} + ADDITIONAL_HEADERS + ${LIB_ADDITIONAL_HEADERS} + ) + endif() + + if(APPLE) + foreach(os ${LIB_OS}) + # Strip out -msse3 if this isn't macOS. + list(LENGTH LIB_CFLAGS HAS_EXTRA_CFLAGS) + if(HAS_EXTRA_CFLAGS AND NOT "${os}" MATCHES "^(osx)$") + list(REMOVE_ITEM LIB_CFLAGS "-msse3") + endif() + if(type STREQUAL "STATIC") + set(libname "${name}_${os}") + else() + set(libname "${name}_${os}_dynamic") + set(extra_link_flags_${libname} ${DARWIN_${os}_LINK_FLAGS} ${LIB_LINK_FLAGS}) + endif() + list_intersect(LIB_ARCHS_${libname} DARWIN_${os}_ARCHS LIB_ARCHS) + if(LIB_ARCHS_${libname}) + list(APPEND libnames ${libname}) + set(extra_cflags_${libname} ${DARWIN_${os}_CFLAGS} ${NO_LTO_FLAGS} ${LIB_CFLAGS}) + set(output_name_${libname} ${libname}${CHEETAH_OS_SUFFIX}) + set(sources_${libname} ${LIB_SOURCES}) + format_object_libs(sources_${libname} ${os} ${LIB_OBJECT_LIBS}) + get_cheetah_output_dir(${CHEETAH_DEFAULT_TARGET_ARCH} output_dir_${libname}) + get_cheetah_install_dir(${CHEETAH_DEFAULT_TARGET_ARCH} install_dir_${libname}) + endif() + endforeach() + else() + foreach(arch ${LIB_ARCHS}) + if(NOT CAN_TARGET_${arch}) + message(FATAL_ERROR "Architecture ${arch} can't be targeted") + return() + endif() + if(type STREQUAL "OBJECT") + set(libname "${name}-${arch}") + set_output_name(output_name_${libname} ${name}${CHEETAH_OS_SUFFIX} ${arch}) + elseif(type STREQUAL "STATIC") + set(libname "${name}-${arch}") + set_output_name(output_name_${libname} ${name} ${arch}) + else() + set(libname "${name}-dynamic-${arch}") + set(extra_cflags_${libname} ${TARGET_${arch}_CFLAGS} ${LIB_CFLAGS}) + set(extra_link_flags_${libname} ${TARGET_${arch}_LINK_FLAGS} ${LIB_LINK_FLAGS}) + if(WIN32) + set_output_name(output_name_${libname} ${name}_dynamic ${arch}) + else() + set_output_name(output_name_${libname} ${name} ${arch}) + endif() + endif() + set(sources_${libname} ${LIB_SOURCES}) + format_object_libs(sources_${libname} ${arch} ${LIB_OBJECT_LIBS}) + set(libnames ${libnames} ${libname}) + set(extra_cflags_${libname} ${TARGET_${arch}_CFLAGS} ${NO_LTO_FLAGS} ${LIB_CFLAGS}) + get_cheetah_output_dir(${arch} output_dir_${libname}) + get_cheetah_install_dir(${arch} install_dir_${libname}) + endforeach() + endif() + + if(NOT libnames) + return() + endif() + + if(LIB_PARENT_TARGET) + # If the parent targets aren't created we should create them + if(NOT TARGET ${LIB_PARENT_TARGET}) + add_custom_target(${LIB_PARENT_TARGET}) + set_target_properties(${LIB_PARENT_TARGET} PROPERTIES + FOLDER "Cheetah Misc") + endif() + endif() + + foreach(libname ${libnames}) + # If you are using a multi-configuration generator we don't generate + # per-library install rules, so we fall back to the parent target COMPONENT + if(CMAKE_CONFIGURATION_TYPES AND LIB_PARENT_TARGET) + set(COMPONENT_OPTION COMPONENT ${LIB_PARENT_TARGET}) + else() + set(COMPONENT_OPTION COMPONENT ${libname}) + endif() + + if(type STREQUAL "OBJECT") + if(CMAKE_C_COMPILER_ID MATCHES Clang AND CMAKE_C_COMPILER_TARGET) + list(APPEND extra_cflags_${libname} "--target=${CMAKE_C_COMPILER_TARGET}") + endif() + if(CMAKE_SYSROOT) + list(APPEND extra_cflags_${libname} "--sysroot=${CMAKE_SYSROOT}") + endif() + string(REPLACE ";" " " extra_cflags_${libname} "${extra_cflags_${libname}}") + string(REGEX MATCHALL "<[A-Za-z0-9_]*>" substitutions + ${CMAKE_C_COMPILE_OBJECT}) + set(compile_command_${libname} "${CMAKE_C_COMPILE_OBJECT}") + + set(output_file_${libname} ${output_name_${libname}}${CMAKE_C_OUTPUT_EXTENSION}) + foreach(substitution ${substitutions}) + if(substitution STREQUAL "") + string(REPLACE "" "${CMAKE_C_COMPILER} ${CMAKE_C_COMPILER_ARG1}" + compile_command_${libname} ${compile_command_${libname}}) + elseif(substitution STREQUAL "") + string(REPLACE "" "${output_dir_${libname}}/${output_file_${libname}}" + compile_command_${libname} ${compile_command_${libname}}) + elseif(substitution STREQUAL "") + string(REPLACE "" "${sources_${libname}}" + compile_command_${libname} ${compile_command_${libname}}) + elseif(substitution STREQUAL "") + string(REPLACE "" "${CMAKE_C_FLAGS} ${extra_cflags_${libname}}" + compile_command_${libname} ${compile_command_${libname}}) + else() + string(REPLACE "${substitution}" "" compile_command_${libname} + ${compile_command_${libname}}) + endif() + endforeach() + separate_arguments(compile_command_${libname}) + add_custom_command( + OUTPUT ${output_dir_${libname}}/${output_file_${libname}} + COMMAND ${compile_command_${libname}} + DEPENDS ${sources_${libname}} + COMMENT "Building C object ${output_file_${libname}}") + add_custom_target(${libname} DEPENDS ${output_dir_${libname}}/${output_file_${libname}}) + install(FILES ${output_dir_${libname}}/${output_file_${libname}} + DESTINATION ${install_dir_${libname}} + ${COMPONENT_OPTION}) + else() + add_library(${libname} ${type} ${sources_${libname}}) + set_target_compile_flags(${libname} ${extra_cflags_${libname}}) + target_include_directories(${libname} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../include) + set_target_link_flags(${libname} ${extra_link_flags_${libname}}) + set_property(TARGET ${libname} APPEND PROPERTY + COMPILE_DEFINITIONS ${LIB_DEFS}) + set_target_output_directories(${libname} ${output_dir_${libname}}) + install(TARGETS ${libname} + ARCHIVE DESTINATION ${install_dir_${libname}} + ${COMPONENT_OPTION} + LIBRARY DESTINATION ${install_dir_${libname}} + ${COMPONENT_OPTION} + RUNTIME DESTINATION ${install_dir_${libname}} + ${COMPONENT_OPTION}) + endif() + set_target_properties(${libname} PROPERTIES + OUTPUT_NAME ${output_name_${libname}}) + set_target_properties(${libname} PROPERTIES FOLDER "Cheetah Runtime") + set_target_properties(${libname} PROPERTIES VERSION ${LIB_VERSION} SOVERSION ${LIB_SOVERSION}) + target_compile_options(${libname} PUBLIC "$<$:${CHEETAH_DEBUG_OPTIONS}>") + target_compile_options(${libname} PUBLIC "$<$:${CHEETAH_RELEASE_OPTIONS}>") + if(LIB_LINK_LIBS) + target_link_libraries(${libname} PRIVATE ${LIB_LINK_LIBS}) + endif() + if(${type} STREQUAL "SHARED") + if(COMMAND llvm_setup_rpath) + llvm_setup_rpath(${libname}) + endif() + if(WIN32 AND NOT CYGWIN AND NOT MINGW) + set_target_properties(${libname} PROPERTIES IMPORT_PREFIX "") + set_target_properties(${libname} PROPERTIES IMPORT_SUFFIX ".lib") + endif() + if(APPLE) + # Ad-hoc sign the dylibs + add_custom_command(TARGET ${libname} + POST_BUILD + COMMAND codesign --sign - $ + WORKING_DIRECTORY ${CHEETAH_LIBRARY_OUTPUT_DIR} + ) + endif() + endif() + + set(parent_target_arg) + if(LIB_PARENT_TARGET) + set(parent_target_arg PARENT_TARGET ${LIB_PARENT_TARGET}) + endif() + add_cheetah_install_targets(${libname} ${parent_target_arg}) + + if(APPLE) + set_target_properties(${libname} PROPERTIES + OSX_ARCHITECTURES "${LIB_ARCHS_${libname}}") + endif() + + if(type STREQUAL "SHARED") + rt_externalize_debuginfo(${libname}) + endif() + endforeach() + if(LIB_PARENT_TARGET) + add_dependencies(${LIB_PARENT_TARGET} ${libnames}) + endif() +endfunction() + +function(rt_externalize_debuginfo name) + if(NOT CHEETAH_EXTERNALIZE_DEBUGINFO) + return() + endif() + + if(NOT CHEETAH_EXTERNALIZE_DEBUGINFO_SKIP_STRIP) + set(strip_command COMMAND xcrun strip -Sl $) + endif() + + if(APPLE) + if(CMAKE_CXX_FLAGS MATCHES "-flto" + OR CMAKE_CXX_FLAGS_${uppercase_CMAKE_BUILD_TYPE} MATCHES "-flto") + + set(lto_object ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${name}-lto.o) + set_property(TARGET ${name} APPEND_STRING PROPERTY + LINK_FLAGS " -Wl,-object_path_lto -Wl,${lto_object}") + endif() + add_custom_command(TARGET ${name} POST_BUILD + COMMAND xcrun dsymutil $ + ${strip_command}) + else() + message(FATAL_ERROR "CHEETAH_EXTERNALIZE_DEBUGINFO isn't implemented for non-darwin platforms!") + endif() +endfunction() + +# Adds bitcode files for a list of architectures and operating systems +# and puts it in the proper directory in the build and install trees. +# add_cheetah_bitcode( +# ARCHS +# OS +# SOURCES +# CFLAGS +# DEFS +# PARENT_TARGET +# ADDITIONAL_HEADERS
) +function(add_cheetah_bitcode name) + cmake_parse_arguments(LIB + "" + "PARENT_TARGET" + "OS;ARCHS;SOURCES;CFLAGS;DEFS;DEPS;ADDITIONAL_HEADERS" + ${ARGN}) + set(libnames) + + # Add headers to LIB_SOURCES for IDEs. It doesn't make sense to do + # this for a runtime library that only consists of OBJECT libraries, + # so only add the headers when source files are present. + cheetah_process_sources(LIB_SOURCES + ${LIB_SOURCES} + ADDITIONAL_HEADERS + ${LIB_ADDITIONAL_HEADERS} + ) + + if(APPLE) + foreach(os ${LIB_OS}) + list(LENGTH LIB_CFLAGS HAS_EXTRA_CFLAGS) + if(HAS_EXTRA_CFLAGS AND NOT "${os}" MATCHES "^(osx)$") + list(REMOVE_ITEM LIB_CFLAGS "-msse3") + endif() + set(libname "${name}_${os}") + list_intersect(LIB_ARCHS_${libname} DARWIN_${os}_ARCHS LIB_ARCHS) + if(LIB_ARCHS_${libname}) + list(APPEND libnames ${libname}) + set(extra_cflags_${libname} ${DARWIN_${os}_CFLAGS} ${LIB_CFLAGS}) + set(output_name_${libname} ${libname}${CHEETAH_OS_SUFFIX}) + set(sources_${libname} ${LIB_SOURCES}) + get_cheetah_output_dir(${CHEETAH_DEFAULT_TARGET_ARCH} output_dir_${libname}) + get_cheetah_install_dir(${CHEETAH_DEFAULT_TARGET_ARCH} install_dir_${libname}) + endif() + endforeach() + else() + foreach(arch ${LIB_ARCHS}) + if(NOT CAN_TARGET_${arch}) + message(FATAL_ERROR "Architecture ${arch} can't be targeted") + return() + endif() + set(libname "${name}-${arch}") + set_output_name(output_name_${libname} ${name}${CHEETAH_OS_SUFFIX} ${arch}) + set(sources_${libname} ${LIB_SOURCES}) + format_object_libs(sources_${libname} ${arch} ${LIB_OBJECT_LIBS}) + list(APPEND libnames ${libname}) + set(extra_cflags_${libname} ${TARGET_${arch}_CFLAGS} ${LIB_CFLAGS}) + get_cheetah_output_dir(${arch} output_dir_${libname}) + get_cheetah_install_dir(${arch} install_dir_${libname}) + endforeach() + endif() + + if(NOT libnames) + return() + endif() + + if(LIB_PARENT_TARGET) + # If the parent targets aren't created we should create them + if(NOT TARGET ${LIB_PARENT_TARGET}) + add_custom_target(${LIB_PARENT_TARGET}) + set_target_properties(${LIB_PARENT_TARGET} PROPERTIES + FOLDER "Cheetah Misc") + endif() + endif() + + foreach(libname ${libnames}) + # If you are using a multi-configuration generator we don't generate + # per-library install rules, so we fall back to the parent target COMPONENT + if(CMAKE_CONFIGURATION_TYPES AND LIB_PARENT_TARGET) + set(COMPONENT_OPTION COMPONENT ${LIB_PARENT_TARGET}) + else() + set(COMPONENT_OPTION COMPONENT ${libname}) + endif() + set(output_file_${libname} ${output_name_${libname}}.bc) + # Add compile command for bitcode file. + add_library(${libname}_compile OBJECT ${LIB_SOURCES}) + target_include_directories(${libname}_compile PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../include) + set_target_compile_flags(${libname}_compile ${extra_cflags_${libname}}) + target_compile_options(${libname}_compile PUBLIC "$<$:${CHEETAH_DEBUG_OPTIONS}>") + target_compile_options(${libname}_compile PUBLIC "$<$:${CHEETAH_RELEASE_OPTIONS}>") + set_property(TARGET ${libname}_compile APPEND PROPERTY + COMPILE_DEFINITIONS ${LIB_DEFS}) + set(output_file_${libname} lib${output_name_${libname}}.bc) + add_custom_command( + OUTPUT ${output_dir_${libname}}/${output_file_${libname}} + COMMAND cp $ ${output_dir_${libname}}/${output_file_${libname}} + DEPENDS ${libname}_compile $ + COMMENT "Building bitcode ${output_file_${libname}}" + VERBATIM) + add_custom_target(${libname} DEPENDS ${output_dir_${libname}}/${output_file_${libname}}) + install(FILES ${output_dir_${libname}}/${output_file_${libname}} + DESTINATION ${install_dir_${libname}} + ${COMPONENT_OPTION}) + + set(parent_target_arg) + if(LIB_PARENT_TARGET) + set(parent_target_arg PARENT_TARGET ${LIB_PARENT_TARGET}) + endif() + add_cheetah_install_targets(${libname} ${parent_target_arg}) + endforeach() + if(LIB_PARENT_TARGET) + add_dependencies(${LIB_PARENT_TARGET} ${libnames}) + endif() +endfunction() diff --git a/cmake/Modules/CheetahDarwinUtils.cmake b/cmake/Modules/CheetahDarwinUtils.cmake new file mode 100644 index 00000000..f2bf2a35 --- /dev/null +++ b/cmake/Modules/CheetahDarwinUtils.cmake @@ -0,0 +1,561 @@ +include(CMakeParseArguments) +include(CheetahUtils) + +set(CMAKE_LIPO "lipo" CACHE PATH "path to the lipo tool") + +# On OS X SDKs can be installed anywhere on the base system and xcode-select can +# set the default Xcode to use. This function finds the SDKs that are present in +# the current Xcode. +function(find_darwin_sdk_dir var sdk_name) + set(DARWIN_${sdk_name}_CACHED_SYSROOT "" CACHE STRING "Darwin SDK path for SDK ${sdk_name}.") + set(DARWIN_PREFER_PUBLIC_SDK OFF CACHE BOOL "Prefer Darwin public SDK, even when an internal SDK is present.") + + if(DARWIN_${sdk_name}_CACHED_SYSROOT) + set(${var} ${DARWIN_${sdk_name}_CACHED_SYSROOT} PARENT_SCOPE) + return() + endif() + if(NOT DARWIN_PREFER_PUBLIC_SDK) + # Let's first try the internal SDK, otherwise use the public SDK. + execute_process( + COMMAND xcrun --sdk ${sdk_name}.internal --show-sdk-path + RESULT_VARIABLE result_process + OUTPUT_VARIABLE var_internal + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_FILE /dev/null + ) + endif() + if((NOT result_process EQUAL 0) OR "" STREQUAL "${var_internal}") + execute_process( + COMMAND xcrun --sdk ${sdk_name} --show-sdk-path + RESULT_VARIABLE result_process + OUTPUT_VARIABLE var_internal + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_FILE /dev/null + ) + else() + set(${var}_INTERNAL ${var_internal} PARENT_SCOPE) + endif() + if(result_process EQUAL 0) + set(${var} ${var_internal} PARENT_SCOPE) + endif() + message(STATUS "Checking DARWIN_${sdk_name}_SYSROOT - '${var_internal}'") + set(DARWIN_${sdk_name}_CACHED_SYSROOT ${var_internal} CACHE STRING "Darwin SDK path for SDK ${sdk_name}." FORCE) +endfunction() + +function(find_darwin_sdk_version var sdk_name) + if (DARWIN_${sdk_name}_OVERRIDE_SDK_VERSION) + message(WARNING "Overriding ${sdk_name} SDK version to ${DARWIN_${sdk_name}_OVERRIDE_SDK_VERSION}") + set(${var} "${DARWIN_${sdk_name}_OVERRIDE_SDK_VERSION}" PARENT_SCOPE) + return() + endif() + set(result_process 1) + if(NOT DARWIN_PREFER_PUBLIC_SDK) + # Let's first try the internal SDK, otherwise use the public SDK. + execute_process( + COMMAND xcrun --sdk ${sdk_name}.internal --show-sdk-version + RESULT_VARIABLE result_process + OUTPUT_VARIABLE var_internal + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_FILE /dev/null + ) + endif() + if((NOT ${result_process} EQUAL 0) OR "" STREQUAL "${var_internal}") + execute_process( + COMMAND xcrun --sdk ${sdk_name} --show-sdk-version + RESULT_VARIABLE result_process + OUTPUT_VARIABLE var_internal + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_FILE /dev/null + ) + endif() + if(NOT result_process EQUAL 0) + message(FATAL_ERROR + "Failed to determine SDK version for \"${sdk_name}\" SDK") + endif() + # Check reported version looks sane. + if (NOT "${var_internal}" MATCHES "^[0-9]+\\.[0-9]+(\\.[0-9]+)?$") + message(FATAL_ERROR + "Reported SDK version \"${var_internal}\" does not look like a version") + endif() + set(${var} ${var_internal} PARENT_SCOPE) +endfunction() + +# There isn't a clear mapping of what architectures are supported with a given +# target platform, but ld's version output does list the architectures it can +# link for. +function(darwin_get_toolchain_supported_archs output_var) + execute_process( + COMMAND "${CMAKE_LINKER}" -v + ERROR_VARIABLE LINKER_VERSION) + + string(REGEX MATCH "configured to support archs: ([^\n]+)" + ARCHES_MATCHED "${LINKER_VERSION}") + if(ARCHES_MATCHED) + set(ARCHES "${CMAKE_MATCH_1}") + message(STATUS "Got ld supported ARCHES: ${ARCHES}") + string(REPLACE " " ";" ARCHES ${ARCHES}) + else() + # If auto-detecting fails, fall back to a default set + message(WARNING "Detecting supported architectures from 'ld -v' failed. Returning default set.") + set(ARCHES "i386;x86_64;armv7;armv7s;arm64") + endif() + + set(${output_var} ${ARCHES} PARENT_SCOPE) +endfunction() + +# This function takes an OS and a list of architectures and identifies the +# subset of the architectures list that the installed toolchain can target. +function(darwin_test_archs os valid_archs) + if(${valid_archs}) + message(STATUS "Using cached valid architectures for ${os}.") + return() + endif() + + set(archs ${ARGN}) + if(NOT TEST_COMPILE_ONLY) + message(STATUS "Finding valid architectures for ${os}...") + set(SIMPLE_C ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/src.c) + file(WRITE ${SIMPLE_C} "#include \nint main() { printf(__FILE__); return 0; }\n") + + set(os_linker_flags) + foreach(flag ${DARWIN_${os}_LINK_FLAGS}) + set(os_linker_flags "${os_linker_flags} ${flag}") + endforeach() + + # Disable building for i386 for macOS SDK >= 10.15. The SDK doesn't support + # linking for i386 and the corresponding OS doesn't allow running macOS i386 + # binaries. + if ("${os}" STREQUAL "osx") + find_darwin_sdk_version(macosx_sdk_version "macosx") + if ("${macosx_sdk_version}" VERSION_GREATER 10.15 OR "${macosx_sdk_version}" VERSION_EQUAL 10.15) + message(STATUS "Disabling i386 slice for ${valid_archs}") + list(REMOVE_ITEM archs "i386") + endif() + endif() + endif() + + # The simple program will build for x86_64h on the simulator because it is + # compatible with x86_64 libraries (mostly), but since x86_64h isn't actually + # a valid or useful architecture for the iOS simulator we should drop it. + if(${os} MATCHES "^(iossim|tvossim|watchossim)$") + list(REMOVE_ITEM archs "x86_64h") + endif() + + set(working_archs) + foreach(arch ${archs}) + + set(arch_linker_flags "-arch ${arch} ${os_linker_flags}") + if(TEST_COMPILE_ONLY) + # `-w` is used to surpress compiler warnings which `try_compile_only()` treats as an error. + try_compile_only(CAN_TARGET_${os}_${arch} FLAGS -v -arch ${arch} ${DARWIN_${os}_CFLAGS} -w) + else() + set(SAVED_CMAKE_EXE_LINKER_FLAGS ${CMAKE_EXE_LINKER_FLAGS}) + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${arch_linker_flags}") + try_compile(CAN_TARGET_${os}_${arch} ${CMAKE_BINARY_DIR} ${SIMPLE_C} + COMPILE_DEFINITIONS "-v -arch ${arch}" ${DARWIN_${os}_CFLAGS} + OUTPUT_VARIABLE TEST_OUTPUT) + set(CMAKE_EXE_LINKER_FLAGS ${SAVED_CMAKE_EXE_LINKER_FLAGS}) + endif() + if(${CAN_TARGET_${os}_${arch}}) + list(APPEND working_archs ${arch}) + else() + file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log + "Testing compiler for supporting ${os}-${arch}:\n" + "${TEST_OUTPUT}\n") + endif() + endforeach() + set(${valid_archs} ${working_archs} + CACHE STRING "List of valid architectures for platform ${os}." FORCE) +endfunction() + +# This function checks the host cputype/cpusubtype to filter supported +# architecture for the host OS. This is used to determine which tests are +# available for the host. +function(darwin_filter_host_archs input output) + list_intersect(tmp_var DARWIN_osx_ARCHS ${input}) + execute_process( + COMMAND sysctl hw.cputype + OUTPUT_VARIABLE CPUTYPE) + string(REGEX MATCH "hw.cputype: ([0-9]*)" + CPUTYPE_MATCHED "${CPUTYPE}") + set(ARM_HOST Off) + if(CPUTYPE_MATCHED) + # ARM cputype is (0x01000000 | 12) and X86(_64) is always 7. + if(${CMAKE_MATCH_1} GREATER 11) + set(ARM_HOST On) + endif() + endif() + + if(ARM_HOST) + list(REMOVE_ITEM tmp_var i386) + else() + list(REMOVE_ITEM tmp_var arm64) + list(REMOVE_ITEM tmp_var arm64e) + execute_process( + COMMAND sysctl hw.cpusubtype + OUTPUT_VARIABLE SUBTYPE) + string(REGEX MATCH "hw.cpusubtype: ([0-9]*)" + SUBTYPE_MATCHED "${SUBTYPE}") + + set(HASWELL_SUPPORTED Off) + if(SUBTYPE_MATCHED) + if(${CMAKE_MATCH_1} GREATER 7) + set(HASWELL_SUPPORTED On) + endif() + endif() + if(NOT HASWELL_SUPPORTED) + list(REMOVE_ITEM tmp_var x86_64h) + endif() + endif() + + set(${output} ${tmp_var} PARENT_SCOPE) +endfunction() + +# Read and process the exclude file into a list of symbols +function(darwin_read_list_from_file output_var file) + if(EXISTS ${file}) + file(READ ${file} EXCLUDES) + string(REPLACE "\n" ";" EXCLUDES ${EXCLUDES}) + set(${output_var} ${EXCLUDES} PARENT_SCOPE) + endif() +endfunction() + +# this function takes an OS, architecture and minimum version and provides a +# list of builtin functions to exclude +function(darwin_find_excluded_builtins_list output_var) + cmake_parse_arguments(LIB + "" + "OS;ARCH;MIN_VERSION" + "" + ${ARGN}) + + if(NOT LIB_OS OR NOT LIB_ARCH) + message(FATAL_ERROR "Must specify OS and ARCH to darwin_find_excluded_builtins_list!") + endif() + + darwin_read_list_from_file(${LIB_OS}_BUILTINS + ${DARWIN_EXCLUDE_DIR}/${LIB_OS}.txt) + darwin_read_list_from_file(${LIB_OS}_${LIB_ARCH}_BASE_BUILTINS + ${DARWIN_EXCLUDE_DIR}/${LIB_OS}-${LIB_ARCH}.txt) + + if(LIB_MIN_VERSION) + file(GLOB builtin_lists ${DARWIN_EXCLUDE_DIR}/${LIB_OS}*-${LIB_ARCH}.txt) + foreach(builtin_list ${builtin_lists}) + string(REGEX MATCH "${LIB_OS}([0-9\\.]*)-${LIB_ARCH}.txt" VERSION_MATCHED "${builtin_list}") + if (VERSION_MATCHED AND NOT CMAKE_MATCH_1 VERSION_LESS LIB_MIN_VERSION) + if(NOT smallest_version) + set(smallest_version ${CMAKE_MATCH_1}) + elseif(CMAKE_MATCH_1 VERSION_LESS smallest_version) + set(smallest_version ${CMAKE_MATCH_1}) + endif() + endif() + endforeach() + + if(smallest_version) + darwin_read_list_from_file(${LIB_ARCH}_${LIB_OS}_BUILTINS + ${DARWIN_EXCLUDE_DIR}/${LIB_OS}${smallest_version}-${LIB_ARCH}.txt) + endif() + endif() + + set(${output_var} + ${${LIB_ARCH}_${LIB_OS}_BUILTINS} + ${${LIB_OS}_${LIB_ARCH}_BASE_BUILTINS} + ${${LIB_OS}_BUILTINS} PARENT_SCOPE) +endfunction() + +# adds a single builtin library for a single OS & ARCH +macro(darwin_add_builtin_library name suffix) + cmake_parse_arguments(LIB + "" + "PARENT_TARGET;OS;ARCH" + "SOURCES;CFLAGS;DEFS;INCLUDE_DIRS" + ${ARGN}) + set(libname "${name}.${suffix}_${LIB_ARCH}_${LIB_OS}") + add_library(${libname} STATIC ${LIB_SOURCES}) + if(DARWIN_${LIB_OS}_SYSROOT) + set(sysroot_flag -isysroot ${DARWIN_${LIB_OS}_SYSROOT}) + endif() + + # Make a copy of the compilation flags. + set(builtin_cflags ${LIB_CFLAGS}) + + # Strip out any inappropriate flags for the target. + if("${LIB_ARCH}" MATCHES "^(armv7|armv7k|armv7s)$") + set(builtin_cflags "") + foreach(cflag "${LIB_CFLAGS}") + string(REPLACE "-fomit-frame-pointer" "" cflag "${cflag}") + list(APPEND builtin_cflags ${cflag}) + endforeach(cflag) + endif() + + set_target_compile_flags(${libname} + ${sysroot_flag} + ${DARWIN_${LIB_OS}_BUILTIN_MIN_VER_FLAG} + ${builtin_cflags}) + target_include_directories(${libname} + PRIVATE ${LIB_INCLUDE_DIRS}) + set_property(TARGET ${libname} APPEND PROPERTY + COMPILE_DEFINITIONS ${LIB_DEFS}) + set_target_properties(${libname} PROPERTIES + OUTPUT_NAME ${libname}${CHEETAH_OS_SUFFIX}) + set_target_properties(${libname} PROPERTIES + OSX_ARCHITECTURES ${LIB_ARCH}) + + if(LIB_PARENT_TARGET) + add_dependencies(${LIB_PARENT_TARGET} ${libname}) + endif() + + list(APPEND ${LIB_OS}_${suffix}_libs ${libname}) + list(APPEND ${LIB_OS}_${suffix}_lipo_flags -arch ${arch} $) + set_target_properties(${libname} PROPERTIES FOLDER "Cheetah Libraries") +endmacro() + +function(darwin_lipo_libs name) + cmake_parse_arguments(LIB + "" + "PARENT_TARGET;OUTPUT_DIR;INSTALL_DIR" + "LIPO_FLAGS;DEPENDS" + ${ARGN}) + if(LIB_DEPENDS AND LIB_LIPO_FLAGS) + add_custom_command(OUTPUT ${LIB_OUTPUT_DIR}/lib${name}.a + COMMAND ${CMAKE_COMMAND} -E make_directory ${LIB_OUTPUT_DIR} + COMMAND ${CMAKE_LIPO} -output + ${LIB_OUTPUT_DIR}/lib${name}.a + -create ${LIB_LIPO_FLAGS} + DEPENDS ${LIB_DEPENDS} + ) + add_custom_target(${name} + DEPENDS ${LIB_OUTPUT_DIR}/lib${name}.a) + set_target_properties(${name} PROPERTIES FOLDER "Cheetah Misc") + add_dependencies(${LIB_PARENT_TARGET} ${name}) + + if(CMAKE_CONFIGURATION_TYPES) + set(install_component ${LIB_PARENT_TARGET}) + else() + set(install_component ${name}) + endif() + install(FILES ${LIB_OUTPUT_DIR}/lib${name}.a + DESTINATION ${LIB_INSTALL_DIR} + COMPONENT ${install_component}) + add_cheetah_install_targets(${name} PARENT_TARGET ${LIB_PARENT_TARGET}) + else() + message(WARNING "Not generating lipo target for ${name} because no input libraries exist.") + endif() +endfunction() + +# Filter the list of builtin sources for Darwin, then delegate to the generic +# filtering. +# +# `exclude_or_include` must be one of: +# - EXCLUDE: remove every item whose name (w/o extension) matches a name in +# `excluded_list`. +# - INCLUDE: keep only items whose name (w/o extension) matches something +# in `excluded_list`. +function(darwin_filter_builtin_sources output_var name exclude_or_include excluded_list) + if(exclude_or_include STREQUAL "EXCLUDE") + set(filter_action GREATER) + set(filter_value -1) + elseif(exclude_or_include STREQUAL "INCLUDE") + set(filter_action LESS) + set(filter_value 0) + else() + message(FATAL_ERROR "darwin_filter_builtin_sources called without EXCLUDE|INCLUDE") + endif() + + set(intermediate ${ARGN}) + foreach(_file ${intermediate}) + get_filename_component(_name_we ${_file} NAME_WE) + list(FIND ${excluded_list} ${_name_we} _found) + if(_found ${filter_action} ${filter_value}) + list(REMOVE_ITEM intermediate ${_file}) + endif() + endforeach() + + filter_builtin_sources(intermediate ${name}) + set(${output_var} ${intermediate} PARENT_SCOPE) +endfunction() + +# Generates builtin libraries for all operating systems specified in ARGN. Each +# OS library is constructed by lipo-ing together single-architecture libraries. +macro(darwin_add_builtin_libraries) + set(DARWIN_EXCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/Darwin-excludes) + + set(CFLAGS "-fPIC -O3 -fvisibility=hidden -DVISIBILITY_HIDDEN -Wall -fomit-frame-pointer") + set(CMAKE_C_FLAGS "") + set(CMAKE_CXX_FLAGS "") + set(CMAKE_ASM_FLAGS "") + + set(PROFILE_SOURCES ../profile/InstrProfiling + ../profile/InstrProfilingBuffer + ../profile/InstrProfilingPlatformDarwin + ../profile/InstrProfilingWriter) + foreach (os ${ARGN}) + list_intersect(DARWIN_BUILTIN_ARCHS DARWIN_${os}_BUILTIN_ARCHS BUILTIN_SUPPORTED_ARCH) + foreach (arch ${DARWIN_BUILTIN_ARCHS}) + darwin_find_excluded_builtins_list(${arch}_${os}_EXCLUDED_BUILTINS + OS ${os} + ARCH ${arch} + MIN_VERSION ${DARWIN_${os}_BUILTIN_MIN_VER}) + + darwin_filter_builtin_sources(filtered_sources + ${os}_${arch} + EXCLUDE ${arch}_${os}_EXCLUDED_BUILTINS + ${${arch}_SOURCES}) + + darwin_add_builtin_library(clang_rt builtins + OS ${os} + ARCH ${arch} + SOURCES ${filtered_sources} + CFLAGS ${CFLAGS} -arch ${arch} + PARENT_TARGET builtins) + endforeach() + + # Don't build cc_kext libraries for simulator platforms + if(NOT DARWIN_${os}_SKIP_CC_KEXT) + foreach (arch ${DARWIN_BUILTIN_ARCHS}) + # By not specifying MIN_VERSION this only reads the OS and OS-arch lists. + # We don't want to filter out the builtins that are present in libSystem + # because kexts can't link libSystem. + darwin_find_excluded_builtins_list(${arch}_${os}_EXCLUDED_BUILTINS + OS ${os} + ARCH ${arch}) + + darwin_filter_builtin_sources(filtered_sources + cc_kext_${os}_${arch} + EXCLUDE ${arch}_${os}_EXCLUDED_BUILTINS + ${${arch}_SOURCES}) + + # In addition to the builtins cc_kext includes some profile sources + darwin_add_builtin_library(clang_rt cc_kext + OS ${os} + ARCH ${arch} + SOURCES ${filtered_sources} ${PROFILE_SOURCES} + CFLAGS ${CFLAGS} -arch ${arch} -mkernel + DEFS KERNEL_USE + INCLUDE_DIRS ../../include + PARENT_TARGET builtins) + endforeach() + set(archive_name clang_rt.cc_kext_${os}) + if(${os} STREQUAL "osx") + set(archive_name clang_rt.cc_kext) + endif() + darwin_lipo_libs(${archive_name} + PARENT_TARGET builtins + LIPO_FLAGS ${${os}_cc_kext_lipo_flags} + DEPENDS ${${os}_cc_kext_libs} + OUTPUT_DIR ${CHEETAH_LIBRARY_OUTPUT_DIR} + INSTALL_DIR ${CHEETAH_LIBRARY_INSTALL_DIR}) + endif() + endforeach() + + # We put the x86 sim slices into the archives for their base OS + foreach (os ${ARGN}) + if(NOT ${os} MATCHES ".*sim$") + darwin_lipo_libs(clang_rt.${os} + PARENT_TARGET builtins + LIPO_FLAGS ${${os}_builtins_lipo_flags} ${${os}sim_builtins_lipo_flags} + DEPENDS ${${os}_builtins_libs} ${${os}sim_builtins_libs} + OUTPUT_DIR ${CHEETAH_LIBRARY_OUTPUT_DIR} + INSTALL_DIR ${CHEETAH_LIBRARY_INSTALL_DIR}) + endif() + endforeach() + darwin_add_embedded_builtin_libraries() +endmacro() + +macro(darwin_add_embedded_builtin_libraries) + # this is a hacky opt-out. If you can't target both intel and arm + # architectures we bail here. + set(DARWIN_SOFT_FLOAT_ARCHS armv6m armv7m armv7em armv7) + set(DARWIN_HARD_FLOAT_ARCHS armv7em armv7) + if(CHEETAH_SUPPORTED_ARCH MATCHES ".*armv.*") + list(FIND CHEETAH_SUPPORTED_ARCH i386 i386_idx) + if(i386_idx GREATER -1) + list(APPEND DARWIN_HARD_FLOAT_ARCHS i386) + endif() + + list(FIND CHEETAH_SUPPORTED_ARCH x86_64 x86_64_idx) + if(x86_64_idx GREATER -1) + list(APPEND DARWIN_HARD_FLOAT_ARCHS x86_64) + endif() + + set(MACHO_SYM_DIR ${CMAKE_CURRENT_SOURCE_DIR}/macho_embedded) + + set(CFLAGS "-Oz -Wall -fomit-frame-pointer -ffreestanding") + set(CMAKE_C_FLAGS "") + set(CMAKE_CXX_FLAGS "") + set(CMAKE_ASM_FLAGS "") + + set(SOFT_FLOAT_FLAG -mfloat-abi=soft) + set(HARD_FLOAT_FLAG -mfloat-abi=hard) + + set(ENABLE_PIC Off) + set(PIC_FLAG -fPIC) + set(STATIC_FLAG -static) + + set(DARWIN_macho_embedded_ARCHS armv6m armv7m armv7em armv7 i386 x86_64) + + set(DARWIN_macho_embedded_LIBRARY_OUTPUT_DIR + ${CHEETAH_OUTPUT_DIR}/lib/macho_embedded) + set(DARWIN_macho_embedded_LIBRARY_INSTALL_DIR + ${CHEETAH_INSTALL_PATH}/lib/macho_embedded) + + set(CFLAGS_armv7 "-target thumbv7-apple-darwin-eabi") + set(CFLAGS_i386 "-march=pentium") + + darwin_read_list_from_file(common_FUNCTIONS ${MACHO_SYM_DIR}/common.txt) + darwin_read_list_from_file(thumb2_FUNCTIONS ${MACHO_SYM_DIR}/thumb2.txt) + darwin_read_list_from_file(thumb2_64_FUNCTIONS ${MACHO_SYM_DIR}/thumb2-64.txt) + darwin_read_list_from_file(arm_FUNCTIONS ${MACHO_SYM_DIR}/arm.txt) + darwin_read_list_from_file(i386_FUNCTIONS ${MACHO_SYM_DIR}/i386.txt) + + + set(armv6m_FUNCTIONS ${common_FUNCTIONS} ${arm_FUNCTIONS}) + set(armv7m_FUNCTIONS ${common_FUNCTIONS} ${arm_FUNCTIONS} ${thumb2_FUNCTIONS}) + set(armv7em_FUNCTIONS ${common_FUNCTIONS} ${arm_FUNCTIONS} ${thumb2_FUNCTIONS}) + set(armv7_FUNCTIONS ${common_FUNCTIONS} ${arm_FUNCTIONS} ${thumb2_FUNCTIONS} ${thumb2_64_FUNCTIONS}) + set(i386_FUNCTIONS ${common_FUNCTIONS} ${i386_FUNCTIONS}) + set(x86_64_FUNCTIONS ${common_FUNCTIONS}) + + foreach(arch ${DARWIN_macho_embedded_ARCHS}) + darwin_filter_builtin_sources(${arch}_filtered_sources + macho_embedded_${arch} + INCLUDE ${arch}_FUNCTIONS + ${${arch}_SOURCES}) + if(NOT ${arch}_filtered_sources) + message(WARNING "${arch}_SOURCES: ${${arch}_SOURCES}") + message(WARNING "${arch}_FUNCTIONS: ${${arch}_FUNCTIONS}") + message(FATAL_ERROR "Empty filtered sources!") + endif() + endforeach() + + foreach(float_type SOFT HARD) + foreach(type PIC STATIC) + string(TOLOWER "${float_type}_${type}" lib_suffix) + foreach(arch ${DARWIN_${float_type}_FLOAT_ARCHS}) + set(DARWIN_macho_embedded_SYSROOT ${DARWIN_osx_SYSROOT}) + set(float_flag) + if(${arch} MATCHES "^arm") + # x86 targets are hard float by default, but the complain about the + # float ABI flag, so don't pass it unless we're targeting arm. + set(float_flag ${${float_type}_FLOAT_FLAG}) + endif() + darwin_add_builtin_library(clang_rt ${lib_suffix} + OS macho_embedded + ARCH ${arch} + SOURCES ${${arch}_filtered_sources} + CFLAGS ${CFLAGS} -arch ${arch} ${${type}_FLAG} ${float_flag} ${CFLAGS_${arch}} + PARENT_TARGET builtins) + endforeach() + foreach(lib ${macho_embedded_${lib_suffix}_libs}) + set_target_properties(${lib} PROPERTIES LINKER_LANGUAGE C) + endforeach() + darwin_lipo_libs(clang_rt.${lib_suffix} + PARENT_TARGET builtins + LIPO_FLAGS ${macho_embedded_${lib_suffix}_lipo_flags} + DEPENDS ${macho_embedded_${lib_suffix}_libs} + OUTPUT_DIR ${DARWIN_macho_embedded_LIBRARY_OUTPUT_DIR} + INSTALL_DIR ${DARWIN_macho_embedded_LIBRARY_INSTALL_DIR}) + endforeach() + endforeach() + endif() +endmacro() diff --git a/cmake/Modules/CheetahUtils.cmake b/cmake/Modules/CheetahUtils.cmake new file mode 100644 index 00000000..021627dd --- /dev/null +++ b/cmake/Modules/CheetahUtils.cmake @@ -0,0 +1,481 @@ +include(CMakePushCheckState) +include(CheckSymbolExists) + +# Because cheetah spends a lot of time setting up custom compile +# flags, define a handy helper function for it. The compile flags +# setting in CMake has serious issues that make its syntax challenging +# at best. +function(set_target_compile_flags target) + set(argstring "") + foreach(arg ${ARGN}) + set(argstring "${argstring} ${arg}") + endforeach() + set_property(TARGET ${target} PROPERTY COMPILE_FLAGS "${argstring}") +endfunction() + +function(set_target_link_flags target) + set(argstring "") + foreach(arg ${ARGN}) + set(argstring "${argstring} ${arg}") + endforeach() + set_property(TARGET ${target} PROPERTY LINK_FLAGS "${argstring}") +endfunction() + +# Set the variable var_PYBOOL to True if var holds a true-ish string, +# otherwise set it to False. +macro(pythonize_bool var) + if (${var}) + set(${var}_PYBOOL True) + else() + set(${var}_PYBOOL False) + endif() +endmacro() + +# Appends value to all lists in ARGN, if the condition is true. +macro(append_list_if condition value) + if(${condition}) + foreach(list ${ARGN}) + list(APPEND ${list} ${value}) + endforeach() + endif() +endmacro() + +# Appends value to all strings in ARGN, if the condition is true. +macro(append_string_if condition value) + if(${condition}) + foreach(str ${ARGN}) + set(${str} "${${str}} ${value}") + endforeach() + endif() +endmacro() + +macro(append_rtti_flag polarity list) + if(${polarity}) + append_list_if(CHEETAH_HAS_FRTTI_FLAG -frtti ${list}) + append_list_if(CHEETAH_HAS_GR_FLAG /GR ${list}) + else() + append_list_if(CHEETAH_HAS_FNO_RTTI_FLAG -fno-rtti ${list}) + append_list_if(CHEETAH_HAS_GR_FLAG /GR- ${list}) + endif() +endmacro() + +macro(list_intersect output input1 input2) + set(${output}) + foreach(it ${${input1}}) + list(FIND ${input2} ${it} index) + if( NOT (index EQUAL -1)) + list(APPEND ${output} ${it}) + endif() + endforeach() +endmacro() + +function(list_replace input_list old new) + set(replaced_list) + foreach(item ${${input_list}}) + if(${item} STREQUAL ${old}) + list(APPEND replaced_list ${new}) + else() + list(APPEND replaced_list ${item}) + endif() + endforeach() + set(${input_list} "${replaced_list}" PARENT_SCOPE) +endfunction() + +# Takes ${ARGN} and puts only supported architectures in @out_var list. +function(filter_available_targets out_var) + set(archs ${${out_var}}) + foreach(arch ${ARGN}) + list(FIND CHEETAH_CMAKE_SUPPORTED_ARCH ${arch} ARCH_INDEX) + if(NOT (ARCH_INDEX EQUAL -1) AND CAN_TARGET_${arch}) + list(APPEND archs ${arch}) + endif() + endforeach() + set(${out_var} ${archs} PARENT_SCOPE) +endfunction() + +# Add $arch as supported with no additional flags. +macro(add_default_target_arch arch) + set(TARGET_${arch}_CFLAGS "") + set(CAN_TARGET_${arch} 1) + list(APPEND CHEETAH_CMAKE_SUPPORTED_ARCH ${arch}) +endmacro() + +function(check_compile_definition def argstring out_var) + if("${def}" STREQUAL "") + set(${out_var} TRUE PARENT_SCOPE) + return() + endif() + cmake_push_check_state() + set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} ${argstring}") + check_symbol_exists(${def} "" ${out_var}) + cmake_pop_check_state() +endfunction() + +# test_target_arch( ) +# Checks if architecture is supported: runs host compiler with provided +# flags to verify that: +# 1) is defined (if non-empty) +# 2) simple file can be successfully built. +# If successful, saves target flags for this architecture. +macro(test_target_arch arch def) + set(TARGET_${arch}_CFLAGS ${ARGN}) + set(TARGET_${arch}_LINK_FLAGS ${ARGN}) + set(argstring "") + foreach(arg ${ARGN}) + set(argstring "${argstring} ${arg}") + endforeach() + check_compile_definition("${def}" "${argstring}" HAS_${arch}_DEF) + if(NOT DEFINED CAN_TARGET_${arch}) + if(NOT HAS_${arch}_DEF) + set(CAN_TARGET_${arch} FALSE) + elseif(TEST_COMPILE_ONLY) + try_compile_only(CAN_TARGET_${arch} FLAGS ${TARGET_${arch}_CFLAGS}) + else() + set(FLAG_NO_EXCEPTIONS "") + if(CHEETAH_HAS_FNO_EXCEPTIONS_FLAG) + set(FLAG_NO_EXCEPTIONS " -fno-exceptions ") + endif() + set(SAVED_CMAKE_EXE_LINKER_FLAGS ${CMAKE_EXE_LINKER_FLAGS}) + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${argstring}") + try_compile(CAN_TARGET_${arch} ${CMAKE_BINARY_DIR} ${SIMPLE_SOURCE} + COMPILE_DEFINITIONS "${TARGET_${arch}_CFLAGS} ${FLAG_NO_EXCEPTIONS}" + OUTPUT_VARIABLE TARGET_${arch}_OUTPUT) + set(CMAKE_EXE_LINKER_FLAGS ${SAVED_CMAKE_EXE_LINKER_FLAGS}) + endif() + endif() + if(${CAN_TARGET_${arch}}) + list(APPEND CHEETAH_CMAKE_SUPPORTED_ARCH ${arch}) + elseif("${CHEETAH_DEFAULT_TARGET_ARCH}" STREQUAL "${arch}" AND + CHEETAH_HAS_EXPLICIT_DEFAULT_TARGET_TRIPLE) + # Bail out if we cannot target the architecture we plan to test. + message(FATAL_ERROR "Cannot compile for ${arch}:\n${TARGET_${arch}_OUTPUT}") + endif() +endmacro() + +macro(detect_target_arch) + check_symbol_exists(__arm__ "" __ARM) + check_symbol_exists(__aarch64__ "" __AARCH64) + check_symbol_exists(__x86_64__ "" __X86_64) + check_symbol_exists(__i386__ "" __I386) + check_symbol_exists(__mips__ "" __MIPS) + check_symbol_exists(__mips64__ "" __MIPS64) + check_symbol_exists(__powerpc64__ "" __PPC64) + check_symbol_exists(__powerpc64le__ "" __PPC64LE) + check_symbol_exists(__riscv "" __RISCV) + check_symbol_exists(__s390x__ "" __S390X) + check_symbol_exists(__sparc "" __SPARC) + check_symbol_exists(__sparcv9 "" __SPARCV9) + check_symbol_exists(__wasm32__ "" __WEBASSEMBLY32) + check_symbol_exists(__wasm64__ "" __WEBASSEMBLY64) + check_symbol_exists(__ve__ "" __VE) + if(__ARM) + add_default_target_arch(arm) + elseif(__AARCH64) + add_default_target_arch(aarch64) + elseif(__X86_64) + add_default_target_arch(x86_64) + elseif(__I386) + add_default_target_arch(i386) + elseif(__MIPS64) # must be checked before __MIPS + add_default_target_arch(mips64) + elseif(__MIPS) + add_default_target_arch(mips) + elseif(__PPC64) + add_default_target_arch(powerpc64) + elseif(__PPC64LE) + add_default_target_arch(powerpc64le) + elseif(__RISCV) + if(CMAKE_SIZEOF_VOID_P EQUAL "4") + add_default_target_arch(riscv32) + elseif(CMAKE_SIZEOF_VOID_P EQUAL "8") + add_default_target_arch(riscv64) + else() + message(FATAL_ERROR "Unsupport XLEN for RISC-V") + endif() + elseif(__S390X) + add_default_target_arch(s390x) + elseif(__SPARCV9) + add_default_target_arch(sparcv9) + elseif(__SPARC) + add_default_target_arch(sparc) + elseif(__WEBASSEMBLY32) + add_default_target_arch(wasm32) + elseif(__WEBASSEMBLY64) + add_default_target_arch(wasm64) + elseif(__VE) + add_default_target_arch(ve) + endif() +endmacro() + +macro(load_llvm_config) + if (NOT LLVM_CONFIG_PATH) + find_program(LLVM_CONFIG_PATH "llvm-config" + DOC "Path to llvm-config binary") + if (NOT LLVM_CONFIG_PATH) + message(WARNING "UNSUPPORTED CHEETAH CONFIGURATION DETECTED: " + "llvm-config not found.\n" + "Reconfigure with -DLLVM_CONFIG_PATH=path/to/llvm-config.") + endif() + endif() + if (LLVM_CONFIG_PATH) + execute_process( + COMMAND ${LLVM_CONFIG_PATH} "--obj-root" "--bindir" "--libdir" "--src-root" "--includedir" + RESULT_VARIABLE HAD_ERROR + OUTPUT_VARIABLE CONFIG_OUTPUT) + if (HAD_ERROR) + message(FATAL_ERROR "llvm-config failed with status ${HAD_ERROR}") + endif() + string(REGEX REPLACE "[ \t]*[\r\n]+[ \t]*" ";" CONFIG_OUTPUT ${CONFIG_OUTPUT}) + list(GET CONFIG_OUTPUT 0 BINARY_DIR) + list(GET CONFIG_OUTPUT 1 TOOLS_BINARY_DIR) + list(GET CONFIG_OUTPUT 2 LIBRARY_DIR) + list(GET CONFIG_OUTPUT 3 MAIN_SRC_DIR) + list(GET CONFIG_OUTPUT 4 INCLUDE_DIR) + + set(LLVM_BINARY_DIR ${BINARY_DIR} CACHE PATH "Path to LLVM build tree") + set(LLVM_LIBRARY_DIR ${LIBRARY_DIR} CACHE PATH "Path to llvm/lib") + set(LLVM_MAIN_SRC_DIR ${MAIN_SRC_DIR} CACHE PATH "Path to LLVM source tree") + set(LLVM_TOOLS_BINARY_DIR ${TOOLS_BINARY_DIR} CACHE PATH "Path to llvm/bin") + set(LLVM_INCLUDE_DIR ${INCLUDE_DIR} CACHE PATH "Paths to LLVM headers") + + # Detect if we have the LLVMXRay and TestingSupport library installed and + # available from llvm-config. + execute_process( + COMMAND ${LLVM_CONFIG_PATH} "--ldflags" "--libs" "xray" + RESULT_VARIABLE HAD_ERROR + OUTPUT_VARIABLE CONFIG_OUTPUT + ERROR_QUIET) + if (HAD_ERROR) + message(WARNING "llvm-config finding xray failed with status ${HAD_ERROR}") + set(CHEETAH_HAS_LLVMXRAY FALSE) + else() + string(REGEX REPLACE "[ \t]*[\r\n]+[ \t]*" ";" CONFIG_OUTPUT ${CONFIG_OUTPUT}) + list(GET CONFIG_OUTPUT 0 LDFLAGS) + list(GET CONFIG_OUTPUT 1 LIBLIST) + file(TO_CMAKE_PATH "${LDFLAGS}" LDFLAGS) + file(TO_CMAKE_PATH "${LIBLIST}" LIBLIST) + set(LLVM_XRAY_LDFLAGS ${LDFLAGS} CACHE STRING "Linker flags for LLVMXRay library") + set(LLVM_XRAY_LIBLIST ${LIBLIST} CACHE STRING "Library list for LLVMXRay") + set(CHEETAH_HAS_LLVMXRAY TRUE) + endif() + + # CHEETAH_HAS_LLVMTESTINGSUPPORT is currently unused, and this + # test triggers a CMake warning. Removing this test for now. + # + # set(CHEETAH_HAS_LLVMTESTINGSUPPORT FALSE) + # execute_process( + # COMMAND ${LLVM_CONFIG_PATH} "--ldflags" "--libs" "testingsupport" + # RESULT_VARIABLE HAD_ERROR + # OUTPUT_VARIABLE CONFIG_OUTPUT + # ERROR_QUIET) + # if (HAD_ERROR) + # message(WARNING "llvm-config finding testingsupport failed with status ${HAD_ERROR}") + # elseif(CHEETAH_INCLUDE_TESTS) + # string(REGEX REPLACE "[ \t]*[\r\n]+[ \t]*" ";" CONFIG_OUTPUT ${CONFIG_OUTPUT}) + # list(GET CONFIG_OUTPUT 0 LDFLAGS) + # list(GET CONFIG_OUTPUT 1 LIBLIST) + # if (LIBLIST STREQUAL "") + # message(WARNING "testingsupport library not installed, some tests will be skipped") + # else() + # file(TO_CMAKE_PATH "${LDFLAGS}" LDFLAGS) + # file(TO_CMAKE_PATH "${LIBLIST}" LIBLIST) + # set(LLVM_TESTINGSUPPORT_LDFLAGS ${LDFLAGS} CACHE STRING "Linker flags for LLVMTestingSupport library") + # set(LLVM_TESTINGSUPPORT_LIBLIST ${LIBLIST} CACHE STRING "Library list for LLVMTestingSupport") + # set(CHEETAH_HAS_LLVMTESTINGSUPPORT TRUE) + # endif() + # endif() + + # Make use of LLVM CMake modules. + # --cmakedir is supported since llvm r291218 (4.0 release) + execute_process( + COMMAND ${LLVM_CONFIG_PATH} --cmakedir + RESULT_VARIABLE HAD_ERROR + OUTPUT_VARIABLE CONFIG_OUTPUT) + if(NOT HAD_ERROR) + string(STRIP "${CONFIG_OUTPUT}" LLVM_CMAKE_PATH_FROM_LLVM_CONFIG) + file(TO_CMAKE_PATH ${LLVM_CMAKE_PATH_FROM_LLVM_CONFIG} LLVM_CMAKE_PATH) + else() + file(TO_CMAKE_PATH ${LLVM_BINARY_DIR} LLVM_BINARY_DIR_CMAKE_STYLE) + set(LLVM_CMAKE_PATH "${LLVM_BINARY_DIR_CMAKE_STYLE}/lib${LLVM_LIBDIR_SUFFIX}/cmake/llvm") + endif() + + list(APPEND CMAKE_MODULE_PATH "${LLVM_CMAKE_PATH}") + # Get some LLVM variables from LLVMConfig. + include("${LLVM_CMAKE_PATH}/LLVMConfig.cmake") + + set(LLVM_LIBRARY_OUTPUT_INTDIR + ${LLVM_BINARY_DIR}/${CMAKE_CFG_INTDIR}/lib${LLVM_LIBDIR_SUFFIX}) + endif() +endmacro() + +macro(construct_cheetah_default_triple) + if(CHEETAH_DEFAULT_TARGET_ONLY) + if(DEFINED CHEETAH_DEFAULT_TARGET_TRIPLE) + message(FATAL_ERROR "CHEETAH_DEFAULT_TARGET_TRIPLE isn't supported when building for default target only") + endif() + set(CHEETAH_DEFAULT_TARGET_TRIPLE ${CMAKE_C_COMPILER_TARGET}) + else() + set(CHEETAH_DEFAULT_TARGET_TRIPLE ${TARGET_TRIPLE} CACHE STRING + "Default triple for which cheetah runtime will be built.") + endif() + + if(DEFINED CHEETAH_TEST_TARGET_TRIPLE) + # Backwards compatibility: this variable used to be called + # CHEETAH_TEST_TARGET_TRIPLE. + set(CHEETAH_DEFAULT_TARGET_TRIPLE ${CHEETAH_TEST_TARGET_TRIPLE}) + endif() + + string(REPLACE "-" ";" TARGET_TRIPLE_LIST ${CHEETAH_DEFAULT_TARGET_TRIPLE}) + list(GET TARGET_TRIPLE_LIST 0 CHEETAH_DEFAULT_TARGET_ARCH) + # Determine if test target triple is specified explicitly, and doesn't match the + # default. + if(NOT CHEETAH_DEFAULT_TARGET_TRIPLE STREQUAL TARGET_TRIPLE) + set(CHEEETAH_HAS_EXPLICIT_DEFAULT_TARGET_TRIPLE TRUE) + else() + set(CHEETAH_HAS_EXPLICIT_DEFAULT_TARGET_TRIPLE FALSE) + endif() +endmacro() + +# Filter out generic versions of routines that are re-implemented in an +# architecture specific manner. This prevents multiple definitions of the same +# symbols, making the symbol selection non-deterministic. +# +# We follow the convention that a source file that exists in a sub-directory +# (e.g. `ppc/divtc3.c`) is architecture-specific and that if a generic +# implementation exists it will be a top-level source file with the same name +# modulo the file extension (e.g. `divtc3.c`). +function(filter_builtin_sources inout_var name) + set(intermediate ${${inout_var}}) + foreach(_file ${intermediate}) + get_filename_component(_file_dir ${_file} DIRECTORY) + if (NOT "${_file_dir}" STREQUAL "") + # Architecture specific file. If a generic version exists, print a notice + # and ensure that it is removed from the file list. + get_filename_component(_name ${_file} NAME) + string(REGEX REPLACE "\\.S$" ".c" _cname "${_name}") + if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${_cname}") + message(STATUS "For ${name} builtins preferring ${_file} to ${_cname}") + list(REMOVE_ITEM intermediate ${_cname}) + endif() + endif() + endforeach() + set(${inout_var} ${intermediate} PARENT_SCOPE) +endfunction() + +function(get_cheetah_target arch variable) + string(FIND ${CHEETAH_DEFAULT_TARGET_TRIPLE} "-" dash_index) + string(SUBSTRING ${CHEETAH_DEFAULT_TARGET_TRIPLE} ${dash_index} -1 triple_suffix) + if(CHEETAH_DEFAULT_TARGET_ONLY) + # Use exact spelling when building only for the target specified to CMake. + set(target "${CHEETAH_DEFAULT_TARGET_TRIPLE}") + elseif(ANDROID AND ${arch} STREQUAL "i386") + set(target "i686${triple_suffix}") + else() + set(target "${arch}${triple_suffix}") + endif() + set(${variable} ${target} PARENT_SCOPE) +endfunction() + +function(get_cheetah_install_dir arch install_dir) + if(CHEETAH_ENABLE_PER_TARGET_RUNTIME_DIR AND NOT APPLE) + get_cheetah_target(${arch} target) + set(${install_dir} ${CHEETAH_INSTALL_PATH}/lib/${target} PARENT_SCOPE) + else() + set(${install_dir} ${CHEETAH_LIBRARY_INSTALL_DIR} PARENT_SCOPE) + endif() +endfunction() + +function(get_cheetah_output_dir arch output_dir) + if(CHEETAH_ENABLE_PER_TARGET_RUNTIME_DIR AND NOT APPLE) + get_cheetah_target(${arch} target) + set(${output_dir} ${CHEETAH_OUTPUT_DIR}/lib/${target} PARENT_SCOPE) + else() + set(${output_dir} ${CHEETAH_LIBRARY_OUTPUT_DIR} PARENT_SCOPE) + endif() +endfunction() + +# cheetah_process_sources( +# +# ... +# [ADDITIONAL_HEADERS
...] +# ) +# +# Process the provided sources and write the list of new sources +# into ``. +# +# ADDITIONAL_HEADERS - Adds the supplied header to list of sources for IDEs. +# +# This function is very similar to `llvm_process_sources()` but exists here +# because we need to support standalone builds of cheetah. +function(cheetah_process_sources OUTPUT_VAR) + cmake_parse_arguments( + ARG + "" + "" + "ADDITIONAL_HEADERS" + ${ARGN} + ) + set(sources ${ARG_UNPARSED_ARGUMENTS}) + set(headers "") + if (XCODE OR MSVC_IDE OR CMAKE_EXTRA_GENERATOR) + # For IDEs we need to tell CMake about header files. + # Otherwise they won't show up in UI. + set(headers ${ARG_ADDITIONAL_HEADERS}) + list(LENGTH headers headers_length) + if (${headers_length} GREATER 0) + set_source_files_properties(${headers} + PROPERTIES HEADER_FILE_ONLY ON) + endif() + endif() + set("${OUTPUT_VAR}" ${sources} ${headers} PARENT_SCOPE) +endfunction() + +# Create install targets for a library and its parent component (if specified). +function(add_cheetah_install_targets name) + cmake_parse_arguments(ARG "" "PARENT_TARGET" "" ${ARGN}) + + if(ARG_PARENT_TARGET AND NOT TARGET install-${ARG_PARENT_TARGET}) + # The parent install target specifies the parent component to scrape up + # anything not installed by the individual install targets, and to handle + # installation when running the multi-configuration generators. + add_custom_target(install-${ARG_PARENT_TARGET} + DEPENDS ${ARG_PARENT_TARGET} + COMMAND "${CMAKE_COMMAND}" + -DCMAKE_INSTALL_COMPONENT=${ARG_PARENT_TARGET} + -P "${CMAKE_BINARY_DIR}/cmake_install.cmake") + add_custom_target(install-${ARG_PARENT_TARGET}-stripped + DEPENDS ${ARG_PARENT_TARGET} + COMMAND "${CMAKE_COMMAND}" + -DCMAKE_INSTALL_COMPONENT=${ARG_PARENT_TARGET} + -DCMAKE_INSTALL_DO_STRIP=1 + -P "${CMAKE_BINARY_DIR}/cmake_install.cmake") + set_target_properties(install-${ARG_PARENT_TARGET} PROPERTIES + FOLDER "Cheetah Misc") + set_target_properties(install-${ARG_PARENT_TARGET}-stripped PROPERTIES + FOLDER "Cheetah Misc") + add_dependencies(install-cheetah install-${ARG_PARENT_TARGET}) + add_dependencies(install-cheetah-stripped install-${ARG_PARENT_TARGET}-stripped) + endif() + + # We only want to generate per-library install targets if you aren't using + # an IDE because the extra targets get cluttered in IDEs. + if(NOT CMAKE_CONFIGURATION_TYPES) + add_custom_target(install-${name} + DEPENDS ${name} + COMMAND "${CMAKE_COMMAND}" + -DCMAKE_INSTALL_COMPONENT=${name} + -P "${CMAKE_BINARY_DIR}/cmake_install.cmake") + add_custom_target(install-${name}-stripped + DEPENDS ${name} + COMMAND "${CMAKE_COMMAND}" + -DCMAKE_INSTALL_COMPONENT=${name} + -DCMAKE_INSTALL_DO_STRIP=1 + -P "${CMAKE_BINARY_DIR}/cmake_install.cmake") + # If you have a parent target specified, we bind the new install target + # to the parent install target. + if(LIB_PARENT_TARGET) + add_dependencies(install-${LIB_PARENT_TARGET} install-${name}) + add_dependencies(install-${LIB_PARENT_TARGET}-stripped install-${name}-stripped) + endif() + endif() +endfunction() diff --git a/cmake/Modules/HandleCheetahFlags.cmake b/cmake/Modules/HandleCheetahFlags.cmake index 77245073..4c20b966 100644 --- a/cmake/Modules/HandleCheetahFlags.cmake +++ b/cmake/Modules/HandleCheetahFlags.cmake @@ -1,8 +1,7 @@ # HandleCheetahFlags - A set of macros used to setup the flags used to compile # and link cheetah. These macros add flags to the following CMake variables. -# - CHEETAH_COMPILE_FLAGS: flags used to compile libc++abi -# - CHEETAH_LINK_FLAGS: flags used to link libc++abi -# - CHEETAH_LIBRARIES: libraries to link libc++abi to. +# - CHEETAH_COMPILE_FLAGS: flags used to compile cheetah +# - CHEETAH_LINK_FLAGS: flags used to link cheetah include(CheckCXXCompilerFlag) @@ -187,21 +186,6 @@ macro(add_link_flags_if_supported) endforeach() endmacro() -# Add a list of libraries or link flags to 'CHEETAH_LIBRARIES'. -macro(add_library_flags) - foreach(lib ${ARGN}) - list(APPEND CHEETAH_LIBRARIES ${lib}) - endforeach() -endmacro() - -# if 'condition' is true then add the specified list of libraries and flags -# to 'CHEETAH_LIBRARIES'. -macro(add_library_flags_if condition) - if(${condition}) - add_library_flags(${ARGN}) - endif() -endmacro() - # Turn a comma separated CMake list into a space separated string. macro(split_list listname) string(REPLACE ";" " " ${listname} "${${listname}}") diff --git a/cmake/Modules/HandleOutOfTreeLLVM.cmake b/cmake/Modules/HandleOutOfTreeLLVM.cmake deleted file mode 100644 index 54af3714..00000000 --- a/cmake/Modules/HandleOutOfTreeLLVM.cmake +++ /dev/null @@ -1,140 +0,0 @@ -macro(find_llvm_parts) -# Rely on llvm-config. - set(CONFIG_OUTPUT) - if(NOT LLVM_CONFIG_PATH) - find_program(LLVM_CONFIG_PATH "llvm-config") - endif() - if(DEFINED LLVM_PATH) - set(LLVM_INCLUDE_DIR ${LLVM_INCLUDE_DIR} CACHE PATH "Path to llvm/include") - set(LLVM_PATH ${LLVM_PATH} CACHE PATH "Path to LLVM source tree") - set(LLVM_MAIN_SRC_DIR ${LLVM_PATH}) - set(LLVM_CMAKE_PATH "${LLVM_PATH}/cmake/modules") - elseif(LLVM_CONFIG_PATH) - message(STATUS "Found LLVM_CONFIG_PATH as ${LLVM_CONFIG_PATH}") - set(CHEETAH_USING_INSTALLED_LLVM 1) - set(CONFIG_COMMAND ${LLVM_CONFIG_PATH} - "--includedir" - "--prefix" - "--src-root") - execute_process( - COMMAND ${CONFIG_COMMAND} - RESULT_VARIABLE HAD_ERROR - OUTPUT_VARIABLE CONFIG_OUTPUT - ) - if(NOT HAD_ERROR) - string(REGEX REPLACE - "[ \t]*[\r\n]+[ \t]*" ";" - CONFIG_OUTPUT ${CONFIG_OUTPUT}) - else() - string(REPLACE ";" " " CONFIG_COMMAND_STR "${CONFIG_COMMAND}") - message(STATUS "${CONFIG_COMMAND_STR}") - message(FATAL_ERROR "llvm-config failed with status ${HAD_ERROR}") - endif() - - list(GET CONFIG_OUTPUT 0 INCLUDE_DIR) - list(GET CONFIG_OUTPUT 1 LLVM_OBJ_ROOT) - list(GET CONFIG_OUTPUT 2 MAIN_SRC_DIR) - - set(LLVM_INCLUDE_DIR ${INCLUDE_DIR} CACHE PATH "Path to llvm/include") - set(LLVM_BINARY_DIR ${LLVM_OBJ_ROOT} CACHE PATH "Path to LLVM build tree") - set(LLVM_MAIN_SRC_DIR ${MAIN_SRC_DIR} CACHE PATH "Path to LLVM source tree") - - # --cmakedir is supported since llvm r291218 (4.0 release) - execute_process( - COMMAND ${LLVM_CONFIG_PATH} --cmakedir - RESULT_VARIABLE HAD_ERROR - OUTPUT_VARIABLE CONFIG_OUTPUT - ERROR_QUIET) - if(NOT HAD_ERROR) - string(STRIP "${CONFIG_OUTPUT}" LLVM_CMAKE_PATH_FROM_LLVM_CONFIG) - file(TO_CMAKE_PATH "${LLVM_CMAKE_PATH_FROM_LLVM_CONFIG}" LLVM_CMAKE_PATH) - else() - file(TO_CMAKE_PATH "${LLVM_BINARY_DIR}" LLVM_BINARY_DIR_CMAKE_STYLE) - set(LLVM_CMAKE_PATH "${LLVM_BINARY_DIR_CMAKE_STYLE}/lib${LLVM_LIBDIR_SUFFIX}/cmake/llvm") - endif() - else() - set(LLVM_FOUND OFF) - message(WARNING "UNSUPPORTED CHEETAH CONFIGURATION DETECTED: " - "llvm-config not found and LLVM_PATH not defined.\n" - "Reconfigure with -DLLVM_CONFIG_PATH=path/to/llvm-config " - "or -DLLVM_PATH=path/to/llvm-source-root.") - return() - endif() - - if (EXISTS "${LLVM_CMAKE_PATH}") - list(APPEND CMAKE_MODULE_PATH "${LLVM_CMAKE_PATH}") - elseif (EXISTS "${LLVM_MAIN_SRC_DIR}/cmake/modules") - list(APPEND CMAKE_MODULE_PATH "${LLVM_MAIN_SRC_DIR}/cmake/modules") - else() - set(LLVM_FOUND OFF) - message(WARNING "Neither ${LLVM_CMAKE_PATH} nor ${LLVM_MAIN_SRC_DIR}/cmake/modules found") - return() - endif() - - set(LLVM_FOUND ON) -endmacro(find_llvm_parts) - -macro(configure_out_of_tree_llvm) - message(STATUS "Configuring for standalone build.") - set(CHEETAH_STANDALONE_BUILD 1) - - find_llvm_parts() - - # Add LLVM Functions -------------------------------------------------------- - if (LLVM_FOUND AND CHEETAH_USING_INSTALLED_LLVM) - include(LLVMConfig) # For TARGET_TRIPLE - else() - if (WIN32) - set(LLVM_ON_UNIX 0) - set(LLVM_ON_WIN32 1) - else() - set(LLVM_ON_UNIX 1) - set(LLVM_ON_WIN32 0) - endif() - endif() - if (LLVM_FOUND) - include(AddLLVM OPTIONAL) - include(HandleLLVMOptions OPTIONAL) - endif() - - # LLVM Options -------------------------------------------------------------- - if (NOT DEFINED LLVM_INCLUDE_TESTS) - set(LLVM_INCLUDE_TESTS ${LLVM_FOUND}) - endif() - if (NOT DEFINED LLVM_INCLUDE_DOCS) - set(LLVM_INCLUDE_DOCS ${LLVM_FOUND}) - endif() - if (NOT DEFINED LLVM_ENABLE_SPHINX) - set(LLVM_ENABLE_SPHINX OFF) - endif() - - # In a standalone build, we don't have llvm to automatically generate the - # llvm-lit script for us. So we need to provide an explicit directory that - # the configurator should write the script into. - set(LLVM_LIT_OUTPUT_DIR "${cheetah_BINARY_DIR}/bin") - - if (LLVM_INCLUDE_TESTS) - # Required LIT Configuration ------------------------------------------------ - # Define the default arguments to use with 'lit', and an option for the user - # to override. - set(LLVM_DEFAULT_EXTERNAL_LIT "${LLVM_MAIN_SRC_DIR}/utils/lit/lit.py") - set(LIT_ARGS_DEFAULT "-sv --show-xfail --show-unsupported") - if (MSVC OR XCODE) - set(LIT_ARGS_DEFAULT "${LIT_ARGS_DEFAULT} --no-progress-bar") - endif() - set(LLVM_LIT_ARGS "${LIT_ARGS_DEFAULT}" CACHE STRING "Default options for lit") - endif() - - # Required doc configuration - if (LLVM_ENABLE_SPHINX) - find_package(Sphinx REQUIRED) - endif() - - if (LLVM_ON_UNIX AND NOT APPLE) - set(LLVM_HAVE_LINK_VERSION_SCRIPT 1) - else() - set(LLVM_HAVE_LINK_VERSION_SCRIPT 0) - endif() -endmacro(configure_out_of_tree_llvm) - -configure_out_of_tree_llvm() diff --git a/cmake/base-config-ix.cmake b/cmake/base-config-ix.cmake new file mode 100644 index 00000000..798affc3 --- /dev/null +++ b/cmake/base-config-ix.cmake @@ -0,0 +1,245 @@ +# The Cheetah build system requires CMake version 2.8.8 or higher in order +# to use its support for building convenience "libraries" as a collection of +# .o files. This is particularly useful in producing larger, more complex +# runtime libraries. + +include(CheckIncludeFile) +include(CheckCXXSourceCompiles) +include(TestBigEndian) + +check_include_file(unwind.h HAVE_UNWIND_H) + +# Used by sanitizer_common and tests. +check_include_file(rpc/xdr.h HAVE_RPC_XDR_H) +if (NOT HAVE_RPC_XDR_H) + set(HAVE_RPC_XDR_H 0) +endif() + +# Top level target used to build all cheetah libraries. +add_custom_target(cheetah ALL) +add_custom_target(install-cheetah) +add_custom_target(install-cheetah-stripped) +set_property( + TARGET + cheetah + install-cheetah + install-cheetah-stripped + PROPERTY + FOLDER "Cheetah Misc" +) + +# Setting these variables from an LLVM build is sufficient that cilktools can +# construct the output paths, so it can behave as if it were in-tree here. +if (LLVM_LIBRARY_OUTPUT_INTDIR AND LLVM_RUNTIME_OUTPUT_INTDIR AND PACKAGE_VERSION) + set(LLVM_TREE_AVAILABLE On) +endif() + +if (LLVM_TREE_AVAILABLE) + # Compute the Clang version from the LLVM version. + # FIXME: We should be able to reuse CLANG_VERSION variable calculated + # in Clang cmake files, instead of copying the rules here. + string(REGEX MATCH "[0-9]+\\.[0-9]+(\\.[0-9]+)?" CLANG_VERSION + ${PACKAGE_VERSION}) + # Setup the paths where cheetah runtimes and headers should be stored. + set(CHEETAH_OUTPUT_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR}/clang/${CLANG_VERSION}) + set(CHEETAH_EXEC_OUTPUT_DIR ${LLVM_RUNTIME_OUTPUT_INTDIR}) + set(CHEETAH_INSTALL_PATH lib${LLVM_LIBDIR_SUFFIX}/clang/${CLANG_VERSION}) + option(CHEETAH_INCLUDE_TESTS "Generate and build cheetah unit tests." + ${LLVM_INCLUDE_TESTS}) + option(CHEETAH_ENABLE_WERROR "Fail and stop if warning is triggered" + ${LLVM_ENABLE_WERROR}) + + # Use just-built Clang to compile/link tests on all platforms. + if (CMAKE_CROSSCOMPILING) + if (CMAKE_HOST_WIN32) + set(_host_executable_suffix ".exe") + else() + set(_host_executable_suffix "") + endif() + else() + set(_host_executable_suffix ${CMAKE_EXECUTABLE_SUFFIX}) + endif() + set(CHEETAH_TEST_COMPILER + ${LLVM_RUNTIME_OUTPUT_INTDIR}/clang${_host_executable_suffix}) + set(CHEETAH_TEST_CXX_COMPILER + ${LLVM_RUNTIME_OUTPUT_INTDIR}/clang++${_host_executable_suffix}) +else() + # Take output dir and install path from the user. + set(CHEETAH_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR} CACHE PATH + "Path where built cheetah libraries should be stored.") + set(CHEETAH_EXEC_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/bin CACHE PATH + "Path where built cheetah executables should be stored.") + set(CHEETAH_INSTALL_PATH ${CMAKE_INSTALL_PREFIX} CACHE PATH + "Path where built cheetah libraries should be installed.") + option(CHEETAH_INCLUDE_TESTS "Generate and build cheetah unit tests." OFF) + option(CHEETAH_ENABLE_WERROR "Fail and stop if warning is triggered" OFF) + # Use a host compiler to compile/link tests. + set(CHEETAH_TEST_COMPILER ${CMAKE_C_COMPILER} CACHE PATH "Compiler to use for testing") + set(CHEETAH_TEST_CXX_COMPILER ${CMAKE_CXX_COMPILER} CACHE PATH "C++ Compiler to use for testing") +endif() + +if("${CHEETAH_TEST_COMPILER}" MATCHES "clang[+]*$") + set(CHEETAH_TEST_COMPILER_ID Clang) +elseif("${CHEETAH_TEST_COMPILER}" MATCHES "clang.*.exe$") + set(CHEETAH_TEST_COMPILER_ID Clang) +else() + set(CHEETAH_TEST_COMPILER_ID GNU) +endif() + +if(NOT DEFINED CHEETAH_OS_DIR) + string(TOLOWER ${CMAKE_SYSTEM_NAME} CHEETAH_OS_DIR) +endif() +if(CHEETAH_ENABLE_PER_TARGET_RUNTIME_DIR AND NOT APPLE) + set(CHEETAH_LIBRARY_OUTPUT_DIR + ${CHEETAH_OUTPUT_DIR}) + set(CHEETAH_LIBRARY_INSTALL_DIR + ${CHEETAH_INSTALL_PATH}) +else(CHEETAH_ENABLE_PER_TARGET_RUNTIME_DIR) + set(CHEETAH_LIBRARY_OUTPUT_DIR + ${CHEETAH_OUTPUT_DIR}/lib/${CHEETAH_OS_DIR}) + set(CHEETAH_LIBRARY_INSTALL_DIR + ${CHEETAH_INSTALL_PATH}/lib/${CHEETAH_OS_DIR}) +endif() + +if(APPLE) + # On Darwin if /usr/include/c++ doesn't exist, the user probably has Xcode but + # not the command line tools (or is using macOS 10.14 or newer). If this is + # the case, we need to find the OS X sysroot to pass to clang. + if(NOT EXISTS /usr/include/c++) + execute_process(COMMAND xcrun -sdk macosx --show-sdk-path + OUTPUT_VARIABLE OSX_SYSROOT + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + if (NOT OSX_SYSROOT OR NOT EXISTS ${OSX_SYSROOT}) + message(WARNING "Detected OSX_SYSROOT ${OSX_SYSROOT} does not exist") + else() + message(STATUS "Found OSX_SYSROOT: ${OSX_SYSROOT}") + set(OSX_SYSROOT_FLAG "-isysroot${OSX_SYSROOT}") + endif() + else() + set(OSX_SYSROOT_FLAG "") + endif() + + option(CHEETAH_ENABLE_IOS "Enable building for iOS" On) + option(CHEETAH_ENABLE_WATCHOS "Enable building for watchOS - Experimental" Off) + option(CHEETAH_ENABLE_TVOS "Enable building for tvOS - Experimental" Off) + +else() + option(CHEETAH_DEFAULT_TARGET_ONLY "Build builtins only for the default target" Off) +endif() + +if(WIN32 AND NOT MINGW AND NOT CYGWIN) + set(CMAKE_SHARED_LIBRARY_PREFIX_C "") + set(CMAKE_SHARED_LIBRARY_PREFIX_CXX "") + set(CMAKE_STATIC_LIBRARY_PREFIX_C "") + set(CMAKE_STATIC_LIBRARY_PREFIX_CXX "") + set(CMAKE_STATIC_LIBRARY_SUFFIX_C ".lib") + set(CMAKE_STATIC_LIBRARY_SUFFIX_CXX ".lib") +endif() + +macro(test_targets) + # Find and run MSVC (not clang-cl) and get its version. This will tell clang-cl + # what version of MSVC to pretend to be so that the STL works. + set(MSVC_VERSION_FLAG "") + if (MSVC) + execute_process(COMMAND "$ENV{VSINSTALLDIR}/VC/bin/cl.exe" + OUTPUT_QUIET + ERROR_VARIABLE MSVC_COMPAT_VERSION + ) + string(REGEX REPLACE "^.*Compiler Version ([0-9.]+) for .*$" "\\1" + MSVC_COMPAT_VERSION "${MSVC_COMPAT_VERSION}") + if (MSVC_COMPAT_VERSION MATCHES "^[0-9].+$") + set(MSVC_VERSION_FLAG "-fms-compatibility-version=${MSVC_COMPAT_VERSION}") + # Add this flag into the host build if this is clang-cl. + if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") + append("${MSVC_VERSION_FLAG}" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) + elseif (CHEETAH_TEST_COMPILER_ID MATCHES "Clang") + # Add this flag to test compiles to suppress clang's auto-detection + # logic. + append("${MSVC_VERSION_FLAG}" CHEETAH_TEST_COMPILER_CFLAGS) + endif() + endif() + endif() + + # Generate the CHEETAH_SUPPORTED_ARCH list. + if(ANDROID) + # Examine compiler output to determine target architecture. + detect_target_arch() + set(CHEETAH_OS_SUFFIX "-android") + elseif(NOT APPLE) # Supported archs for Apple platforms are generated later + if(CHEETAH_DEFAULT_TARGET_ONLY) + add_default_target_arch(${CHEETAH_DEFAULT_TARGET_ARCH}) + elseif("${CHEETAH_DEFAULT_TARGET_ARCH}" MATCHES "i[2-6]86|x86|amd64") + if(NOT MSVC) + if(CMAKE_SYSTEM_NAME MATCHES "OpenBSD") + if (CMAKE_SIZEOF_VOID_P EQUAL 4) + test_target_arch(i386 __i386__ "-m32") + else() + test_target_arch(x86_64 "" "-m64") + endif() + else() + test_target_arch(x86_64 "" "-m64") + test_target_arch(i386 __i386__ "-m32") + endif() + else() + if (CMAKE_SIZEOF_VOID_P EQUAL 4) + test_target_arch(i386 "" "") + else() + test_target_arch(x86_64 "" "") + endif() + endif() + elseif("${CHEETAH_DEFAULT_TARGET_ARCH}" MATCHES "powerpc") + # Strip out -nodefaultlibs when calling TEST_BIG_ENDIAN. Configuration + # will fail with this option when building with a sanitizer. + cmake_push_check_state() + string(REPLACE "-nodefaultlibs" "" CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}") + TEST_BIG_ENDIAN(HOST_IS_BIG_ENDIAN) + cmake_pop_check_state() + + if(HOST_IS_BIG_ENDIAN) + test_target_arch(powerpc64 "" "-m64") + else() + test_target_arch(powerpc64le "" "-m64") + endif() + elseif("${CHEETAH_DEFAULT_TARGET_ARCH}" MATCHES "s390x") + test_target_arch(s390x "" "") + elseif("${CHEETAH_DEFAULT_TARGET_ARCH}" MATCHES "sparc") + test_target_arch(sparc "" "-m32") + test_target_arch(sparcv9 "" "-m64") + elseif("${CHEETAH_DEFAULT_TARGET_ARCH}" MATCHES "mipsel|mips64el") + # Gcc doesn't accept -m32/-m64 so we do the next best thing and use + # -mips32r2/-mips64r2. We don't use -mips1/-mips3 because we want to match + # clang's default CPU's. In the 64-bit case, we must also specify the ABI + # since the default ABI differs between gcc and clang. + # FIXME: Ideally, we would build the N32 library too. + test_target_arch(mipsel "" "-mips32r2" "-mabi=32" "-D_LARGEFILE_SOURCE" "-D_FILE_OFFSET_BITS=64") + test_target_arch(mips64el "" "-mips64r2" "-mabi=64") + elseif("${CHEETAH_DEFAULT_TARGET_ARCH}" MATCHES "mips") + test_target_arch(mips "" "-mips32r2" "-mabi=32" "-D_LARGEFILE_SOURCE" "-D_FILE_OFFSET_BITS=64") + test_target_arch(mips64 "" "-mips64r2" "-mabi=64") + elseif("${CHEETAH_DEFAULT_TARGET_ARCH}" MATCHES "arm") + if(WIN32) + test_target_arch(arm "" "" "") + else() + test_target_arch(arm "" "-march=armv7-a" "-mfloat-abi=soft") + test_target_arch(armhf "" "-march=armv7-a" "-mfloat-abi=hard") + test_target_arch(armv6m "" "-march=armv6m" "-mfloat-abi=soft") + endif() + elseif("${CHEETAH_DEFAULT_TARGET_ARCH}" MATCHES "aarch32") + test_target_arch(aarch32 "" "-march=armv8-a") + elseif("${CHEETAH_DEFAULT_TARGET_ARCH}" MATCHES "aarch64") + test_target_arch(aarch64 "" "-march=armv8-a") + elseif("${CHEETAH_DEFAULT_TARGET_ARCH}" MATCHES "riscv32") + test_target_arch(riscv32 "" "") + elseif("${CHEETAH_DEFAULT_TARGET_ARCH}" MATCHES "riscv64") + test_target_arch(riscv64 "" "") + elseif("${CHEETAH_DEFAULT_TARGET_ARCH}" MATCHES "wasm32") + test_target_arch(wasm32 "" "--target=wasm32-unknown-unknown") + elseif("${CHEETAH_DEFAULT_TARGET_ARCH}" MATCHES "wasm64") + test_target_arch(wasm64 "" "--target=wasm64-unknown-unknown") + elseif("${CHEETAH_DEFAULT_TARGET_ARCH}" MATCHES "ve") + test_target_arch(ve "__ve__" "--target=ve-unknown-none") + endif() + set(CHEETAH_OS_SUFFIX "") + endif() +endmacro() diff --git a/cmake/config-ix.cmake b/cmake/config-ix.cmake index 9c1a5714..87eafc3b 100644 --- a/cmake/config-ix.cmake +++ b/cmake/config-ix.cmake @@ -24,6 +24,289 @@ check_c_compiler_flag(-fomit-frame-pointer CHEETAH_HAS_FOMIT_FRAME_POINTER_FLAG) check_c_compiler_flag(-mavx -Werror CHEETAH_HAS_MAVX_FLAG) check_c_compiler_flag(-march=sandybridge -Werror CHEETAH_HAS_MARCH_SANDYBRIDGE_FLAG) -if (APPLE) +set(CMAKE_REQUIRED_FLAGS -fsanitize=address) +check_c_compiler_flag(-fsanitize=address CHEETAH_HAS_ASAN) +unset(CMAKE_REQUIRED_FLAGS) + +# Architectures. + +# List of all architectures we can target. +set(CHEETAH_SUPPORTED_ARCH) + +# Try to compile a very simple source file to ensure we can target the given +# platform. We use the results of these tests to build only the various target +# runtime libraries supported by our current compilers cross-compiling +# abilities. +set(SIMPLE_SOURCE ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/simple.cc) +file(WRITE ${SIMPLE_SOURCE} "#include \n#include \nint main() { printf(\"hello, world\"); }\n") + +# Detect whether the current target platform is 32-bit or 64-bit, and setup +# the correct commandline flags needed to attempt to target 32-bit and 64-bit. +if (NOT CMAKE_SIZEOF_VOID_P EQUAL 4 AND + NOT CMAKE_SIZEOF_VOID_P EQUAL 8) + message(FATAL_ERROR "Please use architecture with 4 or 8 byte pointers.") +endif() + +test_targets() + +# Returns a list of architecture specific target cflags in @out_var list. +function(get_target_flags_for_arch arch out_var) + list(FIND CHEETAH_SUPPORTED_ARCH ${arch} ARCH_INDEX) + if(ARCH_INDEX EQUAL -1) + message(FATAL_ERROR "Unsupported architecture: ${arch}") + else() + if (NOT APPLE) + set(${out_var} ${TARGET_${arch}_CFLAGS} PARENT_SCOPE) + else() + # This is only called in constructing cflags for tests executing on the + # host. This will need to all be cleaned up to support building tests + # for cross-targeted hardware (i.e. iOS). + set(${out_var} -arch ${arch} PARENT_SCOPE) + endif() + endif() +endfunction() + +# Returns a compiler and CFLAGS that should be used to run tests for the +# specific architecture. When cross-compiling, this is controled via +# CILKTOOLS_TEST_COMPILER and CILKTOOLS_TEST_COMPILER_CFLAGS. +macro(get_test_cc_for_arch arch cc_out cflags_out) + if(ANDROID OR ${arch} MATCHES "arm|aarch64") + # This is only true if we are cross-compiling. + # Build all tests with host compiler and use host tools. + set(${cc_out} ${CILKTOOLS_TEST_COMPILER}) + set(${cflags_out} ${CILKTOOLS_TEST_COMPILER_CFLAGS}) + else() + get_target_flags_for_arch(${arch} ${cflags_out}) + if(APPLE) + list(APPEND ${cflags_out} ${DARWIN_osx_CFLAGS}) + endif() + string(REPLACE ";" " " ${cflags_out} "${${cflags_out}}") + endif() +endmacro() + +# Returns CFLAGS that should be used to run tests for the +# specific apple platform and architecture. +function(get_test_cflags_for_apple_platform platform arch cflags_out) + is_valid_apple_platform("${platform}" is_valid_platform) + if (NOT is_valid_platform) + message(FATAL_ERROR "\"${platform}\" is not a valid apple platform") + endif() + set(test_cflags "") + get_target_flags_for_arch(${arch} test_cflags) + list(APPEND test_cflags ${DARWIN_${platform}_CFLAGS}) + string(REPLACE ";" " " test_cflags_str "${test_cflags}") + string(APPEND test_cflags_str "${CILKTOOLS_TEST_COMPILER_CFLAGS}") + set(${cflags_out} "${test_cflags_str}" PARENT_SCOPE) +endfunction() + +function(get_capitalized_apple_platform platform platform_capitalized) + # TODO(dliew): Remove uses of this function. It exists to preserve needlessly complex + # directory naming conventions used by the Sanitizer lit test suites. + is_valid_apple_platform("${platform}" is_valid_platform) + if (NOT is_valid_platform) + message(FATAL_ERROR "\"${platform}\" is not a valid apple platform") + endif() + string(TOUPPER "${platform}" platform_upper) + string(REGEX REPLACE "OSSIM$" "OSSim" platform_upper_capitalized "${platform_upper}") + set(${platform_capitalized} "${platform_upper_capitalized}" PARENT_SCOPE) +endfunction() + +function(is_valid_apple_platform platform is_valid_out) + set(is_valid FALSE) + if ("${platform}" STREQUAL "") + message(FATAL_ERROR "platform cannot be empty") + endif() + if ("${platform}" MATCHES "^(osx|((ios|watchos|tvos)(sim)?))$") + set(is_valid TRUE) + endif() + set(${is_valid_out} ${is_valid} PARENT_SCOPE) +endfunction() + +set(ARM64 aarch64) +set(ARM32 arm armhf) +set(HEXAGON hexagon) +set(X86 i386) +set(X86_64 x86_64) +set(MIPS32 mips mipsel) +set(MIPS64 mips64 mips64el) +set(PPC64 powerpc64 powerpc64le) +set(RISCV32 riscv32) +set(RISCV64 riscv64) +set(S390X s390x) +set(SPARC sparc) +set(SPARCV9 sparcv9) +set(WASM32 wasm32) +set(WASM64 wasm64) + +if(APPLE) + set(ARM64 arm64) + set(ARM32 armv7 armv7s armv7k) + set(X86_64 x86_64 x86_64h) +endif() + +set(ALL_CHEETAH_SUPPORTED_ARCH ${X86_64} ${ARM64}) + +if(APPLE) + include(CheetahDarwinUtils) + + find_darwin_sdk_dir(DARWIN_osx_SYSROOT macosx) + find_darwin_sdk_dir(DARWIN_iossim_SYSROOT iphonesimulator) + find_darwin_sdk_dir(DARWIN_ios_SYSROOT iphoneos) + find_darwin_sdk_dir(DARWIN_watchossim_SYSROOT watchsimulator) + find_darwin_sdk_dir(DARWIN_watchos_SYSROOT watchos) + find_darwin_sdk_dir(DARWIN_tvossim_SYSROOT appletvsimulator) + find_darwin_sdk_dir(DARWIN_tvos_SYSROOT appletvos) + + if(NOT DARWIN_osx_SYSROOT) + message(WARNING "Could not determine OS X sysroot, trying /usr/include") + if(EXISTS /usr/include) + set(DARWIN_osx_SYSROOT /) + else() + message(ERROR "Could not detect OS X Sysroot. Either install Xcode or the Apple Command Line Tools") + endif() + endif() + + if(CHEETAH_ENABLE_IOS) + list(APPEND DARWIN_EMBEDDED_PLATFORMS ios) + set(DARWIN_ios_MIN_VER 9.0) + set(DARWIN_ios_MIN_VER_FLAG -miphoneos-version-min) + set(DARWIN_ios_SANITIZER_MIN_VER_FLAG + ${DARWIN_ios_MIN_VER_FLAG}=${DARWIN_ios_MIN_VER}) + set(DARWIN_iossim_MIN_VER_FLAG -mios-simulator-version-min) + set(DARWIN_iossim_SANITIZER_MIN_VER_FLAG + ${DARWIN_iossim_MIN_VER_FLAG}=${DARWIN_ios_MIN_VER}) + endif() + if(CHEETAH_ENABLE_WATCHOS) + list(APPEND DARWIN_EMBEDDED_PLATFORMS watchos) + set(DARWIN_watchos_MIN_VER 2.0) + set(DARWIN_watchos_MIN_VER_FLAG -mwatchos-version-min) + set(DARWIN_watchos_SANITIZER_MIN_VER_FLAG + ${DARWIN_watchos_MIN_VER_FLAG}=${DARWIN_watchos_MIN_VER}) + set(DARWIN_watchossim_MIN_VER_FLAG -mwatchos-simulator-version-min) + set(DARWIN_watchossim_SANITIZER_MIN_VER_FLAG + ${DARWIN_watchossim_MIN_VER_FLAG}=${DARWIN_watchos_MIN_VER}) + endif() + if(CHEETAH_ENABLE_TVOS) + list(APPEND DARWIN_EMBEDDED_PLATFORMS tvos) + set(DARWIN_tvos_MIN_VER 9.0) + set(DARWIN_tvos_MIN_VER_FLAG -mtvos-version-min) + set(DARWIN_tvos_SANITIZER_MIN_VER_FLAG + ${DARWIN_tvos_MIN_VER_FLAG}=${DARWIN_tvos_MIN_VER}) + set(DARWIN_tvossim_MIN_VER_FLAG -mtvos-simulator-version-min) + set(DARWIN_tvossim_SANITIZER_MIN_VER_FLAG + ${DARWIN_tvossim_MIN_VER_FLAG}=${DARWIN_tvos_MIN_VER}) + endif() + + set(CHEETAH_SUPPORTED_OS osx) + + # Note: In order to target x86_64h on OS X the minimum deployment target must + # be 10.8 or higher. + set(DARWIN_osx_MIN_VER_FLAG "-mmacosx-version-min") + if(NOT CHEETAH_MIN_OSX_VERSION) + string(REGEX MATCH "${DARWIN_osx_MIN_VER_FLAG}=([.0-9]+)" + MACOSX_VERSION_MIN_FLAG "${CMAKE_CXX_FLAGS}") + if(MACOSX_VERSION_MIN_FLAG) + set(CHEETAH_MIN_OSX_VERSION "${CMAKE_MATCH_1}") + elseif(CMAKE_OSX_DEPLOYMENT_TARGET) + set(CHEETAH_MIN_OSX_VERSION ${CMAKE_OSX_DEPLOYMENT_TARGET}) + else() + set(CHEETAH_MIN_OSX_VERSION ${DEFAULT_CHEETAH_MIN_OSX_VERSION}) + endif() + if(CHEETAH_MIN_OSX_VERSION VERSION_LESS "10.7") + message(FATAL_ERROR "macOS deployment target '${CHEETAH_MIN_OSX_VERSION}' is too old.") + endif() + endif() + + # We're setting the flag manually for each target OS + set(CMAKE_OSX_DEPLOYMENT_TARGET "") + check_linker_flag("-fapplication-extension" CHEETAH_HAS_APP_EXTENSION) + + if(CHEETAH_HAS_APP_EXTENSION) + list(APPEND DARWIN_COMMON_LINK_FLAGS "-fapplication-extension") + endif() + + set(DARWIN_osx_CFLAGS + ${DARWIN_COMMON_CFLAGS} + ${DARWIN_osx_MIN_VER_FLAG}=${CHEETAH_MIN_OSX_VERSION}) + set(DARWIN_osx_LINK_FLAGS + ${DARWIN_COMMON_LINK_FLAGS} + ${DARWIN_osx_MIN_VER_FLAG}=${CHEETAH_MIN_OSX_VERSION}) + + if(DARWIN_osx_SYSROOT) + list(APPEND DARWIN_osx_CFLAGS -isysroot ${DARWIN_osx_SYSROOT}) + list(APPEND DARWIN_osx_LINK_FLAGS -isysroot ${DARWIN_osx_SYSROOT}) + endif() + + # Figure out which arches to use for each OS + darwin_get_toolchain_supported_archs(toolchain_arches) + message(STATUS "Toolchain supported arches: ${toolchain_arches}") + + if(NOT MACOSX_VERSION_MIN_FLAG) + darwin_test_archs(osx + DARWIN_osx_ARCHS + ${toolchain_arches}) + message(STATUS "OSX supported arches: ${DARWIN_osx_ARCHS}") + foreach(arch ${DARWIN_osx_ARCHS}) + list(APPEND CHEETAH_CMAKE_SUPPORTED_ARCH ${arch}) + set(CAN_TARGET_${arch} 1) + endforeach() + + foreach(platform ${DARWIN_EMBEDDED_PLATFORMS}) + if(DARWIN_${platform}sim_SYSROOT) + set(DARWIN_${platform}sim_CFLAGS + ${DARWIN_COMMON_CFLAGS} + ${DARWIN_${platform}sim_SANITIZER_MIN_VER_FLAG} + -isysroot ${DARWIN_${platform}sim_SYSROOT}) + set(DARWIN_${platform}sim_LINK_FLAGS + ${DARWIN_COMMON_LINK_FLAGS} + ${DARWIN_${platform}sim_SANITIZER_MIN_VER_FLAG} + -isysroot ${DARWIN_${platform}sim_SYSROOT}) + + set(DARWIN_${platform}sim_SKIP_CC_KEXT On) + darwin_test_archs(${platform}sim + DARWIN_${platform}sim_ARCHS + ${toolchain_arches}) + message(STATUS "${platform} Simulator supported arches: ${DARWIN_${platform}sim_ARCHS}") + foreach(arch ${DARWIN_${platform}sim_ARCHS}) + list(APPEND CHEETAH_CMAKE_SUPPORTED_ARCH ${arch}) + set(CAN_TARGET_${arch} 1) + endforeach() + endif() + + if(DARWIN_${platform}_SYSROOT) + set(DARWIN_${platform}_CFLAGS + ${DARWIN_COMMON_CFLAGS} + ${DARWIN_${platform}_SANITIZER_MIN_VER_FLAG} + -isysroot ${DARWIN_${platform}_SYSROOT}) + set(DARWIN_${platform}_LINK_FLAGS + ${DARWIN_COMMON_LINK_FLAGS} + ${DARWIN_${platform}_SANITIZER_MIN_VER_FLAG} + -isysroot ${DARWIN_${platform}_SYSROOT}) + + darwin_test_archs(${platform} + DARWIN_${platform}_ARCHS + ${toolchain_arches}) + message(STATUS "${platform} supported arches: ${DARWIN_${platform}_ARCHS}") + foreach(arch ${DARWIN_${platform}_ARCHS}) + list(APPEND CHEETAH_CMAKE_SUPPORTED_ARCH ${arch}) + set(CAN_TARGET_${arch} 1) + endforeach() + endif() + endforeach() + endif() + + # for list_intersect + include(CheetahUtils) + + list_intersect(CHEETAH_SUPPORTED_ARCH + ALL_CHEETAH_SUPPORTED_ARCH + CHEETAH_CMAKE_SUPPORTED_ARCH + ) + +else() + # for filter_available_targets + include(CheetahUtils) + + filter_available_targets(CHEETAH_SUPPORTED_ARCH ${ALL_CHEETAH_SUPPORTED_ARCH}) endif() diff --git a/config.mk b/config.mk index 65fded51..417e4863 100644 --- a/config.mk +++ b/config.mk @@ -3,15 +3,24 @@ CC=$(COMPILER_BASE)clang CXX=$(COMPILER_BASE)clang++ LINK_CC=$(CC) LLVM_LINK=$(COMPILER_BASE)llvm-link +LLVM_CONFIG=$(COMPILER_BASE)llvm-config # ABI_DEF=-DOPENCILK_ABI # If use cheetah -RTS_OPT=-fopencilk RTS_DIR=../runtime RTS_LIB=libopencilk RTS_C_PERSONALITY_LIB=libopencilk-personality-c RTS_CXX_PERSONALITY_LIB=libopencilk-personality-cpp + +# All runtime libraries and associated files will be placed in +# `/oath/to/cheetah/lib/`, so that the compiler can easily find +# all of those files using the flag --opencilk-resource-dir=/path/to/cheetah. +RTS_LIBDIR_NAME=lib/$(shell $(LLVM_CONFIG) --host-target) +RESOURCE_DIR=$(PWD) +RTS_LIBDIR=$(RESOURCE_DIR)/$(RTS_LIBDIR_NAME) +RTS_OPT=-fopencilk --opencilk-resource-dir=$(RESOURCE_DIR) #RTS_LIB_FLAG=-lcheetah + #ARCH = -mavx OPT = -O3 DBG = -g3 diff --git a/handcomp_test/Makefile b/handcomp_test/Makefile index 18bf66cd..b5dc5b62 100644 --- a/handcomp_test/Makefile +++ b/handcomp_test/Makefile @@ -12,7 +12,8 @@ OPTIONS = $(OPT) $(ARCH) $(DBG) -Wall $(DEFINES) -fno-omit-frame-pointer # RTS_DLIBS = -L../runtime -Wl,-rpath -Wl,../runtime -lopencilk # RTS_LIBS = ../runtime/$(RTS_LIB).so # static linking -RTS_LIBS = ../runtime/$(RTS_LIB).a +RESOURCE_DIR=$(realpath ..) +RTS_LIBS = $(RTS_LIBDIR)/$(RTS_LIB).a TIMING_COUNT := 1 .PHONY: all check memcheck clean diff --git a/handcomp_test/cilksort.c b/handcomp_test/cilksort.c index 8eab0774..6767dc4f 100644 --- a/handcomp_test/cilksort.c +++ b/handcomp_test/cilksort.c @@ -370,23 +370,15 @@ void cilkmerge(ELM *low1, ELM *high1, *(lowdest + lowsize + 1) = *split1; /* cilk_spawn cilkmerge(low1, split1 - 1, low2, split2, lowdest); */ - __cilkrts_save_fp_ctrl_state(&sf); - if(!__builtin_setjmp(sf.ctx)) { + if (!__cilk_prepare_spawn(&sf)) { cilkmerge_spawn_helper(low1, split1 - 1, low2, split2, lowdest); } cilkmerge(split1 + 1, high1, split2 + 1, high2, lowdest + lowsize + 2); /* cilk_sync; */ - if(sf.flags & CILK_FRAME_UNSYNCHED) { - __cilkrts_save_fp_ctrl_state(&sf); - if(!__builtin_setjmp(sf.ctx)) { - __cilkrts_sync(&sf); - } - } + __cilk_sync_nothrow(&sf); - __cilkrts_pop_frame(&sf); - if (0 != sf.flags) - __cilkrts_leave_frame(&sf); + __cilk_parent_epilogue(&sf); return; } @@ -396,11 +388,10 @@ cilkmerge_spawn_helper(ELM *low1, ELM *high1, ELM *low2, ELM *high2, ELM *lowdest) { __cilkrts_stack_frame sf; - __cilkrts_enter_frame_fast(&sf); + __cilkrts_enter_frame_helper(&sf); __cilkrts_detach(&sf); cilkmerge(low1, high1, low2, high2, lowdest); - __cilkrts_pop_frame(&sf); - __cilkrts_leave_frame(&sf); + __cilk_helper_epilogue(&sf); } static void __attribute__ ((noinline)) cilksort_spawn_helper(ELM *low, ELM *tmp, long size); @@ -438,52 +429,36 @@ void cilksort(ELM *low, ELM *tmp, long size) { tmpD = tmpC + quarter; /* cilk_spawn cilksort(A, tmpA, quarter); */ - __cilkrts_save_fp_ctrl_state(&sf); - if(!__builtin_setjmp(sf.ctx)) { + if (!__cilk_prepare_spawn(&sf)) { cilksort_spawn_helper(A, tmpA, quarter); } /* cilk_spawn cilksort(B, tmpB, quarter); */ - __cilkrts_save_fp_ctrl_state(&sf); - if(!__builtin_setjmp(sf.ctx)) { + if (!__cilk_prepare_spawn(&sf)) { cilksort_spawn_helper(B, tmpB, quarter); } /* cilk_spawn cilksort(C, tmpC, quarter); */ - __cilkrts_save_fp_ctrl_state(&sf); - if(!__builtin_setjmp(sf.ctx)) { + if (!__cilk_prepare_spawn(&sf)) { cilksort_spawn_helper(C, tmpC, quarter); } cilksort(D, tmpD, size - 3 * quarter); /* cilk_sync */ - if(sf.flags & CILK_FRAME_UNSYNCHED) { - __cilkrts_save_fp_ctrl_state(&sf); - if(!__builtin_setjmp(sf.ctx)) { - __cilkrts_sync(&sf); - } - } + __cilk_sync_nothrow(&sf); /* cilk_spawn cilkmerge(A, A + quarter - 1, B, B + quarter - 1, tmpA); */ - __cilkrts_save_fp_ctrl_state(&sf); - if(!__builtin_setjmp(sf.ctx)) { + if (!__cilk_prepare_spawn(&sf)) { cilkmerge_spawn_helper(A, A + quarter - 1, B, B + quarter - 1, tmpA); } cilkmerge(C, C + quarter - 1, D, low + size - 1, tmpC); /* cilk_sync */ - if(sf.flags & CILK_FRAME_UNSYNCHED) { - __cilkrts_save_fp_ctrl_state(&sf); - if(!__builtin_setjmp(sf.ctx)) { - __cilkrts_sync(&sf); - } - } + __cilk_sync_nothrow(&sf); cilkmerge(tmpA, tmpC - 1, tmpC, tmpA + size - 1, A); - __cilkrts_pop_frame(&sf); - if (0 != sf.flags) - __cilkrts_leave_frame(&sf); + __cilk_parent_epilogue(&sf); return; } @@ -491,11 +466,10 @@ void cilksort(ELM *low, ELM *tmp, long size) { static void __attribute__ ((noinline)) cilksort_spawn_helper(ELM *low, ELM *tmp, long size) { __cilkrts_stack_frame sf; - __cilkrts_enter_frame_fast(&sf); + __cilkrts_enter_frame_helper(&sf); __cilkrts_detach(&sf); cilksort(low, tmp, size); - __cilkrts_pop_frame(&sf); - __cilkrts_leave_frame(&sf); + __cilk_helper_epilogue(&sf); } void scramble_array(ELM *arr, unsigned long size) { diff --git a/handcomp_test/fib.c b/handcomp_test/fib.c index 6c2283b3..81a54b16 100644 --- a/handcomp_test/fib.c +++ b/handcomp_test/fib.c @@ -47,25 +47,17 @@ int fib(int n) { __cilkrts_enter_frame(&sf); /* x = spawn fib(n-1) */ - __cilkrts_save_fp_ctrl_state(&sf); - if(!__builtin_setjmp(sf.ctx)) { + if (!__cilk_prepare_spawn(&sf)) { fib_spawn_helper(&x, n-1); } y = fib(n - 2); /* cilk_sync */ - if(sf.flags & CILK_FRAME_UNSYNCHED) { - __cilkrts_save_fp_ctrl_state(&sf); - if(!__builtin_setjmp(sf.ctx)) { - __cilkrts_sync(&sf); - } - } + __cilk_sync_nothrow(&sf); _tmp = x + y; - __cilkrts_pop_frame(&sf); - if (0 != sf.flags) - __cilkrts_leave_frame(&sf); + __cilk_parent_epilogue(&sf); return _tmp; } @@ -73,11 +65,10 @@ int fib(int n) { static void __attribute__ ((noinline)) fib_spawn_helper(int *x, int n) { __cilkrts_stack_frame sf; - __cilkrts_enter_frame_fast(&sf); + __cilkrts_enter_frame_helper(&sf); __cilkrts_detach(&sf); *x = fib(n); - __cilkrts_pop_frame(&sf); - __cilkrts_leave_frame(&sf); + __cilk_helper_epilogue(&sf); } int main(int argc, char * args[]) { diff --git a/handcomp_test/mm_dac.c b/handcomp_test/mm_dac.c index 40f10cb7..7c51f5f3 100644 --- a/handcomp_test/mm_dac.c +++ b/handcomp_test/mm_dac.c @@ -104,73 +104,54 @@ static void mm_dac(int *C, const int *A, const int *B, int n, int length) { int const *B11 = B + n*mid + mid; /* cilk_spawn mm_dac(C00, A00, B00, n, mid); */ - __cilkrts_save_fp_ctrl_state(&sf); - if(!__builtin_setjmp(sf.ctx)) { + if (!__cilk_prepare_spawn(&sf)) { mm_dac_spawn_helper(C00, A00, B00, n, mid); } /* cilk_spawn mm_dac(C01, A00, B01, n, mid); */ - __cilkrts_save_fp_ctrl_state(&sf); - if(!__builtin_setjmp(sf.ctx)) { + if (!__cilk_prepare_spawn(&sf)) { mm_dac_spawn_helper(C01, A00, B01, n, mid); } /* cilk_spawn mm_dac(C10, A10, B00, n, mid); */ - __cilkrts_save_fp_ctrl_state(&sf); - if(!__builtin_setjmp(sf.ctx)) { + if (!__cilk_prepare_spawn(&sf)) { mm_dac_spawn_helper(C10, A10, B00, n, mid); } mm_dac(C11, A10, B01, n, mid); /* cilk_sync */ - if(sf.flags & CILK_FRAME_UNSYNCHED) { - __cilkrts_save_fp_ctrl_state(&sf); - if(!__builtin_setjmp(sf.ctx)) { - __cilkrts_sync(&sf); - } - } + __cilk_sync_nothrow(&sf); /* cilk_spawn mm_dac(C00, A01, B10, n, mid); */ - __cilkrts_save_fp_ctrl_state(&sf); - if(!__builtin_setjmp(sf.ctx)) { + if (!__cilk_prepare_spawn(&sf)) { mm_dac_spawn_helper(C00, A01, B10, n, mid); } /* cilk_spawn mm_dac(C01, A01, B11, n, mid); */ - __cilkrts_save_fp_ctrl_state(&sf); - if(!__builtin_setjmp(sf.ctx)) { + if (!__cilk_prepare_spawn(&sf)) { mm_dac_spawn_helper(C01, A01, B11, n, mid); } /* cilk_spawn mm_dac(C10, A11, B10, n, mid); */ - __cilkrts_save_fp_ctrl_state(&sf); - if(!__builtin_setjmp(sf.ctx)) { + if (!__cilk_prepare_spawn(&sf)) { mm_dac_spawn_helper(C10, A11, B10, n, mid); } mm_dac(C11, A11, B11, n, mid); /* cilk_sync */ - if(sf.flags & CILK_FRAME_UNSYNCHED) { - __cilkrts_save_fp_ctrl_state(&sf); - if(!__builtin_setjmp(sf.ctx)) { - __cilkrts_sync(&sf); - } - } + __cilk_sync_nothrow(&sf); - __cilkrts_pop_frame(&sf); - if (0 != sf.flags) - __cilkrts_leave_frame(&sf); + __cilk_parent_epilogue(&sf); } __attribute__((noinline)) static void mm_dac_spawn_helper(int *C, const int *A, const int *B, int n, int length) { __cilkrts_stack_frame sf; - __cilkrts_enter_frame_fast(&sf); + __cilkrts_enter_frame_helper(&sf); __cilkrts_detach(&sf); mm_dac(C, A, B, n, length); - __cilkrts_pop_frame(&sf); - __cilkrts_leave_frame(&sf); + __cilk_helper_epilogue(&sf); } static void rand_matrix(int *dest, int n) { diff --git a/handcomp_test/nqueens.c b/handcomp_test/nqueens.c index c84089af..c0552300 100644 --- a/handcomp_test/nqueens.c +++ b/handcomp_test/nqueens.c @@ -87,27 +87,19 @@ static int nqueens(int n, int j, char *a) { if(ok (j + 1, b)) { /* count[i] = cilk_spawn nqueens(n, j + 1, b); */ - __cilkrts_save_fp_ctrl_state(&sf); - if(!__builtin_setjmp(sf.ctx)) { + if (!__cilk_prepare_spawn(&sf)) { nqueens_spawn_helper(&(count[i]), n, j+1, b); } } } /* cilk_sync */ - if(sf.flags & CILK_FRAME_UNSYNCHED) { - __cilkrts_save_fp_ctrl_state(&sf); - if(!__builtin_setjmp(sf.ctx)) { - __cilkrts_sync(&sf); - } - } + __cilk_sync_nothrow(&sf); for(i = 0; i < n; i++) { solNum += count[i]; } - __cilkrts_pop_frame(&sf); - if (0 != sf.flags) - __cilkrts_leave_frame(&sf); + __cilk_parent_epilogue(&sf); return solNum; } @@ -116,11 +108,10 @@ static void __attribute__ ((noinline)) nqueens_spawn_helper(int *count, int n, int j, char *a) { __cilkrts_stack_frame sf; - __cilkrts_enter_frame_fast(&sf); + __cilkrts_enter_frame_helper(&sf); __cilkrts_detach(&sf); *count = nqueens(n, j, a); - __cilkrts_pop_frame(&sf); - __cilkrts_leave_frame(&sf); + __cilk_helper_epilogue(&sf); } int main(int argc, char *argv[]) { diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt index 1281b160..f0a4722f 100644 --- a/include/CMakeLists.txt +++ b/include/CMakeLists.txt @@ -21,7 +21,7 @@ set(cilk_header_files cilk/reducer_vector.h ) -set(output_dir ${CHEETAH_HEADER_DIR}) +set(output_dir ${CHEETAH_OUTPUT_DIR}/include) set(out_files) function(copy_header_to_output_dir src_dir file) @@ -43,7 +43,7 @@ endforeach( f ) add_custom_target(cilk-headers ALL DEPENDS ${out_files}) set_target_properties(cilk-headers PROPERTIES FOLDER "Cheetah Misc") -set(header_install_dir ${CHEETAH_HEADER_INSTALL_DIR}) +set(header_install_dir ${CHEETAH_INSTALL_PATH}/include) install( FILES ${cilk_header_files} diff --git a/include/cilk/cilk.h b/include/cilk/cilk.h index 62b3147c..900169a4 100644 --- a/include/cilk/cilk.h +++ b/include/cilk/cilk.h @@ -4,5 +4,6 @@ #define cilk_spawn _Cilk_spawn #define cilk_sync _Cilk_sync #define cilk_for _Cilk_for +#define cilk_scope _Cilk_scope #endif /* _CILK_H */ diff --git a/include/cilk/cilk_api.h b/include/cilk/cilk_api.h index 28cb2bf9..4f23dd5d 100644 --- a/include/cilk/cilk_api.h +++ b/include/cilk/cilk_api.h @@ -9,8 +9,7 @@ extern int __cilkrts_atinit(void (*callback)(void)); extern int __cilkrts_atexit(void (*callback)(void)); extern unsigned __cilkrts_get_nworkers(void); extern unsigned __cilkrts_get_worker_number(void) __attribute__((deprecated)); -struct __cilkrts_worker *__cilkrts_get_tls_worker(void); - +extern int __cilkrts_running_on_workers(void); #if defined(__cilk_pedigrees__) || defined(ENABLE_CILKRTS_PEDIGREE) #include diff --git a/include/cilk/cilk_stub.h b/include/cilk/cilk_stub.h index bd6852fa..08a849db 100644 --- a/include/cilk/cilk_stub.h +++ b/include/cilk/cilk_stub.h @@ -1,3 +1,4 @@ #define cilk_for for #define cilk_spawn /* empty */ #define cilk_sync /* empty */ +#define cilk_scope /* empty */ diff --git a/reducer_bench/.gitignore b/reducer_bench/.gitignore deleted file mode 100644 index 7504422c..00000000 --- a/reducer_bench/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -cppsum -intlist -intsum -multispawnsum -repeatedintsum -serialsum diff --git a/reducer_bench/Makefile b/reducer_bench/Makefile deleted file mode 100644 index 49473782..00000000 --- a/reducer_bench/Makefile +++ /dev/null @@ -1,79 +0,0 @@ -include ../config.mk - -SRCS = $(wildcard *.c) -HDRS = $(wildcard *.h) -OBJS = $(patsubst %.c,%.o,$(SRCS)) - -MANY = 8 # how many cores is a lot? -ENABLE_X11 = false - -CTESTS = intlist serialsum intsum multispawnsum repeatedintsum # cilksan_test -CXXTESTS = cppsum -DIRTESTS = nqueens quad_tree -TESTS = $(CTESTS) $(CXXTESTS) $(DIRTESTS) -WARN = -W -Wno-mismatched-tags -Wno-unused-parameter -Werror -OPTIONS = $(OPT) $(SAN) $(ARCH) $(DBG) $(RTS_OPT) $(WARN) # -fno-omit-frame-pointer - -$(CTESTS): RTS_PERSONALITY_LIB = $(RTS_DIR)/$(RTS_C_PERSONALITY_LIB).a -$(CXXTESTS): RTS_PERSONALITY_LIB = $(RTS_DIR)/$(RTS_CXX_PERSONALITY_LIB).a - -RTS_LIBS = $(RTS_PERSONALITY_LIB) $(RTS_DIR)/$(RTS_LIB).a $(patsubst %,../runtime/%/module.a,$(MODS)) - -TIMING_COUNT := 1 - -.PHONY: all check clean $(DIRTESTS) - -all: $(TESTS) - -$(CTESTS): %: %.o ktiming.o getoptions.o - $(CC) $^ -o $@ $(RTS_LIBS) $(RTS_LIB_FLAG) $(SAN) -lrt -lpthread -lm - -$(CXXTESTS): %: %.o ktiming.o getoptions.o - $(CXX) $^ -o $@ $(RTS_LIBS) $(RTS_LIB_FLAG) $(SAN) -lrt -lpthread -lm - -$(DIRTESTS): - $(MAKE) -C $@ $(TOPASS) - -%.o: %.c - $(CC) -c $(OPTIONS) -DTIMING_COUNT=$(TIMING_COUNT) -o $@ $< - -%.o: %.cpp - $(CXX) -c $(OPTIONS) -DTIMING_COUNT=$(TIMING_COUNT) -o $@ $< - -check: - $(MAKE) TIMING_COUNT=5 $(TOPASS) - CILK_NWORKERS=2 ./intlist 40000000 - CILK_NWORKERS=1 ./serialsum 200000000 - CILK_NWORKERS=1 ./intsum 200000000 - CILK_NWORKERS=$(MANY) ./intsum 200000000 - CILK_NWORKERS=2 ./multispawnsum 100000000 - CILK_NWORKERS=2 ./cppsum 200000000 - $(MAKE) -C nqueens check $(TOPASS) - if $(ENABLE_X11); then $(MAKE) -C quad_tree check $(TOPASS) ; else : ; fi - -stress: - $(MAKE) TIMING_COUNT=5 $(TOPASS) - CILK_NWORKERS=$(MANY) ./intlist 40000000 - CILK_NWORKERS=$(MANY) ./intsum 200000000 - if $(ENABLE_X11); then $(MAKE) -C quad_tree check $(TOPASS) ; else : ; fi -# Assertion failure: SPA resize not supported yet! -# CILK_NWORKERS=$(MANY) ./repeatedintsum 10000000 - -#redcheck: -# $(MAKE) clean; $(MAKE) TIMING_COUNT=1 $(TOPASS) > /dev/null 2>&1 -# CILK_NWORKERS=2 ./intlist 2048 -#redgdb: -# $(MAKE) clean; $(MAKE) TIMING_COUNT=1 $(TOPASS) > /dev/null 2>&1 -# CILK_NWORKERS=2 gdb --args ./intlist 2048 - -clean: - rm -f *.o *~ $(CTESTS) $(CXXTESTS) core.* - $(foreach test,$(DIRTESTS),$(MAKE) -C $(test) clean;) - -cppsum.o: ktiming.h -intlist.o: ktiming.h -intsum.o: ktiming.h -ktiming.o: ktiming.h -multispawnsum.o: ktiming.h -repeatedintsum.o: ktiming.h -serialsum.o: ktiming.h diff --git a/reducer_bench/cppsum.cpp b/reducer_bench/cppsum.cpp deleted file mode 100644 index 0d05bb3a..00000000 --- a/reducer_bench/cppsum.cpp +++ /dev/null @@ -1,48 +0,0 @@ -#include -#include -#include -#include - -extern "C" { -#include "ktiming.h" -} - -int test_reducer(int limit) { - - cilk::reducer_opadd radd(0); - - cilk_for(int i = 0; i < limit; i++) { - *radd += 1; - } - - int sum = radd.get_value(); - - return sum; -} - -int main(int argc, const char** args) { - int i; - int n, res = 0; - clockmark_t begin, end; - uint64_t running_time[TIMING_COUNT]; - - if(argc != 2) { - fprintf(stderr, "Usage: ilist_dac [] \n"); - exit(1); - } - - n = atoi(args[1]); - - for(i = 0; i < TIMING_COUNT; i++) { - begin = ktiming_getmark(); - int sum = test_reducer(n); - res += (sum == n) ? 1 : 0; - end = ktiming_getmark(); - // printf("The final sum is %d\n", sum); - running_time[i] = ktiming_diff_nsec(&begin, &end); - } - printf("Result: %d/%d successes!\n", res, TIMING_COUNT); - print_runtime(running_time, TIMING_COUNT); - - return 0; -} diff --git a/reducer_bench/getoptions.c b/reducer_bench/getoptions.c deleted file mode 100644 index 84e78170..00000000 --- a/reducer_bench/getoptions.c +++ /dev/null @@ -1,93 +0,0 @@ -#include "getoptions.h" -#include -#include -#include -#include - -/* Used by example programs to evaluate command line options */ - -void get_options(int argc, char *argv[], const char *specs[], int *types, ...) { - va_list ap; - int type, i; - int *intval; - double *doubleval; - long *longval; - char *stringval; - - va_start(ap, types); - - while (((type = *types++) != 0) && (specs != 0)) { - switch (type) { - case INTARG: - intval = (int *)va_arg(ap, int *); - for (i = 1; i < (argc - 1); i++) - if (!(strcmp(argv[i], specs[0]))) { - *intval = atoi(argv[i + 1]); - argv[i][0] = 0; - argv[i + 1][0] = 0; - } - break; - case DOUBLEARG: - doubleval = (double *)va_arg(ap, double *); - for (i = 1; i < (argc - 1); i++) - if (!(strcmp(argv[i], specs[0]))) { - *doubleval = atof(argv[i + 1]); - argv[i][0] = 0; - argv[i + 1][0] = 0; - } - break; - case LONGARG: - longval = (long *)va_arg(ap, long *); - for (i = 1; i < (argc - 1); i++) - if (!(strcmp(argv[i], specs[0]))) { - *longval = atol(argv[i + 1]); - argv[i][0] = 0; - argv[i + 1][0] = 0; - } - break; - case BOOLARG: - intval = (int *)va_arg(ap, int *); - *intval = 0; - for (i = 1; i < argc; i++) - if (!(strcmp(argv[i], specs[0]))) { - *intval = 1; - argv[i][0] = 0; - } - break; - case STRINGARG: - stringval = (char *)va_arg(ap, char *); - for (i = 1; i < (argc - 1); i++) - if (!(strcmp(argv[i], specs[0]))) { - strcpy(stringval, (char *)argv[i + 1]); - argv[i][0] = 0; - argv[i + 1][0] = 0; - } - break; - case BENCHMARK: - intval = (int *)va_arg(ap, int *); - *intval = 0; - for (i = 1; i < argc; i++) { - if (!(strcmp(argv[i], specs[0]))) { - *intval = 2; - if ((i + 1) < argc) { - if (!(strcmp(argv[i + 1], "short"))) - *intval = 1; - if (!(strcmp(argv[i + 1], "medium"))) - *intval = 2; - if (!(strcmp(argv[i + 1], "long"))) - *intval = 3; - argv[i + 1][0] = 0; - } - argv[i][0] = 0; - } - } - break; - } - specs++; - } - va_end(ap); - - for (i = 1; i < argc; i++) - if (argv[i][0] != 0) - printf("\nInvalid option: %s\n", argv[i]); -} diff --git a/reducer_bench/getoptions.h b/reducer_bench/getoptions.h deleted file mode 100644 index f47e2e1b..00000000 --- a/reducer_bench/getoptions.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Function to evaluate argv[]. specs is a 0 terminated array of command - * line options and types an array that stores the type as one of - */ -#define INTARG 1 -#define DOUBLEARG 2 -#define LONGARG 3 -#define BOOLARG 4 -#define STRINGARG 5 -#define BENCHMARK 6 -/* - * for each specifier. Benchmark is specific for cilk samples. - * -benchmark or -benchmark medium sets integer to 2 - * -benchmark short returns 1 - * -benchmark long returns 2 - * a boolarg is set to 1 if the specifier appears in the option list ow. 0 - * The variables must be given in the same order as specified in specs. - */ - -void get_options(int argc, char *argv[], const char *specs[], int *types,...); diff --git a/reducer_bench/intlist.c b/reducer_bench/intlist.c deleted file mode 100644 index 8383fd1c..00000000 --- a/reducer_bench/intlist.c +++ /dev/null @@ -1,71 +0,0 @@ -#include -#include -#include -#include - -#include "intlist.h" -#include "ktiming.h" - -#ifndef TIMING_COUNT -#define TIMING_COUNT 1 -#endif - -CILK_C_DECLARE_REDUCER(IntList) -my_int_list_reducer = - CILK_C_INIT_REDUCER(IntList, reduce_IntList, identity_IntList, - 0 /* no destructor */, {0}); -// Initial value omitted // - -void ilist_dac(int lo, int hi, int base) { - int mid, ctr; - - if (hi - lo < base) { - for (ctr = lo; ctr < hi; ctr++) - IntList_append(&REDUCER_VIEW(my_int_list_reducer), ctr); - return; - } - - mid = (lo + hi) / 2; - - cilk_spawn ilist_dac(lo, mid, base); - - ilist_dac(mid, hi, base); - - cilk_sync; - - return; -} - -int main(int argc, char *args[]) { - int i; - int n, res = 0, b = 4; - clockmark_t begin, end; - uint64_t running_time[TIMING_COUNT]; - - if (argc != 2 && argc != 3) { - fprintf(stderr, "Usage: ilist_dac [] []\n"); - exit(1); - } - - n = atoi(args[1]); - - if (argc == 3) { - b = atoi(args[2]); - } - - for (i = 0; i < TIMING_COUNT; i++) { - begin = ktiming_getmark(); - CILK_C_REGISTER_REDUCER(my_int_list_reducer); - IntList_init(&REDUCER_VIEW(my_int_list_reducer)); - ilist_dac(0, n, b); - IntList result = REDUCER_VIEW(my_int_list_reducer); - res += IntList_check(&result, 0, n); - CILK_C_UNREGISTER_REDUCER(my_int_list_reducer); - end = ktiming_getmark(); - running_time[i] = ktiming_diff_nsec(&begin, &end); - } - printf("Result: %d/%d successes!\n", res, TIMING_COUNT); - print_runtime(running_time, TIMING_COUNT); - - return 0; -} diff --git a/reducer_bench/intlist.h b/reducer_bench/intlist.h deleted file mode 100644 index 46de0f3f..00000000 --- a/reducer_bench/intlist.h +++ /dev/null @@ -1,76 +0,0 @@ -#ifndef _INTLIST_H -#define _INTLIST_H - -#include -#include - -typedef struct _intListNode { - int value; - struct _intListNode* next; -} IntListNode; -typedef struct { IntListNode* head; IntListNode* tail; } IntList; - -// Initialize a list to be empty -void IntList_init(IntList* list) { - list->head = list->tail = NULL; -} - -// Append an integer to the list -void IntList_append(IntList* list, int x) -{ - IntListNode* node = (IntListNode*) malloc(sizeof(IntListNode)); - node->value = x; - node->next = NULL; - - if (list->tail) { - list->tail->next = node; - } else { - list->head = node; - } - list->tail = node; -} - -// Append the right list to the left list, and leave the right list -// empty -void IntList_concat(IntList* left, IntList* right) -{ - if (left->head) { - left->tail->next = right->head; - if (right->tail) left->tail = right->tail; - } - else { - *left = *right; - } - IntList_init(right); -} - -void identity_IntList(void* reducer, void* list) -{ - IntList_init((IntList*)list); -} - -void reduce_IntList(void* reducer, void* left, void* right) -{ - IntList_concat((IntList*)left, (IntList*)right); -} - -// Append an integer to the list -int IntList_check(IntList* list, int lo, int hi) -{ - IntListNode* node = list->head; - int curr = lo; - - if (hi <= lo) return 0; - - while (node != NULL) { - if (node->value != curr) return 0; - node = node->next; - curr++; - } - - if (curr != hi) return 0; - - return 1; -} - -#endif diff --git a/reducer_bench/intsum.c b/reducer_bench/intsum.c deleted file mode 100644 index dedb2552..00000000 --- a/reducer_bench/intsum.c +++ /dev/null @@ -1,64 +0,0 @@ -#include -#include -#include -#include - -#include "ktiming.h" - -void identity_longsum(void *reducer, void *sum) { *((long *)sum) = 0; } - -void reduce_longsum(void *reducer, void *left, void *right) { - *((long *)left) += *((long *)right); -} - -CILK_C_DECLARE_REDUCER(long) -my_int_sum_reducer = CILK_C_INIT_REDUCER(long, reduce_longsum, identity_longsum, - 0, 0); - -void compute_sum(long limit, int scale) { - for (long i = 0; i < limit; i++) { - REDUCER_VIEW(my_int_sum_reducer) += scale; - } -} - -void test_reducer(long limit) { - #pragma GCC diagnostic ignored "-Wpass-failed" - for (int t = 1; t < 100; ++t) { - cilk_spawn compute_sum(limit, t); - } - compute_sum(limit, 100); - cilk_sync; -} - -int main(int argc, const char **args) { - long i, n; - int res = 0; - clockmark_t begin, end; - uint64_t running_time[TIMING_COUNT]; - - if (argc != 2) { - fprintf(stderr, "Usage: ilist_dac [] \n"); - exit(1); - } - - n = atol(args[1]); - - const long scale = 100 * 101 / 2; - - for (i = 0; i < TIMING_COUNT; i++) { - begin = ktiming_getmark(); - CILK_C_REGISTER_REDUCER(my_int_sum_reducer); - *(&REDUCER_VIEW(my_int_sum_reducer)) = 0; - test_reducer(n); - long sum = REDUCER_VIEW(my_int_sum_reducer); - res += (sum == scale * n) ? 1 : 0; - CILK_C_UNREGISTER_REDUCER(my_int_sum_reducer); - end = ktiming_getmark(); - // prlongf("The final sum is %d\n", sum); - running_time[i] = ktiming_diff_nsec(&begin, &end); - } - printf("Result: %d/%d successes!\n", res, TIMING_COUNT); - print_runtime(running_time, TIMING_COUNT); - - return res != TIMING_COUNT; -} diff --git a/reducer_bench/ktiming.c b/reducer_bench/ktiming.c deleted file mode 100644 index 830dcf22..00000000 --- a/reducer_bench/ktiming.c +++ /dev/null @@ -1,102 +0,0 @@ -/** - * Copyright (c) 2012 MIT License by 6.172 Staff - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - **/ - -/** - * Linux kernel-assisted timing library -- provides high-precision time - * measurements for the execution time of your algorithms. - * - * You shouldn't need to modify this file. More importantly, you should not - * depend on any modifications you make here, as we will replace it with a - * fresh copy when we test your code. - **/ - -#include "./ktiming.h" - -#include -#include -#include -#include - -#define NSEC_TO_SEC(x) ((double)(x)*1.0e-9) - -clockmark_t ktiming_getmark(void) { - struct timespec temp = {0, 0}; - uint64_t nanos; - - int stat = clock_gettime(CLOCK_MONOTONIC, &temp); - if (stat != 0) { - perror("ktiming_getmark()"); - exit(-1); - } - nanos = temp.tv_nsec; - nanos += ((uint64_t)temp.tv_sec) * 1000 * 1000 * 1000; - return nanos; -} - -uint64_t ktiming_diff_nsec(const clockmark_t *const start, - const clockmark_t *const end) { - return *end - *start; -} - -double ktiming_diff_sec(const clockmark_t *const start, - const clockmark_t *const end) { - return NSEC_TO_SEC(ktiming_diff_nsec(start, end)); -} - -static void print_runtime_helper(uint64_t *nsec_elapsed, int size, - int summary) { - - int i; - uint64_t total = 0; - double ave, std_dev = 0, dev_sq_sum = 0; - - for (i = 0; i < size; i++) { - total += nsec_elapsed[i]; - if (!summary) { - printf("Running time %d: %gs\n", (i + 1), - NSEC_TO_SEC(nsec_elapsed[i])); - } - } - ave = total / size; - - if (size > 1) { - for (i = 0; i < size; i++) { - double diff = (double)nsec_elapsed[i] - ave; - dev_sq_sum += diff * diff; - } - std_dev = sqrt(dev_sq_sum / (size - 1)); - } - - printf("Running time average: %g s\n", NSEC_TO_SEC(ave)); - if (std_dev != 0) { - printf("Std. dev: %g s (%2.3f%%)\n", NSEC_TO_SEC(std_dev), - 100.0 * std_dev / ave); - } -} - -void print_runtime(uint64_t *tm_elapsed, int size) { - print_runtime_helper(tm_elapsed, size, 0); -} - -void print_runtime_summary(uint64_t *tm_elapsed, int size) { - print_runtime_helper(tm_elapsed, size, 1); -} diff --git a/reducer_bench/ktiming.h b/reducer_bench/ktiming.h deleted file mode 100644 index b5249f70..00000000 --- a/reducer_bench/ktiming.h +++ /dev/null @@ -1,39 +0,0 @@ -/** - * Copyright (c) 2012 MIT License by 6.172 Staff - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - **/ - -#ifndef _KTIMING_H_ -#define _KTIMING_H_ - -#include - -typedef uint64_t clockmark_t; - -uint64_t -ktiming_diff_nsec(const clockmark_t* const start, const clockmark_t* const end); -double -ktiming_diff_sec(const clockmark_t* const start, const clockmark_t* const end); -clockmark_t ktiming_getmark(void); -void print_runtime(uint64_t *tm_elapsed, int size); -void print_runtime_summary(uint64_t *tm_elapsed, int size); - -#endif // _KTIMING_H_ - diff --git a/reducer_bench/multispawnsum.c b/reducer_bench/multispawnsum.c deleted file mode 100644 index 3b32ca2a..00000000 --- a/reducer_bench/multispawnsum.c +++ /dev/null @@ -1,60 +0,0 @@ -#include -#include -#include -#include - -#include "ktiming.h" - -void identity_intsum(void *reducer, void *sum) { *((int *)sum) = 0; } - -void reduce_intsum(void *reducer, void *left, void *right) { - *((int *)left) += *((int *)right); -} - -CILK_C_DECLARE_REDUCER(int) -my_int_sum_reducer = CILK_C_INIT_REDUCER(int, reduce_intsum, identity_intsum, - 0 /* no destructor */, 0); - -void compute_sum(int limit) { - for (int i = 0; i < limit; i++) { - REDUCER_VIEW(my_int_sum_reducer) += 1; - } -} - -void test_reducer(int limit) { - cilk_spawn compute_sum(limit); - cilk_spawn compute_sum(limit); - compute_sum(limit); - cilk_sync; -} - -int main(int argc, const char **args) { - int i; - int n, res = 0; - clockmark_t begin, end; - uint64_t running_time[TIMING_COUNT]; - - if (argc != 2) { - fprintf(stderr, "Usage: ilist_dac [] \n"); - exit(1); - } - - n = atoi(args[1]); - - for (i = 0; i < TIMING_COUNT; i++) { - begin = ktiming_getmark(); - CILK_C_REGISTER_REDUCER(my_int_sum_reducer); - *(&REDUCER_VIEW(my_int_sum_reducer)) = 0; - test_reducer(n); - int sum = REDUCER_VIEW(my_int_sum_reducer); - res += (sum == 3 * n) ? 1 : 0; - CILK_C_UNREGISTER_REDUCER(my_int_sum_reducer); - end = ktiming_getmark(); - // printf("The final sum is %d\n", sum); - running_time[i] = ktiming_diff_nsec(&begin, &end); - } - printf("Result: %d/%d successes!\n", res, TIMING_COUNT); - print_runtime(running_time, TIMING_COUNT); - - return 0; -} diff --git a/reducer_bench/nqueens/.gitignore b/reducer_bench/nqueens/.gitignore deleted file mode 100644 index 63d0c065..00000000 --- a/reducer_bench/nqueens/.gitignore +++ /dev/null @@ -1,12 +0,0 @@ -# Exes -* -!*.* -!*/ -!Makefile - -# Emacs backups -*~ -\#*# - -# Compilations -*.o \ No newline at end of file diff --git a/reducer_bench/nqueens/Makefile b/reducer_bench/nqueens/Makefile deleted file mode 100644 index 6518bc3c..00000000 --- a/reducer_bench/nqueens/Makefile +++ /dev/null @@ -1,39 +0,0 @@ -include ../../config.mk - -ABI=opencilk - -OPTIONS = $(OPT) $(DBG) $(ARCH) -Wall - -TIMING_COUNT := 1 - -ifneq ($(DEBUG),1) - OPTIONS += -DNDEBUG -endif - -CFLAGS := -std=gnu99 -fopencilk $(OPTIONS) - -LDFLAGS := -lrt -lm - -RTS_LIBS = - -.PHONY: all check clean - -all: nqueens_int nqueens - -nqueens_int: nqueens_int.o ktiming.o - $(CC) $^ -o $@ $(RTS_OPT) $(RTS_LIBS) -lrt -lpthread -lm - -nqueens: board.o nqueens.o ktiming.o - $(CC) $^ -o $@ $(RTS_OPT) $(RTS_LIBS) -lrt -lpthread -lm - -# $(CC) -o queens board.o queens.o $(LDFLAGS) - -#%.o: %.c -# $(CC) -c $(OPTIONS) -DTIMING_COUNT=$(TIMING_COUNT) -o $@ $< - -check: nqueens_int nqueens - CILK_NWORKERS=2 ./nqueens_int - CILK_NWORKERS=2 ./nqueens - -clean: - rm -f nqueens_int nqueens *.o *~ core.* diff --git a/reducer_bench/nqueens/board.c b/reducer_bench/nqueens/board.c deleted file mode 100644 index 751428e8..00000000 --- a/reducer_bench/nqueens/board.c +++ /dev/null @@ -1,71 +0,0 @@ -/** - * Copyright (c) 2013 MIT License by 6.172 Staff - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - **/ - -#include "./board.h" - -#include -#include - -void print_board(board_t board) { - for (int row = 0; row < 8; row++) { - for (int col = 0; col < 8; col++) { - printf("%s ", (board & board_bitmask(row, col)) != 0 ? "Q" : "."); - } - printf("\n"); - } - printf("\n"); -} - -void append_node(BoardList *board_list, board_t board) { - BoardNode *new_node = malloc(sizeof(BoardNode)); - if (new_node == NULL) { - return; - } - new_node->board = board; - new_node->next = NULL; - if (board_list->head == NULL) { - board_list->head = new_node; - } else { - board_list->tail->next = new_node; - } - board_list->tail = new_node; - board_list->size++; -} - -void init_nodes(BoardList *board_list) { - board_list->head = NULL; - board_list->tail = NULL; - board_list->size = 0; -} - -void delete_nodes(BoardList *board_list) { - BoardNode *cur_node = board_list->head; - BoardNode *next_node = NULL; - while (cur_node != NULL) { - next_node = cur_node->next; - free(cur_node); - cur_node = next_node; - } - board_list->head = NULL; - board_list->tail = NULL; - board_list->size = 0; -} diff --git a/reducer_bench/nqueens/board.h b/reducer_bench/nqueens/board.h deleted file mode 100644 index ddbac06d..00000000 --- a/reducer_bench/nqueens/board.h +++ /dev/null @@ -1,59 +0,0 @@ -/** - * Copyright (c) 2013 MIT License by 6.172 Staff - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - **/ - -#ifndef _BOARD_H_ -#define _BOARD_H_ - -#include - -#define N (8) - -// Saves a queen in (row, col) in the (row * N + col)th bit. -// row, col must be 0-indexed. -typedef uint64_t board_t; - -static inline board_t board_bitmask(int row, int col) { - return ((board_t)1) << (row * N + col); -} - -void print_board(board_t board); - -struct BoardNode { - board_t board; - struct BoardNode *next; -}; -typedef struct BoardNode BoardNode; - -struct BoardList { - BoardNode *head; - BoardNode *tail; - int size; -}; -typedef struct BoardList BoardList; - -void append_node(BoardList *board_list, board_t board); - -void init_nodes(BoardList *board_list); - -void delete_nodes(BoardList *board_list); - -#endif // _BOARD_H_ diff --git a/reducer_bench/nqueens/fasttime.h b/reducer_bench/nqueens/fasttime.h deleted file mode 100644 index 5577ae54..00000000 --- a/reducer_bench/nqueens/fasttime.h +++ /dev/null @@ -1,94 +0,0 @@ -/** - * Copyright (c) 2014 MIT License by 6.172 Staff - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - **/ - -#ifndef INCLUDED_FASTTIME_DOT_H -#define INCLUDED_FASTTIME_DOT_H - -#define _POSIX_C_SOURCE 200809L - -#include - -#ifdef __MACH__ -#include // mach_absolute_time - -typedef uint64_t fasttime_t; - -// Return the current time. -static inline fasttime_t gettime(void) { return mach_absolute_time(); } - -// Return the time different between the start and the end, as a float -// in units of seconds. This function does not need to be fast. -// Implementation notes: See -// https://developer.apple.com/library/mac/qa/qa1398/_index.html -static inline double tdiff(fasttime_t start, fasttime_t end) { - static mach_timebase_info_data_t timebase; - int r = mach_timebase_info(&timebase); - assert(r == 0); - fasttime_t elapsed = end - start; - double ns = (double)elapsed * timebase.numer / timebase.denom; - return ns * 1e-9; -} - -static inline unsigned int random_seed_from_clock(void) { - fasttime_t now = gettime(); - return (now & 0xFFFFFFFF) + (now >> 32); -} - -#else // LINUX - -// We need _POSIX_C_SOURCE to pick up 'struct timespec' and clock_gettime. -// #define _POSIX_C_SOURCE 200809L - -#include - -typedef struct timespec fasttime_t; - -// Return the current time. -static inline fasttime_t gettime(void) { - struct timespec s; -#ifdef NDEBUG - clock_gettime(CLOCK_MONOTONIC, &s); -#else - int r = clock_gettime(CLOCK_MONOTONIC, &s); - assert(r == 0); -#endif - return s; -} - -// Return the time different between the start and the end, as a float -// in units of seconds. This function does not need to be fast. -static inline double tdiff(fasttime_t start, fasttime_t end) { - return end.tv_sec - start.tv_sec + 1e-9 * (end.tv_nsec - start.tv_nsec); -} - -static inline unsigned int random_seed_from_clock(void) { - fasttime_t now = gettime(); - return now.tv_sec + now.tv_nsec; -} - -// Poison these symbols to help find portability problems. -int clock_gettime(clockid_t, struct timespec *) __attribute__((deprecated)); -time_t time(time_t *) __attribute__((deprecated)); - -#endif // LINUX - -#endif // INCLUDED_FASTTIME_DOT_H diff --git a/reducer_bench/nqueens/ktiming.c b/reducer_bench/nqueens/ktiming.c deleted file mode 100644 index 84fae700..00000000 --- a/reducer_bench/nqueens/ktiming.c +++ /dev/null @@ -1,101 +0,0 @@ -/** - * Copyright (c) 2012 MIT License by 6.172 Staff - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - **/ - -/** - * Linux kernel-assisted timing library -- provides high-precision time - * measurements for the execution time of your algorithms. - * - * You shouldn't need to modify this file. More importantly, you should not - * depend on any modifications you make here, as we will replace it with a - * fresh copy when we test your code. - **/ - -#include "./ktiming.h" - -#include -#include -#include -#include - -#define USEC_TO_SEC(x) ((double)x * 1.0e-9) - -clockmark_t ktiming_getmark(void) { - struct timespec temp; - uint64_t nanos; - - int stat = clock_gettime(CLOCK_MONOTONIC, &temp); - if (stat != 0) { - perror("ktiming_getmark()"); - exit(-1); - } - nanos = temp.tv_nsec; - nanos += ((uint64_t)temp.tv_sec) * 1000 * 1000 * 1000; - return nanos; -} - -uint64_t ktiming_diff_usec(const clockmark_t *const start, - const clockmark_t *const end) { - return *end - *start; -} - -double ktiming_diff_sec(const clockmark_t *const start, - const clockmark_t *const end) { - return ((double)ktiming_diff_usec(start, end)) / 1000000000.0f; -} - -static void print_runtime_helper(uint64_t *usec_elapsed, int size, - int summary) { - - int i; - uint64_t total = 0; - double ave, std_dev = 0, dev_sq_sum = 0; - - for (i = 0; i < size; i++) { - total += usec_elapsed[i]; - if (!summary) { - printf("Running time %d: %gs\n", (i + 1), USEC_TO_SEC(usec_elapsed[i])); - } - } - ave = total / size; - - if (size > 1) { - for (i = 0; i < size; i++) { - dev_sq_sum += - ((ave - (double)usec_elapsed[i]) * (ave - (double)usec_elapsed[i])); - } - std_dev = sqrt(dev_sq_sum / (size - 1)); - } - - printf("Running time average: %g s\n", USEC_TO_SEC(ave)); - if (std_dev != 0) { - printf("Std. dev: %g s (%2.3f%%)\n", USEC_TO_SEC(std_dev), - 100.0 * USEC_TO_SEC(std_dev / ave)); - } -} - -void print_runtime(uint64_t *tm_elapsed, int size) { - print_runtime_helper(tm_elapsed, size, 0); -} - -void print_runtime_summary(uint64_t *tm_elapsed, int size) { - print_runtime_helper(tm_elapsed, size, 1); -} diff --git a/reducer_bench/nqueens/ktiming.h b/reducer_bench/nqueens/ktiming.h deleted file mode 100644 index 3b6babc1..00000000 --- a/reducer_bench/nqueens/ktiming.h +++ /dev/null @@ -1,38 +0,0 @@ -/** - * Copyright (c) 2012 MIT License by 6.172 Staff - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - **/ - -#ifndef _KTIMING_H_ -#define _KTIMING_H_ - -#include - -typedef uint64_t clockmark_t; - -uint64_t ktiming_diff_usec(const clockmark_t *const start, - const clockmark_t *const end); -double ktiming_diff_sec(const clockmark_t *const start, - const clockmark_t *const end); -clockmark_t ktiming_getmark(void); -void print_runtime(uint64_t *tm_elapsed, int size); -void print_runtime_summary(uint64_t *tm_elapsed, int size); - -#endif // _KTIMING_H_ diff --git a/reducer_bench/nqueens/nqueens.c b/reducer_bench/nqueens/nqueens.c deleted file mode 100644 index 57b6c11e..00000000 --- a/reducer_bench/nqueens/nqueens.c +++ /dev/null @@ -1,166 +0,0 @@ -/** - * Copyright (c) 2013 MIT License by 6.172 Staff - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - **/ - -#include -#include - -#include "board.h" -#include -#include -#include -#include -// #include "fasttime.h" -#include "ktiming.h" - -// board.h defines N, board_t, and helper functions. - -#ifndef TIMING_COUNT -#define TIMING_COUNT 1 -#endif - -// Feel free to make this 0. -#define TO_PRINT (3) // number of sample solutions to print -#define BITMASK (255) // 8 "1"s - -void merge_lists(BoardList *list1, BoardList *list2) { - if (list2->head == NULL) - return; // Nothing to do... - - if (list1->head == NULL) { - // Set list1 to list2 - list1->head = list2->head; - list1->size = list2->size; - } else { - // Append list2 to list1 - list1->tail->next = list2->head; - list1->size += list2->size; - } - - list1->tail = list2->tail; - - // Set list2 to empty - list2->head = NULL; - list2->tail = NULL; - list2->size = 0; -} - -// Evaluates *left = *left OPERATOR *right. -void board_list_reduce(void *key, void *left, void *right) { - BoardList *a = (BoardList *)left; - BoardList *b = (BoardList *)right; - merge_lists(a, b); -} - -// Sets *value to the the identity value. -void board_list_identity(void *key, void *value) { - BoardList *a = (BoardList *)value; - a->head = NULL; - a->tail = NULL; - a->size = 0; -} - -// Destroys any dynamically allocated memory. Hint: delete_nodes. -void board_list_destroy(void *key, void *value) { - BoardList *a = (BoardList *)value; - delete_nodes(a); -} - -typedef CILK_C_DECLARE_REDUCER(BoardList) BoardListReducer; - -BoardListReducer X = CILK_C_INIT_REDUCER( - BoardList, // type - board_list_reduce, board_list_identity, board_list_destroy, // functions - (BoardList){.head = NULL, .tail = NULL, .size = 0}); // initial value - -void queens(board_t cur_board, int row, int down, int left, int right) { - if (row == N) { - // A solution to 8 queens! - append_node(&REDUCER_VIEW(X), cur_board); - } else { - int open_cols_bitmap = BITMASK & ~(down | left | right); - - while (open_cols_bitmap != 0) { - int bit = -open_cols_bitmap & open_cols_bitmap; - int col = log2(bit); - open_cols_bitmap ^= bit; - - // Recurse! This can be parallelized. - cilk_spawn queens(cur_board | board_bitmask(row, col), row + 1, - down | bit, (left | bit) << 1, (right | bit) >> 1); - } - cilk_sync; - } -} - -int run_queens(bool verbose) { - CILK_C_REGISTER_REDUCER(X); - init_nodes(&REDUCER_VIEW(X)); - queens((board_t)0, 0, 0, 0, 0); - BoardList board_list = REDUCER_VIEW(X); - - int num_solutions = board_list.size; - - if (verbose) { - // Print the first few solutions to check correctness. - BoardNode *cur_node = board_list.head; - int num_printed = 0; - while (cur_node != NULL && num_printed < TO_PRINT) { - printf("Solution # %d / %d\n", num_printed + 1, num_solutions); - print_board(cur_node->board); - cur_node = cur_node->next; - num_printed++; - } - } - CILK_C_UNREGISTER_REDUCER(X); - delete_nodes(&board_list); - return num_solutions; -} - -int main(int argc, char *argv[]) { - clockmark_t begin, end; - uint64_t running_time[TIMING_COUNT]; - - int count = argc > 1 ? atoi(argv[1]) : -1; - if (count <= 0) - count = TIMING_COUNT; - - int num_solutions = 92, res = 0; - - for (int i = 0; i < count; i++) { - begin = ktiming_getmark(); - int run_solutions = run_queens(false); - - res += (num_solutions == run_solutions) ? 1 : 0; - end = ktiming_getmark(); - running_time[i] = ktiming_diff_usec(&begin, &end); - } - if (res == count) { - printf("Success\n"); - } else { - printf("Result: %d/%d successes (%d failures)\n", res, count, count - res); - } - if (count > 0) { - print_runtime(running_time, TIMING_COUNT); - } - - return res != TIMING_COUNT; -} diff --git a/reducer_bench/nqueens/nqueens_int.c b/reducer_bench/nqueens/nqueens_int.c deleted file mode 100644 index e4b3f715..00000000 --- a/reducer_bench/nqueens/nqueens_int.c +++ /dev/null @@ -1,118 +0,0 @@ -/** - * Copyright (c) 2013 MIT License by 6.172 Staff - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - **/ - -#include -#include - -#include -#include -#include -#include -// #include "board.h" -// #include "fasttime.h" -#include "ktiming.h" - -// board.h defines N, board_t, and helper functions. - -#ifndef TIMING_COUNT -#define TIMING_COUNT 1 -#endif - -// Feel free to make this 0. -#define TO_PRINT (3) // number of sample solutions to print -#define BITMASK (255) // 8 "1"s -#define N (8) - -// Saves a queen in (row, col) in the (row * N + col)th bit. -// row, col must be 0-indexed. -typedef uint64_t board_t; - -static inline board_t board_bitmask(int row, int col) { - return ((board_t)1) << (row * N + col); -} -typedef int BoardList; - -void board_list_identity(void *reducer, void *sum) { *((int *)sum) = 0; } - -void board_list_reduce(void *reducer, void *left, void *right) { - *((int *)left) += *((int *)right); -} - -typedef CILK_C_DECLARE_REDUCER(BoardList) BoardListReducer; - -BoardListReducer X = - CILK_C_INIT_REDUCER(BoardList, // type - board_list_reduce, board_list_identity, 0, // functions - (BoardList)0); // initial value - -void queens(board_t cur_board, int row, int down, int left, int right) { - if (row == N) { - // A solution to 8 queens! - REDUCER_VIEW(X) += 1; - } else { - int open_cols_bitmap = BITMASK & ~(down | left | right); - - while (open_cols_bitmap != 0) { - int bit = -open_cols_bitmap & open_cols_bitmap; - int col = log2(bit); - open_cols_bitmap ^= bit; - - // Recurse! This can be parallelized. - cilk_spawn queens(cur_board | board_bitmask(row, col), row + 1, - down | bit, (left | bit) << 1, (right | bit) >> 1); - } - cilk_sync; - } -} - -int run_queens(bool verbose) { - CILK_C_REGISTER_REDUCER(X); - *(&REDUCER_VIEW(X)) = 0; - queens((board_t)0, 0, 0, 0, 0); - BoardList board_list = REDUCER_VIEW(X); - - int num_solutions = board_list; - - CILK_C_UNREGISTER_REDUCER(X); - return num_solutions; -} - -int main(int argc, char *argv[]) { - int i; - clockmark_t begin, end; - uint64_t running_time[TIMING_COUNT]; - - int num_solutions = 92, res = 0; - - for (i = 0; i < TIMING_COUNT; i++) { - begin = ktiming_getmark(); - int run_solutions = run_queens(false); - - res += (num_solutions == run_solutions) ? 1 : 0; - end = ktiming_getmark(); - running_time[i] = ktiming_diff_usec(&begin, &end); - } - printf("Result: %d/%d successes!\n", res, TIMING_COUNT); - print_runtime(running_time, TIMING_COUNT); - - return 0; -} diff --git a/reducer_bench/quad_tree/.gitignore b/reducer_bench/quad_tree/.gitignore deleted file mode 100644 index f4020e1d..00000000 --- a/reducer_bench/quad_tree/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -screensaver -job_*_in.tar -log.cqrun/ -*.o diff --git a/reducer_bench/quad_tree/Makefile b/reducer_bench/quad_tree/Makefile deleted file mode 100644 index b729a290..00000000 --- a/reducer_bench/quad_tree/Makefile +++ /dev/null @@ -1,67 +0,0 @@ -include ../../config.mk - -OPTIONS = -g -Wall $(OPT) -fno-omit-frame-pointer -fopencilk - -RTS_LIBS = ../../runtime/$(RTS_LIB).a $(patsubst %,../../runtime/%/module.a,$(MODS)) - -# The sources we're building -HDRS = $(wildcard *.h) -SRCS = $(filter-out graphic_stuff.c, $(wildcard *.c)) - -# What we're building -OBJS = $(SRCS:.c=.o) - -# What we're building with -CXX = $(CC) -CXXFLAGS = -std=gnu99 -Wall -ftapir=cilkr -LDFLAGS = -lrt -lm $(RTS_LIBS) -lpthread - - -# Determine which profile--debug or release--we should build against, and set -# CFLAGS appropriately. - -ifneq ($(DEBUG),1) - # We want release mode. - OPTIONS += -DNDEBUG -endif - -ifdef MAX_SIZE - OPTIONS += -D"MAX_SIZE=$(MAX_SIZE)" -endif - -ifdef MAX_DEPTH - OPTIONS += -D"MAX_DEPTH=$(MAX_DEPTH)" -endif - -ifdef X_CELLS - OPTIONS += -D"X_CELLS=$(X_CELLS)" -endif - -ifdef Y_CELLS - OPTIONS += -D"Y_CELLS=$(Y_CELLS)" -endif - -ifdef CELLS - OPTIONS += -D"X_CELLS=$(CELLS)" -D"Y_CELLS=$(CELLS)" -endif - -ifdef LIVE - OPTIONS += -DLIVE -endif - -all: screensaver - -#$(PRODUCT): LDFLAGS += -lX11 -screensaver: $(OBJS) graphic_stuff.o - $(CC) $^ -o $@ $(RTS_LIBS) -lrt -lpthread -lm -lX11 -# $(CXX) $(LDFLAGS) $(EXTRA_LDFLAGS) -o $@ $(OBJS) graphic_stuff.o - -%.o: %.c $(HDRS) - $(CC) -c $(OPTIONS) -o $@ $< -# $(CXX) $(CXXFLAGS) $(EXTRA_CXXFLAGS) -o $@ -c $< - -check: screensaver - ./screensaver --cheetah-nproc 2 1000 - -clean: - rm -f screensaver *.o *.out *~ core.* diff --git a/reducer_bench/quad_tree/beta b/reducer_bench/quad_tree/beta deleted file mode 100644 index e69de29b..00000000 diff --git a/reducer_bench/quad_tree/bin.c b/reducer_bench/quad_tree/bin.c deleted file mode 100644 index bd88012f..00000000 --- a/reducer_bench/quad_tree/bin.c +++ /dev/null @@ -1,516 +0,0 @@ -#include "./bin.h" -#include -#include "./reducer_defs.h" - -// Compare two cells -// Do I really need this -int compCell(cell_t c1, cell_t c2) { - int pl = (c1 < c2); - int mi = (c1 > c2); - return pl - mi; - - // if (c1 == c2) return 0; - // if (c1 > c2) return -1; - // if (c1 < c2) return 1; -} - -// Compare two bins -int compBin(bin_t b1, bin_t b2) { - int ret = compCell(b1.xcell, b2.xcell); - ret = (ret == 0) ? compCell(b1.ycell, b2.ycell) : ret; - return ret; -} - -// Get l's bin -bin_t getBin(Line * l, CollisionWorld * cw) { - bin_t ret; - - // Get the displacement parallelogram - Vec p1 = l->p1; - Vec p2 = l->p2; - Vec p3 = Vec_add(p1, Vec_multiply(l->velocity, cw->timeStep)); - Vec p4 = Vec_add(p2, Vec_multiply(l->velocity, cw->timeStep)); - - // Get lower-left corner of AABB - double xmin = p1.x; - double ymin = p1.y; - xmin = (p2.x < xmin) ? p2.x : xmin; - ymin = (p2.y < ymin) ? p2.y : ymin; - xmin = (p3.x < xmin) ? p3.x : xmin; - ymin = (p3.y < ymin) ? p3.y : ymin; - xmin = (p4.x < xmin) ? p4.x : xmin; - ymin = (p4.y < ymin) ? p4.y : ymin; - - xmin = 2 * xmin - 1; - ymin = 2 * ymin - 1; - - // Convert to bin - ret.xcell = (cell_t) (xmin * X_CELLS); - ret.xcell = (-1 > ret.xcell) ? -1 : ret.xcell; - ret.xcell = (ret.xcell > X_CELLS) ? X_CELLS : ret.xcell; - - ret.ycell = (cell_t) (ymin * Y_CELLS); - ret.ycell = (-1 > ret.ycell) ? -1 : ret.ycell; - ret.ycell = (ret.ycell > Y_CELLS) ? Y_CELLS : ret.ycell; - - return ret; -} - -// Get bin version of l's AABB -bin_range_t getRange(Line * l, CollisionWorld * cw) { - bin_range_t ret; - - // Get the displacement parallelogram - Vec p1 = l->p1; - Vec p2 = l->p2; - Vec p3 = Vec_add(p1, Vec_multiply(l->velocity, cw->timeStep)); - Vec p4 = Vec_add(p2, Vec_multiply(l->velocity, cw->timeStep)); - - // Get AABB - double xmin = p1.x; - double ymin = p1.y; - double xmax = p1.x; - double ymax = p1.y; - - xmin = (p2.x < xmin) ? p2.x : xmin; - ymin = (p2.y < ymin) ? p2.y : ymin; - xmax = (p2.x > xmax) ? p2.x : xmax; - ymax = (p2.y > ymax) ? p2.y : ymax; - - xmin = (p3.x < xmin) ? p3.x : xmin; - ymin = (p3.y < ymin) ? p3.y : ymin; - xmax = (p3.x > xmax) ? p3.x : xmax; - ymax = (p3.y > ymax) ? p3.y : ymax; - - xmin = (p4.x < xmin) ? p4.x : xmin; - ymin = (p4.y < ymin) ? p4.y : ymin; - xmax = (p4.x > xmax) ? p4.x : xmax; - ymax = (p4.y > ymax) ? p4.y : ymax; - - xmin = 2 * xmin - 1; - ymin = 2 * ymin - 1; - xmax = 2 * xmax - 1; - ymax = 2 * ymax - 1; - - // Convert to bin - cell_t xcell_min = (cell_t) (xmin * X_CELLS); - xcell_min = (-1 > xcell_min) ? -1 : xcell_min; - xcell_min = (xcell_min > X_CELLS) ? X_CELLS : xcell_min; - - cell_t ycell_min = (cell_t) (ymin * Y_CELLS); - ycell_min = (-1 > ycell_min) ? -1 : ycell_min; - ycell_min = (ycell_min > Y_CELLS) ? Y_CELLS : ycell_min; - - cell_t xcell_max = (cell_t) (xmax * X_CELLS); - xcell_max = (-1 > xcell_max) ? -1 : xcell_max; - xcell_max = (xcell_max > X_CELLS) ? X_CELLS : xcell_max; - - cell_t ycell_max = (cell_t) (ymax * Y_CELLS); - ycell_max = (-1 > ycell_max) ? -1 : ycell_max; - ycell_max = (ycell_max > Y_CELLS) ? Y_CELLS : ycell_max; - - ret.min.xcell = xcell_min; - ret.min.ycell = ycell_min; - ret.max.xcell = xcell_max; - ret.max.ycell = ycell_max; - - return ret; -} - -// Standard new -bin_manager_t * new_bin_manager() { - bin_manager_t * ret = (bin_manager_t *) malloc(sizeof(bin_manager_t)); - - int size = (X_CELLS + 2) * (Y_CELLS + 2) ; - bin_loc_t * bins = (bin_loc_t *) malloc(sizeof(bin_loc_t) * size); - - ret->bins = bins; - ret->size = size; - - return ret; -} - -// Standard free -void free_bin_manager(bin_manager_t * man) { - free(man->bins); - free(man); -} - -// Convert cell's to an index -int getBin_ind(cell_t x, cell_t y) { - x = (-1 > x) ? -1 : x; - x = (x > X_CELLS) ? X_CELLS : x; - y = (-1 > y) ? -1 : y; - y = (y > Y_CELLS) ? Y_CELLS : y; - int ind = (x + 1) * (Y_CELLS + 2) + y + 1; - return ind; -} - -// Do I even use this? -unsigned int getBin_start(cell_t x, cell_t y, bin_manager_t * man) { - x = (-1 > x) ? -1 : x; - x = (x > X_CELLS) ? X_CELLS : x; - y = (-1 > y) ? -1 : y; - y = (y > Y_CELLS) ? Y_CELLS : y; - int ind = (x + 1) * (Y_CELLS + 2) + y + 1; - return man->bins[ind].start; -} - -// Do I even use this? -unsigned int getBin_end(cell_t x, cell_t y, bin_manager_t * man) { - x = (-1 > x) ? -1 : x; - x = (x > X_CELLS) ? X_CELLS : x; - y = (-1 > y) ? -1 : y; - y = (y > Y_CELLS) ? Y_CELLS : y; - int ind = (x + 1) * (Y_CELLS + 2) + y + 1; - return man->bins[ind].end; -} - -// Initialize man with data from cw->lines -// Only works if cw->lines is sorted -void setBins(CollisionWorld * cw, bin_manager_t * man) { - unsigned int n = cw->numOfLines; - int ind = 0; - int oldind = 0; - - // Starting data for first bin - man->bins[0].start = 0; - man->bins[0].top = -2; - man->bins[0].right = -2; - - // Iterate over lines - for (unsigned int i = 0; i < n; i++) { - // Get AABB - bin_range_t bin = getRange(cw->lines[i], cw); - ind = getBin_ind(bin.min.xcell, bin.min.ycell); - - // We moved to a new bin - if (ind > oldind) { - man->bins[oldind].end = i; - - // Populate intermediary bins - for (int j = oldind + 1; j < ind; j++) { - man->bins[j].start = i; - man->bins[j].end = i; - man->bins[j].top = -2; - man->bins[j].right = -2; - } - - // Start news bins - man->bins[ind].start = i; - man->bins[ind].top = -2; - man->bins[ind].right = -2; - oldind = ind; - } - - // Update range - man->bins[ind].top = (bin.max.ycell > man->bins[ind].top) ? bin.max.ycell : man->bins[ind].top; - man->bins[ind].right = (bin.max.xcell > man->bins[ind].right) ? bin.max.xcell : man->bins[ind].right; - } - - // Fill trailing bins - man->bins[ind].end = n; - for (int j = ind + 1; j < man->size; j++) { - man->bins[j].start = n; - man->bins[j].end = n; - man->bins[j].top = -2; - man->bins[j].right = -2; - } -} - -// Insertion sort on cw->lines -// Assuming velocities are low, amortized very fast -void sortLines(CollisionWorld * cw) { - unsigned int n = cw->numOfLines; - - // Need i, j signed, so make them ssize_t - for (ssize_t i = 0; i < n; i++) { - // cw->lines[i]->id = i; - bin_t bin = getBin(cw->lines[i], cw); - int ind = getBin_ind(bin.xcell, bin.ycell); - cw->lines[i]->ind = ind; - for (ssize_t j = i - 1; j >= 0; j--) { - // bin_t binj = getBin(cw->lines[j], cw); - if (cw->lines[j]->ind > ind) { // (compBin(binj, bin) < 0) { - Line * temp = cw->lines[j + 1]; - cw->lines[j + 1] = cw->lines[j]; - cw->lines[j] = temp; - // cw->lines[j + 1]->id++; - // cw->lines[j]->id--; - } else { - break; - } - } - } -} - -// Find lines in man->bins[ind1:ind2] that cw->lines[i] collides with -// Only checks lines after cw->lines[i] -unsigned int intersect_range(unsigned int i, int ind1, int ind2, bin_manager_t * man, IntersectionEventList * iel, CollisionWorld * cw) { - - unsigned int start = man->bins[ind1].start; - unsigned int end = man->bins[ind2].end; - - for (unsigned int j = (start > i) ? start : i + 1; j < end; j++) { - Line * l1 = cw->lines[i]; - Line * l2 = cw->lines[j]; - - // intersect expects compareLines(l1, l2) < 0 to be true. - // Swap l1 and l2, if necessary. - if (compareLines(l1, l2) >= 0) { - Line *temp = l1; - l1 = l2; - l2 = temp; - } - uint8_t res = intersectFast(l1, l2, cw->timeStep); - if (res) { - IntersectionType intersectionType = intersectDecode(res, l1, l2, cw->timeStep); - // IntersectionType intersectionType2 = intersect(l1, l2, cw->timeStep); - // assert(intersectionType == intersectionType2); - IntersectionEventList_appendNode(iel, l1, l2, intersectionType); - } - } - - return 0; -} - -// Reducer version -void intersect_range_red(unsigned int i, int ind1, int ind2, bin_manager_t * man, IELReducer * red, CollisionWorld * cw) { - - unsigned int start = man->bins[ind1].start; - start = (start > i) ? start : i + 1; - unsigned int end = man->bins[ind2].end; - - if (end - start < 32) { - IntersectionEventList * iel = &REDVAL(*red); - for (unsigned int j = start; j < end; j++) { - Line * l1 = cw->lines[i]; - Line * l2 = cw->lines[j]; - - // intersect expects compareLines(l1, l2) < 0 to be true. - // Swap l1 and l2, if necessary. - if (compareLines(l1, l2) >= 0) { - Line *temp = l1; - l1 = l2; - l2 = temp; - } - uint8_t res = intersectFast(l1, l2, cw->timeStep); - if (res) { - IntersectionType intersectionType = intersectDecode(res, l1, l2, cw->timeStep); - // IntersectionType intersectionType2 = intersect(l1, l2, cw->timeStep); - // assert(intersectionType == intersectionType2); - IntersectionEventList_appendNode(iel, l1, l2, intersectionType); - } - } - } else { - cilk_for (unsigned int j = start; j < end; j++) { - Line * l1 = cw->lines[i]; - Line * l2 = cw->lines[j]; - - // intersect expects compareLines(l1, l2) < 0 to be true. - // Swap l1 and l2, if necessary. - if (compareLines(l1, l2) >= 0) { - Line *temp = l1; - l1 = l2; - l2 = temp; - } - uint8_t res = intersectFast(l1, l2, cw->timeStep); - if (res) { - IntersectionType intersectionType = intersectDecode(res, l1, l2, cw->timeStep); - // IntersectionType intersectionType2 = intersect(l1, l2, cw->timeStep); - // assert(intersectionType == intersectionType2); - IntersectionEventList_appendNode(&REDVAL(*red), l1, l2, intersectionType); - } - } - } -} - -// Find lines in man->bins[ind] that hit the wall -unsigned int wallCollision_range(int ind, bin_manager_t * man, CollisionWorld * cw) { - unsigned int numLineWallCollisions = 0; - - unsigned int start = man->bins[ind].start; - unsigned int end = man->bins[ind].end; - for (unsigned int j = start; j < end; j++) { - Line *line = cw->lines[j]; - bool collide = false; - - // Right side - if ((line->p1.x > BOX_XMAX || line->p2.x > BOX_XMAX) - && (line->velocity.x > 0)) { - line->velocity.x = -line->velocity.x; - collide = true; - } - // Left side - if ((line->p1.x < BOX_XMIN || line->p2.x < BOX_XMIN) - && (line->velocity.x < 0)) { - line->velocity.x = -line->velocity.x; - collide = true; - } - // Top side - if ((line->p1.y > BOX_YMAX || line->p2.y > BOX_YMAX) - && (line->velocity.y > 0)) { - line->velocity.y = -line->velocity.y; - collide = true; - } - // Bottom side - if ((line->p1.y < BOX_YMIN || line->p2.y < BOX_YMIN) - && (line->velocity.y < 0)) { - line->velocity.y = -line->velocity.y; - collide = true; - } - // Update total number of collisions. - if (collide == true) { - numLineWallCollisions++; - } - } - - return numLineWallCollisions; -} - -// Get colliding lines -unsigned int bin_intersect(bin_manager_t * man, IntersectionEventList * iel, CollisionWorld * cw) { - unsigned int n = cw->numOfLines; - - IELReducer red = IEL_RED; - REGRED(red); - - // Iterate through all lines - cilk_for (unsigned int i = 0; i < n; i++) { - Line * l1 = cw->lines[i]; - bin_range_t r = getRange(l1, cw); - - // Test bins [r.min.xcell, r.min.ycell:r.max.ycell] - int ind1 = (r.min.xcell + 1) * (Y_CELLS + 2) + r.min.ycell + 1; - int ind2 = (r.min.xcell + 1) * (Y_CELLS + 2) + r.max.ycell + 1; - intersect_range_red(i, ind1, ind2, man, &red, cw); - - for (cell_t x = r.min.xcell + 1; x <= r.max.xcell; x++) { - // Test bins [x, -1:r.min.ycell] - for (cell_t y = -1; y < r.min.ycell; y++) { - int ind = (x + 1) * (Y_CELLS + 2) + y + 1; - // only test if bin's potential rang intersects r - if (man->bins[ind].top >= r.min.ycell) intersect_range_red(i, ind, ind, man, &red, cw); - } - - // Test bins [x, r.min.ycell:r.max.ycell] - ind1 = (x + 1) * (Y_CELLS + 2) + r.min.ycell + 1; - ind2 = (x + 1) * (Y_CELLS + 2) + r.max.ycell + 1; - intersect_range_red(i, ind1, ind2, man, &red, cw); - } - - } - // numLineLineCollisions += REDVAL(red).size; - IEL_merge(iel, &REDVAL(red)); - KILLRED(red); - - return 0; -} - -// Resolve Wall collisions -unsigned int bin_wallCollision(bin_manager_t * man, CollisionWorld * cw) { - unsigned int numLineWallCollisions = 0; - - // Iterate through all bins - for (cell_t x = -1; x <= X_CELLS; x++) { - for (cell_t y = -1; y <= Y_CELLS; y++) { - int ind = (x + 1) * (Y_CELLS + 2) + y + 1; - // only test if bin's potential range intersects border - if (x == -1 || x == X_CELLS || y == -1 || y == Y_CELLS || man->bins[ind].top == Y_CELLS || man->bins[ind].right == X_CELLS) { - numLineWallCollisions += wallCollision_range(ind, man, cw); - } - } - } - - return numLineWallCollisions; -} - -// Detect IF lines l1 and l2 will intersect between now and the next time step -// Encodes additional info to aid intersectDecode -uint8_t intersectFast(Line *l1, Line *l2, double time) { - assert(compareLines(l1, l2) < 0); - - Vec disp; - Vec p1; - Vec p2; - - // Get relative velocity. - disp = Vec_multiply(Vec_subtract(l2->velocity, l1->velocity), time); - - // Get the parallelogram. - p1 = Vec_add(l2->p1, disp); - p2 = Vec_add(l2->p2, disp); - - uint8_t res = 0; - - // Encode additional info - res = (intersectLines(l1->p1, l1->p2, l2->p1, l2->p2)) ? 32 : 0; - res += (intersectLines(l1->p1, l1->p2, p1, p2)) ? 1 : 0; - res += (intersectLines(l1->p1, l1->p2, p1, l2->p1)) ? 9 : 0; - res += (intersectLines(l1->p1, l1->p2, p2, l2->p2)) ? 5 : 0; - if ((res >> 5) == 0 && (res & 3) != 2) { - res += (pointInParallelogram(l1->p1, l2->p1, l2->p2, p1, p2) && pointInParallelogram(l1->p2, l2->p1, l2->p2, p1, p2)) ? 16 : 0; - } - return res; -} - - -// Detect HOW lines l1 and l2 will intersect between now and the next time step -// Uses info in res -IntersectionType intersectDecode(uint8_t res, Line *l1, Line *l2, double time) { - assert(compareLines(l1, l2) < 0); - - Vec disp; - Vec p1; - Vec p2; - - // Get relative velocity. - disp = Vec_multiply(Vec_subtract(l2->velocity, l1->velocity), time); - - // Get the parallelogram. - p1 = Vec_add(l2->p1, disp); - p2 = Vec_add(l2->p2, disp); - - int num_line_intersections = res & 3; - bool bottom_intersected = (res >> 2) & 1; - bool top_intersected = (res >> 3) & 1; - - if (res >> 5) { - return ALREADY_INTERSECTED; - } - - if (num_line_intersections == 2) { - return L2_WITH_L1; - } - - if ((res >> 4) & 1) { - return L1_WITH_L2; - } - - if (num_line_intersections == 0) { - return NO_INTERSECTION; - } - - Vec v1 = Vec_makeFromLine(*l1); - Vec v2 = Vec_makeFromLine(*l2); - double angle = Vec_angle(v1, v2); - - if (top_intersected) { - if (angle < 0) { - return L2_WITH_L1; - } else { - return L1_WITH_L2; - } - } - - if (bottom_intersected) { - if (angle > 0) { - return L2_WITH_L1; - } else { - return L1_WITH_L2; - } - } - - return L1_WITH_L2; -} - diff --git a/reducer_bench/quad_tree/bin.h b/reducer_bench/quad_tree/bin.h deleted file mode 100644 index e0432e25..00000000 --- a/reducer_bench/quad_tree/bin.h +++ /dev/null @@ -1,109 +0,0 @@ -#ifndef BIN_H_ -#define BIN_H_ - - -#include -#include - -#include "./vec.h" -#include "./line.h" -#include "./collision_world.h" -#include "./intersection_event_list.h" -#include "./intersection_detection.h" - - -#ifndef X_CELLS -#define X_CELLS 64 -#endif - -#ifndef Y_CELLS -#define Y_CELLS 64 -#endif - -// Type for bin coordinates -typedef int16_t cell_t; - -// Bin coordinates -typedef struct { - cell_t xcell; - cell_t ycell; -} bin_t; - -// Bin AABB -typedef struct { - bin_t min; - bin_t max; -} bin_range_t; - -// Data for each bin -typedef struct { - unsigned int start; - unsigned int end; - cell_t top; - cell_t right; -} bin_loc_t; - -// Maps bin info onto CollisionWorld -typedef struct { - bin_loc_t * bins; - int size; -} bin_manager_t; - -// Compare two cells -// Do I really need this -int compCell(cell_t c1, cell_t c2); - -// Compare two bins -int compBin(bin_t b1, bin_t b2); - -// Get l's bin -bin_t getBin(Line * l, CollisionWorld * cw); - -// Get bin version of l's AABB -bin_range_t getRange(Line * l, CollisionWorld * cw); - -// Standard new -bin_manager_t * new_bin_manager(); - -// Standard free -void free_bin_manager(bin_manager_t * man); - -// Convert cell's to an index -int getBin_ind(cell_t x, cell_t y); - -// Do I even use this? -unsigned int getBin_start(cell_t x, cell_t y, bin_manager_t * man); - -// Do I even use this? -unsigned int getBin_end(cell_t x, cell_t y, bin_manager_t * man); - -// Initialize man with data from cw->lines -// Only works if cw->lines is sorted -void setBins(CollisionWorld * cw, bin_manager_t * man); - -// Insertion sort on cw->lines -// Assuming velocities are low, amortized very fast -void sortLines(CollisionWorld * cw); - -// Find lines in man->bins[ind1:ind2] that cw->lines[i] collides with -// Only checks lines after cw->lines[i] -unsigned int intersect_range(unsigned int i, int ind1, int ind2, bin_manager_t * man, IntersectionEventList * iel, CollisionWorld * cw); - -// Find lines in man->bins[ind] that hit the wall -unsigned int wallCollision_range(int ind, bin_manager_t * man, CollisionWorld * cw); - -// Get colliding lines -unsigned int bin_intersect(bin_manager_t * man, IntersectionEventList * iel, CollisionWorld * cw); - -// Resolve Wall collisions -unsigned int bin_wallCollision(bin_manager_t * man, CollisionWorld * cw); - -// Detect IF lines l1 and l2 will intersect between now and the next time step -// Encodes additional info to aid intersectDecode -uint8_t intersectFast(Line *l1, Line *l2, double time); - -// Detect HOW lines l1 and l2 will intersect between now and the next time step -// Uses info in res -IntersectionType intersectDecode(uint8_t res, Line *l1, Line *l2, double time); - -#endif diff --git a/reducer_bench/quad_tree/clint.py b/reducer_bench/quad_tree/clint.py deleted file mode 100644 index 54747e13..00000000 --- a/reducer_bench/quad_tree/clint.py +++ /dev/null @@ -1,3373 +0,0 @@ -#!/usr/bin/python -# -# Copyright (c) 2009 Google Inc. All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -#NOTE(TFK): Modified by 6.172 Staff to lint-ify C code. - -# Here are some issues that I've had people identify in my code during reviews, -# that I think are possible to flag automatically in a lint tool. If these were -# caught by lint, it would save time both for myself and that of my reviewers. -# Most likely, some of these are beyond the scope of the current lint framework, -# but I think it is valuable to retain these wish-list items even if they cannot -# be immediately implemented. -# -# Suggestions -# ----------- -# - Check for no 'explicit' for multi-arg ctor -# - Check for boolean assign RHS in parens -# - Check for ctor initializer-list colon position and spacing -# - Check that if there's a ctor, there should be a dtor -# - Check accessors that return non-pointer member variables are -# declared const -# - Check accessors that return non-const pointer member vars are -# *not* declared const -# - Check for using public includes for testing -# - Check for spaces between brackets in one-line inline method -# - Check for no assert() -# - Check for spaces surrounding operators -# - Check for 0 in pointer context (should be NULL) -# - Check for 0 in char context (should be '\0') -# - Check for camel-case method name conventions for methods -# that are not simple inline getters and setters -# - Check that base classes have virtual destructors -# put " // namespace" after } that closes a namespace, with -# namespace's name after 'namespace' if it is named. -# - Do not indent namespace contents -# - Avoid inlining non-trivial constructors in header files -# include base/basictypes.h if DISALLOW_EVIL_CONSTRUCTORS is used -# - Check for old-school (void) cast for call-sites of functions -# ignored return value -# - Check gUnit usage of anonymous namespace -# - Check for class declaration order (typedefs, consts, enums, -# ctor(s?), dtor, friend declarations, methods, member vars) -# - -#NOTE(TFK): Modified to lint-ify C files by 6.172. - - -"""Does google-lint on c++ files. - -The goal of this script is to identify places in the code that *may* -be in non-compliance with google style. It does not attempt to fix -up these problems -- the point is to educate. It does also not -attempt to find all problems, or to ensure that everything it does -find is legitimately a problem. - -In particular, we can get very confused by /* and // inside strings! -We do a small hack, which is to ignore //'s with "'s after them on the -same line, but it is far from perfect (in either direction). -""" - -import codecs -import getopt -import math # for log -import os -import re -import sre_compile -import string -import sys -import unicodedata - - -_USAGE = """ -Syntax: cpplint.py [--verbose=#] [--output=vs7] [--filter=-x,+y,...] - [--counting=total|toplevel|detailed] - [file] ... - - The style guidelines this tries to follow are those in - http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml - - Every problem is given a confidence score from 1-5, with 5 meaning we are - certain of the problem, and 1 meaning it could be a legitimate construct. - This will miss some errors, and is not a substitute for a code review. - - To suppress false-positive errors of a certain category, add a - 'NOLINT(category)' comment to the line. NOLINT or NOLINT(*) - suppresses errors of all categories on that line. - - The files passed in will be linted; at least one file must be provided. - Linted extensions are .c, .cpp, and .h. Other file types will be ignored. - - Flags: - - output=vs7 - By default, the output is formatted to ease emacs parsing. Visual Studio - compatible output (vs7) may also be used. Other formats are unsupported. - - verbose=# - Specify a number 0-5 to restrict errors to certain verbosity levels. - - filter=-x,+y,... - Specify a comma-separated list of category-filters to apply: only - error messages whose category names pass the filters will be printed. - (Category names are printed with the message and look like - "[whitespace/indent]".) Filters are evaluated left to right. - "-FOO" and "FOO" means "do not print categories that start with FOO". - "+FOO" means "do print categories that start with FOO". - - Examples: --filter=-whitespace,+whitespace/braces - --filter=whitespace,runtime/printf,+runtime/printf_format - --filter=-,+build/include_what_you_use - - To see a list of all the categories used in cpplint, pass no arg: - --filter= - - counting=total|toplevel|detailed - The total number of errors found is always printed. If - 'toplevel' is provided, then the count of errors in each of - the top-level categories like 'build' and 'whitespace' will - also be printed. If 'detailed' is provided, then a count - is provided for each category like 'build/class'. -""" - -# We categorize each error message we print. Here are the categories. -# We want an explicit list so we can list them all in cpplint --filter=. -# If you add a new error message with a new category, add it to the list -# here! cpplint_unittest.py should tell you if you forget to do this. -# \ used for clearer layout -- pylint: disable-msg=C6013 -_ERROR_CATEGORIES = [ - 'build/class', - 'build/deprecated', - 'build/endif_comment', - 'build/explicit_make_pair', - 'build/forward_decl', - 'build/header_guard', - 'build/include', - 'build/include_alpha', - 'build/include_order', - 'build/include_what_you_use', - 'build/namespaces', - 'build/printf_format', - 'build/storage_class', - 'legal/copyright', - 'readability/braces', - 'readability/casting', - 'readability/check', - 'readability/constructors', - 'readability/fn_size', - 'readability/function', - 'readability/multiline_comment', - 'readability/multiline_string', - 'readability/nolint', - 'readability/streams', - 'readability/todo', - 'readability/utf8', - 'runtime/arrays', - 'runtime/casting', - 'runtime/explicit', - 'runtime/int', - 'runtime/init', - 'runtime/invalid_increment', - 'runtime/member_string_references', - 'runtime/memset', - 'runtime/operator', - 'runtime/printf', - 'runtime/printf_format', - 'runtime/references', - 'runtime/rtti', - 'runtime/sizeof', - 'runtime/string', - 'runtime/threadsafe_fn', - 'runtime/virtual', - 'whitespace/blank_line', - 'whitespace/braces', - 'whitespace/comma', - 'whitespace/comments', - 'whitespace/end_of_line', - 'whitespace/ending_newline', - 'whitespace/indent', - 'whitespace/labels', - 'whitespace/line_length', - 'whitespace/newline', - 'whitespace/operators', - 'whitespace/parens', - 'whitespace/semicolon', - 'whitespace/tab', - 'whitespace/todo' - ] - -# The default state of the category filter. This is overrided by the --filter= -# flag. By default all errors are on, so only add here categories that should be -# off by default (i.e., categories that must be enabled by the --filter= flags). -# All entries here should start with a '-' or '+', as in the --filter= flag. -_DEFAULT_FILTERS = ['-build/include_alpha'] - -# We used to check for high-bit characters, but after much discussion we -# decided those were OK, as long as they were in UTF-8 and didn't represent -# hard-coded international strings, which belong in a separate i18n file. - -# Headers that we consider STL headers. -_STL_HEADERS = frozenset([ - 'algobase.h', 'algorithm', 'alloc.h', 'bitset', 'deque', 'exception', - 'function.h', 'functional', 'hash_map', 'hash_map.h', 'hash_set', - 'hash_set.h', 'iterator', 'list', 'list.h', 'map', 'memory', 'new', - 'pair.h', 'pthread_alloc', 'queue', 'set', 'set.h', 'sstream', 'stack', - 'stl_alloc.h', 'stl_relops.h', 'type_traits.h', - 'utility', 'vector', 'vector.h', - ]) - - -# Non-STL C++ system headers. -_CPP_HEADERS = frozenset([ - 'algo.h', 'builtinbuf.h', 'bvector.h', 'cassert', 'cctype', - 'cerrno', 'cfloat', 'ciso646', 'climits', 'clocale', 'cmath', - 'complex', 'complex.h', 'csetjmp', 'csignal', 'cstdarg', 'cstddef', - 'cstdio', 'cstdlib', 'cstring', 'ctime', 'cwchar', 'cwctype', - 'defalloc.h', 'deque.h', 'editbuf.h', 'exception', 'fstream', - 'fstream.h', 'hashtable.h', 'heap.h', 'indstream.h', 'iomanip', - 'iomanip.h', 'ios', 'iosfwd', 'iostream', 'iostream.h', 'istream', - 'istream.h', 'iterator.h', 'limits', 'map.h', 'multimap.h', 'multiset.h', - 'numeric', 'ostream', 'ostream.h', 'parsestream.h', 'pfstream.h', - 'PlotFile.h', 'procbuf.h', 'pthread_alloc.h', 'rope', 'rope.h', - 'ropeimpl.h', 'SFile.h', 'slist', 'slist.h', 'stack.h', 'stdexcept', - 'stdiostream.h', 'streambuf.h', 'stream.h', 'strfile.h', 'string', - 'strstream', 'strstream.h', 'tempbuf.h', 'tree.h', 'typeinfo', 'valarray', - ]) - - -# Assertion macros. These are defined in base/logging.h and -# testing/base/gunit.h. Note that the _M versions need to come first -# for substring matching to work. -_CHECK_MACROS = [ - 'DCHECK', 'CHECK', - 'EXPECT_TRUE_M', 'EXPECT_TRUE', - 'ASSERT_TRUE_M', 'ASSERT_TRUE', - 'EXPECT_FALSE_M', 'EXPECT_FALSE', - 'ASSERT_FALSE_M', 'ASSERT_FALSE', - ] - -# Replacement macros for CHECK/DCHECK/EXPECT_TRUE/EXPECT_FALSE -_CHECK_REPLACEMENT = dict([(m, {}) for m in _CHECK_MACROS]) - -for op, replacement in [('==', 'EQ'), ('!=', 'NE'), - ('>=', 'GE'), ('>', 'GT'), - ('<=', 'LE'), ('<', 'LT')]: - _CHECK_REPLACEMENT['DCHECK'][op] = 'DCHECK_%s' % replacement - _CHECK_REPLACEMENT['CHECK'][op] = 'CHECK_%s' % replacement - _CHECK_REPLACEMENT['EXPECT_TRUE'][op] = 'EXPECT_%s' % replacement - _CHECK_REPLACEMENT['ASSERT_TRUE'][op] = 'ASSERT_%s' % replacement - _CHECK_REPLACEMENT['EXPECT_TRUE_M'][op] = 'EXPECT_%s_M' % replacement - _CHECK_REPLACEMENT['ASSERT_TRUE_M'][op] = 'ASSERT_%s_M' % replacement - -for op, inv_replacement in [('==', 'NE'), ('!=', 'EQ'), - ('>=', 'LT'), ('>', 'LE'), - ('<=', 'GT'), ('<', 'GE')]: - _CHECK_REPLACEMENT['EXPECT_FALSE'][op] = 'EXPECT_%s' % inv_replacement - _CHECK_REPLACEMENT['ASSERT_FALSE'][op] = 'ASSERT_%s' % inv_replacement - _CHECK_REPLACEMENT['EXPECT_FALSE_M'][op] = 'EXPECT_%s_M' % inv_replacement - _CHECK_REPLACEMENT['ASSERT_FALSE_M'][op] = 'ASSERT_%s_M' % inv_replacement - - -# These constants define types of headers for use with -# _IncludeState.CheckNextIncludeOrder(). -_C_SYS_HEADER = 1 -_CPP_SYS_HEADER = 2 -_LIKELY_MY_HEADER = 3 -_POSSIBLE_MY_HEADER = 4 -_OTHER_HEADER = 5 - - -_regexp_compile_cache = {} - -# Finds occurrences of NOLINT or NOLINT(...). -_RE_SUPPRESSION = re.compile(r'\bNOLINT\b(\([^)]*\))?') - -# {str, set(int)}: a map from error categories to sets of linenumbers -# on which those errors are expected and should be suppressed. -_error_suppressions = {} - -def ParseNolintSuppressions(filename, raw_line, linenum, error): - """Updates the global list of error-suppressions. - - Parses any NOLINT comments on the current line, updating the global - error_suppressions store. Reports an error if the NOLINT comment - was malformed. - - Args: - filename: str, the name of the input file. - raw_line: str, the line of input text, with comments. - linenum: int, the number of the current line. - error: function, an error handler. - """ - # FIXME(adonovan): "NOLINT(" is misparsed as NOLINT(*). - matched = _RE_SUPPRESSION.search(raw_line) - if matched: - category = matched.group(1) - if category in (None, '(*)'): # => "suppress all" - _error_suppressions.setdefault(None, set()).add(linenum) - else: - if category.startswith('(') and category.endswith(')'): - category = category[1:-1] - if category in _ERROR_CATEGORIES: - _error_suppressions.setdefault(category, set()).add(linenum) - else: - error(filename, linenum, 'readability/nolint', 5, - 'Unknown NOLINT error category: %s' % category) - - -def ResetNolintSuppressions(): - "Resets the set of NOLINT suppressions to empty." - _error_suppressions.clear() - - -def IsErrorSuppressedByNolint(category, linenum): - """Returns true if the specified error category is suppressed on this line. - - Consults the global error_suppressions map populated by - ParseNolintSuppressions/ResetNolintSuppressions. - - Args: - category: str, the category of the error. - linenum: int, the current line number. - Returns: - bool, True iff the error should be suppressed due to a NOLINT comment. - """ - return (linenum in _error_suppressions.get(category, set()) or - linenum in _error_suppressions.get(None, set())) - -def Match(pattern, s): - """Matches the string with the pattern, caching the compiled regexp.""" - # The regexp compilation caching is inlined in both Match and Search for - # performance reasons; factoring it out into a separate function turns out - # to be noticeably expensive. - if not pattern in _regexp_compile_cache: - _regexp_compile_cache[pattern] = sre_compile.compile(pattern) - return _regexp_compile_cache[pattern].match(s) - - -def Search(pattern, s): - """Searches the string for the pattern, caching the compiled regexp.""" - if not pattern in _regexp_compile_cache: - _regexp_compile_cache[pattern] = sre_compile.compile(pattern) - return _regexp_compile_cache[pattern].search(s) - - -class _IncludeState(dict): - """Tracks line numbers for includes, and the order in which includes appear. - - As a dict, an _IncludeState object serves as a mapping between include - filename and line number on which that file was included. - - Call CheckNextIncludeOrder() once for each header in the file, passing - in the type constants defined above. Calls in an illegal order will - raise an _IncludeError with an appropriate error message. - - """ - # self._section will move monotonically through this set. If it ever - # needs to move backwards, CheckNextIncludeOrder will raise an error. - _INITIAL_SECTION = 0 - _MY_H_SECTION = 1 - _C_SECTION = 2 - _CPP_SECTION = 3 - _OTHER_H_SECTION = 4 - - _TYPE_NAMES = { - _C_SYS_HEADER: 'C system header', - _CPP_SYS_HEADER: 'C++ system header', - _LIKELY_MY_HEADER: 'header this file implements', - _POSSIBLE_MY_HEADER: 'header this file may implement', - _OTHER_HEADER: 'other header', - } - _SECTION_NAMES = { - _INITIAL_SECTION: "... nothing. (This can't be an error.)", - _MY_H_SECTION: 'a header this file implements', - _C_SECTION: 'C system header', - _CPP_SECTION: 'C++ system header', - _OTHER_H_SECTION: 'other header', - } - - def __init__(self): - dict.__init__(self) - # The name of the current section. - self._section = self._INITIAL_SECTION - # The path of last found header. - self._last_header = '' - - def CanonicalizeAlphabeticalOrder(self, header_path): - """Returns a path canonicalized for alphabetical comparison. - - - replaces "-" with "_" so they both cmp the same. - - removes '-inl' since we don't require them to be after the main header. - - lowercase everything, just in case. - - Args: - header_path: Path to be canonicalized. - - Returns: - Canonicalized path. - """ - return header_path.replace('-inl.h', '.h').replace('-', '_').lower() - - def IsInAlphabeticalOrder(self, header_path): - """Check if a header is in alphabetical order with the previous header. - - Args: - header_path: Header to be checked. - - Returns: - Returns true if the header is in alphabetical order. - """ - canonical_header = self.CanonicalizeAlphabeticalOrder(header_path) - if self._last_header > canonical_header: - return False - self._last_header = canonical_header - return True - - def CheckNextIncludeOrder(self, header_type): - """Returns a non-empty error message if the next header is out of order. - - This function also updates the internal state to be ready to check - the next include. - - Args: - header_type: One of the _XXX_HEADER constants defined above. - - Returns: - The empty string if the header is in the right order, or an - error message describing what's wrong. - - """ - error_message = ('Found %s after %s' % - (self._TYPE_NAMES[header_type], - self._SECTION_NAMES[self._section])) - - last_section = self._section - - if header_type == _C_SYS_HEADER: - if self._section <= self._C_SECTION: - self._section = self._C_SECTION - else: - self._last_header = '' - return error_message - elif header_type == _CPP_SYS_HEADER: - if self._section <= self._CPP_SECTION: - self._section = self._CPP_SECTION - else: - self._last_header = '' - return error_message - elif header_type == _LIKELY_MY_HEADER: - if self._section <= self._MY_H_SECTION: - self._section = self._MY_H_SECTION - else: - self._section = self._OTHER_H_SECTION - elif header_type == _POSSIBLE_MY_HEADER: - if self._section <= self._MY_H_SECTION: - self._section = self._MY_H_SECTION - else: - # This will always be the fallback because we're not sure - # enough that the header is associated with this file. - self._section = self._OTHER_H_SECTION - else: - assert header_type == _OTHER_HEADER - self._section = self._OTHER_H_SECTION - - if last_section != self._section: - self._last_header = '' - - return '' - - -class _CppLintState(object): - """Maintains module-wide state..""" - - def __init__(self): - self.verbose_level = 1 # global setting. - self.error_count = 0 # global count of reported errors - # filters to apply when emitting error messages - self.filters = _DEFAULT_FILTERS[:] - self.counting = 'total' # In what way are we counting errors? - self.errors_by_category = {} # string to int dict storing error counts - - # output format: - # "emacs" - format that emacs can parse (default) - # "vs7" - format that Microsoft Visual Studio 7 can parse - self.output_format = 'emacs' - - def SetOutputFormat(self, output_format): - """Sets the output format for errors.""" - self.output_format = output_format - - def SetVerboseLevel(self, level): - """Sets the module's verbosity, and returns the previous setting.""" - last_verbose_level = self.verbose_level - self.verbose_level = level - return last_verbose_level - - def SetCountingStyle(self, counting_style): - """Sets the module's counting options.""" - self.counting = counting_style - - def SetFilters(self, filters): - """Sets the error-message filters. - - These filters are applied when deciding whether to emit a given - error message. - - Args: - filters: A string of comma-separated filters (eg "+whitespace/indent"). - Each filter should start with + or -; else we die. - - Raises: - ValueError: The comma-separated filters did not all start with '+' or '-'. - E.g. "-,+whitespace,-whitespace/indent,whitespace/badfilter" - """ - # Default filters always have less priority than the flag ones. - self.filters = _DEFAULT_FILTERS[:] - for filt in filters.split(','): - clean_filt = filt.strip() - if clean_filt: - self.filters.append(clean_filt) - for filt in self.filters: - if not (filt.startswith('+') or filt.startswith('-')): - raise ValueError('Every filter in --filters must start with + or -' - ' (%s does not)' % filt) - - def ResetErrorCounts(self): - """Sets the module's error statistic back to zero.""" - self.error_count = 0 - self.errors_by_category = {} - - def IncrementErrorCount(self, category): - """Bumps the module's error statistic.""" - self.error_count += 1 - if self.counting in ('toplevel', 'detailed'): - if self.counting != 'detailed': - category = category.split('/')[0] - if category not in self.errors_by_category: - self.errors_by_category[category] = 0 - self.errors_by_category[category] += 1 - - def PrintErrorCounts(self): - """Print a summary of errors by category, and the total.""" - for category, count in self.errors_by_category.iteritems(): - sys.stderr.write('Category \'%s\' errors found: %d\n' % - (category, count)) - sys.stderr.write('Total errors found: %d\n' % self.error_count) - -_cpplint_state = _CppLintState() - - -def _OutputFormat(): - """Gets the module's output format.""" - return _cpplint_state.output_format - - -def _SetOutputFormat(output_format): - """Sets the module's output format.""" - _cpplint_state.SetOutputFormat(output_format) - - -def _VerboseLevel(): - """Returns the module's verbosity setting.""" - return _cpplint_state.verbose_level - - -def _SetVerboseLevel(level): - """Sets the module's verbosity, and returns the previous setting.""" - return _cpplint_state.SetVerboseLevel(level) - - -def _SetCountingStyle(level): - """Sets the module's counting options.""" - _cpplint_state.SetCountingStyle(level) - - -def _Filters(): - """Returns the module's list of output filters, as a list.""" - return _cpplint_state.filters - - -def _SetFilters(filters): - """Sets the module's error-message filters. - - These filters are applied when deciding whether to emit a given - error message. - - Args: - filters: A string of comma-separated filters (eg "whitespace/indent"). - Each filter should start with + or -; else we die. - """ - _cpplint_state.SetFilters(filters) - - -class _FunctionState(object): - """Tracks current function name and the number of lines in its body.""" - - _NORMAL_TRIGGER = 250 # for --v=0, 500 for --v=1, etc. - _TEST_TRIGGER = 400 # about 50% more than _NORMAL_TRIGGER. - - def __init__(self): - self.in_a_function = False - self.lines_in_function = 0 - self.current_function = '' - - def Begin(self, function_name): - """Start analyzing function body. - - Args: - function_name: The name of the function being tracked. - """ - self.in_a_function = True - self.lines_in_function = 0 - self.current_function = function_name - - def Count(self): - """Count line in current function body.""" - if self.in_a_function: - self.lines_in_function += 1 - - def Check(self, error, filename, linenum): - """Report if too many lines in function body. - - Args: - error: The function to call with any errors found. - filename: The name of the current file. - linenum: The number of the line to check. - """ - if Match(r'T(EST|est)', self.current_function): - base_trigger = self._TEST_TRIGGER - else: - base_trigger = self._NORMAL_TRIGGER - trigger = base_trigger * 2**_VerboseLevel() - - if self.lines_in_function > trigger: - error_level = int(math.log(self.lines_in_function / base_trigger, 2)) - # 50 => 0, 100 => 1, 200 => 2, 400 => 3, 800 => 4, 1600 => 5, ... - if error_level > 5: - error_level = 5 - error(filename, linenum, 'readability/fn_size', error_level, - 'Small and focused functions are preferred:' - ' %s has %d non-comment lines' - ' (error triggered by exceeding %d lines).' % ( - self.current_function, self.lines_in_function, trigger)) - - def End(self): - """Stop analyzing function body.""" - self.in_a_function = False - - -class _IncludeError(Exception): - """Indicates a problem with the include order in a file.""" - pass - - -class FileInfo: - """Provides utility functions for filenames. - - FileInfo provides easy access to the components of a file's path - relative to the project root. - """ - - def __init__(self, filename): - self._filename = filename - - def FullName(self): - """Make Windows paths like Unix.""" - return os.path.abspath(self._filename).replace('\\', '/') - - def RepositoryName(self): - """FullName after removing the local path to the repository. - - If we have a real absolute path name here we can try to do something smart: - detecting the root of the checkout and truncating /path/to/checkout from - the name so that we get header guards that don't include things like - "C:\Documents and Settings\..." or "/home/username/..." in them and thus - people on different computers who have checked the source out to different - locations won't see bogus errors. - """ - fullname = self.FullName() - - if os.path.exists(fullname): - project_dir = os.path.dirname(fullname) - - if os.path.exists(os.path.join(project_dir, ".svn")): - # If there's a .svn file in the current directory, we recursively look - # up the directory tree for the top of the SVN checkout - root_dir = project_dir - one_up_dir = os.path.dirname(root_dir) - while os.path.exists(os.path.join(one_up_dir, ".svn")): - root_dir = os.path.dirname(root_dir) - one_up_dir = os.path.dirname(one_up_dir) - - prefix = os.path.commonprefix([root_dir, project_dir]) - return fullname[len(prefix) + 1:] - - # Not SVN <= 1.6? Try to find a git, hg, or svn top level directory by - # searching up from the current path. - root_dir = os.path.dirname(fullname) - while (root_dir != os.path.dirname(root_dir) and - not os.path.exists(os.path.join(root_dir, ".git")) and - not os.path.exists(os.path.join(root_dir, ".hg")) and - not os.path.exists(os.path.join(root_dir, ".svn"))): - root_dir = os.path.dirname(root_dir) - - if (os.path.exists(os.path.join(root_dir, ".git")) or - os.path.exists(os.path.join(root_dir, ".hg")) or - os.path.exists(os.path.join(root_dir, ".svn"))): - prefix = os.path.commonprefix([root_dir, project_dir]) - return fullname[len(prefix) + 1:] - - # Don't know what to do; header guard warnings may be wrong... - return fullname - - def Split(self): - """Splits the file into the directory, basename, and extension. - - For 'chrome/browser/browser.c', Split() would - return ('chrome/browser', 'browser', '.c') - - Returns: - A tuple of (directory, basename, extension). - """ - - googlename = self.RepositoryName() - project, rest = os.path.split(googlename) - return (project,) + os.path.splitext(rest) - - def BaseName(self): - """File base name - text after the final slash, before the final period.""" - return self.Split()[1] - - def Extension(self): - """File extension - text following the final period.""" - return self.Split()[2] - - def NoExtension(self): - """File has no source file extension.""" - return '/'.join(self.Split()[0:2]) - - def IsSource(self): - """File has a source file extension.""" - return self.Extension()[1:] in ('c', 'cc', 'cpp', 'cxx') - - -def _ShouldPrintError(category, confidence, linenum): - """If confidence >= verbose, category passes filter and is not suppressed.""" - - # There are three ways we might decide not to print an error message: - # a "NOLINT(category)" comment appears in the source, - # the verbosity level isn't high enough, or the filters filter it out. - if IsErrorSuppressedByNolint(category, linenum): - return False - if confidence < _cpplint_state.verbose_level: - return False - - is_filtered = False - for one_filter in _Filters(): - if one_filter.startswith('-'): - if category.startswith(one_filter[1:]): - is_filtered = True - elif one_filter.startswith('+'): - if category.startswith(one_filter[1:]): - is_filtered = False - else: - assert False # should have been checked for in SetFilter. - if is_filtered: - return False - - return True - - -def Error(filename, linenum, category, confidence, message): - """Logs the fact we've found a lint error. - - We log where the error was found, and also our confidence in the error, - that is, how certain we are this is a legitimate style regression, and - not a misidentification or a use that's sometimes justified. - - False positives can be suppressed by the use of - "cpplint(category)" comments on the offending line. These are - parsed into _error_suppressions. - - Args: - filename: The name of the file containing the error. - linenum: The number of the line containing the error. - category: A string used to describe the "category" this bug - falls under: "whitespace", say, or "runtime". Categories - may have a hierarchy separated by slashes: "whitespace/indent". - confidence: A number from 1-5 representing a confidence score for - the error, with 5 meaning that we are certain of the problem, - and 1 meaning that it could be a legitimate construct. - message: The error message. - """ - if _ShouldPrintError(category, confidence, linenum): - _cpplint_state.IncrementErrorCount(category) - if _cpplint_state.output_format == 'vs7': - sys.stderr.write('%s(%s): %s [%s] [%d]\n' % ( - filename, linenum, message, category, confidence)) - else: - sys.stderr.write('%s:%s: %s [%s] [%d]\n' % ( - filename, linenum, message, category, confidence)) - - -# Matches standard C++ escape esequences per 2.13.2.3 of the C++ standard. -_RE_PATTERN_CLEANSE_LINE_ESCAPES = re.compile( - r'\\([abfnrtv?"\\\']|\d+|x[0-9a-fA-F]+)') -# Matches strings. Escape codes should already be removed by ESCAPES. -_RE_PATTERN_CLEANSE_LINE_DOUBLE_QUOTES = re.compile(r'"[^"]*"') -# Matches characters. Escape codes should already be removed by ESCAPES. -_RE_PATTERN_CLEANSE_LINE_SINGLE_QUOTES = re.compile(r"'.'") -# Matches multi-line C++ comments. -# This RE is a little bit more complicated than one might expect, because we -# have to take care of space removals tools so we can handle comments inside -# statements better. -# The current rule is: We only clear spaces from both sides when we're at the -# end of the line. Otherwise, we try to remove spaces from the right side, -# if this doesn't work we try on left side but only if there's a non-character -# on the right. -_RE_PATTERN_CLEANSE_LINE_C_COMMENTS = re.compile( - r"""(\s*/\*.*\*/\s*$| - /\*.*\*/\s+| - \s+/\*.*\*/(?=\W)| - /\*.*\*/)""", re.VERBOSE) - - -def IsCppString(line): - """Does line terminate so, that the next symbol is in string constant. - - This function does not consider single-line nor multi-line comments. - - Args: - line: is a partial line of code starting from the 0..n. - - Returns: - True, if next character appended to 'line' is inside a - string constant. - """ - - line = line.replace(r'\\', 'XX') # after this, \\" does not match to \" - return ((line.count('"') - line.count(r'\"') - line.count("'\"'")) & 1) == 1 - - -def FindNextMultiLineCommentStart(lines, lineix): - """Find the beginning marker for a multiline comment.""" - while lineix < len(lines): - if lines[lineix].strip().startswith('/*'): - # Only return this marker if the comment goes beyond this line - if lines[lineix].strip().find('*/', 2) < 0: - return lineix - lineix += 1 - return len(lines) - - -def FindNextMultiLineCommentEnd(lines, lineix): - """We are inside a comment, find the end marker.""" - while lineix < len(lines): - if lines[lineix].strip().endswith('*/'): - return lineix - lineix += 1 - return len(lines) - - -def RemoveMultiLineCommentsFromRange(lines, begin, end): - """Clears a range of lines for multi-line comments.""" - # Having // dummy comments makes the lines non-empty, so we will not get - # unnecessary blank line warnings later in the code. - for i in range(begin, end): - lines[i] = '// dummy' - - -def RemoveMultiLineComments(filename, lines, error): - """Removes multiline (c-style) comments from lines.""" - lineix = 0 - while lineix < len(lines): - lineix_begin = FindNextMultiLineCommentStart(lines, lineix) - if lineix_begin >= len(lines): - return - lineix_end = FindNextMultiLineCommentEnd(lines, lineix_begin) - if lineix_end >= len(lines): - error(filename, lineix_begin + 1, 'readability/multiline_comment', 5, - 'Could not find end of multi-line comment') - return - RemoveMultiLineCommentsFromRange(lines, lineix_begin, lineix_end + 1) - lineix = lineix_end + 1 - - -def CleanseComments(line): - """Removes //-comments and single-line C-style /* */ comments. - - Args: - line: A line of C++ source. - - Returns: - The line with single-line comments removed. - """ - commentpos = line.find('//') - if commentpos != -1 and not IsCppString(line[:commentpos]): - line = line[:commentpos].rstrip() - # get rid of /* ... */ - return _RE_PATTERN_CLEANSE_LINE_C_COMMENTS.sub('', line) - - -class CleansedLines(object): - """Holds 3 copies of all lines with different preprocessing applied to them. - - 1) elided member contains lines without strings and comments, - 2) lines member contains lines without comments, and - 3) raw member contains all the lines without processing. - All these three members are of , and of the same length. - """ - - def __init__(self, lines): - self.elided = [] - self.lines = [] - self.raw_lines = lines - self.num_lines = len(lines) - for linenum in range(len(lines)): - self.lines.append(CleanseComments(lines[linenum])) - elided = self._CollapseStrings(lines[linenum]) - self.elided.append(CleanseComments(elided)) - - def NumLines(self): - """Returns the number of lines represented.""" - return self.num_lines - - @staticmethod - def _CollapseStrings(elided): - """Collapses strings and chars on a line to simple "" or '' blocks. - - We nix strings first so we're not fooled by text like '"http://"' - - Args: - elided: The line being processed. - - Returns: - The line with collapsed strings. - """ - if not _RE_PATTERN_INCLUDE.match(elided): - # Remove escaped characters first to make quote/single quote collapsing - # basic. Things that look like escaped characters shouldn't occur - # outside of strings and chars. - elided = _RE_PATTERN_CLEANSE_LINE_ESCAPES.sub('', elided) - elided = _RE_PATTERN_CLEANSE_LINE_SINGLE_QUOTES.sub("''", elided) - elided = _RE_PATTERN_CLEANSE_LINE_DOUBLE_QUOTES.sub('""', elided) - return elided - - -def CloseExpression(clean_lines, linenum, pos): - """If input points to ( or { or [, finds the position that closes it. - - If lines[linenum][pos] points to a '(' or '{' or '[', finds the - linenum/pos that correspond to the closing of the expression. - - Args: - clean_lines: A CleansedLines instance containing the file. - linenum: The number of the line to check. - pos: A position on the line. - - Returns: - A tuple (line, linenum, pos) pointer *past* the closing brace, or - (line, len(lines), -1) if we never find a close. Note we ignore - strings and comments when matching; and the line we return is the - 'cleansed' line at linenum. - """ - - line = clean_lines.elided[linenum] - startchar = line[pos] - if startchar not in '({[': - return (line, clean_lines.NumLines(), -1) - if startchar == '(': endchar = ')' - if startchar == '[': endchar = ']' - if startchar == '{': endchar = '}' - - num_open = line.count(startchar) - line.count(endchar) - while linenum < clean_lines.NumLines() and num_open > 0: - linenum += 1 - line = clean_lines.elided[linenum] - num_open += line.count(startchar) - line.count(endchar) - # OK, now find the endchar that actually got us back to even - endpos = len(line) - while num_open >= 0: - endpos = line.rfind(')', 0, endpos) - num_open -= 1 # chopped off another ) - return (line, linenum, endpos + 1) - - -def CheckForCopyright(filename, lines, error): - """Logs an error if no Copyright message appears at the top of the file.""" - - # We'll say it should occur by line 10. Don't forget there's a - # dummy line at the front. - for line in xrange(1, min(len(lines), 11)): - if re.search(r'Copyright', lines[line], re.I): break - else: # means no copyright line was found - error(filename, 0, 'legal/copyright', 5, - 'No copyright message found. ' - 'You should have a line: "Copyright [year] "') - - -def GetHeaderGuardCPPVariable(filename): - """Returns the CPP variable that should be used as a header guard. - - Args: - filename: The name of a C++ header file. - - Returns: - The CPP variable that should be used as a header guard in the - named file. - - """ - - # Restores original filename in case that cpplint is invoked from Emacs's - # flymake. - filename = re.sub(r'_flymake\.h$', '.h', filename) - - fileinfo = FileInfo(filename) - return re.sub(r'[-./\s]', '_', fileinfo.RepositoryName()).upper() + '_' - - -def CheckForHeaderGuard(filename, lines, error): - """Checks that the file contains a header guard. - - Logs an error if no #ifndef header guard is present. For other - headers, checks that the full pathname is used. - - Args: - filename: The name of the C++ header file. - lines: An array of strings, each representing a line of the file. - error: The function to call with any errors found. - """ - - #cppvar = GetHeaderGuardCPPVariable(filename) - - ifndef = None - ifndef_linenum = 0 - define = None - endif = None - endif_linenum = 0 - for linenum, line in enumerate(lines): - linesplit = line.split() - if len(linesplit) >= 2: - # find the first occurrence of #ifndef and #define, save arg - if not ifndef and linesplit[0] == '#ifndef': - # set ifndef to the header guard presented on the #ifndef line. - ifndef = linesplit[1] - ifndef_linenum = linenum - if not define and linesplit[0] == '#define': - define = linesplit[1] - # find the last occurrence of #endif, save entire line - if line.startswith('#endif'): - endif = line - endif_linenum = linenum - - #NOTE(TFK): Added this here - cppvar = GetHeaderGuardCPPVariable(filename) - if not ifndef: - error(filename, 0, 'build/header_guard', 5, - 'No #ifndef header guard found, suggested CPP variable is: %s' % - cppvar) - return - #NOTE(TFK): Below line is a hack so that it'll accept any header guard name. - cppvar = ifndef - #ENDNOTE - if not define: - error(filename, 0, 'build/header_guard', 5, - 'No #define header guard found, suggested CPP variable is: %s' % - cppvar) - return - - # The guard should be PATH_FILE_H_, but we also allow PATH_FILE_H__ - # for backward compatibility. - if ifndef != cppvar: - error_level = 0 - if ifndef != cppvar + '_': - error_level = 5 - - ParseNolintSuppressions(filename, lines[ifndef_linenum], ifndef_linenum, - error) - # NOTE(TFK): Remove header guard name checks until we sort out paths. - #error(filename, ifndef_linenum, 'build/header_guard', error_level, - # '#ifndef header guard has wrong style, please use: %s' % cppvar) - - if define != ifndef: - error(filename, 0, 'build/header_guard', 5, - '#ifndef and #define don\'t match, suggested CPP variable is: %s' % - cppvar) - return - - if endif != ('#endif // %s' % cppvar): - error_level = 0 - if endif != ('#endif // %s' % (cppvar + '_')): - error_level = 5 - - ParseNolintSuppressions(filename, lines[endif_linenum], endif_linenum, - error) - error(filename, endif_linenum, 'build/header_guard', error_level, - '#endif line should be "#endif // %s"' % cppvar) - - -def CheckForUnicodeReplacementCharacters(filename, lines, error): - """Logs an error for each line containing Unicode replacement characters. - - These indicate that either the file contained invalid UTF-8 (likely) - or Unicode replacement characters (which it shouldn't). Note that - it's possible for this to throw off line numbering if the invalid - UTF-8 occurred adjacent to a newline. - - Args: - filename: The name of the current file. - lines: An array of strings, each representing a line of the file. - error: The function to call with any errors found. - """ - for linenum, line in enumerate(lines): - if u'\ufffd' in line: - error(filename, linenum, 'readability/utf8', 5, - 'Line contains invalid UTF-8 (or Unicode replacement character).') - - -def CheckForNewlineAtEOF(filename, lines, error): - """Logs an error if there is no newline char at the end of the file. - - Args: - filename: The name of the current file. - lines: An array of strings, each representing a line of the file. - error: The function to call with any errors found. - """ - - # The array lines() was created by adding two newlines to the - # original file (go figure), then splitting on \n. - # To verify that the file ends in \n, we just have to make sure the - # last-but-two element of lines() exists and is empty. - if len(lines) < 3 or lines[-2]: - error(filename, len(lines) - 2, 'whitespace/ending_newline', 5, - 'Could not find a newline character at the end of the file.') - - -def CheckForMultilineCommentsAndStrings(filename, clean_lines, linenum, error): - """Logs an error if we see /* ... */ or "..." that extend past one line. - - /* ... */ comments are legit inside macros, for one line. - Otherwise, we prefer // comments, so it's ok to warn about the - other. Likewise, it's ok for strings to extend across multiple - lines, as long as a line continuation character (backslash) - terminates each line. Although not currently prohibited by the C++ - style guide, it's ugly and unnecessary. We don't do well with either - in this lint program, so we warn about both. - - Args: - filename: The name of the current file. - clean_lines: A CleansedLines instance containing the file. - linenum: The number of the line to check. - error: The function to call with any errors found. - """ - line = clean_lines.elided[linenum] - - # Remove all \\ (escaped backslashes) from the line. They are OK, and the - # second (escaped) slash may trigger later \" detection erroneously. - line = line.replace('\\\\', '') - - if line.count('/*') > line.count('*/'): - error(filename, linenum, 'readability/multiline_comment', 5, - 'Complex multi-line /*...*/-style comment found. ' - 'Lint may give bogus warnings. ' - 'Consider replacing these with //-style comments, ' - 'with #if 0...#endif, ' - 'or with more clearly structured multi-line comments.') - - if (line.count('"') - line.count('\\"')) % 2: - error(filename, linenum, 'readability/multiline_string', 5, - 'Multi-line string ("...") found. This lint script doesn\'t ' - 'do well with such strings, and may give bogus warnings. They\'re ' - 'ugly and unnecessary, and you should use concatenation instead".') - - -threading_list = ( - ('asctime(', 'asctime_r('), - ('ctime(', 'ctime_r('), - ('getgrgid(', 'getgrgid_r('), - ('getgrnam(', 'getgrnam_r('), - ('getlogin(', 'getlogin_r('), - ('getpwnam(', 'getpwnam_r('), - ('getpwuid(', 'getpwuid_r('), - ('gmtime(', 'gmtime_r('), - ('localtime(', 'localtime_r('), - ('rand(', 'rand_r('), - ('readdir(', 'readdir_r('), - ('strtok(', 'strtok_r('), - ('ttyname(', 'ttyname_r('), - ) - - -def CheckPosixThreading(filename, clean_lines, linenum, error): - """Checks for calls to thread-unsafe functions. - - Much code has been originally written without consideration of - multi-threading. Also, engineers are relying on their old experience; - they have learned posix before threading extensions were added. These - tests guide the engineers to use thread-safe functions (when using - posix directly). - - Args: - filename: The name of the current file. - clean_lines: A CleansedLines instance containing the file. - linenum: The number of the line to check. - error: The function to call with any errors found. - """ - line = clean_lines.elided[linenum] - for single_thread_function, multithread_safe_function in threading_list: - ix = line.find(single_thread_function) - # Comparisons made explicit for clarity -- pylint: disable-msg=C6403 - if ix >= 0 and (ix == 0 or (not line[ix - 1].isalnum() and - line[ix - 1] not in ('_', '.', '>'))): - error(filename, linenum, 'runtime/threadsafe_fn', 2, - 'Consider using ' + multithread_safe_function + - '...) instead of ' + single_thread_function + - '...) for improved thread safety.') - - -# Matches invalid increment: *count++, which moves pointer instead of -# incrementing a value. -_RE_PATTERN_INVALID_INCREMENT = re.compile( - r'^\s*\*\w+(\+\+|--);') - - -def CheckInvalidIncrement(filename, clean_lines, linenum, error): - """Checks for invalid increment *count++. - - For example following function: - void increment_counter(int* count) { - *count++; - } - is invalid, because it effectively does count++, moving pointer, and should - be replaced with ++*count, (*count)++ or *count += 1. - - Args: - filename: The name of the current file. - clean_lines: A CleansedLines instance containing the file. - linenum: The number of the line to check. - error: The function to call with any errors found. - """ - line = clean_lines.elided[linenum] - if _RE_PATTERN_INVALID_INCREMENT.match(line): - error(filename, linenum, 'runtime/invalid_increment', 5, - 'Changing pointer instead of value (or unused value of operator*).') - - -class _ClassInfo(object): - """Stores information about a class.""" - - def __init__(self, name, clean_lines, linenum): - self.name = name - self.linenum = linenum - self.seen_open_brace = False - self.is_derived = False - self.virtual_method_linenumber = None - self.has_virtual_destructor = False - self.brace_depth = 0 - - # Try to find the end of the class. This will be confused by things like: - # class A { - # } *x = { ... - # - # But it's still good enough for CheckSectionSpacing. - self.last_line = 0 - depth = 0 - for i in range(linenum, clean_lines.NumLines()): - line = clean_lines.lines[i] - depth += line.count('{') - line.count('}') - if not depth: - self.last_line = i - break - - -class _ClassState(object): - """Holds the current state of the parse relating to class declarations. - - It maintains a stack of _ClassInfos representing the parser's guess - as to the current nesting of class declarations. The innermost class - is at the top (back) of the stack. Typically, the stack will either - be empty or have exactly one entry. - """ - - def __init__(self): - self.classinfo_stack = [] - - def CheckFinished(self, filename, error): - """Checks that all classes have been completely parsed. - - Call this when all lines in a file have been processed. - Args: - filename: The name of the current file. - error: The function to call with any errors found. - """ - if self.classinfo_stack: - # Note: This test can result in false positives if #ifdef constructs - # get in the way of brace matching. See the testBuildClass test in - # cpplint_unittest.py for an example of this. - error(filename, self.classinfo_stack[0].linenum, 'build/class', 5, - 'Failed to find complete declaration of class %s' % - self.classinfo_stack[0].name) - - -def CheckForNonStandardConstructs(filename, clean_lines, linenum, - class_state, error): - """Logs an error if we see certain non-ANSI constructs ignored by gcc-2. - - Complain about several constructs which gcc-2 accepts, but which are - not standard C++. Warning about these in lint is one way to ease the - transition to new compilers. - - put storage class first (e.g. "static const" instead of "const static"). - - "%lld" instead of %qd" in printf-type functions. - - "%1$d" is non-standard in printf-type functions. - - "\%" is an undefined character escape sequence. - - text after #endif is not allowed. - - invalid inner-style forward declaration. - - >? and ?= and )\?=?\s*(\w+|[+-]?\d+)(\.\d*)?', - line): - error(filename, linenum, 'build/deprecated', 3, - '>? and ))?' - # r'\s*const\s*' + type_name + '\s*&\s*\w+\s*;' - error(filename, linenum, 'runtime/member_string_references', 2, - 'const string& members are dangerous. It is much better to use ' - 'alternatives, such as pointers or simple constants.') - - # Track class entry and exit, and attempt to find cases within the - # class declaration that don't meet the C++ style - # guidelines. Tracking is very dependent on the code matching Google - # style guidelines, but it seems to perform well enough in testing - # to be a worthwhile addition to the checks. - classinfo_stack = class_state.classinfo_stack - # Look for a class declaration. The regexp accounts for decorated classes - # such as in: - # class LOCKABLE API Object { - # }; - class_decl_match = Match( - r'\s*(template\s*<[\w\s<>,:]*>\s*)?' - '(class|struct)\s+([A-Z_]+\s+)*(\w+(::\w+)*)', line) - if class_decl_match: - classinfo_stack.append(_ClassInfo( - class_decl_match.group(4), clean_lines, linenum)) - - # Everything else in this function uses the top of the stack if it's - # not empty. - if not classinfo_stack: - return - - classinfo = classinfo_stack[-1] - - # If the opening brace hasn't been seen look for it and also - # parent class declarations. - if not classinfo.seen_open_brace: - # If the line has a ';' in it, assume it's a forward declaration or - # a single-line class declaration, which we won't process. - if line.find(';') != -1: - classinfo_stack.pop() - return - classinfo.seen_open_brace = (line.find('{') != -1) - # Look for a bare ':' - if Search('(^|[^:]):($|[^:])', line): - classinfo.is_derived = True - if not classinfo.seen_open_brace: - return # Everything else in this function is for after open brace - - # The class may have been declared with namespace or classname qualifiers. - # The constructor and destructor will not have those qualifiers. - base_classname = classinfo.name.split('::')[-1] - - # Look for single-argument constructors that aren't marked explicit. - # Technically a valid construct, but against style. - args = Match(r'\s+(?:inline\s+)?%s\s*\(([^,()]+)\)' - % re.escape(base_classname), - line) - if (args and - args.group(1) != 'void' and - not Match(r'(const\s+)?%s\s*(?:<\w+>\s*)?&' % re.escape(base_classname), - args.group(1).strip())): - error(filename, linenum, 'runtime/explicit', 5, - 'Single-argument constructors should be marked explicit.') - - # Look for methods declared virtual. - if Search(r'\bvirtual\b', line): - classinfo.virtual_method_linenumber = linenum - # Only look for a destructor declaration on the same line. It would - # be extremely unlikely for the destructor declaration to occupy - # more than one line. - if Search(r'~%s\s*\(' % base_classname, line): - classinfo.has_virtual_destructor = True - - # Look for class end. - brace_depth = classinfo.brace_depth - brace_depth = brace_depth + line.count('{') - line.count('}') - if brace_depth <= 0: - classinfo = classinfo_stack.pop() - # Try to detect missing virtual destructor declarations. - # For now, only warn if a non-derived class with virtual methods lacks - # a virtual destructor. This is to make it less likely that people will - # declare derived virtual destructors without declaring the base - # destructor virtual. - if ((classinfo.virtual_method_linenumber is not None) and - (not classinfo.has_virtual_destructor) and - (not classinfo.is_derived)): # Only warn for base classes - error(filename, classinfo.linenum, 'runtime/virtual', 4, - 'The class %s probably needs a virtual destructor due to ' - 'having virtual method(s), one declared at line %d.' - % (classinfo.name, classinfo.virtual_method_linenumber)) - else: - classinfo.brace_depth = brace_depth - - -def CheckSpacingForFunctionCall(filename, line, linenum, error): - """Checks for the correctness of various spacing around function calls. - - Args: - filename: The name of the current file. - line: The text of the line to check. - linenum: The number of the line to check. - error: The function to call with any errors found. - """ - - # Since function calls often occur inside if/for/while/switch - # expressions - which have their own, more liberal conventions - we - # first see if we should be looking inside such an expression for a - # function call, to which we can apply more strict standards. - fncall = line # if there's no control flow construct, look at whole line - for pattern in (r'\bif\s*\((.*)\)\s*{', - r'\bfor\s*\((.*)\)\s*{', - r'\bwhile\s*\((.*)\)\s*[{;]', - r'\bswitch\s*\((.*)\)\s*{'): - match = Search(pattern, line) - if match: - fncall = match.group(1) # look inside the parens for function calls - break - - # Except in if/for/while/switch, there should never be space - # immediately inside parens (eg "f( 3, 4 )"). We make an exception - # for nested parens ( (a+b) + c ). Likewise, there should never be - # a space before a ( when it's a function argument. I assume it's a - # function argument when the char before the whitespace is legal in - # a function name (alnum + _) and we're not starting a macro. Also ignore - # pointers and references to arrays and functions coz they're too tricky: - # we use a very simple way to recognize these: - # " (something)(maybe-something)" or - # " (something)(maybe-something," or - # " (something)[something]" - # Note that we assume the contents of [] to be short enough that - # they'll never need to wrap. - if ( # Ignore control structures. - not Search(r'\b(if|for|while|switch|return|delete)\b', fncall) and - # Ignore pointers/references to functions. - not Search(r' \([^)]+\)\([^)]*(\)|,$)', fncall) and - # Ignore pointers/references to arrays. - not Search(r' \([^)]+\)\[[^\]]+\]', fncall)): - if Search(r'\w\s*\(\s(?!\s*\\$)', fncall): # a ( used for a fn call - error(filename, linenum, 'whitespace/parens', 4, - 'Extra space after ( in function call') - elif Search(r'\(\s+(?!(\s*\\)|\()', fncall): - error(filename, linenum, 'whitespace/parens', 2, - 'Extra space after (') - if (Search(r'\w\s+\(', fncall) and - not Search(r'#\s*define|typedef', fncall)): - error(filename, linenum, 'whitespace/parens', 4, - 'Extra space before ( in function call') - # If the ) is followed only by a newline or a { + newline, assume it's - # part of a control statement (if/while/etc), and don't complain - if Search(r'[^)]\s+\)\s*[^{\s]', fncall): - # If the closing parenthesis is preceded by only whitespaces, - # try to give a more descriptive error message. - if Search(r'^\s+\)', fncall): - error(filename, linenum, 'whitespace/parens', 2, - 'Closing ) should be moved to the previous line') - else: - error(filename, linenum, 'whitespace/parens', 2, - 'Extra space before )') - - -def IsBlankLine(line): - """Returns true if the given line is blank. - - We consider a line to be blank if the line is empty or consists of - only white spaces. - - Args: - line: A line of a string. - - Returns: - True, if the given line is blank. - """ - return not line or line.isspace() - - -def CheckForFunctionLengths(filename, clean_lines, linenum, - function_state, error): - """Reports for long function bodies. - - For an overview why this is done, see: - http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Write_Short_Functions - - Uses a simplistic algorithm assuming other style guidelines - (especially spacing) are followed. - Only checks unindented functions, so class members are unchecked. - Trivial bodies are unchecked, so constructors with huge initializer lists - may be missed. - Blank/comment lines are not counted so as to avoid encouraging the removal - of vertical space and comments just to get through a lint check. - NOLINT *on the last line of a function* disables this check. - - Args: - filename: The name of the current file. - clean_lines: A CleansedLines instance containing the file. - linenum: The number of the line to check. - function_state: Current function name and lines in body so far. - error: The function to call with any errors found. - """ - lines = clean_lines.lines - line = lines[linenum] - raw = clean_lines.raw_lines - raw_line = raw[linenum] - joined_line = '' - - starting_func = False - regexp = r'(\w(\w|::|\*|\&|\s)*)\(' # decls * & space::name( ... - match_result = Match(regexp, line) - if match_result: - # If the name is all caps and underscores, figure it's a macro and - # ignore it, unless it's TEST or TEST_F. - function_name = match_result.group(1).split()[-1] - if function_name == 'TEST' or function_name == 'TEST_F' or ( - not Match(r'[A-Z_]+$', function_name)): - starting_func = True - - if starting_func: - body_found = False - for start_linenum in xrange(linenum, clean_lines.NumLines()): - start_line = lines[start_linenum] - joined_line += ' ' + start_line.lstrip() - if Search(r'(;|})', start_line): # Declarations and trivial functions - body_found = True - break # ... ignore - elif Search(r'{', start_line): - body_found = True - function = Search(r'((\w|:)*)\(', line).group(1) - if Match(r'TEST', function): # Handle TEST... macros - parameter_regexp = Search(r'(\(.*\))', joined_line) - if parameter_regexp: # Ignore bad syntax - function += parameter_regexp.group(1) - else: - function += '()' - function_state.Begin(function) - break - if not body_found: - # No body for the function (or evidence of a non-function) was found. - error(filename, linenum, 'readability/fn_size', 5, - 'Lint failed to find start of function body.') - elif Match(r'^\}\s*$', line): # function end - function_state.Check(error, filename, linenum) - function_state.End() - elif not Match(r'^\s*$', line): - function_state.Count() # Count non-blank/non-comment lines. - - -_RE_PATTERN_TODO = re.compile(r'^//(\s*)TODO(\(.+?\))?:?(\s|$)?') - - -def CheckComment(comment, filename, linenum, error): - """Checks for common mistakes in TODO comments. - - Args: - comment: The text of the comment from the line in question. - filename: The name of the current file. - linenum: The number of the line to check. - error: The function to call with any errors found. - """ - match = _RE_PATTERN_TODO.match(comment) - if match: - # One whitespace is correct; zero whitespace is handled elsewhere. - leading_whitespace = match.group(1) - if len(leading_whitespace) > 1: - error(filename, linenum, 'whitespace/todo', 2, - 'Too many spaces before TODO') - - username = match.group(2) - if not username: - error(filename, linenum, 'readability/todo', 2, - 'Missing username in TODO; it should look like ' - '"// TODO(my_username): Stuff."') - - middle_whitespace = match.group(3) - # Comparisons made explicit for correctness -- pylint: disable-msg=C6403 - if middle_whitespace != ' ' and middle_whitespace != '': - error(filename, linenum, 'whitespace/todo', 2, - 'TODO(my_username) should be followed by a space') - - -def CheckSpacing(filename, clean_lines, linenum, error): - """Checks for the correctness of various spacing issues in the code. - - Things we check for: spaces around operators, spaces after - if/for/while/switch, no spaces around parens in function calls, two - spaces between code and comment, don't start a block with a blank - line, don't end a function with a blank line, don't add a blank line - after public/protected/private, don't have too many blank lines in a row. - - Args: - filename: The name of the current file. - clean_lines: A CleansedLines instance containing the file. - linenum: The number of the line to check. - error: The function to call with any errors found. - """ - - raw = clean_lines.raw_lines - line = raw[linenum] - - # Before nixing comments, check if the line is blank for no good - # reason. This includes the first line after a block is opened, and - # blank lines at the end of a function (ie, right before a line like '}' - if IsBlankLine(line): - elided = clean_lines.elided - prev_line = elided[linenum - 1] - prevbrace = prev_line.rfind('{') - # TODO(unknown): Don't complain if line before blank line, and line after, - # both start with alnums and are indented the same amount. - # This ignores whitespace at the start of a namespace block - # because those are not usually indented. - if (prevbrace != -1 and prev_line[prevbrace:].find('}') == -1 - and prev_line[:prevbrace].find('namespace') == -1): - # OK, we have a blank line at the start of a code block. Before we - # complain, we check if it is an exception to the rule: The previous - # non-empty line has the parameters of a function header that are indented - # 4 spaces (because they did not fit in a 80 column line when placed on - # the same line as the function name). We also check for the case where - # the previous line is indented 6 spaces, which may happen when the - # initializers of a constructor do not fit into a 80 column line. - exception = False - if Match(r' {6}\w', prev_line): # Initializer list? - # We are looking for the opening column of initializer list, which - # should be indented 4 spaces to cause 6 space indentation afterwards. - search_position = linenum-2 - while (search_position >= 0 - and Match(r' {6}\w', elided[search_position])): - search_position -= 1 - exception = (search_position >= 0 - and elided[search_position][:5] == ' :') - else: - # Search for the function arguments or an initializer list. We use a - # simple heuristic here: If the line is indented 4 spaces; and we have a - # closing paren, without the opening paren, followed by an opening brace - # or colon (for initializer lists) we assume that it is the last line of - # a function header. If we have a colon indented 4 spaces, it is an - # initializer list. - exception = (Match(r' {4}\w[^\(]*\)\s*(const\s*)?(\{\s*$|:)', - prev_line) - or Match(r' {4}:', prev_line)) - - if not exception: - error(filename, linenum, 'whitespace/blank_line', 2, - 'Blank line at the start of a code block. Is this needed?') - # This doesn't ignore whitespace at the end of a namespace block - # because that is too hard without pairing open/close braces; - # however, a special exception is made for namespace closing - # brackets which have a comment containing "namespace". - # - # Also, ignore blank lines at the end of a block in a long if-else - # chain, like this: - # if (condition1) { - # // Something followed by a blank line - # - # } else if (condition2) { - # // Something else - # } - if linenum + 1 < clean_lines.NumLines(): - next_line = raw[linenum + 1] - if (next_line - and Match(r'\s*}', next_line) - and next_line.find('namespace') == -1 - and next_line.find('} else ') == -1): - error(filename, linenum, 'whitespace/blank_line', 3, - 'Blank line at the end of a code block. Is this needed?') - - matched = Match(r'\s*(public|protected|private):', prev_line) - if matched: - error(filename, linenum, 'whitespace/blank_line', 3, - 'Do not leave a blank line after "%s:"' % matched.group(1)) - - # Next, we complain if there's a comment too near the text - commentpos = line.find('//') - if commentpos != -1: - # Check if the // may be in quotes. If so, ignore it - # Comparisons made explicit for clarity -- pylint: disable-msg=C6403 - if (line.count('"', 0, commentpos) - - line.count('\\"', 0, commentpos)) % 2 == 0: # not in quotes - # Allow one space for new scopes, two spaces otherwise: - if (not Match(r'^\s*{ //', line) and - ((commentpos >= 1 and - line[commentpos-1] not in string.whitespace) or - (commentpos >= 2 and - line[commentpos-2] not in string.whitespace))): - error(filename, linenum, 'whitespace/comments', 2, - 'At least two spaces is best between code and comments') - # There should always be a space between the // and the comment - commentend = commentpos + 2 - if commentend < len(line) and not line[commentend] == ' ': - # but some lines are exceptions -- e.g. if they're big - # comment delimiters like: - # //---------------------------------------------------------- - # or are an empty C++ style Doxygen comment, like: - # /// - # or they begin with multiple slashes followed by a space: - # //////// Header comment - match = (Search(r'[=/-]{4,}\s*$', line[commentend:]) or - Search(r'^/$', line[commentend:]) or - Search(r'^/+ ', line[commentend:])) - if not match: - error(filename, linenum, 'whitespace/comments', 4, - 'Should have a space between // and comment') - CheckComment(line[commentpos:], filename, linenum, error) - - line = clean_lines.elided[linenum] # get rid of comments and strings - - # Don't try to do spacing checks for operator methods - line = re.sub(r'operator(==|!=|<|<<|<=|>=|>>|>)\(', 'operator\(', line) - - # We allow no-spaces around = within an if: "if ( (a=Foo()) == 0 )". - # Otherwise not. Note we only check for non-spaces on *both* sides; - # sometimes people put non-spaces on one side when aligning ='s among - # many lines (not that this is behavior that I approve of...) - if Search(r'[\w.]=[\w.]', line) and not Search(r'\b(if|while) ', line): - error(filename, linenum, 'whitespace/operators', 4, - 'Missing spaces around =') - - # It's ok not to have spaces around binary operators like + - * /, but if - # there's too little whitespace, we get concerned. It's hard to tell, - # though, so we punt on this one for now. TODO. - - # You should always have whitespace around binary operators. - # Alas, we can't test < or > because they're legitimately used sans spaces - # (a->b, vector a). The only time we can tell is a < with no >, and - # only if it's not template params list spilling into the next line. - match = Search(r'[^<>=!\s](==|!=|<=|>=)[^<>=!\s]', line) - if not match: - # Note that while it seems that the '<[^<]*' term in the following - # regexp could be simplified to '<.*', which would indeed match - # the same class of strings, the [^<] means that searching for the - # regexp takes linear rather than quadratic time. - if not Search(r'<[^<]*,\s*$', line): # template params spill - match = Search(r'[^<>=!\s](<)[^<>=!\s]([^>]|->)*$', line) - if match: - error(filename, linenum, 'whitespace/operators', 3, - 'Missing spaces around %s' % match.group(1)) - # We allow no-spaces around << and >> when used like this: 10<<20, but - # not otherwise (particularly, not when used as streams) - match = Search(r'[^0-9\s](<<|>>)[^0-9\s]', line) - if match: - error(filename, linenum, 'whitespace/operators', 3, - 'Missing spaces around %s' % match.group(1)) - - # There shouldn't be space around unary operators - match = Search(r'(!\s|~\s|[\s]--[\s;]|[\s]\+\+[\s;])', line) - if match: - error(filename, linenum, 'whitespace/operators', 4, - 'Extra space for operator %s' % match.group(1)) - - # A pet peeve of mine: no spaces after an if, while, switch, or for - match = Search(r' (if\(|for\(|while\(|switch\()', line) - if match: - error(filename, linenum, 'whitespace/parens', 5, - 'Missing space before ( in %s' % match.group(1)) - - # For if/for/while/switch, the left and right parens should be - # consistent about how many spaces are inside the parens, and - # there should either be zero or one spaces inside the parens. - # We don't want: "if ( foo)" or "if ( foo )". - # Exception: "for ( ; foo; bar)" and "for (foo; bar; )" are allowed. - match = Search(r'\b(if|for|while|switch)\s*' - r'\(([ ]*)(.).*[^ ]+([ ]*)\)\s*{\s*$', - line) - if match: - if len(match.group(2)) != len(match.group(4)): - if not (match.group(3) == ';' and - len(match.group(2)) == 1 + len(match.group(4)) or - not match.group(2) and Search(r'\bfor\s*\(.*; \)', line)): - error(filename, linenum, 'whitespace/parens', 5, - 'Mismatching spaces inside () in %s' % match.group(1)) - if not len(match.group(2)) in [0, 1]: - error(filename, linenum, 'whitespace/parens', 5, - 'Should have zero or one spaces inside ( and ) in %s' % - match.group(1)) - - # You should always have a space after a comma (either as fn arg or operator) - if Search(r',[^\s]', line): - error(filename, linenum, 'whitespace/comma', 3, - 'Missing space after ,') - - # You should always have a space after a semicolon - # except for few corner cases - # TODO(unknown): clarify if 'if (1) { return 1;}' is requires one more - # space after ; - if Search(r';[^\s};\\)/]', line): - error(filename, linenum, 'whitespace/semicolon', 3, - 'Missing space after ;') - - # Next we will look for issues with function calls. - CheckSpacingForFunctionCall(filename, line, linenum, error) - - # Except after an opening paren, or after another opening brace (in case of - # an initializer list, for instance), you should have spaces before your - # braces. And since you should never have braces at the beginning of a line, - # this is an easy test. - if Search(r'[^ ({]{', line): - error(filename, linenum, 'whitespace/braces', 5, - 'Missing space before {') - - # Make sure '} else {' has spaces. - if Search(r'}else', line): - error(filename, linenum, 'whitespace/braces', 5, - 'Missing space before else') - - # You shouldn't have spaces before your brackets, except maybe after - # 'delete []' or 'new char * []'. - if Search(r'\w\s+\[', line) and not Search(r'delete\s+\[', line): - error(filename, linenum, 'whitespace/braces', 5, - 'Extra space before [') - - # You shouldn't have a space before a semicolon at the end of the line. - # There's a special case for "for" since the style guide allows space before - # the semicolon there. - if Search(r':\s*;\s*$', line): - error(filename, linenum, 'whitespace/semicolon', 5, - 'Semicolon defining empty statement. Use { } instead.') - elif Search(r'^\s*;\s*$', line): - error(filename, linenum, 'whitespace/semicolon', 5, - 'Line contains only semicolon. If this should be an empty statement, ' - 'use { } instead.') - elif (Search(r'\s+;\s*$', line) and - not Search(r'\bfor\b', line)): - error(filename, linenum, 'whitespace/semicolon', 5, - 'Extra space before last semicolon. If this should be an empty ' - 'statement, use { } instead.') - - -def CheckSectionSpacing(filename, clean_lines, class_info, linenum, error): - """Checks for additional blank line issues related to sections. - - Currently the only thing checked here is blank line before protected/private. - - Args: - filename: The name of the current file. - clean_lines: A CleansedLines instance containing the file. - class_info: A _ClassInfo objects. - linenum: The number of the line to check. - error: The function to call with any errors found. - """ - # Skip checks if the class is small, where small means 25 lines or less. - # 25 lines seems like a good cutoff since that's the usual height of - # terminals, and any class that can't fit in one screen can't really - # be considered "small". - # - # Also skip checks if we are on the first line. This accounts for - # classes that look like - # class Foo { public: ... }; - # - # If we didn't find the end of the class, last_line would be zero, - # and the check will be skipped by the first condition. - if (class_info.last_line - class_info.linenum <= 24 or - linenum <= class_info.linenum): - return - - matched = Match(r'\s*(public|protected|private):', clean_lines.lines[linenum]) - if matched: - # Issue warning if the line before public/protected/private was - # not a blank line, but don't do this if the previous line contains - # "class" or "struct". This can happen two ways: - # - We are at the beginning of the class. - # - We are forward-declaring an inner class that is semantically - # private, but needed to be public for implementation reasons. - prev_line = clean_lines.lines[linenum - 1] - if (not IsBlankLine(prev_line) and - not Search(r'\b(class|struct)\b', prev_line)): - # Try a bit harder to find the beginning of the class. This is to - # account for multi-line base-specifier lists, e.g.: - # class Derived - # : public Base { - end_class_head = class_info.linenum - for i in range(class_info.linenum, linenum): - if Search(r'\{\s*$', clean_lines.lines[i]): - end_class_head = i - break - if end_class_head < linenum - 1: - error(filename, linenum, 'whitespace/blank_line', 3, - '"%s:" should be preceded by a blank line' % matched.group(1)) - - -def GetPreviousNonBlankLine(clean_lines, linenum): - """Return the most recent non-blank line and its line number. - - Args: - clean_lines: A CleansedLines instance containing the file contents. - linenum: The number of the line to check. - - Returns: - A tuple with two elements. The first element is the contents of the last - non-blank line before the current line, or the empty string if this is the - first non-blank line. The second is the line number of that line, or -1 - if this is the first non-blank line. - """ - - prevlinenum = linenum - 1 - while prevlinenum >= 0: - prevline = clean_lines.elided[prevlinenum] - if not IsBlankLine(prevline): # if not a blank line... - return (prevline, prevlinenum) - prevlinenum -= 1 - return ('', -1) - - -def CheckBraces(filename, clean_lines, linenum, error): - """Looks for misplaced braces (e.g. at the end of line). - - Args: - filename: The name of the current file. - clean_lines: A CleansedLines instance containing the file. - linenum: The number of the line to check. - error: The function to call with any errors found. - """ - - line = clean_lines.elided[linenum] # get rid of comments and strings - - if Match(r'\s*{\s*$', line): - # We allow an open brace to start a line in the case where someone - # is using braces in a block to explicitly create a new scope, - # which is commonly used to control the lifetime of - # stack-allocated variables. We don't detect this perfectly: we - # just don't complain if the last non-whitespace character on the - # previous non-blank line is ';', ':', '{', or '}'. - prevline = GetPreviousNonBlankLine(clean_lines, linenum)[0] - if not Search(r'[;:}{]\s*$', prevline): - error(filename, linenum, 'whitespace/braces', 4, - '{ should almost always be at the end of the previous line') - - # An else clause should be on the same line as the preceding closing brace. - if Match(r'\s*else\s*', line): - prevline = GetPreviousNonBlankLine(clean_lines, linenum)[0] - if Match(r'\s*}\s*$', prevline): - error(filename, linenum, 'whitespace/newline', 4, - 'An else should appear on the same line as the preceding }') - - # If braces come on one side of an else, they should be on both. - # However, we have to worry about "else if" that spans multiple lines! - if Search(r'}\s*else[^{]*$', line) or Match(r'[^}]*else\s*{', line): - if Search(r'}\s*else if([^{]*)$', line): # could be multi-line if - # find the ( after the if - pos = line.find('else if') - pos = line.find('(', pos) - if pos > 0: - (endline, _, endpos) = CloseExpression(clean_lines, linenum, pos) - if endline[endpos:].find('{') == -1: # must be brace after if - error(filename, linenum, 'readability/braces', 5, - 'If an else has a brace on one side, it should have it on both') - else: # common case: else not followed by a multi-line if - error(filename, linenum, 'readability/braces', 5, - 'If an else has a brace on one side, it should have it on both') - - # Likewise, an else should never have the else clause on the same line - if Search(r'\belse [^\s{]', line) and not Search(r'\belse if\b', line): - error(filename, linenum, 'whitespace/newline', 4, - 'Else clause should never be on same line as else (use 2 lines)') - - # In the same way, a do/while should never be on one line - if Match(r'\s*do [^\s{]', line): - error(filename, linenum, 'whitespace/newline', 4, - 'do/while clauses should not be on a single line') - - # Braces shouldn't be followed by a ; unless they're defining a struct - # or initializing an array. - # We can't tell in general, but we can for some common cases. - prevlinenum = linenum - while True: - (prevline, prevlinenum) = GetPreviousNonBlankLine(clean_lines, prevlinenum) - if Match(r'\s+{.*}\s*;', line) and not prevline.count(';'): - line = prevline + line - else: - break - if (Search(r'{.*}\s*;', line) and - line.count('{') == line.count('}') and - not Search(r'struct|class|enum|\s*=\s*{', line)): - error(filename, linenum, 'readability/braces', 4, - "You don't need a ; after a }") - - -def ReplaceableCheck(operator, macro, line): - """Determine whether a basic CHECK can be replaced with a more specific one. - - For example suggest using CHECK_EQ instead of CHECK(a == b) and - similarly for CHECK_GE, CHECK_GT, CHECK_LE, CHECK_LT, CHECK_NE. - - Args: - operator: The C++ operator used in the CHECK. - macro: The CHECK or EXPECT macro being called. - line: The current source line. - - Returns: - True if the CHECK can be replaced with a more specific one. - """ - - # This matches decimal and hex integers, strings, and chars (in that order). - match_constant = r'([-+]?(\d+|0[xX][0-9a-fA-F]+)[lLuU]{0,3}|".*"|\'.*\')' - - # Expression to match two sides of the operator with something that - # looks like a literal, since CHECK(x == iterator) won't compile. - # This means we can't catch all the cases where a more specific - # CHECK is possible, but it's less annoying than dealing with - # extraneous warnings. - match_this = (r'\s*' + macro + r'\((\s*' + - match_constant + r'\s*' + operator + r'[^<>].*|' - r'.*[^<>]' + operator + r'\s*' + match_constant + - r'\s*\))') - - # Don't complain about CHECK(x == NULL) or similar because - # CHECK_EQ(x, NULL) won't compile (requires a cast). - # Also, don't complain about more complex boolean expressions - # involving && or || such as CHECK(a == b || c == d). - return Match(match_this, line) and not Search(r'NULL|&&|\|\|', line) - - -def CheckCheck(filename, clean_lines, linenum, error): - """Checks the use of CHECK and EXPECT macros. - - Args: - filename: The name of the current file. - clean_lines: A CleansedLines instance containing the file. - linenum: The number of the line to check. - error: The function to call with any errors found. - """ - - # Decide the set of replacement macros that should be suggested - raw_lines = clean_lines.raw_lines - current_macro = '' - for macro in _CHECK_MACROS: - if raw_lines[linenum].find(macro) >= 0: - current_macro = macro - break - if not current_macro: - # Don't waste time here if line doesn't contain 'CHECK' or 'EXPECT' - return - - line = clean_lines.elided[linenum] # get rid of comments and strings - - # Encourage replacing plain CHECKs with CHECK_EQ/CHECK_NE/etc. - for operator in ['==', '!=', '>=', '>', '<=', '<']: - if ReplaceableCheck(operator, current_macro, line): - error(filename, linenum, 'readability/check', 2, - 'Consider using %s instead of %s(a %s b)' % ( - _CHECK_REPLACEMENT[current_macro][operator], - current_macro, operator)) - break - - -def GetLineWidth(line): - """Determines the width of the line in column positions. - - Args: - line: A string, which may be a Unicode string. - - Returns: - The width of the line in column positions, accounting for Unicode - combining characters and wide characters. - """ - if isinstance(line, unicode): - width = 0 - for uc in unicodedata.normalize('NFC', line): - if unicodedata.east_asian_width(uc) in ('W', 'F'): - width += 2 - elif not unicodedata.combining(uc): - width += 1 - return width - else: - return len(line) - - -def CheckStyle(filename, clean_lines, linenum, file_extension, class_state, - error): - """Checks rules from the 'C++ style rules' section of cppguide.html. - - Most of these rules are hard to test (naming, comment style), but we - do what we can. In particular we check for 2-space indents, line lengths, - tab usage, spaces inside code, etc. - - Args: - filename: The name of the current file. - clean_lines: A CleansedLines instance containing the file. - linenum: The number of the line to check. - file_extension: The extension (without the dot) of the filename. - error: The function to call with any errors found. - """ - - raw_lines = clean_lines.raw_lines - line = raw_lines[linenum] - - if line.find('\t') != -1: - error(filename, linenum, 'whitespace/tab', 1, - 'Tab found; better to use spaces') - - # One or three blank spaces at the beginning of the line is weird; it's - # hard to reconcile that with 2-space indents. - # NOTE: here are the conditions rob pike used for his tests. Mine aren't - # as sophisticated, but it may be worth becoming so: RLENGTH==initial_spaces - # if(RLENGTH > 20) complain = 0; - # if(match($0, " +(error|private|public|protected):")) complain = 0; - # if(match(prev, "&& *$")) complain = 0; - # if(match(prev, "\\|\\| *$")) complain = 0; - # if(match(prev, "[\",=><] *$")) complain = 0; - # if(match($0, " <<")) complain = 0; - # if(match(prev, " +for \\(")) complain = 0; - # if(prevodd && match(prevprev, " +for \\(")) complain = 0; - initial_spaces = 0 - cleansed_line = clean_lines.elided[linenum] - while initial_spaces < len(line) and line[initial_spaces] == ' ': - initial_spaces += 1 - if line and line[-1].isspace(): - error(filename, linenum, 'whitespace/end_of_line', 4, - 'Line ends in whitespace. Consider deleting these extra spaces.') - # There are certain situations we allow one space, notably for labels - elif ((initial_spaces == 1 or initial_spaces == 3) and - not Match(r'\s*\w+\s*:\s*$', cleansed_line)): - error(filename, linenum, 'whitespace/indent', 3, - 'Weird number of spaces at line-start. ' - 'Are you using a 2-space indent?') - # Labels should always be indented at least one space. - elif not initial_spaces and line[:2] != '//' and Search(r'[^:]:\s*$', - line): - error(filename, linenum, 'whitespace/labels', 4, - 'Labels should always be indented at least one space. ' - 'If this is a member-initializer list in a constructor or ' - 'the base class list in a class definition, the colon should ' - 'be on the following line.') - - - # Check if the line is a header guard. - is_header_guard = False - if file_extension == 'h': - cppvar = GetHeaderGuardCPPVariable(filename) - if (line.startswith('#ifndef %s' % cppvar) or - line.startswith('#define %s' % cppvar) or - line.startswith('#endif // %s' % cppvar)): - is_header_guard = True - # #include lines and header guards can be long, since there's no clean way to - # split them. - # - # URLs can be long too. It's possible to split these, but it makes them - # harder to cut&paste. - # - # The "$Id:...$" comment may also get very long without it being the - # developers fault. - if (not line.startswith('#include') and not is_header_guard and - not Match(r'^\s*//.*http(s?)://\S*$', line) and - not Match(r'^// \$Id:.*#[0-9]+ \$$', line)): - line_width = GetLineWidth(line) - if line_width > 100: - error(filename, linenum, 'whitespace/line_length', 4, - 'Lines should very rarely be longer than 100 characters') - #elif line_width > 80: - # error(filename, linenum, 'whitespace/line_length', 2, - # 'Lines should be <= 80 characters long') - - if (cleansed_line.count(';') > 1 and - # for loops are allowed two ;'s (and may run over two lines). - cleansed_line.find('for') == -1 and - (GetPreviousNonBlankLine(clean_lines, linenum)[0].find('for') == -1 or - GetPreviousNonBlankLine(clean_lines, linenum)[0].find(';') != -1) and - # It's ok to have many commands in a switch case that fits in 1 line - not ((cleansed_line.find('case ') != -1 or - cleansed_line.find('default:') != -1) and - cleansed_line.find('break;') != -1)): - error(filename, linenum, 'whitespace/newline', 4, - 'More than one command on the same line') - - # Some more style checks - CheckBraces(filename, clean_lines, linenum, error) - CheckSpacing(filename, clean_lines, linenum, error) - CheckCheck(filename, clean_lines, linenum, error) - if class_state and class_state.classinfo_stack: - CheckSectionSpacing(filename, clean_lines, - class_state.classinfo_stack[-1], linenum, error) - - -_RE_PATTERN_INCLUDE_NEW_STYLE = re.compile(r'#include +"[^/]+\.h"') -_RE_PATTERN_INCLUDE = re.compile(r'^\s*#\s*include\s*([<"])([^>"]*)[>"].*$') -# Matches the first component of a filename delimited by -s and _s. That is: -# _RE_FIRST_COMPONENT.match('foo').group(0) == 'foo' -# _RE_FIRST_COMPONENT.match('foo.c').group(0) == 'foo' -# _RE_FIRST_COMPONENT.match('foo-bar_baz.c').group(0) == 'foo' -# _RE_FIRST_COMPONENT.match('foo_bar-baz.c').group(0) == 'foo' -_RE_FIRST_COMPONENT = re.compile(r'^[^-_.]+') - - -def _DropCommonSuffixes(filename): - """Drops common suffixes like _test.c or -inl.h from filename. - - For example: - >>> _DropCommonSuffixes('foo/foo-inl.h') - 'foo/foo' - >>> _DropCommonSuffixes('foo/bar/foo.c') - 'foo/bar/foo' - >>> _DropCommonSuffixes('foo/foo_internal.h') - 'foo/foo' - >>> _DropCommonSuffixes('foo/foo_unusualinternal.h') - 'foo/foo_unusualinternal' - - Args: - filename: The input filename. - - Returns: - The filename with the common suffix removed. - """ - for suffix in ('test.c', 'regtest.c', 'unittest.c', - 'inl.h', 'impl.h', 'internal.h'): - if (filename.endswith(suffix) and len(filename) > len(suffix) and - filename[-len(suffix) - 1] in ('-', '_')): - return filename[:-len(suffix) - 1] - return os.path.splitext(filename)[0] - - -def _IsTestFilename(filename): - """Determines if the given filename has a suffix that identifies it as a test. - - Args: - filename: The input filename. - - Returns: - True if 'filename' looks like a test, False otherwise. - """ - if (filename.endswith('_test.c') or - filename.endswith('_unittest.c') or - filename.endswith('_regtest.c')): - return True - else: - return False - - -def _ClassifyInclude(fileinfo, include, is_system): - """Figures out what kind of header 'include' is. - - Args: - fileinfo: The current file cpplint is running over. A FileInfo instance. - include: The path to a #included file. - is_system: True if the #include used <> rather than "". - - Returns: - One of the _XXX_HEADER constants. - - For example: - >>> _ClassifyInclude(FileInfo('foo/foo.c'), 'stdio.h', True) - _C_SYS_HEADER - >>> _ClassifyInclude(FileInfo('foo/foo.c'), 'string', True) - _CPP_SYS_HEADER - >>> _ClassifyInclude(FileInfo('foo/foo.c'), 'foo/foo.h', False) - _LIKELY_MY_HEADER - >>> _ClassifyInclude(FileInfo('foo/foo_unknown_extension.c'), - ... 'bar/foo_other_ext.h', False) - _POSSIBLE_MY_HEADER - >>> _ClassifyInclude(FileInfo('foo/foo.c'), 'foo/bar.h', False) - _OTHER_HEADER - """ - # This is a list of all standard c++ header files, except - # those already checked for above. - is_stl_h = include in _STL_HEADERS - is_cpp_h = is_stl_h or include in _CPP_HEADERS - - if is_system: - if is_cpp_h: - return _CPP_SYS_HEADER - else: - return _C_SYS_HEADER - - # If the target file and the include we're checking share a - # basename when we drop common extensions, and the include - # lives in . , then it's likely to be owned by the target file. - target_dir, target_base = ( - os.path.split(_DropCommonSuffixes(fileinfo.RepositoryName()))) - include_dir, include_base = os.path.split(_DropCommonSuffixes(include)) - if target_base == include_base and ( - include_dir == target_dir or - include_dir == os.path.normpath(target_dir + '/../public')): - return _LIKELY_MY_HEADER - - # If the target and include share some initial basename - # component, it's possible the target is implementing the - # include, so it's allowed to be first, but we'll never - # complain if it's not there. - target_first_component = _RE_FIRST_COMPONENT.match(target_base) - include_first_component = _RE_FIRST_COMPONENT.match(include_base) - if (target_first_component and include_first_component and - target_first_component.group(0) == - include_first_component.group(0)): - return _POSSIBLE_MY_HEADER - - return _OTHER_HEADER - - - -def CheckIncludeLine(filename, clean_lines, linenum, include_state, error): - """Check rules that are applicable to #include lines. - - Strings on #include lines are NOT removed from elided line, to make - certain tasks easier. However, to prevent false positives, checks - applicable to #include lines in CheckLanguage must be put here. - - Args: - filename: The name of the current file. - clean_lines: A CleansedLines instance containing the file. - linenum: The number of the line to check. - include_state: An _IncludeState instance in which the headers are inserted. - error: The function to call with any errors found. - """ - fileinfo = FileInfo(filename) - - line = clean_lines.lines[linenum] - - # "include" should use the new style "foo/bar.h" instead of just "bar.h" - if _RE_PATTERN_INCLUDE_NEW_STYLE.search(line): - error(filename, linenum, 'build/include', 4, - 'Include the directory when naming .h files') - - # we shouldn't include a file more than once. actually, there are a - # handful of instances where doing so is okay, but in general it's - # not. - match = _RE_PATTERN_INCLUDE.search(line) - if match: - include = match.group(2) - is_system = (match.group(1) == '<') - if include in include_state: - error(filename, linenum, 'build/include', 4, - '"%s" already included at %s:%s' % - (include, filename, include_state[include])) - else: - include_state[include] = linenum - - # We want to ensure that headers appear in the right order: - # 1) for foo.c, foo.h (preferred location) - # 2) c system files - # 3) cpp system files - # 4) for foo.c, foo.h (deprecated location) - # 5) other google headers - # - # We classify each include statement as one of those 5 types - # using a number of techniques. The include_state object keeps - # track of the highest type seen, and complains if we see a - # lower type after that. - error_message = include_state.CheckNextIncludeOrder( - _ClassifyInclude(fileinfo, include, is_system)) - if error_message: - error(filename, linenum, 'build/include_order', 4, - '%s. Should be: %s.h, c system, c++ system, other.' % - (error_message, fileinfo.BaseName())) - if not include_state.IsInAlphabeticalOrder(include): - error(filename, linenum, 'build/include_alpha', 4, - 'Include "%s" not in alphabetical order' % include) - - # Look for any of the stream classes that are part of standard C++. - match = _RE_PATTERN_INCLUDE.match(line) - if match: - include = match.group(2) - if Match(r'(f|ind|io|i|o|parse|pf|stdio|str|)?stream$', include): - # Many unit tests use cout, so we exempt them. - if not _IsTestFilename(filename): - error(filename, linenum, 'readability/streams', 3, - 'Streams are highly discouraged.') - - -def _GetTextInside(text, start_pattern): - """Retrieves all the text between matching open and close parentheses. - - Given a string of lines and a regular expression string, retrieve all the text - following the expression and between opening punctuation symbols like - (, [, or {, and the matching close-punctuation symbol. This properly nested - occurrences of the punctuations, so for the text like - printf(a(), b(c())); - a call to _GetTextInside(text, r'printf\(') will return 'a(), b(c())'. - start_pattern must match string having an open punctuation symbol at the end. - - Args: - text: The lines to extract text. Its comments and strings must be elided. - It can be single line and can span multiple lines. - start_pattern: The regexp string indicating where to start extracting - the text. - Returns: - The extracted text. - None if either the opening string or ending punctuation could not be found. - """ - # TODO(sugawarayu): Audit cpplint.py to see what places could be profitably - # rewritten to use _GetTextInside (and use inferior regexp matching today). - - # Give opening punctuations to get the matching close-punctuations. - matching_punctuation = {'(': ')', '{': '}', '[': ']'} - closing_punctuation = set(matching_punctuation.itervalues()) - - # Find the position to start extracting text. - match = re.search(start_pattern, text, re.M) - if not match: # start_pattern not found in text. - return None - start_position = match.end(0) - - assert start_position > 0, ( - 'start_pattern must ends with an opening punctuation.') - assert text[start_position - 1] in matching_punctuation, ( - 'start_pattern must ends with an opening punctuation.') - # Stack of closing punctuations we expect to have in text after position. - punctuation_stack = [matching_punctuation[text[start_position - 1]]] - position = start_position - while punctuation_stack and position < len(text): - if text[position] == punctuation_stack[-1]: - punctuation_stack.pop() - elif text[position] in closing_punctuation: - # A closing punctuation without matching opening punctuations. - return None - elif text[position] in matching_punctuation: - punctuation_stack.append(matching_punctuation[text[position]]) - position += 1 - if punctuation_stack: - # Opening punctuations left without matching close-punctuations. - return None - # punctuations match. - return text[start_position:position - 1] - - -def CheckLanguage(filename, clean_lines, linenum, file_extension, include_state, - error): - """Checks rules from the 'C++ language rules' section of cppguide.html. - - Some of these rules are hard to test (function overloading, using - uint32 inappropriately), but we do the best we can. - - Args: - filename: The name of the current file. - clean_lines: A CleansedLines instance containing the file. - linenum: The number of the line to check. - file_extension: The extension (without the dot) of the filename. - include_state: An _IncludeState instance in which the headers are inserted. - error: The function to call with any errors found. - """ - # If the line is empty or consists of entirely a comment, no need to - # check it. - line = clean_lines.elided[linenum] - if not line: - return - - match = _RE_PATTERN_INCLUDE.search(line) - if match: - CheckIncludeLine(filename, clean_lines, linenum, include_state, error) - return - - # Create an extended_line, which is the concatenation of the current and - # next lines, for more effective checking of code that may span more than one - # line. - if linenum + 1 < clean_lines.NumLines(): - extended_line = line + clean_lines.elided[linenum + 1] - else: - extended_line = line - - # Make Windows paths like Unix. - fullname = os.path.abspath(filename).replace('\\', '/') - - # TODO(unknown): figure out if they're using default arguments in fn proto. - - # Check for non-const references in functions. This is tricky because & - # is also used to take the address of something. We allow <> for templates, - # (ignoring whatever is between the braces) and : for classes. - # These are complicated re's. They try to capture the following: - # paren (for fn-prototype start), typename, &, varname. For the const - # version, we're willing for const to be before typename or after - # Don't check the implementation on same line. - fnline = line.split('{', 1)[0] - if (len(re.findall(r'\([^()]*\b(?:[\w:]|<[^()]*>)+(\s?&|&\s?)\w+', fnline)) > - len(re.findall(r'\([^()]*\bconst\s+(?:typename\s+)?(?:struct\s+)?' - r'(?:[\w:]|<[^()]*>)+(\s?&|&\s?)\w+', fnline)) + - len(re.findall(r'\([^()]*\b(?:[\w:]|<[^()]*>)+\s+const(\s?&|&\s?)[\w]+', - fnline))): - - # We allow non-const references in a few standard places, like functions - # called "swap()" or iostream operators like "<<" or ">>". - if not Search( - r'(swap|Swap|operator[<>][<>])\s*\(\s*(?:[\w:]|<.*>)+\s*&', - fnline): - error(filename, linenum, 'runtime/references', 2, - 'Is this a non-const reference? ' - 'If so, make const or use a pointer.') - - # Check to see if they're using an conversion function cast. - # I just try to capture the most common basic types, though there are more. - # Parameterless conversion functions, such as bool(), are allowed as they are - # probably a member operator declaration or default constructor. - match = Search( - r'(\bnew\s+)?\b' # Grab 'new' operator, if it's there - r'(int|float|double|bool|char|int32|uint32|int64|uint64)\([^)]', line) - if match: - # gMock methods are defined using some variant of MOCK_METHODx(name, type) - # where type may be float(), int(string), etc. Without context they are - # virtually indistinguishable from int(x) casts. Likewise, gMock's - # MockCallback takes a template parameter of the form return_type(arg_type), - # which looks much like the cast we're trying to detect. - if (match.group(1) is None and # If new operator, then this isn't a cast - not (Match(r'^\s*MOCK_(CONST_)?METHOD\d+(_T)?\(', line) or - Match(r'^\s*MockCallback<.*>', line))): - error(filename, linenum, 'readability/casting', 4, - 'Using deprecated casting style. ' - 'Use static_cast<%s>(...) instead' % - match.group(2)) - - CheckCStyleCast(filename, linenum, line, clean_lines.raw_lines[linenum], - 'static_cast', - r'\((int|float|double|bool|char|u?int(16|32|64))\)', error) - - # This doesn't catch all cases. Consider (const char * const)"hello". - # - # (char *) "foo" should always be a const_cast (reinterpret_cast won't - # compile). - if CheckCStyleCast(filename, linenum, line, clean_lines.raw_lines[linenum], - 'const_cast', r'\((char\s?\*+\s?)\)\s*"', error): - pass - else: - # Check pointer casts for other than string constants - CheckCStyleCast(filename, linenum, line, clean_lines.raw_lines[linenum], - 'reinterpret_cast', r'\((\w+\s?\*+\s?)\)', error) - - # In addition, we look for people taking the address of a cast. This - # is dangerous -- casts can assign to temporaries, so the pointer doesn't - # point where you think. - if Search( - r'(&\([^)]+\)[\w(])|(&(static|dynamic|reinterpret)_cast\b)', line): - error(filename, linenum, 'runtime/casting', 4, - ('Are you taking an address of a cast? ' - 'This is dangerous: could be a temp var. ' - 'Take the address before doing the cast, rather than after')) - - # Check for people declaring static/global STL strings at the top level. - # This is dangerous because the C++ language does not guarantee that - # globals with constructors are initialized before the first access. - match = Match( - r'((?:|static +)(?:|const +))string +([a-zA-Z0-9_:]+)\b(.*)', - line) - # Make sure it's not a function. - # Function template specialization looks like: "string foo(...". - # Class template definitions look like: "string Foo::Method(...". - if match and not Match(r'\s*(<.*>)?(::[a-zA-Z0-9_]+)?\s*\(([^"]|$)', - match.group(3)): - error(filename, linenum, 'runtime/string', 4, - 'For a static/global string constant, use a C style string instead: ' - '"%schar %s[]".' % - (match.group(1), match.group(2))) - - # Check that we're not using RTTI outside of testing code. - if Search(r'\bdynamic_cast<', line) and not _IsTestFilename(filename): - error(filename, linenum, 'runtime/rtti', 5, - 'Do not use dynamic_cast<>. If you need to cast within a class ' - "hierarchy, use static_cast<> to upcast. Google doesn't support " - 'RTTI.') - - if Search(r'\b([A-Za-z0-9_]*_)\(\1\)', line): - error(filename, linenum, 'runtime/init', 4, - 'You seem to be initializing a member variable with itself.') - - if file_extension == 'h': - # TODO(unknown): check that 1-arg constructors are explicit. - # How to tell it's a constructor? - # (handled in CheckForNonStandardConstructs for now) - # TODO(unknown): check that classes have DISALLOW_EVIL_CONSTRUCTORS - # (level 1 error) - pass - - # Check if people are using the verboten C basic types. The only exception - # we regularly allow is "unsigned short port" for port. - if Search(r'\bshort port\b', line): - if not Search(r'\bunsigned short port\b', line): - error(filename, linenum, 'runtime/int', 4, - 'Use "unsigned short" for ports, not "short"') - else: - match = Search(r'\b(short|long(?! +double)|long long)\b', line) - if match: - error(filename, linenum, 'runtime/int', 4, - 'Use int16/int64/etc, rather than the C type %s' % match.group(1)) - - # When snprintf is used, the second argument shouldn't be a literal. - match = Search(r'snprintf\s*\(([^,]*),\s*([0-9]*)\s*,', line) - if match and match.group(2) != '0': - # If 2nd arg is zero, snprintf is used to calculate size. - error(filename, linenum, 'runtime/printf', 3, - 'If you can, use sizeof(%s) instead of %s as the 2nd arg ' - 'to snprintf.' % (match.group(1), match.group(2))) - - # Check if some verboten C functions are being used. - if Search(r'\bsprintf\b', line): - error(filename, linenum, 'runtime/printf', 5, - 'Never use sprintf. Use snprintf instead.') - match = Search(r'\b(strcpy|strcat)\b', line) - if match: - error(filename, linenum, 'runtime/printf', 4, - 'Almost always, snprintf is better than %s' % match.group(1)) - - if Search(r'\bsscanf\b', line): - error(filename, linenum, 'runtime/printf', 1, - 'sscanf can be ok, but is slow and can overflow buffers.') - - # Check if some verboten operator overloading is going on - # TODO(unknown): catch out-of-line unary operator&: - # class X {}; - # int operator&(const X& x) { return 42; } // unary operator& - # The trick is it's hard to tell apart from binary operator&: - # class Y { int operator&(const Y& x) { return 23; } }; // binary operator& - if Search(r'\boperator\s*&\s*\(\s*\)', line): - error(filename, linenum, 'runtime/operator', 4, - 'Unary operator& is dangerous. Do not use it.') - - # Check for suspicious usage of "if" like - # } if (a == b) { - if Search(r'\}\s*if\s*\(', line): - error(filename, linenum, 'readability/braces', 4, - 'Did you mean "else if"? If not, start a new line for "if".') - - # Check for potential format string bugs like printf(foo). - # We constrain the pattern not to pick things like DocidForPrintf(foo). - # Not perfect but it can catch printf(foo.c_str()) and printf(foo->c_str()) - # TODO(sugawarayu): Catch the following case. Need to change the calling - # convention of the whole function to process multiple line to handle it. - # printf( - # boy_this_is_a_really_long_variable_that_cannot_fit_on_the_prev_line); - printf_args = _GetTextInside(line, r'(?i)\b(string)?printf\s*\(') - if printf_args: - match = Match(r'([\w.\->()]+)$', printf_args) - if match: - function_name = re.search(r'\b((?:string)?printf)\s*\(', - line, re.I).group(1) - error(filename, linenum, 'runtime/printf', 4, - 'Potential format string bug. Do %s("%%s", %s) instead.' - % (function_name, match.group(1))) - - # Check for potential memset bugs like memset(buf, sizeof(buf), 0). - match = Search(r'memset\s*\(([^,]*),\s*([^,]*),\s*0\s*\)', line) - if match and not Match(r"^''|-?[0-9]+|0x[0-9A-Fa-f]$", match.group(2)): - error(filename, linenum, 'runtime/memset', 4, - 'Did you mean "memset(%s, 0, %s)"?' - % (match.group(1), match.group(2))) - - if Search(r'\busing namespace\b', line): - error(filename, linenum, 'build/namespaces', 5, - 'Do not use namespace using-directives. ' - 'Use using-declarations instead.') - - # Detect variable-length arrays. - match = Match(r'\s*(.+::)?(\w+) [a-z]\w*\[(.+)];', line) - if (match and match.group(2) != 'return' and match.group(2) != 'delete' and - match.group(3).find(']') == -1): - # Split the size using space and arithmetic operators as delimiters. - # If any of the resulting tokens are not compile time constants then - # report the error. - tokens = re.split(r'\s|\+|\-|\*|\/|<<|>>]', match.group(3)) - is_const = True - skip_next = False - for tok in tokens: - if skip_next: - skip_next = False - continue - - if Search(r'sizeof\(.+\)', tok): continue - if Search(r'arraysize\(\w+\)', tok): continue - - tok = tok.lstrip('(') - tok = tok.rstrip(')') - if not tok: continue - if Match(r'\d+', tok): continue - if Match(r'0[xX][0-9a-fA-F]+', tok): continue - if Match(r'k[A-Z0-9]\w*', tok): continue - if Match(r'(.+::)?k[A-Z0-9]\w*', tok): continue - if Match(r'(.+::)?[A-Z][A-Z0-9_]*', tok): continue - # A catch all for tricky sizeof cases, including 'sizeof expression', - # 'sizeof(*type)', 'sizeof(const type)', 'sizeof(struct StructName)' - # requires skipping the next token because we split on ' ' and '*'. - if tok.startswith('sizeof'): - skip_next = True - continue - is_const = False - break - if not is_const: - error(filename, linenum, 'runtime/arrays', 1, - 'Do not use variable-length arrays. Use an appropriately named ' - "('k' followed by CamelCase) compile-time constant for the size.") - - # If DISALLOW_EVIL_CONSTRUCTORS, DISALLOW_COPY_AND_ASSIGN, or - # DISALLOW_IMPLICIT_CONSTRUCTORS is present, then it should be the last thing - # in the class declaration. - match = Match( - (r'\s*' - r'(DISALLOW_(EVIL_CONSTRUCTORS|COPY_AND_ASSIGN|IMPLICIT_CONSTRUCTORS))' - r'\(.*\);$'), - line) - if match and linenum + 1 < clean_lines.NumLines(): - next_line = clean_lines.elided[linenum + 1] - # We allow some, but not all, declarations of variables to be present - # in the statement that defines the class. The [\w\*,\s]* fragment of - # the regular expression below allows users to declare instances of - # the class or pointers to instances, but not less common types such - # as function pointers or arrays. It's a tradeoff between allowing - # reasonable code and avoiding trying to parse more C++ using regexps. - if not Search(r'^\s*}[\w\*,\s]*;', next_line): - error(filename, linenum, 'readability/constructors', 3, - match.group(1) + ' should be the last thing in the class') - - # Check for use of unnamed namespaces in header files. Registration - # macros are typically OK, so we allow use of "namespace {" on lines - # that end with backslashes. - if (file_extension == 'h' - and Search(r'\bnamespace\s*{', line) - and line[-1] != '\\'): - error(filename, linenum, 'build/namespaces', 4, - 'Do not use unnamed namespaces in header files. See ' - 'http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Namespaces' - ' for more information.') - - -def CheckCStyleCast(filename, linenum, line, raw_line, cast_type, pattern, - error): - # We don't check this for C code. - return False - """Checks for a C-style cast by looking for the pattern. - - This also handles sizeof(type) warnings, due to similarity of content. - - Args: - filename: The name of the current file. - linenum: The number of the line to check. - line: The line of code to check. - raw_line: The raw line of code to check, with comments. - cast_type: The string for the C++ cast to recommend. This is either - reinterpret_cast, static_cast, or const_cast, depending. - pattern: The regular expression used to find C-style casts. - error: The function to call with any errors found. - - Returns: - True if an error was emitted. - False otherwise. - """ - match = Search(pattern, line) - if not match: - return False - - # e.g., sizeof(int) - sizeof_match = Match(r'.*sizeof\s*$', line[0:match.start(1) - 1]) - if sizeof_match: - error(filename, linenum, 'runtime/sizeof', 1, - 'Using sizeof(type). Use sizeof(varname) instead if possible') - return True - - remainder = line[match.end(0):] - - # The close paren is for function pointers as arguments to a function. - # eg, void foo(void (*bar)(int)); - # The semicolon check is a more basic function check; also possibly a - # function pointer typedef. - # eg, void foo(int); or void foo(int) const; - # The equals check is for function pointer assignment. - # eg, void *(*foo)(int) = ... - # The > is for MockCallback<...> ... - # - # Right now, this will only catch cases where there's a single argument, and - # it's unnamed. It should probably be expanded to check for multiple - # arguments with some unnamed. - function_match = Match(r'\s*(\)|=|(const)?\s*(;|\{|throw\(\)|>))', remainder) - if function_match: - if (not function_match.group(3) or - function_match.group(3) == ';' or - ('MockCallback<' not in raw_line and - '/*' not in raw_line)): - error(filename, linenum, 'readability/function', 3, - 'All parameters should be named in a function') - return True - - # At this point, all that should be left is actual casts. - error(filename, linenum, 'readability/casting', 4, - 'Using C-style cast. Use %s<%s>(...) instead' % - (cast_type, match.group(1))) - - return True - - -_HEADERS_CONTAINING_TEMPLATES = ( - ('', ('deque',)), - ('', ('unary_function', 'binary_function', - 'plus', 'minus', 'multiplies', 'divides', 'modulus', - 'negate', - 'equal_to', 'not_equal_to', 'greater', 'less', - 'greater_equal', 'less_equal', - 'logical_and', 'logical_or', 'logical_not', - 'unary_negate', 'not1', 'binary_negate', 'not2', - 'bind1st', 'bind2nd', - 'pointer_to_unary_function', - 'pointer_to_binary_function', - 'ptr_fun', - 'mem_fun_t', 'mem_fun', 'mem_fun1_t', 'mem_fun1_ref_t', - 'mem_fun_ref_t', - 'const_mem_fun_t', 'const_mem_fun1_t', - 'const_mem_fun_ref_t', 'const_mem_fun1_ref_t', - 'mem_fun_ref', - )), - ('', ('numeric_limits',)), - ('', ('list',)), - ('', ('map', 'multimap',)), - ('', ('allocator',)), - ('', ('queue', 'priority_queue',)), - ('', ('set', 'multiset',)), - ('', ('stack',)), - ('', ('char_traits', 'basic_string',)), - ('', ('pair',)), - ('', ('vector',)), - - # gcc extensions. - # Note: std::hash is their hash, ::hash is our hash - ('', ('hash_map', 'hash_multimap',)), - ('', ('hash_set', 'hash_multiset',)), - ('', ('slist',)), - ) - -_RE_PATTERN_STRING = re.compile(r'\bstring\b') - -_re_pattern_algorithm_header = [] -for _template in ('copy', 'max', 'min', 'min_element', 'sort', 'swap', - 'transform'): - # Match max(..., ...), max(..., ...), but not foo->max, foo.max or - # type::max(). - _re_pattern_algorithm_header.append( - (re.compile(r'[^>.]\b' + _template + r'(<.*?>)?\([^\)]'), - _template, - '')) - -_re_pattern_templates = [] -for _header, _templates in _HEADERS_CONTAINING_TEMPLATES: - for _template in _templates: - _re_pattern_templates.append( - (re.compile(r'(\<|\b)' + _template + r'\s*\<'), - _template + '<>', - _header)) - - -def FilesBelongToSameModule(filename_cc, filename_h): - """Check if these two filenames belong to the same module. - - The concept of a 'module' here is a as follows: - foo.h, foo-inl.h, foo.c, foo_test.c and foo_unittest.c belong to the - same 'module' if they are in the same directory. - some/path/public/xyzzy and some/path/internal/xyzzy are also considered - to belong to the same module here. - - If the filename_cc contains a longer path than the filename_h, for example, - '/absolute/path/to/base/sysinfo.c', and this file would include - 'base/sysinfo.h', this function also produces the prefix needed to open the - header. This is used by the caller of this function to more robustly open the - header file. We don't have access to the real include paths in this context, - so we need this guesswork here. - - Known bugs: tools/base/bar.c and base/bar.h belong to the same module - according to this implementation. Because of this, this function gives - some false positives. This should be sufficiently rare in practice. - - Args: - filename_cc: is the path for the .c file - filename_h: is the path for the header path - - Returns: - Tuple with a bool and a string: - bool: True if filename_cc and filename_h belong to the same module. - string: the additional prefix needed to open the header file. - """ - - if not filename_cc.endswith('.c'): - return (False, '') - filename_cc = filename_cc[:-len('.c')] - if filename_cc.endswith('_unittest'): - filename_cc = filename_cc[:-len('_unittest')] - elif filename_cc.endswith('_test'): - filename_cc = filename_cc[:-len('_test')] - filename_cc = filename_cc.replace('/public/', '/') - filename_cc = filename_cc.replace('/internal/', '/') - - if not filename_h.endswith('.h'): - return (False, '') - filename_h = filename_h[:-len('.h')] - if filename_h.endswith('-inl'): - filename_h = filename_h[:-len('-inl')] - filename_h = filename_h.replace('/public/', '/') - filename_h = filename_h.replace('/internal/', '/') - - files_belong_to_same_module = filename_cc.endswith(filename_h) - common_path = '' - if files_belong_to_same_module: - common_path = filename_cc[:-len(filename_h)] - return files_belong_to_same_module, common_path - - -def UpdateIncludeState(filename, include_state, io=codecs): - """Fill up the include_state with new includes found from the file. - - Args: - filename: the name of the header to read. - include_state: an _IncludeState instance in which the headers are inserted. - io: The io factory to use to read the file. Provided for testability. - - Returns: - True if a header was succesfully added. False otherwise. - """ - headerfile = None - try: - headerfile = io.open(filename, 'r', 'utf8', 'replace') - except IOError: - return False - linenum = 0 - for line in headerfile: - linenum += 1 - clean_line = CleanseComments(line) - match = _RE_PATTERN_INCLUDE.search(clean_line) - if match: - include = match.group(2) - # The value formatting is cute, but not really used right now. - # What matters here is that the key is in include_state. - include_state.setdefault(include, '%s:%d' % (filename, linenum)) - return True - - -def CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error, - io=codecs): - """Reports for missing stl includes. - - This function will output warnings to make sure you are including the headers - necessary for the stl containers and functions that you use. We only give one - reason to include a header. For example, if you use both equal_to<> and - less<> in a .h file, only one (the latter in the file) of these will be - reported as a reason to include the . - - Args: - filename: The name of the current file. - clean_lines: A CleansedLines instance containing the file. - include_state: An _IncludeState instance. - error: The function to call with any errors found. - io: The IO factory to use to read the header file. Provided for unittest - injection. - """ - required = {} # A map of header name to linenumber and the template entity. - # Example of required: { '': (1219, 'less<>') } - - for linenum in xrange(clean_lines.NumLines()): - line = clean_lines.elided[linenum] - if not line or line[0] == '#': - continue - - # String is special -- it is a non-templatized type in STL. - matched = _RE_PATTERN_STRING.search(line) - if matched: - # Don't warn about strings in non-STL namespaces: - # (We check only the first match per line; good enough.) - prefix = line[:matched.start()] - if prefix.endswith('std::') or not prefix.endswith('::'): - required[''] = (linenum, 'string') - - for pattern, template, header in _re_pattern_algorithm_header: - if pattern.search(line): - required[header] = (linenum, template) - - # The following function is just a speed up, no semantics are changed. - if not '<' in line: # Reduces the cpu time usage by skipping lines. - continue - - for pattern, template, header in _re_pattern_templates: - if pattern.search(line): - required[header] = (linenum, template) - - # The policy is that if you #include something in foo.h you don't need to - # include it again in foo.c. Here, we will look at possible includes. - # Let's copy the include_state so it is only messed up within this function. - include_state = include_state.copy() - - # Did we find the header for this file (if any) and succesfully load it? - header_found = False - - # Use the absolute path so that matching works properly. - abs_filename = FileInfo(filename).FullName() - - # For Emacs's flymake. - # If cpplint is invoked from Emacs's flymake, a temporary file is generated - # by flymake and that file name might end with '_flymake.c'. In that case, - # restore original file name here so that the corresponding header file can be - # found. - # e.g. If the file name is 'foo_flymake.c', we should search for 'foo.h' - # instead of 'foo_flymake.h' - abs_filename = re.sub(r'_flymake\.c$', '.c', abs_filename) - - # include_state is modified during iteration, so we iterate over a copy of - # the keys. - header_keys = include_state.keys() - for header in header_keys: - (same_module, common_path) = FilesBelongToSameModule(abs_filename, header) - fullpath = common_path + header - if same_module and UpdateIncludeState(fullpath, include_state, io): - header_found = True - - # If we can't find the header file for a .c, assume it's because we don't - # know where to look. In that case we'll give up as we're not sure they - # didn't include it in the .h file. - # TODO(unknown): Do a better job of finding .h files so we are confident that - # not having the .h file means there isn't one. - if filename.endswith('.c') and not header_found: - return - - # All the lines have been processed, report the errors found. - for required_header_unstripped in required: - template = required[required_header_unstripped][1] - if required_header_unstripped.strip('<>"') not in include_state: - error(filename, required[required_header_unstripped][0], - 'build/include_what_you_use', 4, - 'Add #include ' + required_header_unstripped + ' for ' + template) - - -_RE_PATTERN_EXPLICIT_MAKEPAIR = re.compile(r'\bmake_pair\s*<') - - -def CheckMakePairUsesDeduction(filename, clean_lines, linenum, error): - """Check that make_pair's template arguments are deduced. - - G++ 4.6 in C++0x mode fails badly if make_pair's template arguments are - specified explicitly, and such use isn't intended in any case. - - Args: - filename: The name of the current file. - clean_lines: A CleansedLines instance containing the file. - linenum: The number of the line to check. - error: The function to call with any errors found. - """ - raw = clean_lines.raw_lines - line = raw[linenum] - match = _RE_PATTERN_EXPLICIT_MAKEPAIR.search(line) - if match: - error(filename, linenum, 'build/explicit_make_pair', - 4, # 4 = high confidence - 'Omit template arguments from make_pair OR use pair directly OR' - ' if appropriate, construct a pair directly') - - -def ProcessLine(filename, file_extension, - clean_lines, line, include_state, function_state, - class_state, error, extra_check_functions=[]): - """Processes a single line in the file. - - Args: - filename: Filename of the file that is being processed. - file_extension: The extension (dot not included) of the file. - clean_lines: An array of strings, each representing a line of the file, - with comments stripped. - line: Number of line being processed. - include_state: An _IncludeState instance in which the headers are inserted. - function_state: A _FunctionState instance which counts function lines, etc. - class_state: A _ClassState instance which maintains information about - the current stack of nested class declarations being parsed. - error: A callable to which errors are reported, which takes 4 arguments: - filename, line number, error level, and message - extra_check_functions: An array of additional check functions that will be - run on each source line. Each function takes 4 - arguments: filename, clean_lines, line, error - """ - raw_lines = clean_lines.raw_lines - ParseNolintSuppressions(filename, raw_lines[line], line, error) - CheckForFunctionLengths(filename, clean_lines, line, function_state, error) - CheckForMultilineCommentsAndStrings(filename, clean_lines, line, error) - CheckStyle(filename, clean_lines, line, file_extension, class_state, error) - CheckLanguage(filename, clean_lines, line, file_extension, include_state, - error) - CheckForNonStandardConstructs(filename, clean_lines, line, - class_state, error) - #NOTE(TFK): Removed this for project 1. - #CheckPosixThreading(filename, clean_lines, line, error) - CheckInvalidIncrement(filename, clean_lines, line, error) - CheckMakePairUsesDeduction(filename, clean_lines, line, error) - for check_fn in extra_check_functions: - check_fn(filename, clean_lines, line, error) - -def ProcessFileData(filename, file_extension, lines, error, - extra_check_functions=[]): - """Performs lint checks and reports any errors to the given error function. - - Args: - filename: Filename of the file that is being processed. - file_extension: The extension (dot not included) of the file. - lines: An array of strings, each representing a line of the file, with the - last element being empty if the file is terminated with a newline. - error: A callable to which errors are reported, which takes 4 arguments: - filename, line number, error level, and message - extra_check_functions: An array of additional check functions that will be - run on each source line. Each function takes 4 - arguments: filename, clean_lines, line, error - """ - lines = (['// marker so line numbers and indices both start at 1'] + lines + - ['// marker so line numbers end in a known way']) - - include_state = _IncludeState() - function_state = _FunctionState() - class_state = _ClassState() - - ResetNolintSuppressions() - - CheckForCopyright(filename, lines, error) - - if file_extension == 'h': - CheckForHeaderGuard(filename, lines, error) - - RemoveMultiLineComments(filename, lines, error) - clean_lines = CleansedLines(lines) - for line in xrange(clean_lines.NumLines()): - ProcessLine(filename, file_extension, clean_lines, line, - include_state, function_state, class_state, error, - extra_check_functions) - class_state.CheckFinished(filename, error) - - CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error) - - # We check here rather than inside ProcessLine so that we see raw - # lines rather than "cleaned" lines. - CheckForUnicodeReplacementCharacters(filename, lines, error) - - CheckForNewlineAtEOF(filename, lines, error) - -def ProcessFile(filename, vlevel, extra_check_functions=[]): - """Does google-lint on a single file. - - Args: - filename: The name of the file to parse. - - vlevel: The level of errors to report. Every error of confidence - >= verbose_level will be reported. 0 is a good default. - - extra_check_functions: An array of additional check functions that will be - run on each source line. Each function takes 4 - arguments: filename, clean_lines, line, error - """ - - _SetVerboseLevel(vlevel) - - try: - # Support the UNIX convention of using "-" for stdin. Note that - # we are not opening the file with universal newline support - # (which codecs doesn't support anyway), so the resulting lines do - # contain trailing '\r' characters if we are reading a file that - # has CRLF endings. - # If after the split a trailing '\r' is present, it is removed - # below. If it is not expected to be present (i.e. os.linesep != - # '\r\n' as in Windows), a warning is issued below if this file - # is processed. - - if filename == '-': - lines = codecs.StreamReaderWriter(sys.stdin, - codecs.getreader('utf8'), - codecs.getwriter('utf8'), - 'replace').read().split('\n') - else: - lines = codecs.open(filename, 'r', 'utf8', 'replace').read().split('\n') - - carriage_return_found = False - # Remove trailing '\r'. - for linenum in range(len(lines)): - if lines[linenum].endswith('\r'): - lines[linenum] = lines[linenum].rstrip('\r') - carriage_return_found = True - - except IOError: - sys.stderr.write( - "Skipping input '%s': Can't open for reading\n" % filename) - return - - # Note, if no dot is found, this will give the entire filename as the ext. - file_extension = filename[filename.rfind('.') + 1:] - - # When reading from stdin, the extension is unknown, so no cpplint tests - # should rely on the extension. - if (filename != '-' and file_extension != 'c' and file_extension != 'h' - and file_extension != 'cpp'): - sys.stderr.write('Ignoring %s; not a .c or .h file\n' % filename) - else: - ProcessFileData(filename, file_extension, lines, Error, - extra_check_functions) - if carriage_return_found and os.linesep != '\r\n': - # Use 0 for linenum since outputting only one error for potentially - # several lines. - Error(filename, 0, 'whitespace/newline', 1, - 'One or more unexpected \\r (^M) found;' - 'better to use only a \\n') - - sys.stderr.write('Done processing %s\n' % filename) - - -def PrintUsage(message): - """Prints a brief usage string and exits, optionally with an error message. - - Args: - message: The optional error message. - """ - sys.stderr.write(_USAGE) - if message: - sys.exit('\nFATAL ERROR: ' + message) - else: - sys.exit(1) - - -def PrintCategories(): - """Prints a list of all the error-categories used by error messages. - - These are the categories used to filter messages via --filter. - """ - sys.stderr.write(''.join(' %s\n' % cat for cat in _ERROR_CATEGORIES)) - sys.exit(0) - - -def ParseArguments(args): - """Parses the command line arguments. - - This may set the output format and verbosity level as side-effects. - - Args: - args: The command line arguments: - - Returns: - The list of filenames to lint. - """ - try: - (opts, filenames) = getopt.getopt(args, '', ['help', 'output=', 'verbose=', - 'counting=', - 'filter=']) - except getopt.GetoptError: - PrintUsage('Invalid arguments.') - - verbosity = _VerboseLevel() - output_format = _OutputFormat() - filters = '' - counting_style = '' - - for (opt, val) in opts: - if opt == '--help': - PrintUsage(None) - elif opt == '--output': - if not val in ('emacs', 'vs7'): - PrintUsage('The only allowed output formats are emacs and vs7.') - output_format = val - elif opt == '--verbose': - verbosity = int(val) - elif opt == '--filter': - filters = val - if not filters: - PrintCategories() - elif opt == '--counting': - if val not in ('total', 'toplevel', 'detailed'): - PrintUsage('Valid counting options are total, toplevel, and detailed') - counting_style = val - - if not filenames: - PrintUsage('No files were specified.') - - _SetOutputFormat(output_format) - _SetVerboseLevel(verbosity) - _SetFilters(filters) - _SetCountingStyle(counting_style) - - return filenames - - -def main(): - filenames = ParseArguments(sys.argv[1:]) - - # Change stderr to write with replacement characters so we don't die - # if we try to print something containing non-ASCII characters. - sys.stderr = codecs.StreamReaderWriter(sys.stderr, - codecs.getreader('utf8'), - codecs.getwriter('utf8'), - 'replace') - - _cpplint_state.ResetErrorCounts() - for filename in filenames: - ProcessFile(filename, _cpplint_state.verbose_level) - _cpplint_state.PrintErrorCounts() - - sys.exit(_cpplint_state.error_count > 0) - - -if __name__ == '__main__': - main() diff --git a/reducer_bench/quad_tree/collision_world.c b/reducer_bench/quad_tree/collision_world.c deleted file mode 100644 index 2bfb0bc2..00000000 --- a/reducer_bench/quad_tree/collision_world.c +++ /dev/null @@ -1,396 +0,0 @@ -// #define LIVE -/** - * collision_world.c -- detect and handle line segment intersections - * Copyright (c) 2012 the Massachusetts Institute of Technology - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - **/ - -#include "./collision_world.h" - -#include -#include -#include -#include - -#include "./intersection_detection.h" -#include "./intersection_event_list.h" -#include "./line.h" - -#include "./bin.h" - -#include -#include "./reducer_defs.h" - -// ssize_t * dats = NULL; -bin_manager_t * man = NULL; - -CollisionWorld* CollisionWorld_new(const unsigned int capacity) { - assert(capacity > 0); - - CollisionWorld* collisionWorld = malloc(sizeof(CollisionWorld)); - if (collisionWorld == NULL) { - return NULL; - } - - collisionWorld->numLineWallCollisions = 0; - collisionWorld->numLineLineCollisions = 0; - collisionWorld->timeStep = 0.5; - collisionWorld->lines = malloc(capacity * sizeof(Line*)); - collisionWorld->numOfLines = 0; - - - // dats = (ssize_t *)malloc(capacity * sizeof(ssize_t)); - man = new_bin_manager(); - - return collisionWorld; -} - -void CollisionWorld_delete(CollisionWorld* collisionWorld) { - for (int i = 0; i < collisionWorld->numOfLines; i++) { - free(collisionWorld->lines[i]); - } - free(collisionWorld->lines); - free(collisionWorld); - - // free(dats); - free_bin_manager(man); -} - -unsigned int CollisionWorld_getNumOfLines(CollisionWorld* collisionWorld) { - return collisionWorld->numOfLines; -} - -void CollisionWorld_addLine(CollisionWorld* collisionWorld, Line *line) { - collisionWorld->lines[collisionWorld->numOfLines] = line; - collisionWorld->numOfLines++; -} - -Line* CollisionWorld_getLine(CollisionWorld* collisionWorld, - const unsigned int index) { - if (index >= collisionWorld->numOfLines) { - return NULL; - } - return collisionWorld->lines[index]; -} - -void CollisionWorld_updateLines(CollisionWorld* collisionWorld) { - CollisionWorld_detectIntersection(collisionWorld); - CollisionWorld_updatePosition(collisionWorld); - CollisionWorld_lineWallCollision(collisionWorld); -} - -void lineUpdate(Line * line, double t) { - Vec v = Vec_multiply(line->velocity, t); - line->p1 = Vec_add(line->p1, v); - line->p2 = Vec_add(line->p2, v); -} - -void CollisionWorld_updatePosition(CollisionWorld* collisionWorld) { - double t = collisionWorld->timeStep; - unsigned int n = collisionWorld->numOfLines; - - // Unrolled loop - for (int i = 0; i + 7 < n; i += 8) { - lineUpdate(collisionWorld->lines[i], t); - lineUpdate(collisionWorld->lines[i + 1], t); - lineUpdate(collisionWorld->lines[i + 2], t); - lineUpdate(collisionWorld->lines[i + 3], t); - lineUpdate(collisionWorld->lines[i + 4], t); - lineUpdate(collisionWorld->lines[i + 5], t); - lineUpdate(collisionWorld->lines[i + 6], t); - lineUpdate(collisionWorld->lines[i + 7], t); - } - - for (int i = n - (n & 7); i < collisionWorld->numOfLines; i++) { - lineUpdate(collisionWorld->lines[i], t); - } -} - -bool wallLine(Line * line) { - bool collide = false; - - // Right side - if ((line->p1.x > BOX_XMAX || line->p2.x > BOX_XMAX) - && (line->velocity.x > 0)) { - line->velocity.x = -line->velocity.x; - collide = true; - } - // Left side - if ((line->p1.x < BOX_XMIN || line->p2.x < BOX_XMIN) - && (line->velocity.x < 0)) { - line->velocity.x = -line->velocity.x; - collide = true; - } - // Top side - if ((line->p1.y > BOX_YMAX || line->p2.y > BOX_YMAX) - && (line->velocity.y > 0)) { - line->velocity.y = -line->velocity.y; - collide = true; - } - // Bottom side - if ((line->p1.y < BOX_YMIN || line->p2.y < BOX_YMIN) - && (line->velocity.y < 0)) { - line->velocity.y = -line->velocity.y; - collide = true; - } - return collide; -} - -// Parallelizing this causes an 0.02 to 0.09 s slowdown -void CollisionWorld_lineWallCollision_orig(CollisionWorld* collisionWorld) { - unsigned int n = collisionWorld->numOfLines; - //Unrolled loop - for (int i = 0; i + 7 < n; i += 8) { - Line * line0 = collisionWorld->lines[i]; - Line * line1 = collisionWorld->lines[i + 1]; - Line * line2 = collisionWorld->lines[i + 2]; - Line * line3 = collisionWorld->lines[i + 3]; - Line * line4 = collisionWorld->lines[i + 4]; - Line * line5 = collisionWorld->lines[i + 5]; - Line * line6 = collisionWorld->lines[i + 6]; - Line * line7 = collisionWorld->lines[i + 7]; - - uint8_t res = 0; - - res += (wallLine(line0)) ? 1 : 0; - res += (wallLine(line1)) ? 1 : 0; - res += (wallLine(line2)) ? 1 : 0; - res += (wallLine(line3)) ? 1 : 0; - res += (wallLine(line4)) ? 1 : 0; - res += (wallLine(line5)) ? 1 : 0; - res += (wallLine(line6)) ? 1 : 0; - res += (wallLine(line7)) ? 1 : 0; - - // Update total number of collisions. - collisionWorld->numLineWallCollisions += res; - } - - for (int i = n - (n & 7); i < collisionWorld->numOfLines; i++) { - Line *line = collisionWorld->lines[i]; - bool collide = wallLine(line); - // Update total number of collisions. - if (collide == true) { - collisionWorld->numLineWallCollisions++; - } - } -} - -void CollisionWorld_lineWallCollision(CollisionWorld* collisionWorld) { - CollisionWorld_lineWallCollision_orig(collisionWorld); -} - -// That godawful bubblesort, separated out for readability. -void IntersectionEventList_sort(IntersectionEventList * iel) { - // Sort the intersection event list. - IntersectionEventNode* startNode = iel->head; - while (startNode != NULL) { - IntersectionEventNode* minNode = startNode; - IntersectionEventNode* curNode = startNode->next; - while (curNode != NULL) { - if (IntersectionEventNode_compareData(curNode, minNode) < 0) { - minNode = curNode; - } - curNode = curNode->next; - } - if (minNode != startNode) { - IntersectionEventNode_swapData(minNode, startNode); - } - startNode = startNode->next; - } -} - -// The original collision detection -unsigned int CollisionWorld_IntersectionEventList_orig(IntersectionEventList * iel, CollisionWorld* collisionWorld) { - unsigned int numLineLineCollisions = 0; - // Test all line-line pairs to see if they will intersect before the - // next time step. - for (int i = 0; i < collisionWorld->numOfLines; i++) { - - for (int j = i + 1; j < collisionWorld->numOfLines; j++) { - Line *l1 = collisionWorld->lines[i]; // NOTE: I moved this in, as per https://piazza.com/class/ism98km5jrx2fl?cid=290 - Line *l2 = collisionWorld->lines[j]; - - // intersect expects compareLines(l1, l2) < 0 to be true. - // Swap l1 and l2, if necessary. - if (compareLines(l1, l2) >= 0) { - Line *temp = l1; - l1 = l2; - l2 = temp; - } - - IntersectionType intersectionType = - intersect(l1, l2, collisionWorld->timeStep); - if (intersectionType != NO_INTERSECTION) { - IntersectionEventList_appendNode(iel, l1, l2, - intersectionType); - numLineLineCollisions++; - } - } - } - - IntersectionEventList_sort(iel); - - return numLineLineCollisions; -} - -unsigned int CollisionWorld_IntersectionEventList_bin(IntersectionEventList * iel, CollisionWorld* collisionWorld) { - unsigned int numLineLineCollisions = 0; - - // (Re) sort the lines - sortLines(collisionWorld); - - // Build the bin - // bin_manager_t * man = new_bin_manager(); - setBins(collisionWorld, man); - - numLineLineCollisions = bin_intersect(man, iel, collisionWorld); - - // free_bin_manager(man); - - IntersectionEventList_sort(iel); - - return numLineLineCollisions; -} - -void CollisionWorld_detectIntersection(CollisionWorld* collisionWorld) { - // Uncomment out lines for live testing - IntersectionEventList intersectionEventList1 = IntersectionEventList_make(); -#ifdef LIVE - IntersectionEventList intersectionEventList2 = IntersectionEventList_make(); -#endif - - CollisionWorld_IntersectionEventList_bin(&intersectionEventList1, collisionWorld); - unsigned int col1 = intersectionEventList1.size; -#ifdef LIVE - unsigned int col2 = CollisionWorld_IntersectionEventList_orig(&intersectionEventList2, collisionWorld); - - assert(col1 == col2); -#endif - - collisionWorld->numLineLineCollisions += col1; - // Call the collision solver for each intersection event. - IntersectionEventNode* curNode = intersectionEventList1.head; -#ifdef LIVE - curNode = intersectionEventList2.head; - IntersectionEventNode* curNode2 = intersectionEventList1.head; -#endif - - while (curNode != NULL) { -#ifdef LIVE - assert(curNode->l1 == curNode2->l1); - assert(curNode->l2 == curNode2->l2); - assert(curNode->intersectionType == curNode2->intersectionType); -#endif - CollisionWorld_collisionSolver(collisionWorld, curNode->l1, curNode->l2, - curNode->intersectionType); - curNode = curNode->next; -#ifdef LIVE - curNode2 = curNode2->next; -#endif - } - - IntersectionEventList_deleteNodes(&intersectionEventList1); -#ifdef LIVE - IntersectionEventList_deleteNodes(&intersectionEventList2); -#endif -} - -unsigned int CollisionWorld_getNumLineWallCollisions( - CollisionWorld* collisionWorld) { - return collisionWorld->numLineWallCollisions; -} - -unsigned int CollisionWorld_getNumLineLineCollisions( - CollisionWorld* collisionWorld) { - return collisionWorld->numLineLineCollisions; -} - -void CollisionWorld_collisionSolver(CollisionWorld* collisionWorld, - Line *l1, Line *l2, - IntersectionType intersectionType) { - assert(compareLines(l1, l2) < 0); - assert(intersectionType == L1_WITH_L2 - || intersectionType == L2_WITH_L1 - || intersectionType == ALREADY_INTERSECTED); - - // Despite our efforts to determine whether lines will intersect ahead - // of time (and to modify their velocities appropriately), our - // simplified model can sometimes cause lines to intersect. In such a - // case, we compute velocities so that the two lines can get unstuck in - // the fastest possible way, while still conserving momentum and kinetic - // energy. - if (intersectionType == ALREADY_INTERSECTED) { - Vec p = getIntersectionPoint(l1->p1, l1->p2, l2->p1, l2->p2); - Vec l_p1_p = Vec_subtract(l1->p1, p); - Vec l_p2_p = Vec_subtract(l1->p2, p); - - // Simplified control flow; replaced ifs with ?:s - - // bool lcomp = (Vec_length(l_p1_p) < Vec_length(l_p2_p)); - bool lcomp = (l_p1_p.x * l_p1_p.x + l_p1_p.y * l_p1_p.y < l_p2_p.x * l_p2_p.x + l_p2_p.y * l_p2_p.y); - - l1->velocity = Vec_multiply(Vec_normalize(lcomp ? l_p2_p : l_p1_p), Vec_length(l1->velocity)); - - l_p1_p = Vec_subtract(l2->p1, p); - l_p2_p = Vec_subtract(l2->p2, p); - - lcomp = (l_p1_p.x * l_p1_p.x + l_p1_p.y * l_p1_p.y < l_p2_p.x * l_p2_p.x + l_p2_p.y * l_p2_p.y); - - l2->velocity = Vec_multiply(Vec_normalize(lcomp ? l_p2_p : l_p1_p), Vec_length(l2->velocity)); - - return; - } - - // Simplified control flow; replaced ifs with ?:s - // Compute the collision face/normal vectors. - bool itype = (intersectionType == L1_WITH_L2); - Line * l = itype ? l2 : l1; - - Vec v = Vec_makeFromLine(*l); - Vec face = Vec_divide(v, Vec_length(v)); - Vec normal = Vec_orthogonal(face); - - // Obtain each line's velocity components with respect to the collision - // face/normal vectors. - double v1Face = Vec_dotProduct(l1->velocity, face); - double v2Face = Vec_dotProduct(l2->velocity, face); - double v1Normal = Vec_dotProduct(l1->velocity, normal); - double v2Normal = Vec_dotProduct(l2->velocity, normal); - - // Compute the mass of each line (we simply use its length). - double m1 = Vec_length(Vec_makeFromLine(*l1)); - double m2 = Vec_length(Vec_makeFromLine(*l2)); - - // Perform the collision calculation (computes the new velocities along - // the direction normal to the collision face such that momentum and - // kinetic energy are conserved). - double newV1Normal = ((m1 - m2) / (m1 + m2)) * v1Normal - + (2 * m2 / (m1 + m2)) * v2Normal; - double newV2Normal = (2 * m1 / (m1 + m2)) * v1Normal - + ((m2 - m1) / (m2 + m1)) * v2Normal; - - // Combine the resulting velocities. - l1->velocity = Vec_add(Vec_multiply(normal, newV1Normal), - Vec_multiply(face, v1Face)); - l2->velocity = Vec_add(Vec_multiply(normal, newV2Normal), - Vec_multiply(face, v2Face)); - - return; -} diff --git a/reducer_bench/quad_tree/collision_world.h b/reducer_bench/quad_tree/collision_world.h deleted file mode 100644 index 4de22976..00000000 --- a/reducer_bench/quad_tree/collision_world.h +++ /dev/null @@ -1,88 +0,0 @@ -/** - * collision_world.h -- detect and handle line segment intersections - * Copyright (c) 2012 the Massachusetts Institute of Technology - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - **/ - -#ifndef COLLISIONWORLD_H_ -#define COLLISIONWORLD_H_ - -#include "./line.h" -#include "./intersection_detection.h" - -struct CollisionWorld { - // Time step used for simulation - double timeStep; - - // Container that holds all the lines as an array of Line* lines. - // This CollisionWorld owns the Line* lines. - Line** lines; - unsigned int numOfLines; - - // Record the total number of line-wall collisions. - unsigned int numLineWallCollisions; - - // Record the total number of line-line intersections. - unsigned int numLineLineCollisions; -}; -typedef struct CollisionWorld CollisionWorld; - -CollisionWorld* CollisionWorld_new(const unsigned int capacity); - -void CollisionWorld_delete(CollisionWorld* collisionWorld); - -// Return the total number of lines in the box. -unsigned int CollisionWorld_getNumOfLines(CollisionWorld* collisionWorld); - -// Add a line into the box. Must be under capacity. -// This CollisionWorld becomes owner of the Line* line. -void CollisionWorld_addLine(CollisionWorld* collisionWorld, Line *line); - -// Get a line from box. -Line* CollisionWorld_getLine(CollisionWorld* collisionWorld, - const unsigned int index); - -// Update lines' situation in the box. -void CollisionWorld_updateLines(CollisionWorld* collisionWorld); - -// Update position of lines. -void CollisionWorld_updatePosition(CollisionWorld* collisionWorld); - -// Handle line-wall collision. -void CollisionWorld_lineWallCollision(CollisionWorld* collisionWorld); - -// Detect line-line intersection. -void CollisionWorld_detectIntersection(CollisionWorld* collisionWorld); - -// Get total number of line-wall collisions. -unsigned int CollisionWorld_getNumLineWallCollisions( - CollisionWorld* collisionWorld); - -// Get total number of line-line intersections. -unsigned int CollisionWorld_getNumLineLineCollisions( - CollisionWorld* collisionWorld); - -// Update the two lines based on their intersection event. -// Precondition: compareLines(l1, l2) < 0 must be true. -void CollisionWorld_collisionSolver(CollisionWorld* collisionWorld, Line *l1, - Line *l2, - IntersectionType intersectionType); - -#endif // COLLISIONWORLD_H_ diff --git a/reducer_bench/quad_tree/fasttime.h b/reducer_bench/quad_tree/fasttime.h deleted file mode 100644 index f12c8567..00000000 --- a/reducer_bench/quad_tree/fasttime.h +++ /dev/null @@ -1,97 +0,0 @@ -/** - * Copyright (c) 2014 MIT License by 6.172 Staff - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - **/ - -#ifndef INCLUDED_FASTTIME_DOT_H -#define INCLUDED_FASTTIME_DOT_H - -#define _POSIX_C_SOURCE 200809L - -#include - -#ifdef __MACH__ -#include // mach_absolute_time - -typedef uint64_t fasttime_t; - - -// Return the current time. -static inline fasttime_t gettime(void) { - return mach_absolute_time(); -} - -// Return the time different between the start and the end, as a float -// in units of seconds. This function does not need to be fast. -// Implementation notes: See -// https://developer.apple.com/library/mac/qa/qa1398/_index.html -static inline double tdiff(fasttime_t start, fasttime_t end) { - static mach_timebase_info_data_t timebase; - int r = mach_timebase_info(&timebase); - assert(r == 0); - fasttime_t elapsed = end-start; - double ns = (double)elapsed * timebase.numer / timebase.denom; - return ns*1e-9; -} - -static inline unsigned int random_seed_from_clock(void) { - fasttime_t now = gettime(); - return (now & 0xFFFFFFFF) + (now>>32); -} - -#else // LINUX - -// We need _POSIX_C_SOURCE to pick up 'struct timespec' and clock_gettime. -// #define _POSIX_C_SOURCE 200809L - -#include - -typedef struct timespec fasttime_t; - -// Return the current time. -static inline fasttime_t gettime(void) { - struct timespec s; -#ifdef NDEBUG - clock_gettime(CLOCK_MONOTONIC, &s); -#else - int r = clock_gettime(CLOCK_MONOTONIC, &s); - assert(r == 0); -#endif - return s; -} - -// Return the time different between the start and the end, as a float -// in units of seconds. This function does not need to be fast. -static inline double tdiff(fasttime_t start, fasttime_t end) { - return end.tv_sec - start.tv_sec + 1e-9*(end.tv_nsec - start.tv_nsec); -} - -static inline unsigned int random_seed_from_clock(void) { - fasttime_t now = gettime(); - return now.tv_sec + now.tv_nsec; -} - -// Poison these symbols to help find portability problems. -int clock_gettime(clockid_t, struct timespec *) __attribute__((deprecated)); -time_t time(time_t *) __attribute__((deprecated)); - -#endif // LINUX - -#endif // INCLUDED_FASTTIME_DOT_H diff --git a/reducer_bench/quad_tree/graphic_stuff.c b/reducer_bench/quad_tree/graphic_stuff.c deleted file mode 100644 index f8bf102b..00000000 --- a/reducer_bench/quad_tree/graphic_stuff.c +++ /dev/null @@ -1,252 +0,0 @@ -/** - * Copyright (c) 2012 the Massachusetts Institute of Technology - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - **/ - -#include "./graphic_stuff.h" - -#include -#include -#include - -#include "./line.h" -#include "./line_demo.h" - -static LineDemo *gLineDemo = NULL; -XSegment *segments = NULL; -XSegment *gray_segments = NULL; - - -Display *display; - -Window window; -Window root; -Window parent; - -int screen; -int depth; -int visibility; - -int windowwidth; -int windowheight; - -static void drawLineSegments(Display *display, Drawable drawable) { - Line *line; - unsigned int nsegments; - window_dimension px1; - window_dimension py1; - window_dimension px2; - window_dimension py2; - - Colormap cmap; - XGCValues gcval; - XColor color; - XColor ignore; - int64_t fgcolor; - GC gray; - GC red; - - cmap = DefaultColormap(display, screen); - XAllocNamedColor(display, cmap, "gray", &color, &ignore); - fgcolor = color.pixel; - gcval.foreground = fgcolor; - gray = XCreateGC(display, window, GCForeground, &gcval); - - XAllocNamedColor(display, cmap, "dark red", &color, &ignore); - fgcolor = color.pixel; - gcval.foreground = fgcolor; - red = XCreateGC(display, window, GCForeground, &gcval); - - nsegments = LineDemo_getNumOfLines(gLineDemo); - if (segments == NULL || gray_segments == NULL) { - segments = malloc(nsegments * sizeof(XSegment)); - gray_segments = malloc(nsegments * sizeof(XSegment)); - } - XClearWindow(display, window); - int red_segments_count = 0; - int gray_segments_count = 0; - for (unsigned int i = 0; i < nsegments; i++) { - line = LineDemo_getLine(gLineDemo, i); - - // Convert box coordinates to window coordinates. - boxToWindow(&px1, &py1, line->p1.x, line->p1.y); - boxToWindow(&px2, &py2, line->p2.x, line->p2.y); - // Set line color. - switch (line->color) { - case RED: - // Convert doubles to short ints and store into segments. - segments[red_segments_count].x1 = (int16_t) px1; - segments[red_segments_count].y1 = (int16_t) py1; - segments[red_segments_count].x2 = (int16_t) px2; - segments[red_segments_count].y2 = (int16_t) py2; - red_segments_count++; - break; - case GRAY: - gray_segments[gray_segments_count].x1 = (int16_t) px1; - gray_segments[gray_segments_count].y1 = (int16_t) py1; - gray_segments[gray_segments_count].x2 = (int16_t) px2; - gray_segments[gray_segments_count].y2 = (int16_t) py2; - gray_segments_count++; - break; - } - } - XDrawSegments(display, drawable, red, segments, red_segments_count); - XDrawSegments(display, drawable, gray, gray_segments, gray_segments_count); - XSync(display, 0); -} - -static void checkEvent() { - XEvent event; - bool block = false; - - while ((XPending(display) > 0) || (block == true)) { - XNextEvent(display, &event); - switch (event.type) { - case ReparentNotify: - if (event.xreparent.window != window) { - break; - } - XSelectInput(display, event.xreparent.parent, StructureNotifyMask); - XSelectInput(display, parent, 0); - parent = event.xreparent.parent; - break; - - case UnmapNotify: - if ((event.xunmap.window != window) - && (event.xunmap.window != parent)) { - break; - } - block = true; - break; - - case VisibilityNotify: - if (event.xvisibility.window != window) { - break; - } - if (event.xvisibility.state == VisibilityFullyObscured) { - block = true; - break; - } - if ((event.xvisibility.state == VisibilityUnobscured) - && (visibility == 1)) { - visibility = 0; - block = false; - break; - } - if (event.xvisibility.state == VisibilityPartiallyObscured) { - visibility = 1; - block = false; - } - break; - - case Expose: - block = false; - break; - - case MapNotify: - if ((event.xmap.window != window) && (event.xmap.window != parent)) { - break; - } - block = false; - break; - - case ConfigureNotify: - if (event.xconfigure.window != window) { - break; - } - if ((windowwidth == event.xconfigure.width) - && (windowheight == event.xconfigure.height)) { - break; - } - windowwidth = event.xconfigure.width; - windowheight = event.xconfigure.height; - XClearWindow(display, window); - block = false; - break; - - default: - break; - } - } -} - -static void graphicMainLoop(bool imageOnlyFlag) { - while (true) { - checkEvent(); - drawLineSegments(display, window); - if (!imageOnlyFlag && !LineDemo_update(gLineDemo)) { - return; - } - } -} - -static void graphicInit(int *argc, char *argv[]) { - // Initialization - int64_t fgcolor; - int64_t bgcolor; - int64_t eventmask; - char *host; - - if ((host = ((char *) getenv("DISPLAY"))) == NULL) { - perror("Error: No environment variable DISPLAY\n"); - exit(1); - } - - if (!(display = XOpenDisplay(host))) { - perror("XOpenDisplay"); - exit(1); - } - - screen = DefaultScreen(display); - root = RootWindow(display, screen); - parent = root; - bgcolor = BlackPixel(display, screen); - fgcolor = WhitePixel(display, screen); - depth = DefaultDepth(display, screen); - windowwidth = WINDOW_WIDTH; - windowheight = WINDOW_HEIGHT; - window = XCreateSimpleWindow(display, root, 0, 0, windowwidth, windowheight, - 2, fgcolor, bgcolor); - - eventmask = SubstructureNotifyMask; - XSelectInput(display, window, eventmask); - - XMapWindow(display, window); - - XClearWindow(display, window); - XSync(display, 0); -} - -void graphicMain(int argc, char *argv[], LineDemo *lineDemo, bool imageOnlyFlag) { - gLineDemo = lineDemo; - - // Initialization - graphicInit(&argc, argv); - - // Entering the rendering loop - graphicMainLoop(imageOnlyFlag); - - if (segments != NULL) { - free(segments); - } - if (gray_segments != NULL) { - free(gray_segments); - } -} diff --git a/reducer_bench/quad_tree/graphic_stuff.h b/reducer_bench/quad_tree/graphic_stuff.h deleted file mode 100644 index ccfca3d0..00000000 --- a/reducer_bench/quad_tree/graphic_stuff.h +++ /dev/null @@ -1,35 +0,0 @@ -/** - * Copyright (c) 2012 the Massachusetts Institute of Technology - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - **/ - -// Graphics output -#ifndef GRAPHICSTUFF_H_ -#define GRAPHICSTUFF_H_ - -#include -#include - -struct LineDemo; - -void graphicMain(int argc, char *argv[], struct LineDemo *lineDemo, - bool imageOnlyFlag); - -#endif // GRAPHICSTUFF_H_ diff --git a/reducer_bench/quad_tree/input/apple.in b/reducer_bench/quad_tree/input/apple.in deleted file mode 100644 index 900ffdbc..00000000 --- a/reducer_bench/quad_tree/input/apple.in +++ /dev/null @@ -1,536 +0,0 @@ -535 -(435.0, 225), (430.0, 225), -0.499627818977, 0, 0 -(570.0, 225), (565.0, 225), -0.0256987929563, 0, 0 -(420.89326402, 226), (444.10673598, 226), 0.180943610724, 0, 0 -(555.89326402, 226), (579.10673598, 226), 0.362806469405, 0, 0 -(415.100251258, 227), (449.899748742, 227), 0.464223154637, 0, 0 -(550.100251258, 227), (584.899748742, 227), 0.0771573245807, 0, 0 -(410.689508438, 228), (454.310491562, 228), 0.0668782249886, 0, 0 -(545.689508438, 228), (589.310491562, 228), -0.114703738039, 0, 0 -(407.0, 229), (458.0, 229), 0.410931843836, 0, 0 -(542.0, 229), (593.0, 229), 0.495952392578, 0, 0 -(403.775010008, 230), (461.224989992, 230), 0.191870639295, 0, 0 -(538.775010008, 230), (596.224989992, 230), 0.353593703131, 0, 0 -(400.882555782, 231), (464.117444218, 231), -0.251070976155, 0, 0 -(535.882555782, 231), (599.117444218, 231), -0.0402767349806, 0, 0 -(398.244048101, 232), (466.755951899, 232), 0.444488578913, 0, 0 -(533.244048101, 232), (601.755951899, 232), -0.0725090199593, 0, 0 -(395.808164115, 233), (469.191835885, 233), 0.162636421772, 0, 0 -(530.808164115, 233), (604.191835885, 233), -0.476566442546, 0, 0 -(393.539175117, 234), (471.460824883, 234), -0.441579046478, 0, 0 -(528.539175117, 234), (606.460824883, 234), -0.377171094435, 0, 0 -(391.411010565, 235), (473.588989435, 235), -0.0209601304485, 0, 0 -(526.411010565, 235), (608.588989435, 235), -0.157248900369, 0, 0 -(389.403947539, 236), (475.596052461, 236), 0.424602114848, 0, 0 -(524.403947539, 236), (610.596052461, 236), -0.300170752342, 0, 0 -(387.502631652, 237), (477.497368348, 237), 0.00921649027118, 0, 0 -(522.502631652, 237), (612.497368348, 237), -0.0230018125244, 0, 0 -(385.694827858, 238), (479.305172142, 238), 0.0108428955653, 0, 0 -(520.694827858, 238), (614.305172142, 238), -0.0472926974957, 0, 0 -(383.970596711, 239), (481.029403289, 239), 0.422274703059, 0, 0 -(518.970596711, 239), (616.029403289, 239), -0.401472988259, 0, 0 -(382.321731236, 240), (482.678268764, 240), -0.386788001395, 0, 0 -(517.321731236, 240), (617.678268764, 240), 0.449138043052, 0, 0 -(380.741360135, 241), (484.258639865, 241), -0.491410358397, 0, 0 -(515.741360135, 241), (619.258639865, 241), 0.0908227726688, 0, 0 -(379.22366093, 242), (485.77633907, 242), 0.0549058145862, 0, 0 -(514.22366093, 242), (620.77633907, 242), 0.19488185933, 0, 0 -(377.763647915, 243), (487.236352085, 243), 0.150261871572, 0, 0 -(512.763647915, 243), (622.236352085, 243), -0.392475696597, 0, 0 -(376.357012354, 244), (488.642987646, 244), 0.130619472849, 0, 0 -(511.357012354, 244), (623.642987646, 244), 0.0870583346481, 0, 0 -(375.0, 245), (490.0, 245), 0.209416968024, 0, 0 -(510.0, 245), (625.0, 245), -0.098835493861, 0, 0 -(373.689315776, 246), (491.310684224, 246), -0.324172106211, 0, 0 -(508.689315776, 246), (626.310684224, 246), -0.0523581977883, 0, 0 -(372.422048611, 247), (492.577951389, 247), 0.397787827998, 0, 0 -(507.422048611, 247), (627.577951389, 247), -0.110766807077, 0, 0 -(371.195611436, 248), (493.804388564, 248), 0.228889585425, 0, 0 -(506.195611436, 248), (628.804388564, 248), 0.447055644931, 0, 0 -(370.007692763, 249), (494.992307237, 249), 0.152085009806, 0, 0 -(505.007692763, 249), (629.992307237, 249), -0.120687020706, 0, 0 -(368.856217223, 250), (496.143782777, 250), -0.13241902814, 0, 0 -(503.856217223, 250), (631.143782777, 250), -0.00848440765887, 0, 0 -(367.739313117, 251), (497.260686883, 251), -0.291568075624, 0, 0 -(502.739313117, 251), (632.260686883, 251), 0.390386349847, 0, 0 -(366.655285501, 252), (498.344714499, 252), -0.236348970633, 0, 0 -(501.655285501, 252), (633.344714499, 252), -0.0282053197262, 0, 0 -(365.602593708, 253), (499.397406292, 253), 0.438842003935, 0, 0 -(500.602593708, 253), (634.397406292, 253), -0.440400387448, 0, 0 -(364.579832434, 254), (500.420167566, 254), 0.47654602654, 0, 0 -(499.579832434, 254), (635.420167566, 254), -0.236409652252, 0, 0 -(362.25022686, 255), (637.74977314, 255), 0.183759771392, 0, 0 -(361.205187417, 256), (638.794812583, 256), -0.331265197423, 0, 0 -(360.175109512, 257), (639.824890488, 257), -0.293383796417, 0, 0 -(359.159664868, 258), (640.840335132, 258), -0.141816879907, 0, 0 -(358.158539207, 259), (641.841460793, 259), 0.230721060011, 0, 0 -(357.171431429, 260), (642.828568571, 260), -0.162943565964, 0, 0 -(356.198052864, 261), (643.801947136, 261), -0.165519045875, 0, 0 -(355.238126566, 262), (644.761873434, 262), -0.206423075503, 0, 0 -(354.291386665, 263), (645.708613335, 263), -0.307373729846, 0, 0 -(353.357577761, 264), (646.642422239, 264), 0.453546830797, 0, 0 -(352.436454366, 265), (647.563545634, 265), -0.395278499, 0, 0 -(351.527780376, 266), (648.472219624, 266), 0.0424517124367, 0, 0 -(350.631328586, 267), (649.368671414, 267), -0.139972365425, 0, 0 -(349.746880232, 268), (650.253119768, 268), -0.423895066605, 0, 0 -(348.874224568, 269), (651.125775432, 269), 0.434593814929, 0, 0 -(348.013158464, 270), (651.986841536, 270), 0.197451355462, 0, 0 -(347.163486038, 271), (652.836513962, 271), -0.312143976639, 0, 0 -(346.325018302, 272), (653.674981698, 272), 0.232103800766, 0, 0 -(345.497572835, 273), (654.502427165, 273), 0.0815587939093, 0, 0 -(344.680973477, 274), (655.319026523, 274), -0.277074403812, 0, 0 -(343.87505004, 275), (656.12494996, 275), -0.388999360446, 0, 0 -(343.079638033, 276), (656.920361967, 276), -0.397478549772, 0, 0 -(342.294578406, 277), (657.705421594, 277), -0.484789173934, 0, 0 -(341.519717315, 278), (658.480282685, 278), 0.109811712311, 0, 0 -(340.754905884, 279), (659.245094116, 279), 0.167394719774, 0, 0 -(340.0, 280), (660.0, 280), -0.212874161992, 0, 0 -(339.254860105, 281), (660.745139895, 281), -0.489503481444, 0, 0 -(338.519351005, 282), (661.480648995, 282), -0.269032797079, 0, 0 -(337.79334169, 283), (662.20665831, 283), -0.360566302207, 0, 0 -(337.076705165, 284), (662.923294835, 284), -0.318003682599, 0, 0 -(336.36931828, 285), (663.63068172, 285), 0.216538279934, 0, 0 -(335.671061587, 286), (664.328938413, 286), 0.267472991113, 0, 0 -(334.981819183, 287), (665.018180817, 287), 0.0677181608012, 0, 0 -(334.301478582, 288), (665.698521418, 288), -0.0387708914572, 0, 0 -(333.629930576, 289), (666.370069424, 289), -0.361399575198, 0, 0 -(332.967069115, 290), (667.032930885, 290), -0.42553223766, 0, 0 -(332.312791185, 291), (667.687208815, 291), 0.152211343434, 0, 0 -(331.6669967, 292), (668.3330033, 292), -0.332836614062, 0, 0 -(331.029588389, 293), (668.970411611, 293), 0.0255540744769, 0, 0 -(330.400471699, 294), (669.599528301, 294), 0.461018223414, 0, 0 -(329.779554695, 295), (670.220445305, 295), -0.116563636102, 0, 0 -(329.166747967, 296), (670.833252033, 296), -0.257784004344, 0, 0 -(328.561964547, 297), (671.438035453, 297), -0.133599289211, 0, 0 -(327.965119816, 298), (672.034880184, 298), 0.314562115607, 0, 0 -(327.37613143, 299), (672.62386857, 299), 0.393957077745, 0, 0 -(326.794919243, 300), (673.205080757, 300), -0.140318196546, 0, 0 -(326.221405231, 301), (673.778594769, 301), -0.497257584571, 0, 0 -(325.655513422, 302), (674.344486578, 302), 0.252113422573, 0, 0 -(325.097169834, 303), (674.902830166, 303), 0.0122257732685, 0, 0 -(324.546302404, 304), (675.453697596, 304), 0.305299265206, 0, 0 -(324.002840932, 305), (675.997159068, 305), -0.177351201373, 0, 0 -(323.466717019, 306), (676.533282981, 306), 0.422669850848, 0, 0 -(322.937864014, 307), (677.062135986, 307), -0.484889949836, 0, 0 -(322.416216957, 308), (677.583783043, 308), 0.392386304114, 0, 0 -(321.901712529, 309), (678.098287471, 309), -0.285914536225, 0, 0 -(321.394289005, 310), (681.411010565, 310), 0.3844851346, 0, 0 -(320.893886202, 311), (679.403947539, 311), 0.474003121357, 0, 0 -(320.400445435, 312), (677.502631652, 312), -0.0351378976563, 0, 0 -(319.913909477, 313), (675.694827858, 313), 0.209887618813, 0, 0 -(319.434222512, 314), (673.970596711, 314), -0.045771343327, 0, 0 -(318.961330098, 315), (672.321731236, 315), -0.38107192292, 0, 0 -(318.495179127, 316), (670.741360135, 316), 0.105883198639, 0, 0 -(318.035717791, 317), (669.22366093, 317), -0.0828560162025, 0, 0 -(317.582895539, 318), (667.763647915, 318), -0.112187040117, 0, 0 -(317.136663051, 319), (666.357012354, 319), 0.472822218374, 0, 0 -(316.696972202, 320), (665.0, 320), 0.250272748739, 0, 0 -(316.263776027, 321), (663.689315776, 321), -0.279554194233, 0, 0 -(315.837028695, 322), (662.422048611, 322), -0.4700864733, 0, 0 -(315.416685478, 323), (661.195611436, 323), 0.0438911924842, 0, 0 -(315.002702722, 324), (660.007692763, 324), -0.0466346244854, 0, 0 -(314.595037823, 325), (658.856217223, 325), -0.352015731611, 0, 0 -(314.193649194, 326), (657.739313117, 326), -0.125593391615, 0, 0 -(313.798496247, 327), (656.655285501, 327), 0.104263915292, 0, 0 -(313.409539365, 328), (655.602593708, 328), 0.337615164152, 0, 0 -(313.02673988, 329), (654.579832434, 329), -0.0392375643237, 0, 0 -(312.650060048, 330), (653.585715715, 330), -0.0874827135083, 0, 0 -(312.279463031, 331), (652.619063283, 331), -0.0432672564313, 0, 0 -(311.914912872, 332), (651.678788881, 332), 0.3847970365, 0, 0 -(311.556374478, 333), (650.763890188, 333), -0.3423657227, 0, 0 -(311.203813598, 334), (649.873440116, 334), -0.334891952067, 0, 0 -(310.857196806, 335), (649.006579232, 335), -0.391028641513, 0, 0 -(310.516491483, 336), (648.162509151, 336), 0.453631134004, 0, 0 -(310.181665796, 337), (647.340486739, 337), -0.309282150547, 0, 0 -(309.852688686, 338), (646.539819016, 338), 0.463363193234, 0, 0 -(309.529529848, 339), (645.759858657, 339), 0.104325420969, 0, 0 -(309.212159717, 340), (645.0, 340), 0.0684759540761, 0, 0 -(308.900549451, 341), (644.259675502, 341), -0.0395069664154, 0, 0 -(308.594670921, 342), (643.538352582, 342), -0.273335106866, 0, 0 -(308.294496688, 343), (642.835530793, 343), 0.0966753563305, 0, 0 -(308.0, 344), (642.150739291, 344), -0.389404806599, 0, 0 -(307.71115477, 345), (641.483534558, 345), 0.0277530840143, 0, 0 -(307.427935567, 346), (640.83349835, 346), 0.0255676674323, 0, 0 -(307.150317605, 347), (640.200235849, 347), 0.45035849155, 0, 0 -(306.878276727, 348), (639.583373984, 348), -0.12485569312, 0, 0 -(306.611789398, 349), (638.982559908, 349), -0.270071743908, 0, 0 -(306.35083269, 350), (638.397459622, 350), -0.359586900204, 0, 0 -(306.095384274, 351), (637.827756711, 351), 0.11258411396, 0, 0 -(305.845422408, 352), (637.273151202, 352), -0.3120168163, 0, 0 -(305.600925928, 353), (636.73335851, 353), -0.387181341245, 0, 0 -(305.361874238, 354), (636.208108478, 354), -0.238675994264, 0, 0 -(305.128247301, 355), (635.697144503, 355), -0.135529917361, 0, 0 -(304.900025628, 356), (635.200222717, 356), 0.215828404629, 0, 0 -(304.677190272, 357), (634.717111256, 357), 0.349429785166, 0, 0 -(304.459722819, 358), (634.247589564, 358), -0.166515271141, 0, 0 -(304.247605379, 359), (633.791447769, 359), 0.308445655052, 0, 0 -(304.040820577, 360), (633.348486101, 360), -0.473511544938, 0, 0 -(303.839351551, 361), (632.918514347, 361), -0.398120471996, 0, 0 -(303.643181937, 362), (632.501351361, 362), 0.0917172867204, 0, 0 -(303.452295867, 363), (632.096824597, 363), 0.137555389054, 0, 0 -(303.266677962, 364), (631.704769682, 364), 0.271803280659, 0, 0 -(303.086313325, 365), (631.325030024, 365), 0.44283577719, 0, 0 -(302.911187532, 366), (630.957456436, 366), -0.353332482673, 0, 0 -(302.741286631, 367), (630.601906799, 367), -0.448032644666, 0, 0 -(302.576597132, 368), (630.258245741, 368), -0.125012543104, 0, 0 -(302.417106004, 369), (629.926344343, 369), 0.131259452363, 0, 0 -(302.262800667, 370), (629.606079858, 370), -0.155681787721, 0, 0 -(302.113668992, 371), (629.29733546, 371), 0.210120419454, 0, 0 -(301.969699288, 372), (629.0, 372), 0.0901060557319, 0, 0 -(301.830880307, 373), (628.713967783, 373), -0.438788678412, 0, 0 -(301.69720123, 374), (628.439138363, 374), -0.350733150564, 0, 0 -(301.56865167, 375), (628.175416345, 375), 0.290822949481, 0, 0 -(301.445221664, 376), (627.922711204, 376), -0.409747457174, 0, 0 -(301.32690167, 377), (627.680937119, 377), -0.209557511004, 0, 0 -(301.213682563, 378), (627.450012814, 378), 0.164903729052, 0, 0 -(301.105555633, 379), (627.22986141, 379), 0.380431025773, 0, 0 -(301.002512579, 380), (627.020410289, 380), -0.247173374389, 0, 0 -(300.904545506, 381), (626.821590968, 381), 0.351015729648, 0, 0 -(300.811646927, 382), (626.633338981, 382), 0.00192138521634, 0, 0 -(300.723809751, 383), (626.455593766, 383), -0.136045630564, 0, 0 -(300.64102729, 384), (626.288298566, 384), 0.414522423799, 0, 0 -(300.563293248, 385), (626.131400334, 385), -0.410632492609, 0, 0 -(300.490601725, 386), (625.984849644, 386), 0.487734173639, 0, 0 -(300.422947211, 387), (625.848600615, 387), -0.209517742697, 0, 0 -(300.360324585, 388), (625.722610832, 388), 0.472183547061, 0, 0 -(300.302729112, 389), (625.606841282, 389), -0.321013794777, 0, 0 -(300.250156446, 390), (625.501256289, 390), -0.119531638936, 0, 0 -(300.20260262, 391), (625.405823463, 391), -0.433921753408, 0, 0 -(300.160064051, 392), (625.320513645, 392), -0.104689878604, 0, 0 -(300.122537539, 393), (625.245300863, 393), 0.0777887559164, 0, 0 -(300.090020259, 394), (625.180162292, 394), -0.365527449301, 0, 0 -(300.062509769, 395), (625.125078223, 395), 0.0848441523988, 0, 0 -(300.040004001, 396), (625.080032026, 396), 0.450857847931, 0, 0 -(300.022501266, 397), (625.04501013, 397), -0.394592669916, 0, 0 -(300.01000025, 398), (625.020002, 398), 0.212623719597, 0, 0 -(300.002500016, 399), (625.005000125, 399), -0.398057504586, 0, 0 -(300.0, 400), (625.0, 400), -0.486700125257, 0, 0 -(300.002500016, 401), (625.005000125, 401), -0.163463760892, 0, 0 -(300.01000025, 402), (625.020002, 402), -0.36715644303, 0, 0 -(300.022501266, 403), (625.04501013, 403), -0.176167043492, 0, 0 -(300.040004001, 404), (625.080032026, 404), 0.0397626001503, 0, 0 -(300.062509769, 405), (625.125078223, 405), 0.210515762518, 0, 0 -(300.090020259, 406), (625.180162292, 406), -0.0467719392478, 0, 0 -(300.122537539, 407), (625.245300863, 407), 0.243579752073, 0, 0 -(300.160064051, 408), (625.320513645, 408), 0.422331191717, 0, 0 -(300.20260262, 409), (625.405823463, 409), -0.358863021488, 0, 0 -(300.250156446, 410), (625.501256289, 410), -0.433921514085, 0, 0 -(300.302729112, 411), (625.606841282, 411), 0.42181214928, 0, 0 -(300.360324585, 412), (625.722610832, 412), -0.225047992894, 0, 0 -(300.422947211, 413), (625.848600615, 413), 0.106839701016, 0, 0 -(300.490601725, 414), (625.984849644, 414), -0.216765556371, 0, 0 -(300.563293248, 415), (626.131400334, 415), 0.300529277048, 0, 0 -(300.64102729, 416), (626.288298566, 416), 0.202034027149, 0, 0 -(300.723809751, 417), (626.455593766, 417), -0.206669544823, 0, 0 -(300.811646927, 418), (626.633338981, 418), -0.287718143514, 0, 0 -(300.904545506, 419), (626.821590968, 419), 0.497553800241, 0, 0 -(301.002512579, 420), (627.020410289, 420), 0.375283429941, 0, 0 -(301.105555633, 421), (627.22986141, 421), -0.343008299381, 0, 0 -(301.213682563, 422), (627.450012814, 422), -0.00460428654299, 0, 0 -(301.32690167, 423), (627.680937119, 423), -0.150117239198, 0, 0 -(301.445221664, 424), (627.922711204, 424), 0.0079374132212, 0, 0 -(301.56865167, 425), (628.175416345, 425), -0.00495481871839, 0, 0 -(301.69720123, 426), (628.439138363, 426), 0.0416152966744, 0, 0 -(301.830880307, 427), (628.713967783, 427), -0.41986464981, 0, 0 -(301.969699288, 428), (629.0, 428), 0.0672047577394, 0, 0 -(302.113668992, 429), (629.29733546, 429), -0.397355864117, 0, 0 -(302.262800667, 430), (629.606079858, 430), 0.196785761017, 0, 0 -(302.417106004, 431), (629.926344343, 431), -0.00629878251785, 0, 0 -(302.576597132, 432), (630.258245741, 432), 0.0294475337896, 0, 0 -(302.741286631, 433), (630.601906799, 433), -0.450256822423, 0, 0 -(302.911187532, 434), (630.957456436, 434), -0.394452364774, 0, 0 -(303.086313325, 435), (631.325030024, 435), -0.131480848584, 0, 0 -(303.266677962, 436), (631.704769682, 436), -0.167271822009, 0, 0 -(303.452295867, 437), (632.096824597, 437), 0.441336074309, 0, 0 -(303.643181937, 438), (632.501351361, 438), 0.441387295627, 0, 0 -(303.839351551, 439), (632.918514347, 439), 0.370607147092, 0, 0 -(304.040820577, 440), (633.348486101, 440), -0.381059479557, 0, 0 -(304.247605379, 441), (633.791447769, 441), 0.209268124949, 0, 0 -(304.459722819, 442), (634.247589564, 442), -0.172470837613, 0, 0 -(304.677190272, 443), (634.717111256, 443), 0.0300561297914, 0, 0 -(304.900025628, 444), (635.200222717, 444), 0.240119366367, 0, 0 -(305.128247301, 445), (635.697144503, 445), -0.320874941593, 0, 0 -(305.361874238, 446), (636.208108478, 446), 0.366400203078, 0, 0 -(305.600925928, 447), (636.73335851, 447), 0.251184721012, 0, 0 -(305.845422408, 448), (637.273151202, 448), 0.272856441112, 0, 0 -(306.095384274, 449), (637.827756711, 449), 0.179491189379, 0, 0 -(306.35083269, 450), (638.397459622, 450), 0.37904771469, 0, 0 -(306.611789398, 451), (638.982559908, 451), 0.058086787613, 0, 0 -(306.878276727, 452), (639.583373984, 452), -0.338802622313, 0, 0 -(307.150317605, 453), (640.200235849, 453), -0.315606377982, 0, 0 -(307.427935567, 454), (640.83349835, 454), 0.389426440026, 0, 0 -(307.71115477, 455), (641.483534558, 455), 0.139069244599, 0, 0 -(308.0, 456), (642.150739291, 456), -0.161457346986, 0, 0 -(308.294496688, 457), (642.835530793, 457), -0.131146164983, 0, 0 -(308.594670921, 458), (643.538352582, 458), -0.0686656471236, 0, 0 -(308.900549451, 459), (644.259675502, 459), -0.224166694737, 0, 0 -(309.212159717, 460), (645.0, 460), -0.413288175277, 0, 0 -(309.529529848, 461), (645.759858657, 461), 0.486261893879, 0, 0 -(309.852688686, 462), (646.539819016, 462), 0.431194460924, 0, 0 -(310.181665796, 463), (647.340486739, 463), 0.0814562797337, 0, 0 -(310.516491483, 464), (648.162509151, 464), -0.230754207765, 0, 0 -(310.857196806, 465), (649.006579232, 465), -0.404335406227, 0, 0 -(311.203813598, 466), (649.873440116, 466), -0.355184404221, 0, 0 -(311.556374478, 467), (650.763890188, 467), -0.0452067328529, 0, 0 -(311.914912872, 468), (651.678788881, 468), 0.342118202784, 0, 0 -(312.279463031, 469), (652.619063283, 469), 0.214627492807, 0, 0 -(312.650060048, 470), (653.585715715, 470), -0.18667087275, 0, 0 -(313.02673988, 471), (654.579832434, 471), -0.327812634983, 0, 0 -(313.409539365, 472), (655.602593708, 472), 0.301787587707, 0, 0 -(313.798496247, 473), (656.655285501, 473), -0.035913584527, 0, 0 -(314.193649194, 474), (657.739313117, 474), 0.230879653799, 0, 0 -(314.595037823, 475), (658.856217223, 475), 0.43468922179, 0, 0 -(315.002702722, 476), (660.007692763, 476), 0.225384749535, 0, 0 -(315.416685478, 477), (661.195611436, 477), 0.377622828734, 0, 0 -(315.837028695, 478), (662.422048611, 478), -0.0103163584716, 0, 0 -(316.263776027, 479), (663.689315776, 479), 0.145595347353, 0, 0 -(316.696972202, 480), (665.0, 480), 0.30581266269, 0, 0 -(317.136663051, 481), (666.357012354, 481), -0.497244816576, 0, 0 -(317.582895539, 482), (667.763647915, 482), -0.427578507754, 0, 0 -(318.035717791, 483), (669.22366093, 483), -0.157371836864, 0, 0 -(318.495179127, 484), (670.741360135, 484), -0.21914838617, 0, 0 -(318.961330098, 485), (672.321731236, 485), -0.164550209043, 0, 0 -(319.434222512, 486), (673.970596711, 486), -0.10209395241, 0, 0 -(319.913909477, 487), (675.694827858, 487), 0.116446669262, 0, 0 -(320.400445435, 488), (677.502631652, 488), -0.49879551529, 0, 0 -(320.893886202, 489), (679.403947539, 489), -0.195923108, 0, 0 -(321.394289005, 490), (678.605710995, 490), -0.0896640802652, 0, 0 -(321.901712529, 491), (678.098287471, 491), 0.0564014357236, 0, 0 -(322.416216957, 492), (677.583783043, 492), 0.00272419065986, 0, 0 -(322.937864014, 493), (677.062135986, 493), 0.271142084611, 0, 0 -(323.466717019, 494), (676.533282981, 494), 0.427223321108, 0, 0 -(324.002840932, 495), (675.997159068, 495), -0.18208971072, 0, 0 -(324.546302404, 496), (675.453697596, 496), 0.404583185005, 0, 0 -(325.097169834, 497), (674.902830166, 497), 0.111748899231, 0, 0 -(325.655513422, 498), (674.344486578, 498), -0.226392515845, 0, 0 -(326.221405231, 499), (673.778594769, 499), -0.243192492987, 0, 0 -(326.794919243, 500), (673.205080757, 500), -0.251596521889, 0, 0 -(327.37613143, 501), (672.62386857, 501), 0.257314973221, 0, 0 -(327.965119816, 502), (672.034880184, 502), -0.311043118178, 0, 0 -(328.561964547, 503), (671.438035453, 503), -0.248430552833, 0, 0 -(329.166747967, 504), (670.833252033, 504), 0.382756951534, 0, 0 -(329.779554695, 505), (670.220445305, 505), -0.0654757701151, 0, 0 -(330.400471699, 506), (669.599528301, 506), -0.445392956609, 0, 0 -(331.029588389, 507), (668.970411611, 507), -0.299411974335, 0, 0 -(331.6669967, 508), (668.3330033, 508), -0.372354877889, 0, 0 -(332.312791185, 509), (667.687208815, 509), 0.160176449219, 0, 0 -(332.967069115, 510), (667.032930885, 510), -0.400355271233, 0, 0 -(333.629930576, 511), (666.370069424, 511), -0.131783741625, 0, 0 -(334.301478582, 512), (665.698521418, 512), 0.314663797558, 0, 0 -(334.981819183, 513), (665.018180817, 513), -0.0630004528403, 0, 0 -(335.671061587, 514), (664.328938413, 514), -0.408134799259, 0, 0 -(336.36931828, 515), (663.63068172, 515), -0.475422046638, 0, 0 -(337.076705165, 516), (662.923294835, 516), 0.485126161714, 0, 0 -(337.79334169, 517), (662.20665831, 517), 0.087913410533, 0, 0 -(338.519351005, 518), (661.480648995, 518), 0.40302847683, 0, 0 -(339.254860105, 519), (660.745139895, 519), -0.35497088858, 0, 0 -(340.0, 520), (660.0, 520), -0.219819616829, 0, 0 -(340.754905884, 521), (659.245094116, 521), -0.273314623486, 0, 0 -(341.519717315, 522), (658.480282685, 522), -0.0586718393648, 0, 0 -(342.294578406, 523), (657.705421594, 523), -0.312699313397, 0, 0 -(343.079638033, 524), (656.920361967, 524), -0.496308096506, 0, 0 -(343.87505004, 525), (656.12494996, 525), -0.0296058092568, 0, 0 -(344.680973477, 526), (655.319026523, 526), 0.45238834666, 0, 0 -(345.497572835, 527), (654.502427165, 527), 0.0484673006444, 0, 0 -(346.325018302, 528), (653.674981698, 528), -0.291912777011, 0, 0 -(347.163486038, 529), (652.836513962, 529), -0.0478697885889, 0, 0 -(348.013158464, 530), (651.986841536, 530), 0.0980372902357, 0, 0 -(348.874224568, 531), (651.125775432, 531), 0.222909707088, 0, 0 -(349.746880232, 532), (650.253119768, 532), -0.0444322044176, 0, 0 -(350.631328586, 533), (649.368671414, 533), 0.221392254219, 0, 0 -(351.527780376, 534), (648.472219624, 534), 0.352778325076, 0, 0 -(352.436454366, 535), (647.563545634, 535), 0.205651137036, 0, 0 -(353.357577761, 536), (646.642422239, 536), 0.480889227129, 0, 0 -(354.291386665, 537), (645.708613335, 537), 0.49722839722, 0, 0 -(355.238126566, 538), (644.761873434, 538), -0.123355209778, 0, 0 -(356.198052864, 539), (643.801947136, 539), -0.460982478997, 0, 0 -(357.171431429, 540), (642.828568571, 540), -0.438338447855, 0, 0 -(358.158539207, 541), (641.841460793, 541), 0.0675100156944, 0, 0 -(359.159664868, 542), (640.840335132, 542), -0.149079057241, 0, 0 -(360.175109512, 543), (639.824890488, 543), -0.496991450718, 0, 0 -(361.205187417, 544), (638.794812583, 544), 0.289099008151, 0, 0 -(362.25022686, 545), (637.74977314, 545), 0.0347179505199, 0, 0 -(363.310571001, 546), (636.689428999, 546), 0.0939457093936, 0, 0 -(364.386578835, 547), (635.613421165, 547), -0.228060317003, 0, 0 -(365.478626234, 548), (634.521373766, 548), 0.17494523678, 0, 0 -(366.58710707, 549), (633.41289293, 549), -0.228140020271, 0, 0 -(367.712434447, 550), (500.0, 550), -0.338256324792, 0, 0 -(500.0, 550), (632.287565553, 550), -0.163697539619, 0, 0 -(368.855042034, 551), (487.793444384, 551), 0.257841569334, 0, 0 -(512.206555616, 551), (631.144957966, 551), -0.423377521133, 0, 0 -(370.015385526, 552), (482.795349466, 552), 0.0192616847585, 0, 0 -(517.204650534, 552), (629.984614474, 552), -0.0274268530543, 0, 0 -(371.193944242, 553), (479.0, 553), -0.313177551312, 0, 0 -(521.0, 553), (628.806055758, 553), 0.359699370671, 0, 0 -(372.391222872, 554), (475.833908053, 554), -0.178118694957, 0, 0 -(524.166091947, 554), (627.608777128, 554), 0.371261134601, 0, 0 -(373.607753402, 555), (473.074175964, 555), -0.396682911133, 0, 0 -(526.925824036, 555), (626.392246598, 555), 0.240282418294, 0, 0 -(374.844097223, 556), (470.606123087, 556), -0.46118402453, 0, 0 -(529.393876913, 556), (625.155902777, 556), -0.142018559363, 0, 0 -(376.100847461, 557), (468.361415961, 557), 0.232363237465, 0, 0 -(531.638584039, 557), (623.899152539, 557), -0.385305422955, 0, 0 -(377.378631552, 558), (466.295400907, 558), -0.487476447787, 0, 0 -(533.704599093, 558), (622.621368448, 558), -0.478797326567, 0, 0 -(378.678114093, 559), (464.376973739, 559), 0.156747322877, 0, 0 -(535.623026261, 559), (621.321885907, 559), -0.103158897231, 0, 0 -(380.0, 560), (462.583426132, 560), -0.450331449067, 0, 0 -(537.416573868, 560), (620.0, 560), -0.121414040149, 0, 0 -(381.34503803, 561), (460.897570408, 561), 0.416145200906, 0, 0 -(539.102429592, 561), (618.65496197, 561), 0.223983420704, 0, 0 -(382.714024709, 562), (459.306020101, 562), -0.0364307646881, 0, 0 -(540.693979899, 562), (617.285975291, 562), -0.312730460134, 0, 0 -(384.107808719, 563), (457.798104308, 563), -0.405233502583, 0, 0 -(542.201895692, 563), (615.892191281, 563), 0.33801835395, 0, 0 -(385.52729583, 564), (456.365151541, 564), 0.307593626249, 0, 0 -(543.634848459, 564), (614.47270417, 564), 0.457286979953, 0, 0 -(387.250827824, 565), (452.749172176, 565), 0.270726704296, 0, 0 -(547.250827824, 565), (612.749172176, 565), -0.304750342759, 0, 0 -(388.33939444, 566), (451.66060556, 566), -0.302795308686, 0, 0 -(548.33939444, 566), (611.66060556, 566), 0.13401874189, 0, 0 -(389.489438191, 567), (450.510561809, 567), -0.1710729791, 0, 0 -(549.489438191, 567), (610.510561809, 567), -0.251723520113, 0, 0 -(390.707143601, 568), (449.292856399, 568), 0.450096091211, 0, 0 -(550.707143601, 568), (609.292856399, 568), 0.0437188826074, 0, 0 -(392.0, 569), (448.0, 569), -0.0787297404045, 0, 0 -(552.0, 569), (608.0, 569), 0.126658858539, 0, 0 -(393.377223398, 570), (446.622776602, 570), -0.453174485338, 0, 0 -(553.377223398, 570), (606.622776602, 570), -0.433552777886, 0, 0 -(394.850373137, 571), (445.149626863, 571), 0.394309370751, 0, 0 -(554.850373137, 571), (605.149626863, 571), -0.209525092142, 0, 0 -(396.434286286, 572), (443.565713714, 572), 0.0726169141485, 0, 0 -(556.434286286, 572), (603.565713714, 572), -0.25660770133, 0, 0 -(398.148556836, 573), (441.851443164, 573), -0.350078536271, 0, 0 -(558.148556836, 573), (601.851443164, 573), -0.0951039538176, 0, 0 -(400.020008006, 574), (439.979991994, 574), -0.00073491362209, 0, 0 -(560.020008006, 574), (599.979991994, 574), 0.178051578972, 0, 0 -(402.087121525, 575), (437.912878475, 575), 0.201708029861, 0, 0 -(562.087121525, 575), (597.912878475, 575), 0.0490185267141, 0, 0 -(404.408739718, 576), (435.591260282, 576), 0.230540791066, 0, 0 -(564.408739718, 576), (595.591260282, 576), -0.215339239415, 0, 0 -(407.083527133, 577), (432.916472867, 577), 0.060129023877, 0, 0 -(567.083527133, 577), (592.916472867, 577), 0.0305538971168, 0, 0 -(410.303061543, 578), (429.696938457, 578), 0.231354970968, 0, 0 -(570.303061543, 578), (589.696938457, 578), 0.135779262855, 0, 0 -(414.559693491, 579), (425.440306509, 579), 0.0135289478848, 0, 0 -(574.559693491, 579), (585.440306509, 579), -0.339228832207, 0, 0 -(572.5, 126.25), (572.5, 126.25), 3.125, -4.0625, 1 -(572.476513654, 127.525202811), (571.273486346, 126.599797189), 3.125, -4.0625, 1 -(572.437588527, 128.788529636), (570.062411473, 126.961470364), 3.125, -4.0625, 1 -(572.38363123, 130.040293254), (568.86636877, 127.334706746), 3.125, -4.0625, 1 -(572.315024326, 131.280787943), (567.684975674, 127.719212057), 3.125, -4.0625, 1 -(572.232128172, 132.510290902), (566.517871828, 128.114709098), 3.125, -4.0625, 1 -(572.135282591, 133.729063531), (565.364717409, 128.520936469), 3.125, -4.0625, 1 -(572.024808372, 134.937352594), (564.225191628, 128.937647406), 3.125, -4.0625, 1 -(571.901008638, 136.13539126), (563.098991362, 129.36460874), 3.125, -4.0625, 1 -(571.764170075, 137.323400058), (561.985829925, 129.801599942), 3.125, -4.0625, 1 -(571.614564057, 138.501587737), (560.885435943, 130.248412263), 3.125, -4.0625, 1 -(571.452447672, 139.670152055), (559.797552328, 130.704847945), 3.125, -4.0625, 1 -(571.278064648, 140.829280499), (558.721935352, 131.170719501), 3.125, -4.0625, 1 -(571.091646211, 141.979150932), (557.658353789, 131.645849068), 3.125, -4.0625, 1 -(570.893411861, 143.119932201), (556.606588139, 132.130067799), 3.125, -4.0625, 1 -(570.683570092, 144.251784686), (555.566429908, 132.623215314), 3.125, -4.0625, 1 -(570.462319042, 145.374860802), (554.537680958, 133.125139198), 3.125, -4.0625, 1 -(570.229847105, 146.489305465), (553.520152895, 133.635694535), 3.125, -4.0625, 1 -(569.986333479, 147.595256523), (552.513666521, 134.154743477), 3.125, -4.0625, 1 -(569.731948687, 148.692845144), (551.518051313, 134.682154856), 3.125, -4.0625, 1 -(569.466855043, 149.782196187), (550.533144957, 135.217803813), 3.125, -4.0625, 1 -(569.191207093, 150.863428533), (549.558792907, 135.761571467), 3.125, -4.0625, 1 -(568.905152019, 151.936655399), (548.594847981, 136.313344601), 3.125, -4.0625, 1 -(568.608830015, 153.001984627), (547.641169985, 136.873015373), 3.125, -4.0625, 1 -(568.302374633, 154.059518948), (546.697625367, 137.440481052), 3.125, -4.0625, 1 -(567.985913105, 155.109356235), (545.764086895, 138.015643765), 3.125, -4.0625, 1 -(567.659566646, 156.151589728), (544.840433354, 138.598410272), 3.125, -4.0625, 1 -(567.323450726, 157.186308251), (543.926549274, 139.188691749), 3.125, -4.0625, 1 -(566.977675335, 158.213596412), (543.022324665, 139.786403588), 3.125, -4.0625, 1 -(566.622345221, 159.233534786), (542.127654779, 140.391465214), 3.125, -4.0625, 1 -(566.257560115, 160.246200089), (541.242439885, 141.003799911), 3.125, -4.0625, 1 -(565.883414939, 161.251665337), (540.366585061, 141.623334663), 3.125, -4.0625, 1 -(565.5, 162.25), (539.5, 142.25), 3.125, -4.0625, 1 -(565.107401176, 163.241270135), (538.642598824, 142.883729865), 3.125, -4.0625, 1 -(564.70570008, 164.225538523), (537.79429992, 143.524461477), 3.125, -4.0625, 1 -(564.29497422, 165.202864784), (536.95502578, 144.172135216), 3.125, -4.0625, 1 -(563.875297147, 166.173305498), (536.124702853, 144.826694502), 3.125, -4.0625, 1 -(563.446738591, 167.136914301), (535.303261409, 145.488085699), 3.125, -4.0625, 1 -(563.009364589, 168.093741991), (534.490635411, 146.156258009), 3.125, -4.0625, 1 -(562.563237605, 169.043836619), (533.686762395, 146.831163381), 3.125, -4.0625, 1 -(562.10841664, 169.98724357), (532.89158336, 147.51275643), 3.125, -4.0625, 1 -(561.644957338, 170.924005645), (532.105042662, 148.200994355), 3.125, -4.0625, 1 -(561.172912078, 171.854163137), (531.327087922, 148.895836863), 3.125, -4.0625, 1 -(560.692330065, 172.777753896), (530.557669935, 149.597246104), 3.125, -4.0625, 1 -(560.203257415, 173.694813396), (529.796742585, 150.305186604), 3.125, -4.0625, 1 -(559.705737229, 174.605374792), (529.044262771, 151.019625208), 3.125, -4.0625, 1 -(559.199809664, 175.509468972), (528.300190336, 151.740531028), 3.125, -4.0625, 1 -(558.685512, 176.407124616), (527.564488, 152.467875384), 3.125, -4.0625, 1 -(558.162878699, 177.29836823), (526.837121301, 153.20163177), 3.125, -4.0625, 1 -(557.631941459, 178.183224199), (526.118058541, 153.941775801), 3.125, -4.0625, 1 -(557.092729265, 179.061714819), (525.407270735, 154.688285181), 3.125, -4.0625, 1 -(556.545268436, 179.933860335), (524.704731564, 155.441139665), 3.125, -4.0625, 1 -(555.989582663, 180.799678972), (524.010417337, 156.200321028), 3.125, -4.0625, 1 -(555.425693049, 181.659186961), (523.324306951, 156.965813039), 3.125, -4.0625, 1 -(554.853618138, 182.512398567), (522.646381862, 157.737601433), 3.125, -4.0625, 1 -(554.273373944, 183.359326111), (521.976626056, 158.515673889), 3.125, -4.0625, 1 -(553.684973979, 184.199979984), (521.315026021, 159.300020016), 3.125, -4.0625, 1 -(553.08842927, 185.034368669), (520.66157073, 160.090631331), 3.125, -4.0625, 1 -(552.483748375, 185.86249875), (520.016251625, 160.88750125), 3.125, -4.0625, 1 -(551.870937398, 186.684374922), (519.379062602, 161.690625078), 3.125, -4.0625, 1 -(551.25, 187.5), (518.75, 162.5), 3.125, -4.0625, 1 -(550.620937398, 188.309374922), (518.129062602, 163.315625078), 3.125, -4.0625, 1 -(549.983748375, 189.11249875), (517.516251625, 164.13750125), 3.125, -4.0625, 1 -(549.33842927, 189.909368669), (516.91157073, 164.965631331), 3.125, -4.0625, 1 -(548.684973979, 190.699979984), (516.315026021, 165.800020016), 3.125, -4.0625, 1 -(548.023373944, 191.484326111), (515.726626056, 166.640673889), 3.125, -4.0625, 1 -(547.353618138, 192.262398567), (515.146381862, 167.487601433), 3.125, -4.0625, 1 -(546.675693049, 193.034186961), (514.574306951, 168.340813039), 3.125, -4.0625, 1 -(545.989582663, 193.799678972), (514.010417337, 169.200321028), 3.125, -4.0625, 1 -(545.295268436, 194.558860335), (513.454731564, 170.066139665), 3.125, -4.0625, 1 -(544.592729265, 195.311714819), (512.907270735, 170.938285181), 3.125, -4.0625, 1 -(543.881941459, 196.058224199), (512.368058541, 171.816775801), 3.125, -4.0625, 1 -(543.162878699, 196.79836823), (511.837121301, 172.70163177), 3.125, -4.0625, 1 -(542.435512, 197.532124616), (511.314488, 173.592875384), 3.125, -4.0625, 1 -(541.699809664, 198.259468972), (510.800190336, 174.490531028), 3.125, -4.0625, 1 -(540.955737229, 198.980374792), (510.294262771, 175.394625208), 3.125, -4.0625, 1 -(540.203257415, 199.694813396), (509.796742585, 176.305186604), 3.125, -4.0625, 1 -(539.442330065, 200.402753896), (509.307669935, 177.222246104), 3.125, -4.0625, 1 -(538.672912078, 201.104163137), (508.827087922, 178.145836863), 3.125, -4.0625, 1 -(537.894957338, 201.799005645), (508.355042662, 179.075994355), 3.125, -4.0625, 1 -(537.10841664, 202.48724357), (507.89158336, 180.01275643), 3.125, -4.0625, 1 -(536.313237605, 203.168836619), (507.436762395, 180.956163381), 3.125, -4.0625, 1 -(535.509364589, 203.843741991), (506.990635411, 181.906258009), 3.125, -4.0625, 1 -(534.696738591, 204.511914301), (506.553261409, 182.863085699), 3.125, -4.0625, 1 -(533.875297147, 205.173305498), (506.124702853, 183.826694502), 3.125, -4.0625, 1 -(533.04497422, 205.827864784), (505.70502578, 184.797135216), 3.125, -4.0625, 1 -(532.20570008, 206.475538523), (505.29429992, 185.774461477), 3.125, -4.0625, 1 -(531.357401176, 207.116270135), (504.892598824, 186.758729865), 3.125, -4.0625, 1 -(530.5, 207.75), (504.5, 187.75), 3.125, -4.0625, 1 -(529.633414939, 208.376665337), (504.116585061, 188.748334663), 3.125, -4.0625, 1 -(528.757560115, 208.996200089), (503.742439885, 189.753799911), 3.125, -4.0625, 1 -(527.872345221, 209.608534786), (503.377654779, 190.766465214), 3.125, -4.0625, 1 -(526.977675335, 210.213596412), (503.022324665, 191.786403588), 3.125, -4.0625, 1 -(526.073450726, 210.811308251), (502.676549274, 192.813691749), 3.125, -4.0625, 1 -(525.159566646, 211.401589728), (502.340433354, 193.848410272), 3.125, -4.0625, 1 -(524.235913105, 211.984356235), (502.014086895, 194.890643765), 3.125, -4.0625, 1 -(523.302374633, 212.559518948), (501.697625367, 195.940481052), 3.125, -4.0625, 1 -(522.358830015, 213.126984627), (501.391169985, 196.998015373), 3.125, -4.0625, 1 -(521.405152019, 213.686655399), (501.094847981, 198.063344601), 3.125, -4.0625, 1 -(520.441207093, 214.238428533), (500.808792907, 199.136571467), 3.125, -4.0625, 1 -(519.466855043, 214.782196187), (500.533144957, 200.217803813), 3.125, -4.0625, 1 -(518.481948687, 215.317845144), (500.268051313, 201.307154856), 3.125, -4.0625, 1 -(517.486333479, 215.845256523), (500.013666521, 202.404743477), 3.125, -4.0625, 1 -(516.479847105, 216.364305465), (499.770152895, 203.510694535), 3.125, -4.0625, 1 -(515.462319042, 216.874860802), (499.537680958, 204.625139198), 3.125, -4.0625, 1 -(514.433570092, 217.376784686), (499.316429908, 205.748215314), 3.125, -4.0625, 1 -(513.393411861, 217.869932201), (499.106588139, 206.880067799), 3.125, -4.0625, 1 -(512.341646211, 218.354150932), (498.908353789, 208.020849068), 3.125, -4.0625, 1 -(511.278064648, 218.829280499), (498.721935352, 209.170719501), 3.125, -4.0625, 1 -(510.202447672, 219.295152055), (498.547552328, 210.329847945), 3.125, -4.0625, 1 -(509.114564057, 219.751587737), (498.385435943, 211.498412263), 3.125, -4.0625, 1 -(508.014170075, 220.198400058), (498.235829925, 212.676599942), 3.125, -4.0625, 1 -(506.901008638, 220.63539126), (498.098991362, 213.86460874), 3.125, -4.0625, 1 -(505.774808372, 221.062352594), (497.975191628, 215.062647406), 3.125, -4.0625, 1 -(504.635282591, 221.479063531), (497.864717409, 216.270936469), 3.125, -4.0625, 1 -(503.482128172, 221.885290902), (497.767871828, 217.489709098), 3.125, -4.0625, 1 -(502.315024326, 222.280787943), (497.684975674, 218.719212057), 3.125, -4.0625, 1 -(501.13363123, 222.665293254), (497.61636877, 219.959706746), 3.125, -4.0625, 1 -(499.937588527, 223.038529636), (497.562411473, 221.211470364), 3.125, -4.0625, 1 -(498.726513654, 223.400202811), (497.523486346, 222.474797189), 3.125, -4.0625, 1 diff --git a/reducer_bench/quad_tree/input/beaver.in b/reducer_bench/quad_tree/input/beaver.in deleted file mode 100644 index 7b9c7949..00000000 --- a/reducer_bench/quad_tree/input/beaver.in +++ /dev/null @@ -1,294 +0,0 @@ -293 -(276, 206), (293, 219), -0.19221, -0.055276, 0 -(297, 226), (272, 237), -0.195101, -0.043993, 0 -(264, 239), (270, 212), -0.194817, -0.045236, 0 -(280, 200), (300, 189), -0.188575, -0.06663, 0 -(305, 182), (318, 166), -0.182274, -0.082317, 0 -(328, 164), (395, 142), -0.168307, -0.10804, 0 -(407, 141), (481, 141), -0.135271, -0.147315, 0 -(490, 143), (531, 146), -0.091263, -0.177963, 0 -(541, 146), (641, 142), 0.001282, -0.199996, 0 -(660, 136), (768, 175), 0.129986, -0.151999, 0 -(776, 182), (814, 214), 0.17906, -0.089093, 0 -(824, 221), (852, 261), 0.19457, -0.046289, 0 -(858, 271), (879, 334), 0.199995, 0.001439, 0 -(881, 342), (894, 405), 0.194219, 0.047737, 0 -(896, 415), (896, 484), 0.179816, 0.087557, 0 -(897, 495), (885, 534), 0.163002, 0.115889, 0 -(872, 542), (830, 570), 0.142782, 0.140047, 0 -(819, 574), (737, 580), 0.112315, 0.165485, 0 -(726, 578), (662, 543), 0.074278, 0.185695, 0 -(654, 538), (627, 475), 0.047174, 0.194357, 0 -(631, 458), (641, 430), 0.060859, 0.190516, 0 -(647, 406), (679, 365), 0.130305, 0.151725, 0 -(695, 358), (738, 349), 0.184355, 0.077546, 0 -(755, 364), (741, 359), 0.186578, 0.072033, 0 -(727, 357), (680, 375), 0.1727, 0.100869, 0 -(673, 387), (661, 402), 0.126737, 0.154718, 0 -(657, 411), (642, 445), 0.083722, 0.181633, 0 -(641, 464), (642, 486), 0.055958, 0.192012, 0 -(647, 501), (663, 530), 0.057878, 0.191442, 0 -(676, 541), (698, 552), 0.073364, 0.186058, 0 -(709, 560), (735, 567), 0.089714, 0.178749, 0 -(748, 569), (785, 564), 0.110361, 0.166795, 0 -(801, 563), (841, 546), 0.134564, 0.147962, 0 -(857, 525), (880, 499), 0.159034, 0.121278, 0 -(884, 481), (879, 428), 0.176772, 0.09355, 0 -(878, 404), (870, 361), 0.192151, 0.05548, 0 -(861, 329), (849, 301), 0.19968, 0.011303, 0 -(855, 287), (833, 255), 0.198709, -0.022687, 0 -(824, 241), (796, 230), 0.191804, -0.056669, 0 -(835, 278), (809, 245), 0.197233, -0.033155, 0 -(806, 222), (758, 189), 0.179257, -0.088695, 0 -(778, 220), (726, 185), 0.171125, -0.10352, 0 -(797, 254), (744, 215), 0.187775, -0.068851, 0 -(738, 180), (684, 160), 0.136263, -0.146398, 0 -(662, 149), (620, 153), 0.064767, -0.189223, 0 -(442, 181), (456, 165), -0.148606, -0.133851, 0 -(467, 173), (475, 191), -0.142017, -0.140823, 0 -(469, 201), (455, 213), -0.161802, -0.117559, 0 -(472, 222), (477, 241), -0.17189, -0.102245, 0 -(477, 261), (467, 278), -0.193436, -0.050818, 0 -(451, 296), (425, 309), -0.199983, 0.002631, 0 -(401, 314), (377, 318), -0.199369, 0.01587, 0 -(350, 308), (335, 296), -0.199993, 0.001613, 0 -(357, 310), (368, 314), -0.199724, 0.010512, 0 -(410, 318), (420, 315), -0.199169, 0.01821, 0 -(458, 295), (462, 283), -0.199288, -0.016863, 0 -(297, 279), (324, 273), -0.199269, -0.01708, 0 -(332, 273), (335, 286), -0.199336, -0.016288, 0 -(318, 281), (322, 293), -0.199769, -0.009618, 0 -(314, 298), (306, 284), -0.199897, -0.006425, 0 -(301, 289), (307, 299), -0.199956, -0.004195, 0 -(291, 275), (276, 270), -0.199173, -0.018166, 0 -(274, 263), (269, 249), -0.198124, -0.027327, 0 -(577, 331), (597, 360), -0.013304, 0.199557, 0 -(598, 373), (605, 402), 0.025088, 0.19842, 0 -(603, 413), (592, 429), 0.011551, 0.199666, 0 -(582, 441), (545, 457), -0.035661, 0.196795, 0 -(528, 460), (490, 464), -0.089443, 0.178885, 0 -(477, 462), (425, 443), -0.134969, 0.147592, 0 -(409, 438), (369, 406), -0.170971, 0.103773, 0 -(358, 396), (341, 382), -0.187615, 0.069285, 0 -(318, 325), (299, 330), -0.19909, 0.019062, 0 -(314, 349), (303, 335), -0.197818, 0.029462, 0 -(292, 334), (284, 344), -0.198353, 0.025615, 0 -(289, 353), (300, 361), -0.196392, 0.037819, 0 -(288, 367), (313, 363), -0.195158, 0.043742, 0 -(292, 379), (309, 372), -0.193629, 0.050077, 0 -(315, 382), (323, 390), -0.190631, 0.060496, 0 -(324, 366), (346, 365), -0.193803, 0.049401, 0 -(329, 351), (344, 347), -0.196379, 0.037884, 0 -(350, 351), (377, 359), -0.194376, 0.047095, 0 -(386, 355), (396, 347), -0.193739, 0.049652, 0 -(393, 340), (383, 328), -0.197226, 0.033196, 0 -(323, 321), (338, 337), -0.198767, 0.02217, 0 -(325, 401), (350, 400), -0.185998, 0.073517, 0 -(899, 507), (908, 527), 0.164363, 0.113951, 0 -(912, 534), (934, 544), 0.162483, 0.116617, 0 -(944, 544), (978, 546), 0.166893, 0.110212, 0 -(993, 550), (1062, 581), 0.171013, 0.103704, 0 -(1081, 588), (1155, 632), 0.172471, 0.101261, 0 -(1156, 642), (1152, 663), 0.169667, 0.105892, 0 -(1140, 663), (1029, 680), 0.159922, 0.120104, 0 -(1014, 682), (990, 684), 0.146483, 0.136172, 0 -(981, 680), (885, 631), 0.13897, 0.143831, 0 -(874, 615), (843, 580), 0.133986, 0.148485, 0 -(857, 576), (889, 559), 0.145474, 0.137249, 0 -(881, 573), (905, 563), 0.149809, 0.132504, 0 -(911, 551), (916, 578), 0.154856, 0.126569, 0 -(903, 577), (907, 599), 0.147606, 0.134954, 0 -(893, 585), (898, 618), 0.142352, 0.140485, 0 -(861, 587), (880, 583), 0.140164, 0.142667, 0 -(871, 599), (888, 596), 0.139478, 0.143339, 0 -(903, 610), (932, 601), 0.146256, 0.136416, 0 -(915, 591), (947, 582), 0.153238, 0.128522, 0 -(929, 573), (964, 571), 0.158922, 0.121424, 0 -(958, 585), (960, 618), 0.154978, 0.126419, 0 -(946, 598), (946, 638), 0.149158, 0.133236, 0 -(932, 618), (932, 649), 0.143294, 0.139523, 0 -(908, 632), (929, 630), 0.140776, 0.142064, 0 -(917, 618), (935, 612), 0.145907, 0.136788, 0 -(922, 561), (961, 554), 0.161369, 0.118153, 0 -(976, 565), (977, 598), 0.161693, 0.117709, 0 -(969, 610), (1000, 604), 0.157763, 0.122927, 0 -(985, 618), (990, 647), 0.153422, 0.128303, 0 -(999, 635), (1030, 629), 0.15747, 0.123302, 0 -(1003, 616), (1044, 614), 0.161731, 0.117657, 0 -(1040, 629), (1041, 653), 0.159403, 0.120792, 0 -(1026, 642), (1027, 673), 0.154744, 0.126706, 0 -(992, 665), (1016, 658), 0.150741, 0.131443, 0 -(971, 623), (973, 641), 0.150955, 0.131197, 0 -(955, 633), (956, 650), 0.146144, 0.136535, 0 -(954, 657), (983, 657), 0.145403, 0.137325, 0 -(994, 592), (1014, 590), 0.163623, 0.115011, 0 -(989, 575), (1005, 578), 0.165529, 0.112251, 0 -(1020, 570), (1024, 597), 0.167298, 0.109596, 0 -(1037, 592), (1059, 593), 0.168641, 0.107518, 0 -(1058, 609), (1060, 630), 0.165372, 0.112481, 0 -(1051, 644), (1085, 642), 0.162494, 0.116601, 0 -(1073, 625), (1097, 621), 0.167495, 0.109295, 0 -(1069, 608), (1093, 608), 0.169425, 0.106279, 0 -(1048, 666), (1077, 659), 0.1587, 0.121715, 0 -(1098, 634), (1120, 631), 0.168478, 0.107774, 0 -(1131, 623), (1133, 650), 0.169986, 0.105379, 0 -(1094, 652), (1122, 651), 0.165569, 0.112191, 0 -(1103, 607), (1107, 624), 0.170615, 0.104357, 0 -(1143, 633), (1143, 652), 0.170099, 0.105197, 0 -(351, 190), (341, 198), -0.183438, -0.07969, 0 -(350, 202), (360, 209), -0.185422, -0.074958, 0 -(368, 203), (364, 192), -0.18171, -0.083554, 0 -(347, 227), (394, 233), -0.190585, -0.060641, 0 -(349, 238), (394, 259), -0.19459, -0.046204, 0 -(344, 250), (378, 263), -0.196407, -0.037738, 0 -(343, 261), (355, 272), -0.198039, -0.027939, 0 -(283, 248), (291, 250), -0.197226, -0.033196, 0 -(286, 257), (300, 254), -0.197743, -0.029961, 0 -(299, 266), (309, 259), -0.198258, -0.026342, 0 -(495, 154), (534, 159), -0.093352, -0.176877, 0 -(544, 156), (593, 155), -0.030001, -0.197737, 0 -(485, 165), (532, 177), -0.10729, -0.168786, 0 -(491, 180), (536, 191), -0.111273, -0.166187, 0 -(500, 206), (549, 219), -0.12, -0.16, 0 -(557, 173), (577, 178), -0.036192, -0.196698, 0 -(549, 193), (585, 203), -0.043993, -0.195101, 0 -(615, 176), (647, 193), 0.066649, -0.188568, 0 -(615, 223), (683, 267), 0.146293, -0.136375, 0 -(581, 237), (607, 259), 0.015339, -0.199411, 0 -(520, 259), (550, 276), -0.171499, -0.102899, 0 -(549, 245), (608, 279), -0.060226, -0.190717, 0 -(519, 291), (533, 304), -0.199781, -0.009365, 0 -(535, 332), (549, 362), -0.142902, 0.139925, 0 -(522, 359), (527, 402), -0.127277, 0.154275, 0 -(497, 379), (482, 411), -0.145682, 0.137028, 0 -(460, 399), (421, 401), -0.16641, 0.11094, 0 -(362, 368), (396, 388), -0.187593, 0.069347, 0 -(406, 388), (451, 389), -0.175745, 0.095466, 0 -(460, 383), (468, 361), -0.173649, 0.099228, 0 -(458, 344), (417, 342), -0.19254, 0.054113, 0 -(431, 367), (458, 310), -0.193552, 0.050376, 0 -(472, 334), (483, 351), -0.18747, 0.069679, 0 -(482, 304), (491, 330), -0.19738, 0.032264, 0 -(501, 319), (517, 343), -0.186788, 0.071487, 0 -(543, 382), (541, 409), -0.090194, 0.178508, 0 -(503, 413), (483, 435), -0.123227, 0.157528, 0 -(456, 426), (418, 418), -0.156373, 0.12469, 0 -(381, 399), (401, 401), -0.178705, 0.089802, 0 -(490, 442), (521, 428), -0.106563, 0.169247, 0 -(526, 443), (559, 409), -0.071199, 0.186898, 0 -(569, 360), (577, 399), -0.042075, 0.195524, 0 -(554, 336), (549, 287), -0.19249, 0.054292, 0 -(498, 226), (533, 247), -0.152137, -0.129824, 0 -(495, 264), (503, 291), -0.193903, -0.049008, 0 -(565, 275), (611, 310), -0.048507, -0.194029, 0 -(597, 322), (611, 347), 0.07615, 0.184936, 0 -(620, 367), (622, 391), 0.073058, 0.186179, 0 -(532, 469), (552, 474), -0.054051, 0.192558, 0 -(563, 480), (579, 482), -0.02088, 0.198907, 0 -(589, 491), (604, 495), 0.006215, 0.199903, 0 -(614, 501), (625, 512), 0.02788, 0.198047, 0 -(636, 519), (644, 529), 0.043571, 0.195196, 0 -(573, 459), (591, 449), -0.010376, 0.199731, 0 -(590, 467), (607, 441), 0.010376, 0.199731, 0 -(616, 482), (609, 461), 0.025521, 0.198365, 0 -(617, 445), (629, 404), 0.051436, 0.193273, 0 -(618, 412), (635, 385), 0.068963, 0.187734, 0 -(632, 355), (629, 326), 0.141421, 0.141421, 0 -(652, 359), (645, 340), 0.152777, 0.12907, 0 -(668, 340), (657, 319), 0.185517, 0.074722, 0 -(688, 335), (658, 294), 0.197214, 0.033265, 0 -(629, 301), (616, 276), 0.187266, -0.070225, 0 -(624, 255), (646, 275), 0.15787, -0.122788, 0 -(636, 252), (670, 279), 0.174831, -0.097129, 0 -(603, 186), (647, 216), 0.066664, -0.188563, 0 -(565, 214), (601, 230), -0.017877, -0.199199, 0 -(642, 172), (674, 176), 0.094987, -0.176004, 0 -(663, 191), (715, 203), 0.138594, -0.144194, 0 -(693, 179), (730, 201), 0.147988, -0.134535, 0 -(672, 211), (706, 221), 0.152502, -0.129395, 0 -(727, 222), (758, 251), 0.184327, -0.077611, 0 -(664, 231), (696, 242), 0.162991, -0.115905, 0 -(712, 239), (737, 261), 0.187381, -0.069918, 0 -(768, 249), (786, 277), 0.196196, -0.03882, 0 -(698, 253), (720, 274), 0.190981, -0.059381, 0 -(689, 295), (713, 309), 0.199968, 0.003603, 0 -(707, 279), (734, 299), 0.199288, -0.016863, 0 -(734, 277), (752, 297), 0.199282, -0.016932, 0 -(760, 285), (786, 331), 0.199809, 0.008735, 0 -(806, 268), (824, 304), 0.199614, -0.01242, 0 -(837, 320), (844, 357), 0.197729, 0.030055, 0 -(850, 384), (856, 419), 0.186706, 0.071701, 0 -(856, 458), (853, 491), 0.166992, 0.110063, 0 -(834, 524), (804, 539), 0.140805, 0.142035, 0 -(776, 550), (733, 543), 0.11094, 0.16641, 0 -(694, 532), (677, 510), 0.078984, 0.183743, 0 -(664, 480), (661, 448), 0.080398, 0.183129, 0 -(679, 414), (694, 391), 0.137073, 0.14564, 0 -(723, 377), (750, 377), 0.176905, 0.093299, 0 -(708, 405), (686, 437), 0.132488, 0.149823, 0 -(679, 472), (689, 502), 0.089825, 0.178694, 0 -(709, 516), (751, 513), 0.109492, 0.167366, 0 -(761, 530), (813, 501), 0.135114, 0.147459, 0 -(830, 468), (830, 438), 0.168645, 0.107511, 0 -(830, 402), (826, 361), 0.189335, 0.064438, 0 -(816, 329), (805, 303), 0.199473, 0.014507, 0 -(747, 316), (772, 358), 0.195372, 0.042774, 0 -(712, 323), (726, 338), 0.194802, 0.045303, 0 -(792, 364), (801, 394), 0.186739, 0.071614, 0 -(801, 434), (802, 457), 0.164831, 0.113273, 0 -(785, 481), (757, 487), 0.140254, 0.142579, 0 -(719, 484), (710, 462), 0.116514, 0.162556, 0 -(709, 430), (733, 400), 0.150302, 0.131944, 0 -(782, 397), (787, 428), 0.173207, 0.099996, 0 -(771, 456), (744, 464), 0.144416, 0.138362, 0 -(730, 444), (743, 412), 0.150388, 0.131847, 0 -(763, 402), (766, 427), 0.167292, 0.109605, 0 -(752, 435), (746, 427), 0.154358, 0.127175, 0 -(702, 490), (692, 458), 0.104765, 0.170365, 0 -(799, 314), (814, 373), 0.196151, 0.039049, 0 -(817, 447), (802, 485), 0.159387, 0.120814, 0 -(766, 503), (737, 491), 0.126562, 0.154861, 0 -(351, 161), (370, 155), -0.170179, -0.105067, 0 -(377, 170), (412, 161), -0.16471, -0.113448, 0 -(414, 180), (421, 150), -0.157674, -0.12304, 0 -(438, 150), (392, 207), -0.164066, -0.114378, 0 -(407, 218), (432, 220), -0.180748, -0.085617, 0 -(413, 235), (432, 239), -0.187266, -0.070225, 0 -(417, 275), (443, 256), -0.19538, -0.042739, 0 -(397, 274), (409, 254), -0.196394, -0.037808, 0 -(357, 289), (379, 275), -0.199346, -0.016163, 0 -(374, 297), (396, 290), -0.199884, -0.006825, 0 -(392, 301), (425, 286), -0.199852, -0.007687, 0 -(438, 275), (456, 255), -0.194266, -0.047548, 0 -(453, 231), (446, 211), -0.17448, -0.097758, 0 -(450, 200), (455, 184), -0.157501, -0.123262, 0 -(424, 203), (430, 172), -0.164366, -0.113947, 0 -(358, 169), (335, 174), -0.17681, -0.093478, 0 -(322, 192), (307, 204), -0.187599, -0.06933, 0 -(300, 239), (325, 248), -0.195924, -0.040171, 0 -(317, 227), (335, 224), -0.192387, -0.054655, 0 -(317, 208), (336, 211), -0.189082, -0.065176, 0 -(383, 188), (400, 175), -0.171651, -0.102645, 0 -(375, 219), (380, 204), -0.184538, -0.077108, 0 -(359, 178), (343, 182), -0.178736, -0.089742, 0 -(393, 221), (358, 221), -0.187728, -0.068979, 0 -(76, 378), (203, 384), -0.19685, 0.035354, 0 -(111, 474), (249, 471), -0.184429, 0.07737, 0 -(245, 392), (310, 399), -0.191379, 0.058086, 0 -(301, 484), (393, 517), -0.154423, 0.127097, 0 -(402, 528), (481, 546), -0.106449, 0.169318, 0 -(516, 565), (573, 576), -0.03359, 0.197159, 0 -(586, 575), (689, 579), 0.033457, 0.197182, 0 -(492, 556), (505, 560), -0.067175, 0.188381, 0 -(142, 431), (166, 419), -0.192255, 0.055119, 0 -(181, 423), (201, 432), -0.190579, 0.06066, 0 -(252, 444), (276, 431), -0.18438, 0.077485, 0 -(348, 457), (360, 471), -0.164238, 0.114131, 0 -(366, 476), (381, 489), -0.153238, 0.128522, 0 -(451, 474), (474, 480), -0.117198, 0.162063, 0 -(481, 485), (493, 498), -0.09493, 0.176035, 0 -(516, 518), (554, 524), -0.0483, 0.19408, 0 -(563, 526), (579, 534), -0.016466, 0.199321, 0 -(591, 541), (605, 554), 0.006474, 0.199895, 0 -(441, 472), (401, 459), -0.143105, 0.139718, 0 -(313, 268), (484, 154), -0.181453, -0.084111, 0 diff --git a/reducer_bench/quad_tree/input/box.in b/reducer_bench/quad_tree/input/box.in deleted file mode 100644 index e4112aea..00000000 --- a/reducer_bench/quad_tree/input/box.in +++ /dev/null @@ -1,401 +0,0 @@ -400 -(301.000000, 299.500000), (301.000000, 300.500000), 5.000000, 0.000000, 1 -(299.000000, 299.500000), (299.000000, 300.500000), -5.000000, 0.000000, 1 -(300.500000, 299.000000), (299.500000, 299.000000), 0.000000, -5.000000, 0 -(300.500000, 301.000000), (299.500000, 301.000000), 0.000000, 5.000000, 0 -(302.000000, 299.000000), (302.000000, 301.000000), 5.000000, 0.000000, 1 -(298.000000, 299.000000), (298.000000, 301.000000), -5.000000, 0.000000, 1 -(301.000000, 298.000000), (299.000000, 298.000000), 0.000000, -5.000000, 0 -(301.000000, 302.000000), (299.000000, 302.000000), 0.000000, 5.000000, 0 -(303.000000, 298.500000), (303.000000, 301.500000), 5.000000, 0.000000, 1 -(297.000000, 298.500000), (297.000000, 301.500000), -5.000000, 0.000000, 1 -(301.500000, 297.000000), (298.500000, 297.000000), 0.000000, -5.000000, 0 -(301.500000, 303.000000), (298.500000, 303.000000), 0.000000, 5.000000, 0 -(304.000000, 298.000000), (304.000000, 302.000000), 5.000000, 0.000000, 1 -(296.000000, 298.000000), (296.000000, 302.000000), -5.000000, 0.000000, 1 -(302.000000, 296.000000), (298.000000, 296.000000), 0.000000, -5.000000, 0 -(302.000000, 304.000000), (298.000000, 304.000000), 0.000000, 5.000000, 0 -(305.000000, 297.500000), (305.000000, 302.500000), 5.000000, 0.000000, 1 -(295.000000, 297.500000), (295.000000, 302.500000), -5.000000, 0.000000, 1 -(302.500000, 295.000000), (297.500000, 295.000000), 0.000000, -5.000000, 0 -(302.500000, 305.000000), (297.500000, 305.000000), 0.000000, 5.000000, 0 -(306.000000, 297.000000), (306.000000, 303.000000), 5.000000, 0.000000, 1 -(294.000000, 297.000000), (294.000000, 303.000000), -5.000000, 0.000000, 1 -(303.000000, 294.000000), (297.000000, 294.000000), 0.000000, -5.000000, 0 -(303.000000, 306.000000), (297.000000, 306.000000), 0.000000, 5.000000, 0 -(307.000000, 296.500000), (307.000000, 303.500000), 5.000000, 0.000000, 1 -(293.000000, 296.500000), (293.000000, 303.500000), -5.000000, 0.000000, 1 -(303.500000, 293.000000), (296.500000, 293.000000), 0.000000, -5.000000, 0 -(303.500000, 307.000000), (296.500000, 307.000000), 0.000000, 5.000000, 0 -(308.000000, 296.000000), (308.000000, 304.000000), 5.000000, 0.000000, 1 -(292.000000, 296.000000), (292.000000, 304.000000), -5.000000, 0.000000, 1 -(304.000000, 292.000000), (296.000000, 292.000000), 0.000000, -5.000000, 0 -(304.000000, 308.000000), (296.000000, 308.000000), 0.000000, 5.000000, 0 -(309.000000, 295.500000), (309.000000, 304.500000), 5.000000, 0.000000, 1 -(291.000000, 295.500000), (291.000000, 304.500000), -5.000000, 0.000000, 1 -(304.500000, 291.000000), (295.500000, 291.000000), 0.000000, -5.000000, 0 -(304.500000, 309.000000), (295.500000, 309.000000), 0.000000, 5.000000, 0 -(310.000000, 295.000000), (310.000000, 305.000000), 5.000000, 0.000000, 1 -(290.000000, 295.000000), (290.000000, 305.000000), -5.000000, 0.000000, 1 -(305.000000, 290.000000), (295.000000, 290.000000), 0.000000, -5.000000, 0 -(305.000000, 310.000000), (295.000000, 310.000000), 0.000000, 5.000000, 0 -(311.000000, 294.500000), (311.000000, 305.500000), 5.000000, 0.000000, 1 -(289.000000, 294.500000), (289.000000, 305.500000), -5.000000, 0.000000, 1 -(305.500000, 289.000000), (294.500000, 289.000000), 0.000000, -5.000000, 0 -(305.500000, 311.000000), (294.500000, 311.000000), 0.000000, 5.000000, 0 -(312.000000, 294.000000), (312.000000, 306.000000), 5.000000, 0.000000, 1 -(288.000000, 294.000000), (288.000000, 306.000000), -5.000000, 0.000000, 1 -(306.000000, 288.000000), (294.000000, 288.000000), 0.000000, -5.000000, 0 -(306.000000, 312.000000), (294.000000, 312.000000), 0.000000, 5.000000, 0 -(313.000000, 293.500000), (313.000000, 306.500000), 5.000000, 0.000000, 1 -(287.000000, 293.500000), (287.000000, 306.500000), -5.000000, 0.000000, 1 -(306.500000, 287.000000), (293.500000, 287.000000), 0.000000, -5.000000, 0 -(306.500000, 313.000000), (293.500000, 313.000000), 0.000000, 5.000000, 0 -(314.000000, 293.000000), (314.000000, 307.000000), 5.000000, 0.000000, 1 -(286.000000, 293.000000), (286.000000, 307.000000), -5.000000, 0.000000, 1 -(307.000000, 286.000000), (293.000000, 286.000000), 0.000000, -5.000000, 0 -(307.000000, 314.000000), (293.000000, 314.000000), 0.000000, 5.000000, 0 -(315.000000, 292.500000), (315.000000, 307.500000), 5.000000, 0.000000, 1 -(285.000000, 292.500000), (285.000000, 307.500000), -5.000000, 0.000000, 1 -(307.500000, 285.000000), (292.500000, 285.000000), 0.000000, -5.000000, 0 -(307.500000, 315.000000), (292.500000, 315.000000), 0.000000, 5.000000, 0 -(316.000000, 292.000000), (316.000000, 308.000000), 5.000000, 0.000000, 1 -(284.000000, 292.000000), (284.000000, 308.000000), -5.000000, 0.000000, 1 -(308.000000, 284.000000), (292.000000, 284.000000), 0.000000, -5.000000, 0 -(308.000000, 316.000000), (292.000000, 316.000000), 0.000000, 5.000000, 0 -(317.000000, 291.500000), (317.000000, 308.500000), 5.000000, 0.000000, 1 -(283.000000, 291.500000), (283.000000, 308.500000), -5.000000, 0.000000, 1 -(308.500000, 283.000000), (291.500000, 283.000000), 0.000000, -5.000000, 0 -(308.500000, 317.000000), (291.500000, 317.000000), 0.000000, 5.000000, 0 -(318.000000, 291.000000), (318.000000, 309.000000), 5.000000, 0.000000, 1 -(282.000000, 291.000000), (282.000000, 309.000000), -5.000000, 0.000000, 1 -(309.000000, 282.000000), (291.000000, 282.000000), 0.000000, -5.000000, 0 -(309.000000, 318.000000), (291.000000, 318.000000), 0.000000, 5.000000, 0 -(319.000000, 290.500000), (319.000000, 309.500000), 5.000000, 0.000000, 1 -(281.000000, 290.500000), (281.000000, 309.500000), -5.000000, 0.000000, 1 -(309.500000, 281.000000), (290.500000, 281.000000), 0.000000, -5.000000, 0 -(309.500000, 319.000000), (290.500000, 319.000000), 0.000000, 5.000000, 0 -(320.000000, 290.000000), (320.000000, 310.000000), 5.000000, 0.000000, 1 -(280.000000, 290.000000), (280.000000, 310.000000), -5.000000, 0.000000, 1 -(310.000000, 280.000000), (290.000000, 280.000000), 0.000000, -5.000000, 0 -(310.000000, 320.000000), (290.000000, 320.000000), 0.000000, 5.000000, 0 -(321.000000, 289.500000), (321.000000, 310.500000), 5.000000, 0.000000, 1 -(279.000000, 289.500000), (279.000000, 310.500000), -5.000000, 0.000000, 1 -(310.500000, 279.000000), (289.500000, 279.000000), 0.000000, -5.000000, 0 -(310.500000, 321.000000), (289.500000, 321.000000), 0.000000, 5.000000, 0 -(322.000000, 289.000000), (322.000000, 311.000000), 5.000000, 0.000000, 1 -(278.000000, 289.000000), (278.000000, 311.000000), -5.000000, 0.000000, 1 -(311.000000, 278.000000), (289.000000, 278.000000), 0.000000, -5.000000, 0 -(311.000000, 322.000000), (289.000000, 322.000000), 0.000000, 5.000000, 0 -(323.000000, 288.500000), (323.000000, 311.500000), 5.000000, 0.000000, 1 -(277.000000, 288.500000), (277.000000, 311.500000), -5.000000, 0.000000, 1 -(311.500000, 277.000000), (288.500000, 277.000000), 0.000000, -5.000000, 0 -(311.500000, 323.000000), (288.500000, 323.000000), 0.000000, 5.000000, 0 -(324.000000, 288.000000), (324.000000, 312.000000), 5.000000, 0.000000, 1 -(276.000000, 288.000000), (276.000000, 312.000000), -5.000000, 0.000000, 1 -(312.000000, 276.000000), (288.000000, 276.000000), 0.000000, -5.000000, 0 -(312.000000, 324.000000), (288.000000, 324.000000), 0.000000, 5.000000, 0 -(325.000000, 287.500000), (325.000000, 312.500000), 5.000000, 0.000000, 1 -(275.000000, 287.500000), (275.000000, 312.500000), -5.000000, 0.000000, 1 -(312.500000, 275.000000), (287.500000, 275.000000), 0.000000, -5.000000, 0 -(312.500000, 325.000000), (287.500000, 325.000000), 0.000000, 5.000000, 0 -(326.000000, 287.000000), (326.000000, 313.000000), 5.000000, 0.000000, 1 -(274.000000, 287.000000), (274.000000, 313.000000), -5.000000, 0.000000, 1 -(313.000000, 274.000000), (287.000000, 274.000000), 0.000000, -5.000000, 0 -(313.000000, 326.000000), (287.000000, 326.000000), 0.000000, 5.000000, 0 -(327.000000, 286.500000), (327.000000, 313.500000), 5.000000, 0.000000, 1 -(273.000000, 286.500000), (273.000000, 313.500000), -5.000000, 0.000000, 1 -(313.500000, 273.000000), (286.500000, 273.000000), 0.000000, -5.000000, 0 -(313.500000, 327.000000), (286.500000, 327.000000), 0.000000, 5.000000, 0 -(328.000000, 286.000000), (328.000000, 314.000000), 5.000000, 0.000000, 1 -(272.000000, 286.000000), (272.000000, 314.000000), -5.000000, 0.000000, 1 -(314.000000, 272.000000), (286.000000, 272.000000), 0.000000, -5.000000, 0 -(314.000000, 328.000000), (286.000000, 328.000000), 0.000000, 5.000000, 0 -(329.000000, 285.500000), (329.000000, 314.500000), 5.000000, 0.000000, 1 -(271.000000, 285.500000), (271.000000, 314.500000), -5.000000, 0.000000, 1 -(314.500000, 271.000000), (285.500000, 271.000000), 0.000000, -5.000000, 0 -(314.500000, 329.000000), (285.500000, 329.000000), 0.000000, 5.000000, 0 -(330.000000, 285.000000), (330.000000, 315.000000), 5.000000, 0.000000, 1 -(270.000000, 285.000000), (270.000000, 315.000000), -5.000000, 0.000000, 1 -(315.000000, 270.000000), (285.000000, 270.000000), 0.000000, -5.000000, 0 -(315.000000, 330.000000), (285.000000, 330.000000), 0.000000, 5.000000, 0 -(331.000000, 284.500000), (331.000000, 315.500000), 5.000000, 0.000000, 1 -(269.000000, 284.500000), (269.000000, 315.500000), -5.000000, 0.000000, 1 -(315.500000, 269.000000), (284.500000, 269.000000), 0.000000, -5.000000, 0 -(315.500000, 331.000000), (284.500000, 331.000000), 0.000000, 5.000000, 0 -(332.000000, 284.000000), (332.000000, 316.000000), 5.000000, 0.000000, 1 -(268.000000, 284.000000), (268.000000, 316.000000), -5.000000, 0.000000, 1 -(316.000000, 268.000000), (284.000000, 268.000000), 0.000000, -5.000000, 0 -(316.000000, 332.000000), (284.000000, 332.000000), 0.000000, 5.000000, 0 -(333.000000, 283.500000), (333.000000, 316.500000), 5.000000, 0.000000, 1 -(267.000000, 283.500000), (267.000000, 316.500000), -5.000000, 0.000000, 1 -(316.500000, 267.000000), (283.500000, 267.000000), 0.000000, -5.000000, 0 -(316.500000, 333.000000), (283.500000, 333.000000), 0.000000, 5.000000, 0 -(334.000000, 283.000000), (334.000000, 317.000000), 5.000000, 0.000000, 1 -(266.000000, 283.000000), (266.000000, 317.000000), -5.000000, 0.000000, 1 -(317.000000, 266.000000), (283.000000, 266.000000), 0.000000, -5.000000, 0 -(317.000000, 334.000000), (283.000000, 334.000000), 0.000000, 5.000000, 0 -(335.000000, 282.500000), (335.000000, 317.500000), 5.000000, 0.000000, 1 -(265.000000, 282.500000), (265.000000, 317.500000), -5.000000, 0.000000, 1 -(317.500000, 265.000000), (282.500000, 265.000000), 0.000000, -5.000000, 0 -(317.500000, 335.000000), (282.500000, 335.000000), 0.000000, 5.000000, 0 -(336.000000, 282.000000), (336.000000, 318.000000), 5.000000, 0.000000, 1 -(264.000000, 282.000000), (264.000000, 318.000000), -5.000000, 0.000000, 1 -(318.000000, 264.000000), (282.000000, 264.000000), 0.000000, -5.000000, 0 -(318.000000, 336.000000), (282.000000, 336.000000), 0.000000, 5.000000, 0 -(337.000000, 281.500000), (337.000000, 318.500000), 5.000000, 0.000000, 1 -(263.000000, 281.500000), (263.000000, 318.500000), -5.000000, 0.000000, 1 -(318.500000, 263.000000), (281.500000, 263.000000), 0.000000, -5.000000, 0 -(318.500000, 337.000000), (281.500000, 337.000000), 0.000000, 5.000000, 0 -(338.000000, 281.000000), (338.000000, 319.000000), 5.000000, 0.000000, 1 -(262.000000, 281.000000), (262.000000, 319.000000), -5.000000, 0.000000, 1 -(319.000000, 262.000000), (281.000000, 262.000000), 0.000000, -5.000000, 0 -(319.000000, 338.000000), (281.000000, 338.000000), 0.000000, 5.000000, 0 -(339.000000, 280.500000), (339.000000, 319.500000), 5.000000, 0.000000, 1 -(261.000000, 280.500000), (261.000000, 319.500000), -5.000000, 0.000000, 1 -(319.500000, 261.000000), (280.500000, 261.000000), 0.000000, -5.000000, 0 -(319.500000, 339.000000), (280.500000, 339.000000), 0.000000, 5.000000, 0 -(340.000000, 280.000000), (340.000000, 320.000000), 5.000000, 0.000000, 1 -(260.000000, 280.000000), (260.000000, 320.000000), -5.000000, 0.000000, 1 -(320.000000, 260.000000), (280.000000, 260.000000), 0.000000, -5.000000, 0 -(320.000000, 340.000000), (280.000000, 340.000000), 0.000000, 5.000000, 0 -(341.000000, 279.500000), (341.000000, 320.500000), 5.000000, 0.000000, 1 -(259.000000, 279.500000), (259.000000, 320.500000), -5.000000, 0.000000, 1 -(320.500000, 259.000000), (279.500000, 259.000000), 0.000000, -5.000000, 0 -(320.500000, 341.000000), (279.500000, 341.000000), 0.000000, 5.000000, 0 -(342.000000, 279.000000), (342.000000, 321.000000), 5.000000, 0.000000, 1 -(258.000000, 279.000000), (258.000000, 321.000000), -5.000000, 0.000000, 1 -(321.000000, 258.000000), (279.000000, 258.000000), 0.000000, -5.000000, 0 -(321.000000, 342.000000), (279.000000, 342.000000), 0.000000, 5.000000, 0 -(343.000000, 278.500000), (343.000000, 321.500000), 5.000000, 0.000000, 1 -(257.000000, 278.500000), (257.000000, 321.500000), -5.000000, 0.000000, 1 -(321.500000, 257.000000), (278.500000, 257.000000), 0.000000, -5.000000, 0 -(321.500000, 343.000000), (278.500000, 343.000000), 0.000000, 5.000000, 0 -(344.000000, 278.000000), (344.000000, 322.000000), 5.000000, 0.000000, 1 -(256.000000, 278.000000), (256.000000, 322.000000), -5.000000, 0.000000, 1 -(322.000000, 256.000000), (278.000000, 256.000000), 0.000000, -5.000000, 0 -(322.000000, 344.000000), (278.000000, 344.000000), 0.000000, 5.000000, 0 -(345.000000, 277.500000), (345.000000, 322.500000), 5.000000, 0.000000, 1 -(255.000000, 277.500000), (255.000000, 322.500000), -5.000000, 0.000000, 1 -(322.500000, 255.000000), (277.500000, 255.000000), 0.000000, -5.000000, 0 -(322.500000, 345.000000), (277.500000, 345.000000), 0.000000, 5.000000, 0 -(346.000000, 277.000000), (346.000000, 323.000000), 5.000000, 0.000000, 1 -(254.000000, 277.000000), (254.000000, 323.000000), -5.000000, 0.000000, 1 -(323.000000, 254.000000), (277.000000, 254.000000), 0.000000, -5.000000, 0 -(323.000000, 346.000000), (277.000000, 346.000000), 0.000000, 5.000000, 0 -(347.000000, 276.500000), (347.000000, 323.500000), 5.000000, 0.000000, 1 -(253.000000, 276.500000), (253.000000, 323.500000), -5.000000, 0.000000, 1 -(323.500000, 253.000000), (276.500000, 253.000000), 0.000000, -5.000000, 0 -(323.500000, 347.000000), (276.500000, 347.000000), 0.000000, 5.000000, 0 -(348.000000, 276.000000), (348.000000, 324.000000), 5.000000, 0.000000, 1 -(252.000000, 276.000000), (252.000000, 324.000000), -5.000000, 0.000000, 1 -(324.000000, 252.000000), (276.000000, 252.000000), 0.000000, -5.000000, 0 -(324.000000, 348.000000), (276.000000, 348.000000), 0.000000, 5.000000, 0 -(349.000000, 275.500000), (349.000000, 324.500000), 5.000000, 0.000000, 1 -(251.000000, 275.500000), (251.000000, 324.500000), -5.000000, 0.000000, 1 -(324.500000, 251.000000), (275.500000, 251.000000), 0.000000, -5.000000, 0 -(324.500000, 349.000000), (275.500000, 349.000000), 0.000000, 5.000000, 0 -(350.000000, 275.000000), (350.000000, 325.000000), 5.000000, 0.000000, 1 -(250.000000, 275.000000), (250.000000, 325.000000), -5.000000, 0.000000, 1 -(325.000000, 250.000000), (275.000000, 250.000000), 0.000000, -5.000000, 0 -(325.000000, 350.000000), (275.000000, 350.000000), 0.000000, 5.000000, 0 -(351.000000, 274.500000), (351.000000, 325.500000), 5.000000, 0.000000, 1 -(249.000000, 274.500000), (249.000000, 325.500000), -5.000000, 0.000000, 1 -(325.500000, 249.000000), (274.500000, 249.000000), 0.000000, -5.000000, 0 -(325.500000, 351.000000), (274.500000, 351.000000), 0.000000, 5.000000, 0 -(352.000000, 274.000000), (352.000000, 326.000000), 5.000000, 0.000000, 1 -(248.000000, 274.000000), (248.000000, 326.000000), -5.000000, 0.000000, 1 -(326.000000, 248.000000), (274.000000, 248.000000), 0.000000, -5.000000, 0 -(326.000000, 352.000000), (274.000000, 352.000000), 0.000000, 5.000000, 0 -(353.000000, 273.500000), (353.000000, 326.500000), 5.000000, 0.000000, 1 -(247.000000, 273.500000), (247.000000, 326.500000), -5.000000, 0.000000, 1 -(326.500000, 247.000000), (273.500000, 247.000000), 0.000000, -5.000000, 0 -(326.500000, 353.000000), (273.500000, 353.000000), 0.000000, 5.000000, 0 -(354.000000, 273.000000), (354.000000, 327.000000), 5.000000, 0.000000, 1 -(246.000000, 273.000000), (246.000000, 327.000000), -5.000000, 0.000000, 1 -(327.000000, 246.000000), (273.000000, 246.000000), 0.000000, -5.000000, 0 -(327.000000, 354.000000), (273.000000, 354.000000), 0.000000, 5.000000, 0 -(355.000000, 272.500000), (355.000000, 327.500000), 5.000000, 0.000000, 1 -(245.000000, 272.500000), (245.000000, 327.500000), -5.000000, 0.000000, 1 -(327.500000, 245.000000), (272.500000, 245.000000), 0.000000, -5.000000, 0 -(327.500000, 355.000000), (272.500000, 355.000000), 0.000000, 5.000000, 0 -(356.000000, 272.000000), (356.000000, 328.000000), 5.000000, 0.000000, 1 -(244.000000, 272.000000), (244.000000, 328.000000), -5.000000, 0.000000, 1 -(328.000000, 244.000000), (272.000000, 244.000000), 0.000000, -5.000000, 0 -(328.000000, 356.000000), (272.000000, 356.000000), 0.000000, 5.000000, 0 -(357.000000, 271.500000), (357.000000, 328.500000), 5.000000, 0.000000, 1 -(243.000000, 271.500000), (243.000000, 328.500000), -5.000000, 0.000000, 1 -(328.500000, 243.000000), (271.500000, 243.000000), 0.000000, -5.000000, 0 -(328.500000, 357.000000), (271.500000, 357.000000), 0.000000, 5.000000, 0 -(358.000000, 271.000000), (358.000000, 329.000000), 5.000000, 0.000000, 1 -(242.000000, 271.000000), (242.000000, 329.000000), -5.000000, 0.000000, 1 -(329.000000, 242.000000), (271.000000, 242.000000), 0.000000, -5.000000, 0 -(329.000000, 358.000000), (271.000000, 358.000000), 0.000000, 5.000000, 0 -(359.000000, 270.500000), (359.000000, 329.500000), 5.000000, 0.000000, 1 -(241.000000, 270.500000), (241.000000, 329.500000), -5.000000, 0.000000, 1 -(329.500000, 241.000000), (270.500000, 241.000000), 0.000000, -5.000000, 0 -(329.500000, 359.000000), (270.500000, 359.000000), 0.000000, 5.000000, 0 -(360.000000, 270.000000), (360.000000, 330.000000), 5.000000, 0.000000, 1 -(240.000000, 270.000000), (240.000000, 330.000000), -5.000000, 0.000000, 1 -(330.000000, 240.000000), (270.000000, 240.000000), 0.000000, -5.000000, 0 -(330.000000, 360.000000), (270.000000, 360.000000), 0.000000, 5.000000, 0 -(361.000000, 269.500000), (361.000000, 330.500000), 5.000000, 0.000000, 1 -(239.000000, 269.500000), (239.000000, 330.500000), -5.000000, 0.000000, 1 -(330.500000, 239.000000), (269.500000, 239.000000), 0.000000, -5.000000, 0 -(330.500000, 361.000000), (269.500000, 361.000000), 0.000000, 5.000000, 0 -(362.000000, 269.000000), (362.000000, 331.000000), 5.000000, 0.000000, 1 -(238.000000, 269.000000), (238.000000, 331.000000), -5.000000, 0.000000, 1 -(331.000000, 238.000000), (269.000000, 238.000000), 0.000000, -5.000000, 0 -(331.000000, 362.000000), (269.000000, 362.000000), 0.000000, 5.000000, 0 -(363.000000, 268.500000), (363.000000, 331.500000), 5.000000, 0.000000, 1 -(237.000000, 268.500000), (237.000000, 331.500000), -5.000000, 0.000000, 1 -(331.500000, 237.000000), (268.500000, 237.000000), 0.000000, -5.000000, 0 -(331.500000, 363.000000), (268.500000, 363.000000), 0.000000, 5.000000, 0 -(364.000000, 268.000000), (364.000000, 332.000000), 5.000000, 0.000000, 1 -(236.000000, 268.000000), (236.000000, 332.000000), -5.000000, 0.000000, 1 -(332.000000, 236.000000), (268.000000, 236.000000), 0.000000, -5.000000, 0 -(332.000000, 364.000000), (268.000000, 364.000000), 0.000000, 5.000000, 0 -(365.000000, 267.500000), (365.000000, 332.500000), 5.000000, 0.000000, 1 -(235.000000, 267.500000), (235.000000, 332.500000), -5.000000, 0.000000, 1 -(332.500000, 235.000000), (267.500000, 235.000000), 0.000000, -5.000000, 0 -(332.500000, 365.000000), (267.500000, 365.000000), 0.000000, 5.000000, 0 -(366.000000, 267.000000), (366.000000, 333.000000), 5.000000, 0.000000, 1 -(234.000000, 267.000000), (234.000000, 333.000000), -5.000000, 0.000000, 1 -(333.000000, 234.000000), (267.000000, 234.000000), 0.000000, -5.000000, 0 -(333.000000, 366.000000), (267.000000, 366.000000), 0.000000, 5.000000, 0 -(367.000000, 266.500000), (367.000000, 333.500000), 5.000000, 0.000000, 1 -(233.000000, 266.500000), (233.000000, 333.500000), -5.000000, 0.000000, 1 -(333.500000, 233.000000), (266.500000, 233.000000), 0.000000, -5.000000, 0 -(333.500000, 367.000000), (266.500000, 367.000000), 0.000000, 5.000000, 0 -(368.000000, 266.000000), (368.000000, 334.000000), 5.000000, 0.000000, 1 -(232.000000, 266.000000), (232.000000, 334.000000), -5.000000, 0.000000, 1 -(334.000000, 232.000000), (266.000000, 232.000000), 0.000000, -5.000000, 0 -(334.000000, 368.000000), (266.000000, 368.000000), 0.000000, 5.000000, 0 -(369.000000, 265.500000), (369.000000, 334.500000), 5.000000, 0.000000, 1 -(231.000000, 265.500000), (231.000000, 334.500000), -5.000000, 0.000000, 1 -(334.500000, 231.000000), (265.500000, 231.000000), 0.000000, -5.000000, 0 -(334.500000, 369.000000), (265.500000, 369.000000), 0.000000, 5.000000, 0 -(370.000000, 265.000000), (370.000000, 335.000000), 5.000000, 0.000000, 1 -(230.000000, 265.000000), (230.000000, 335.000000), -5.000000, 0.000000, 1 -(335.000000, 230.000000), (265.000000, 230.000000), 0.000000, -5.000000, 0 -(335.000000, 370.000000), (265.000000, 370.000000), 0.000000, 5.000000, 0 -(371.000000, 264.500000), (371.000000, 335.500000), 5.000000, 0.000000, 1 -(229.000000, 264.500000), (229.000000, 335.500000), -5.000000, 0.000000, 1 -(335.500000, 229.000000), (264.500000, 229.000000), 0.000000, -5.000000, 0 -(335.500000, 371.000000), (264.500000, 371.000000), 0.000000, 5.000000, 0 -(372.000000, 264.000000), (372.000000, 336.000000), 5.000000, 0.000000, 1 -(228.000000, 264.000000), (228.000000, 336.000000), -5.000000, 0.000000, 1 -(336.000000, 228.000000), (264.000000, 228.000000), 0.000000, -5.000000, 0 -(336.000000, 372.000000), (264.000000, 372.000000), 0.000000, 5.000000, 0 -(373.000000, 263.500000), (373.000000, 336.500000), 5.000000, 0.000000, 1 -(227.000000, 263.500000), (227.000000, 336.500000), -5.000000, 0.000000, 1 -(336.500000, 227.000000), (263.500000, 227.000000), 0.000000, -5.000000, 0 -(336.500000, 373.000000), (263.500000, 373.000000), 0.000000, 5.000000, 0 -(374.000000, 263.000000), (374.000000, 337.000000), 5.000000, 0.000000, 1 -(226.000000, 263.000000), (226.000000, 337.000000), -5.000000, 0.000000, 1 -(337.000000, 226.000000), (263.000000, 226.000000), 0.000000, -5.000000, 0 -(337.000000, 374.000000), (263.000000, 374.000000), 0.000000, 5.000000, 0 -(375.000000, 262.500000), (375.000000, 337.500000), 5.000000, 0.000000, 1 -(225.000000, 262.500000), (225.000000, 337.500000), -5.000000, 0.000000, 1 -(337.500000, 225.000000), (262.500000, 225.000000), 0.000000, -5.000000, 0 -(337.500000, 375.000000), (262.500000, 375.000000), 0.000000, 5.000000, 0 -(376.000000, 262.000000), (376.000000, 338.000000), 5.000000, 0.000000, 1 -(224.000000, 262.000000), (224.000000, 338.000000), -5.000000, 0.000000, 1 -(338.000000, 224.000000), (262.000000, 224.000000), 0.000000, -5.000000, 0 -(338.000000, 376.000000), (262.000000, 376.000000), 0.000000, 5.000000, 0 -(377.000000, 261.500000), (377.000000, 338.500000), 5.000000, 0.000000, 1 -(223.000000, 261.500000), (223.000000, 338.500000), -5.000000, 0.000000, 1 -(338.500000, 223.000000), (261.500000, 223.000000), 0.000000, -5.000000, 0 -(338.500000, 377.000000), (261.500000, 377.000000), 0.000000, 5.000000, 0 -(378.000000, 261.000000), (378.000000, 339.000000), 5.000000, 0.000000, 1 -(222.000000, 261.000000), (222.000000, 339.000000), -5.000000, 0.000000, 1 -(339.000000, 222.000000), (261.000000, 222.000000), 0.000000, -5.000000, 0 -(339.000000, 378.000000), (261.000000, 378.000000), 0.000000, 5.000000, 0 -(379.000000, 260.500000), (379.000000, 339.500000), 5.000000, 0.000000, 1 -(221.000000, 260.500000), (221.000000, 339.500000), -5.000000, 0.000000, 1 -(339.500000, 221.000000), (260.500000, 221.000000), 0.000000, -5.000000, 0 -(339.500000, 379.000000), (260.500000, 379.000000), 0.000000, 5.000000, 0 -(380.000000, 260.000000), (380.000000, 340.000000), 5.000000, 0.000000, 1 -(220.000000, 260.000000), (220.000000, 340.000000), -5.000000, 0.000000, 1 -(340.000000, 220.000000), (260.000000, 220.000000), 0.000000, -5.000000, 0 -(340.000000, 380.000000), (260.000000, 380.000000), 0.000000, 5.000000, 0 -(381.000000, 259.500000), (381.000000, 340.500000), 5.000000, 0.000000, 1 -(219.000000, 259.500000), (219.000000, 340.500000), -5.000000, 0.000000, 1 -(340.500000, 219.000000), (259.500000, 219.000000), 0.000000, -5.000000, 0 -(340.500000, 381.000000), (259.500000, 381.000000), 0.000000, 5.000000, 0 -(382.000000, 259.000000), (382.000000, 341.000000), 5.000000, 0.000000, 1 -(218.000000, 259.000000), (218.000000, 341.000000), -5.000000, 0.000000, 1 -(341.000000, 218.000000), (259.000000, 218.000000), 0.000000, -5.000000, 0 -(341.000000, 382.000000), (259.000000, 382.000000), 0.000000, 5.000000, 0 -(383.000000, 258.500000), (383.000000, 341.500000), 5.000000, 0.000000, 1 -(217.000000, 258.500000), (217.000000, 341.500000), -5.000000, 0.000000, 1 -(341.500000, 217.000000), (258.500000, 217.000000), 0.000000, -5.000000, 0 -(341.500000, 383.000000), (258.500000, 383.000000), 0.000000, 5.000000, 0 -(384.000000, 258.000000), (384.000000, 342.000000), 5.000000, 0.000000, 1 -(216.000000, 258.000000), (216.000000, 342.000000), -5.000000, 0.000000, 1 -(342.000000, 216.000000), (258.000000, 216.000000), 0.000000, -5.000000, 0 -(342.000000, 384.000000), (258.000000, 384.000000), 0.000000, 5.000000, 0 -(385.000000, 257.500000), (385.000000, 342.500000), 5.000000, 0.000000, 1 -(215.000000, 257.500000), (215.000000, 342.500000), -5.000000, 0.000000, 1 -(342.500000, 215.000000), (257.500000, 215.000000), 0.000000, -5.000000, 0 -(342.500000, 385.000000), (257.500000, 385.000000), 0.000000, 5.000000, 0 -(386.000000, 257.000000), (386.000000, 343.000000), 5.000000, 0.000000, 1 -(214.000000, 257.000000), (214.000000, 343.000000), -5.000000, 0.000000, 1 -(343.000000, 214.000000), (257.000000, 214.000000), 0.000000, -5.000000, 0 -(343.000000, 386.000000), (257.000000, 386.000000), 0.000000, 5.000000, 0 -(387.000000, 256.500000), (387.000000, 343.500000), 5.000000, 0.000000, 1 -(213.000000, 256.500000), (213.000000, 343.500000), -5.000000, 0.000000, 1 -(343.500000, 213.000000), (256.500000, 213.000000), 0.000000, -5.000000, 0 -(343.500000, 387.000000), (256.500000, 387.000000), 0.000000, 5.000000, 0 -(388.000000, 256.000000), (388.000000, 344.000000), 5.000000, 0.000000, 1 -(212.000000, 256.000000), (212.000000, 344.000000), -5.000000, 0.000000, 1 -(344.000000, 212.000000), (256.000000, 212.000000), 0.000000, -5.000000, 0 -(344.000000, 388.000000), (256.000000, 388.000000), 0.000000, 5.000000, 0 -(389.000000, 255.500000), (389.000000, 344.500000), 5.000000, 0.000000, 1 -(211.000000, 255.500000), (211.000000, 344.500000), -5.000000, 0.000000, 1 -(344.500000, 211.000000), (255.500000, 211.000000), 0.000000, -5.000000, 0 -(344.500000, 389.000000), (255.500000, 389.000000), 0.000000, 5.000000, 0 -(390.000000, 255.000000), (390.000000, 345.000000), 5.000000, 0.000000, 1 -(210.000000, 255.000000), (210.000000, 345.000000), -5.000000, 0.000000, 1 -(345.000000, 210.000000), (255.000000, 210.000000), 0.000000, -5.000000, 0 -(345.000000, 390.000000), (255.000000, 390.000000), 0.000000, 5.000000, 0 -(391.000000, 254.500000), (391.000000, 345.500000), 5.000000, 0.000000, 1 -(209.000000, 254.500000), (209.000000, 345.500000), -5.000000, 0.000000, 1 -(345.500000, 209.000000), (254.500000, 209.000000), 0.000000, -5.000000, 0 -(345.500000, 391.000000), (254.500000, 391.000000), 0.000000, 5.000000, 0 -(392.000000, 254.000000), (392.000000, 346.000000), 5.000000, 0.000000, 1 -(208.000000, 254.000000), (208.000000, 346.000000), -5.000000, 0.000000, 1 -(346.000000, 208.000000), (254.000000, 208.000000), 0.000000, -5.000000, 0 -(346.000000, 392.000000), (254.000000, 392.000000), 0.000000, 5.000000, 0 -(393.000000, 253.500000), (393.000000, 346.500000), 5.000000, 0.000000, 1 -(207.000000, 253.500000), (207.000000, 346.500000), -5.000000, 0.000000, 1 -(346.500000, 207.000000), (253.500000, 207.000000), 0.000000, -5.000000, 0 -(346.500000, 393.000000), (253.500000, 393.000000), 0.000000, 5.000000, 0 -(394.000000, 253.000000), (394.000000, 347.000000), 5.000000, 0.000000, 1 -(206.000000, 253.000000), (206.000000, 347.000000), -5.000000, 0.000000, 1 -(347.000000, 206.000000), (253.000000, 206.000000), 0.000000, -5.000000, 0 -(347.000000, 394.000000), (253.000000, 394.000000), 0.000000, 5.000000, 0 -(395.000000, 252.500000), (395.000000, 347.500000), 5.000000, 0.000000, 1 -(205.000000, 252.500000), (205.000000, 347.500000), -5.000000, 0.000000, 1 -(347.500000, 205.000000), (252.500000, 205.000000), 0.000000, -5.000000, 0 -(347.500000, 395.000000), (252.500000, 395.000000), 0.000000, 5.000000, 0 -(396.000000, 252.000000), (396.000000, 348.000000), 5.000000, 0.000000, 1 -(204.000000, 252.000000), (204.000000, 348.000000), -5.000000, 0.000000, 1 -(348.000000, 204.000000), (252.000000, 204.000000), 0.000000, -5.000000, 0 -(348.000000, 396.000000), (252.000000, 396.000000), 0.000000, 5.000000, 0 -(397.000000, 251.500000), (397.000000, 348.500000), 5.000000, 0.000000, 1 -(203.000000, 251.500000), (203.000000, 348.500000), -5.000000, 0.000000, 1 -(348.500000, 203.000000), (251.500000, 203.000000), 0.000000, -5.000000, 0 -(348.500000, 397.000000), (251.500000, 397.000000), 0.000000, 5.000000, 0 -(398.000000, 251.000000), (398.000000, 349.000000), 5.000000, 0.000000, 1 -(202.000000, 251.000000), (202.000000, 349.000000), -5.000000, 0.000000, 1 -(349.000000, 202.000000), (251.000000, 202.000000), 0.000000, -5.000000, 0 -(349.000000, 398.000000), (251.000000, 398.000000), 0.000000, 5.000000, 0 -(399.000000, 250.500000), (399.000000, 349.500000), 5.000000, 0.000000, 1 -(201.000000, 250.500000), (201.000000, 349.500000), -5.000000, 0.000000, 1 -(349.500000, 201.000000), (250.500000, 201.000000), 0.000000, -5.000000, 0 -(349.500000, 399.000000), (250.500000, 399.000000), 0.000000, 5.000000, 0 -(400.000000, 250.000000), (400.000000, 350.000000), 5.000000, 0.000000, 1 -(200.000000, 250.000000), (200.000000, 350.000000), -5.000000, 0.000000, 1 -(350.000000, 200.000000), (250.000000, 200.000000), 0.000000, -5.000000, 0 -(350.000000, 400.000000), (250.000000, 400.000000), 0.000000, 5.000000, 0 diff --git a/reducer_bench/quad_tree/input/explosion.in b/reducer_bench/quad_tree/input/explosion.in deleted file mode 100644 index b59b4cf1..00000000 --- a/reducer_bench/quad_tree/input/explosion.in +++ /dev/null @@ -1,601 +0,0 @@ -600 -(839.986292341, 402.617946029), (889.98355081, 396.858464765), -1.0, -0.0, 0 -(839.876640091, 407.85268977), (889.98355081, 403.141535235), -0.999780683475, -0.0209424198834, 0 -(839.657383689, 413.083989061), (889.85196811, 409.423227723), -0.999122830099, -0.0418756537292, 0 -(839.328619306, 418.309549282), (889.588860426, 415.700786873), -0.998026728428, -0.0627905195293, 0 -(838.890491151, 423.52707833), (889.194343167, 421.971459138), -0.99649285925, -0.0836778433323, 0 -(838.3431914, 428.734287623), (888.668589381, 428.232493996), -0.994521895368, -0.104528463268, 0 -(837.686960118, 433.928893109), (888.01182968, 434.481145148), -0.992114701314, -0.125333233564, 0 -(836.922085149, 439.10861626), (887.224352141, 440.71467173), -0.989272332963, -0.146083028562, 0 -(836.048901992, 444.27118508), (886.306502179, 446.930339512), -0.985996037071, -0.166768746716, 0 -(835.067793655, 449.414335095), (885.258682391, 453.125422096), -0.982287250729, -0.187381314586, 0 -(833.979190485, 454.535810349), (884.081352387, 459.297202114), -0.978147600734, -0.207911690818, 0 -(832.783569977, 459.633364395), (882.775028582, 465.442972419), -0.973578902873, -0.228350870111, 0 -(831.481456572, 464.704761276), (881.340283973, 471.560037274), -0.968583161129, -0.248689887165, 0 -(830.073421419, 469.74777651), (879.777747887, 477.645713531), -0.963162566798, -0.268919820615, 0 -(828.560082129, 474.760198064), (878.088105703, 483.697331812), -0.957319497532, -0.289031796944, 0 -(826.942102502, 479.739827325), (876.272098555, 489.712237677), -0.951056516295, -0.309016994375, 0 -(825.220192239, 484.684480061), (874.330523003, 495.687792789), -0.944376370237, -0.328866646739, 0 -(823.395106624, 489.591987386), (872.264230686, 501.621376074), -0.937281989492, -0.348572047322, 0 -(821.467646202, 494.460196705), (870.074127949, 507.510384864), -0.929776485888, -0.368124552685, 0 -(819.438656421, 499.286972659), (867.761175443, 513.352236046), -0.921863151589, -0.387515586452, 0 -(817.309027262, 504.070198065), (865.326387705, 519.14436719), -0.913545457643, -0.406736643076, 0 -(815.079692851, 508.807774843), (862.770832714, 524.884237678), -0.904827052466, -0.425779291565, 0 -(812.751631047, 513.497624935), (860.095631421, 530.569329812), -0.895711760239, -0.444635179185, 0 -(810.325863016, 518.137691217), (857.301957257, 536.197149922), -0.886203579231, -0.46329603512, 0 -(807.80345278, 522.725938404), (854.391035619, 541.765229461), -0.876306680044, -0.481753674102, 0 -(805.185506751, 527.260353938), (851.364143336, 547.271126085), -0.866025403784, -0.5, 0 -(802.473173247, 531.738948874), (848.222608101, 552.712424725), -0.855364260161, -0.518027009373, 0 -(799.667641986, 536.159758754), (844.967807896, 558.086738649), -0.844327925502, -0.535826794979, 0 -(796.770143569, 540.520844463), (841.601170384, 563.391710505), -0.83292124071, -0.553391549243, 0 -(793.781948932, 544.820293086), (838.124172282, 568.625013356), -0.821149209134, -0.570713567684, 0 -(790.704368798, 549.056218741), (834.538338719, 573.784351703), -0.809016994375, -0.587785252292, 0 -(787.538753094, 553.226763413), (830.845242557, 578.86746249), -0.796529918024, -0.604599114862, 0 -(784.286490364, 557.330097762), (827.046503713, 583.872116096), -0.783693457326, -0.621147780278, 0 -(780.949007159, 561.364421931), (823.143788437, 588.796117315), -0.770513242776, -0.637423989749, 0 -(777.527767408, 565.327966331), (819.13880859, 593.637306317), -0.756995055652, -0.65342060399, 0 -(774.02427178, 569.218992421), (815.033320889, 598.393559597), -0.743144825477, -0.669130606359, 0 -(770.440057025, 573.035793468), (810.829126136, 603.062790905), -0.728968627421, -0.684547105929, 0 -(766.776695297, 576.776695297), (806.52806843, 607.642952161), -0.714472679633, -0.699663340513, 0 -(763.035793468, 580.440057025), (802.132034356, 612.132034356), -0.699663340513, -0.714472679633, 0 -(759.218992421, 584.02427178), (797.642952161, 616.52806843), -0.684547105929, -0.728968627421, 0 -(755.327966331, 587.527767408), (793.062790905, 620.829126136), -0.669130606359, -0.743144825477, 0 -(751.364421931, 590.949007159), (788.393559597, 625.033320889), -0.65342060399, -0.756995055652, 0 -(747.330097762, 594.286490364), (783.637306317, 629.13880859), -0.637423989749, -0.770513242776, 0 -(743.226763413, 597.538753094), (778.796117315, 633.143788437), -0.621147780278, -0.783693457326, 0 -(739.056218741, 600.704368798), (773.872116096, 637.046503713), -0.604599114862, -0.796529918024, 0 -(734.820293086, 603.781948932), (768.86746249, 640.845242557), -0.587785252292, -0.809016994375, 0 -(730.520844463, 606.770143569), (763.784351703, 644.538338719), -0.570713567684, -0.821149209134, 0 -(726.159758754, 609.667641986), (758.625013356, 648.124172282), -0.553391549243, -0.83292124071, 0 -(721.738948874, 612.473173247), (753.391710505, 651.601170384), -0.535826794979, -0.844327925502, 0 -(717.260353938, 615.185506751), (748.086738649, 654.967807896), -0.518027009373, -0.855364260161, 0 -(712.725938404, 617.80345278), (742.712424725, 658.222608101), -0.5, -0.866025403784, 0 -(708.137691217, 620.325863016), (737.271126085, 661.364143336), -0.481753674102, -0.876306680044, 0 -(703.497624935, 622.751631047), (731.765229461, 664.391035619), -0.46329603512, -0.886203579231, 0 -(698.807774843, 625.079692851), (726.197149922, 667.301957257), -0.444635179185, -0.895711760239, 0 -(694.070198065, 627.309027262), (720.569329812, 670.095631421), -0.425779291565, -0.904827052466, 0 -(689.286972659, 629.438656421), (714.884237678, 672.770832714), -0.406736643076, -0.913545457643, 0 -(684.460196705, 631.467646202), (709.14436719, 675.326387705), -0.387515586452, -0.921863151589, 0 -(679.591987386, 633.395106624), (703.352236046, 677.761175443), -0.368124552685, -0.929776485888, 0 -(674.684480061, 635.220192239), (697.510384864, 680.074127949), -0.348572047322, -0.937281989492, 0 -(669.739827325, 636.942102502), (691.621376074, 682.264230686), -0.328866646739, -0.944376370237, 0 -(664.760198064, 638.560082129), (685.687792789, 684.330523003), -0.309016994375, -0.951056516295, 0 -(659.74777651, 640.073421419), (679.712237677, 686.272098555), -0.289031796944, -0.957319497532, 0 -(654.704761276, 641.481456572), (673.697331812, 688.088105703), -0.268919820615, -0.963162566798, 0 -(649.633364395, 642.783569977), (667.645713531, 689.777747887), -0.248689887165, -0.968583161129, 0 -(644.535810349, 643.979190485), (661.560037274, 691.340283973), -0.228350870111, -0.973578902873, 0 -(639.414335095, 645.067793655), (655.442972419, 692.775028582), -0.207911690818, -0.978147600734, 0 -(634.27118508, 646.048901992), (649.297202114, 694.081352387), -0.187381314586, -0.982287250729, 0 -(629.10861626, 646.922085149), (643.125422096, 695.258682391), -0.166768746716, -0.985996037071, 0 -(623.928893109, 647.686960118), (636.930339512, 696.306502179), -0.146083028562, -0.989272332963, 0 -(618.734287623, 648.3431914), (630.71467173, 697.224352141), -0.125333233564, -0.992114701314, 0 -(613.52707833, 648.890491151), (624.481145148, 698.01182968), -0.104528463268, -0.994521895368, 0 -(608.309549282, 649.328619306), (618.232493996, 698.668589381), -0.0836778433323, -0.99649285925, 0 -(603.083989061, 649.657383689), (611.971459138, 699.194343167), -0.0627905195293, -0.998026728428, 0 -(597.85268977, 649.876640091), (605.700786873, 699.588860426), -0.0418756537292, -0.999122830099, 0 -(592.617946029, 649.986292341), (599.423227723, 699.85196811), -0.0209424198834, -0.999780683475, 0 -(587.382053971, 649.986292341), (593.141535235, 699.98355081), -6.12323399574e-17, -1.0, 0 -(582.14731023, 649.876640091), (586.858464765, 699.98355081), 0.0209424198834, -0.999780683475, 0 -(576.916010939, 649.657383689), (580.576772277, 699.85196811), 0.0418756537292, -0.999122830099, 0 -(571.690450718, 649.328619306), (574.299213127, 699.588860426), 0.0627905195293, -0.998026728428, 0 -(566.47292167, 648.890491151), (568.028540862, 699.194343167), 0.0836778433323, -0.99649285925, 0 -(561.265712377, 648.3431914), (561.767506004, 698.668589381), 0.104528463268, -0.994521895368, 0 -(556.071106891, 647.686960118), (555.518854852, 698.01182968), 0.125333233564, -0.992114701314, 0 -(550.89138374, 646.922085149), (549.28532827, 697.224352141), 0.146083028562, -0.989272332963, 0 -(545.72881492, 646.048901992), (543.069660488, 696.306502179), 0.166768746716, -0.985996037071, 0 -(540.585664905, 645.067793655), (536.874577904, 695.258682391), 0.187381314586, -0.982287250729, 0 -(535.464189651, 643.979190485), (530.702797886, 694.081352387), 0.207911690818, -0.978147600734, 0 -(530.366635605, 642.783569977), (524.557027581, 692.775028582), 0.228350870111, -0.973578902873, 0 -(525.295238724, 641.481456572), (518.439962726, 691.340283973), 0.248689887165, -0.968583161129, 0 -(520.25222349, 640.073421419), (512.354286469, 689.777747887), 0.268919820615, -0.963162566798, 0 -(515.239801936, 638.560082129), (506.302668188, 688.088105703), 0.289031796944, -0.957319497532, 0 -(510.260172675, 636.942102502), (500.287762323, 686.272098555), 0.309016994375, -0.951056516295, 0 -(505.315519939, 635.220192239), (494.312207211, 684.330523003), 0.328866646739, -0.944376370237, 0 -(500.408012614, 633.395106624), (488.378623926, 682.264230686), 0.348572047322, -0.937281989492, 0 -(495.539803295, 631.467646202), (482.489615136, 680.074127949), 0.368124552685, -0.929776485888, 0 -(490.713027341, 629.438656421), (476.647763954, 677.761175443), 0.387515586452, -0.921863151589, 0 -(485.929801935, 627.309027262), (470.85563281, 675.326387705), 0.406736643076, -0.913545457643, 0 -(481.192225157, 625.079692851), (465.115762322, 672.770832714), 0.425779291565, -0.904827052466, 0 -(476.502375065, 622.751631047), (459.430670188, 670.095631421), 0.444635179185, -0.895711760239, 0 -(471.862308783, 620.325863016), (453.802850078, 667.301957257), 0.46329603512, -0.886203579231, 0 -(467.274061596, 617.80345278), (448.234770539, 664.391035619), 0.481753674102, -0.876306680044, 0 -(462.739646062, 615.185506751), (442.728873915, 661.364143336), 0.5, -0.866025403784, 0 -(458.261051126, 612.473173247), (437.287575275, 658.222608101), 0.518027009373, -0.855364260161, 0 -(453.840241246, 609.667641986), (431.913261351, 654.967807896), 0.535826794979, -0.844327925502, 0 -(449.479155537, 606.770143569), (426.608289495, 651.601170384), 0.553391549243, -0.83292124071, 0 -(445.179706914, 603.781948932), (421.374986644, 648.124172282), 0.570713567684, -0.821149209134, 0 -(440.943781259, 600.704368798), (416.215648297, 644.538338719), 0.587785252292, -0.809016994375, 0 -(436.773236587, 597.538753094), (411.13253751, 640.845242557), 0.604599114862, -0.796529918024, 0 -(432.669902238, 594.286490364), (406.127883904, 637.046503713), 0.621147780278, -0.783693457326, 0 -(428.635578069, 590.949007159), (401.203882685, 633.143788437), 0.637423989749, -0.770513242776, 0 -(424.672033669, 587.527767408), (396.362693683, 629.13880859), 0.65342060399, -0.756995055652, 0 -(420.781007579, 584.02427178), (391.606440403, 625.033320889), 0.669130606359, -0.743144825477, 0 -(416.964206532, 580.440057025), (386.937209095, 620.829126136), 0.684547105929, -0.728968627421, 0 -(413.223304703, 576.776695297), (382.357047839, 616.52806843), 0.699663340513, -0.714472679633, 0 -(409.559942975, 573.035793468), (377.867965644, 612.132034356), 0.714472679633, -0.699663340513, 0 -(405.97572822, 569.218992421), (373.47193157, 607.642952161), 0.728968627421, -0.684547105929, 0 -(402.472232592, 565.327966331), (369.170873864, 603.062790905), 0.743144825477, -0.669130606359, 0 -(399.050992841, 561.364421931), (364.966679111, 598.393559597), 0.756995055652, -0.65342060399, 0 -(395.713509636, 557.330097762), (360.86119141, 593.637306317), 0.770513242776, -0.637423989749, 0 -(392.461246906, 553.226763413), (356.856211563, 588.796117315), 0.783693457326, -0.621147780278, 0 -(389.295631202, 549.056218741), (352.953496287, 583.872116096), 0.796529918024, -0.604599114862, 0 -(386.218051068, 544.820293086), (349.154757443, 578.86746249), 0.809016994375, -0.587785252292, 0 -(383.229856431, 540.520844463), (345.461661281, 573.784351703), 0.821149209134, -0.570713567684, 0 -(380.332358014, 536.159758754), (341.875827718, 568.625013356), 0.83292124071, -0.553391549243, 0 -(377.526826753, 531.738948874), (338.398829616, 563.391710505), 0.844327925502, -0.535826794979, 0 -(374.814493249, 527.260353938), (335.032192104, 558.086738649), 0.855364260161, -0.518027009373, 0 -(372.19654722, 522.725938404), (331.777391899, 552.712424725), 0.866025403784, -0.5, 0 -(369.674136984, 518.137691217), (328.635856664, 547.271126085), 0.876306680044, -0.481753674102, 0 -(367.248368953, 513.497624935), (325.608964381, 541.765229461), 0.886203579231, -0.46329603512, 0 -(364.920307149, 508.807774843), (322.698042743, 536.197149922), 0.895711760239, -0.444635179185, 0 -(362.690972738, 504.070198065), (319.904368579, 530.569329812), 0.904827052466, -0.425779291565, 0 -(360.561343579, 499.286972659), (317.229167286, 524.884237678), 0.913545457643, -0.406736643076, 0 -(358.532353798, 494.460196705), (314.673612295, 519.14436719), 0.921863151589, -0.387515586452, 0 -(356.604893376, 489.591987386), (312.238824557, 513.352236046), 0.929776485888, -0.368124552685, 0 -(354.779807761, 484.684480061), (309.925872051, 507.510384864), 0.937281989492, -0.348572047322, 0 -(353.057897498, 479.739827325), (307.735769314, 501.621376074), 0.944376370237, -0.328866646739, 0 -(351.439917871, 474.760198064), (305.669476997, 495.687792789), 0.951056516295, -0.309016994375, 0 -(349.926578581, 469.74777651), (303.727901445, 489.712237677), 0.957319497532, -0.289031796944, 0 -(348.518543428, 464.704761276), (301.911894297, 483.697331812), 0.963162566798, -0.268919820615, 0 -(347.216430023, 459.633364395), (300.222252113, 477.645713531), 0.968583161129, -0.248689887165, 0 -(346.020809515, 454.535810349), (298.659716027, 471.560037274), 0.973578902873, -0.228350870111, 0 -(344.932206345, 449.414335095), (297.224971418, 465.442972419), 0.978147600734, -0.207911690818, 0 -(343.951098008, 444.27118508), (295.918647613, 459.297202114), 0.982287250729, -0.187381314586, 0 -(343.077914851, 439.10861626), (294.741317609, 453.125422096), 0.985996037071, -0.166768746716, 0 -(342.313039882, 433.928893109), (293.693497821, 446.930339512), 0.989272332963, -0.146083028562, 0 -(341.6568086, 428.734287623), (292.775647859, 440.71467173), 0.992114701314, -0.125333233564, 0 -(341.109508849, 423.52707833), (291.98817032, 434.481145148), 0.994521895368, -0.104528463268, 0 -(340.671380694, 418.309549282), (291.331410619, 428.232493996), 0.99649285925, -0.0836778433323, 0 -(340.342616311, 413.083989061), (290.805656833, 421.971459138), 0.998026728428, -0.0627905195293, 0 -(340.123359909, 407.85268977), (290.411139574, 415.700786873), 0.999122830099, -0.0418756537292, 0 -(340.013707659, 402.617946029), (290.14803189, 409.423227723), 0.999780683475, -0.0209424198834, 0 -(340.013707659, 397.382053971), (290.01644919, 403.141535235), 1.0, -1.22464679915e-16, 0 -(340.123359909, 392.14731023), (290.01644919, 396.858464765), 0.999780683475, 0.0209424198834, 0 -(340.342616311, 386.916010939), (290.14803189, 390.576772277), 0.999122830099, 0.0418756537292, 0 -(340.671380694, 381.690450718), (290.411139574, 384.299213127), 0.998026728428, 0.0627905195293, 0 -(341.109508849, 376.47292167), (290.805656833, 378.028540862), 0.99649285925, 0.0836778433323, 0 -(341.6568086, 371.265712377), (291.331410619, 371.767506004), 0.994521895368, 0.104528463268, 0 -(342.313039882, 366.071106891), (291.98817032, 365.518854852), 0.992114701314, 0.125333233564, 0 -(343.077914851, 360.89138374), (292.775647859, 359.28532827), 0.989272332963, 0.146083028562, 0 -(343.951098008, 355.72881492), (293.693497821, 353.069660488), 0.985996037071, 0.166768746716, 0 -(344.932206345, 350.585664905), (294.741317609, 346.874577904), 0.982287250729, 0.187381314586, 0 -(346.020809515, 345.464189651), (295.918647613, 340.702797886), 0.978147600734, 0.207911690818, 0 -(347.216430023, 340.366635605), (297.224971418, 334.557027581), 0.973578902873, 0.228350870111, 0 -(348.518543428, 335.295238724), (298.659716027, 328.439962726), 0.968583161129, 0.248689887165, 0 -(349.926578581, 330.25222349), (300.222252113, 322.354286469), 0.963162566798, 0.268919820615, 0 -(351.439917871, 325.239801936), (301.911894297, 316.302668188), 0.957319497532, 0.289031796944, 0 -(353.057897498, 320.260172675), (303.727901445, 310.287762323), 0.951056516295, 0.309016994375, 0 -(354.779807761, 315.315519939), (305.669476997, 304.312207211), 0.944376370237, 0.328866646739, 0 -(356.604893376, 310.408012614), (307.735769314, 298.378623926), 0.937281989492, 0.348572047322, 0 -(358.532353798, 305.539803295), (309.925872051, 292.489615136), 0.929776485888, 0.368124552685, 0 -(360.561343579, 300.713027341), (312.238824557, 286.647763954), 0.921863151589, 0.387515586452, 0 -(362.690972738, 295.929801935), (314.673612295, 280.85563281), 0.913545457643, 0.406736643076, 0 -(364.920307149, 291.192225157), (317.229167286, 275.115762322), 0.904827052466, 0.425779291565, 0 -(367.248368953, 286.502375065), (319.904368579, 269.430670188), 0.895711760239, 0.444635179185, 0 -(369.674136984, 281.862308783), (322.698042743, 263.802850078), 0.886203579231, 0.46329603512, 0 -(372.19654722, 277.274061596), (325.608964381, 258.234770539), 0.876306680044, 0.481753674102, 0 -(374.814493249, 272.739646062), (328.635856664, 252.728873915), 0.866025403784, 0.5, 0 -(377.526826753, 268.261051126), (331.777391899, 247.287575275), 0.855364260161, 0.518027009373, 0 -(380.332358014, 263.840241246), (335.032192104, 241.913261351), 0.844327925502, 0.535826794979, 0 -(383.229856431, 259.479155537), (338.398829616, 236.608289495), 0.83292124071, 0.553391549243, 0 -(386.218051068, 255.179706914), (341.875827718, 231.374986644), 0.821149209134, 0.570713567684, 0 -(389.295631202, 250.943781259), (345.461661281, 226.215648297), 0.809016994375, 0.587785252292, 0 -(392.461246906, 246.773236587), (349.154757443, 221.13253751), 0.796529918024, 0.604599114862, 0 -(395.713509636, 242.669902238), (352.953496287, 216.127883904), 0.783693457326, 0.621147780278, 0 -(399.050992841, 238.635578069), (356.856211563, 211.203882685), 0.770513242776, 0.637423989749, 0 -(402.472232592, 234.672033669), (360.86119141, 206.362693683), 0.756995055652, 0.65342060399, 0 -(405.97572822, 230.781007579), (364.966679111, 201.606440403), 0.743144825477, 0.669130606359, 0 -(409.559942975, 226.964206532), (369.170873864, 196.937209095), 0.728968627421, 0.684547105929, 0 -(413.223304703, 223.223304703), (373.47193157, 192.357047839), 0.714472679633, 0.699663340513, 0 -(416.964206532, 219.559942975), (377.867965644, 187.867965644), 0.699663340513, 0.714472679633, 0 -(420.781007579, 215.97572822), (382.357047839, 183.47193157), 0.684547105929, 0.728968627421, 0 -(424.672033669, 212.472232592), (386.937209095, 179.170873864), 0.669130606359, 0.743144825477, 0 -(428.635578069, 209.050992841), (391.606440403, 174.966679111), 0.65342060399, 0.756995055652, 0 -(432.669902238, 205.713509636), (396.362693683, 170.86119141), 0.637423989749, 0.770513242776, 0 -(436.773236587, 202.461246906), (401.203882685, 166.856211563), 0.621147780278, 0.783693457326, 0 -(440.943781259, 199.295631202), (406.127883904, 162.953496287), 0.604599114862, 0.796529918024, 0 -(445.179706914, 196.218051068), (411.13253751, 159.154757443), 0.587785252292, 0.809016994375, 0 -(449.479155537, 193.229856431), (416.215648297, 155.461661281), 0.570713567684, 0.821149209134, 0 -(453.840241246, 190.332358014), (421.374986644, 151.875827718), 0.553391549243, 0.83292124071, 0 -(458.261051126, 187.526826753), (426.608289495, 148.398829616), 0.535826794979, 0.844327925502, 0 -(462.739646062, 184.814493249), (431.913261351, 145.032192104), 0.518027009373, 0.855364260161, 0 -(467.274061596, 182.19654722), (437.287575275, 141.777391899), 0.5, 0.866025403784, 0 -(471.862308783, 179.674136984), (442.728873915, 138.635856664), 0.481753674102, 0.876306680044, 0 -(476.502375065, 177.248368953), (448.234770539, 135.608964381), 0.46329603512, 0.886203579231, 0 -(481.192225157, 174.920307149), (453.802850078, 132.698042743), 0.444635179185, 0.895711760239, 0 -(485.929801935, 172.690972738), (459.430670188, 129.904368579), 0.425779291565, 0.904827052466, 0 -(490.713027341, 170.561343579), (465.115762322, 127.229167286), 0.406736643076, 0.913545457643, 0 -(495.539803295, 168.532353798), (470.85563281, 124.673612295), 0.387515586452, 0.921863151589, 0 -(500.408012614, 166.604893376), (476.647763954, 122.238824557), 0.368124552685, 0.929776485888, 0 -(505.315519939, 164.779807761), (482.489615136, 119.925872051), 0.348572047322, 0.937281989492, 0 -(510.260172675, 163.057897498), (488.378623926, 117.735769314), 0.328866646739, 0.944376370237, 0 -(515.239801936, 161.439917871), (494.312207211, 115.669476997), 0.309016994375, 0.951056516295, 0 -(520.25222349, 159.926578581), (500.287762323, 113.727901445), 0.289031796944, 0.957319497532, 0 -(525.295238724, 158.518543428), (506.302668188, 111.911894297), 0.268919820615, 0.963162566798, 0 -(530.366635605, 157.216430023), (512.354286469, 110.222252113), 0.248689887165, 0.968583161129, 0 -(535.464189651, 156.020809515), (518.439962726, 108.659716027), 0.228350870111, 0.973578902873, 0 -(540.585664905, 154.932206345), (524.557027581, 107.224971418), 0.207911690818, 0.978147600734, 0 -(545.72881492, 153.951098008), (530.702797886, 105.918647613), 0.187381314586, 0.982287250729, 0 -(550.89138374, 153.077914851), (536.874577904, 104.741317609), 0.166768746716, 0.985996037071, 0 -(556.071106891, 152.313039882), (543.069660488, 103.693497821), 0.146083028562, 0.989272332963, 0 -(561.265712377, 151.6568086), (549.28532827, 102.775647859), 0.125333233564, 0.992114701314, 0 -(566.47292167, 151.109508849), (555.518854852, 101.98817032), 0.104528463268, 0.994521895368, 0 -(571.690450718, 150.671380694), (561.767506004, 101.331410619), 0.0836778433323, 0.99649285925, 0 -(576.916010939, 150.342616311), (568.028540862, 100.805656833), 0.0627905195293, 0.998026728428, 0 -(582.14731023, 150.123359909), (574.299213127, 100.411139574), 0.0418756537292, 0.999122830099, 0 -(587.382053971, 150.013707659), (580.576772277, 100.14803189), 0.0209424198834, 0.999780683475, 0 -(592.617946029, 150.013707659), (586.858464765, 100.01644919), 1.83697019872e-16, 1.0, 0 -(597.85268977, 150.123359909), (593.141535235, 100.01644919), -0.0209424198834, 0.999780683475, 0 -(603.083989061, 150.342616311), (599.423227723, 100.14803189), -0.0418756537292, 0.999122830099, 0 -(608.309549282, 150.671380694), (605.700786873, 100.411139574), -0.0627905195293, 0.998026728428, 0 -(613.52707833, 151.109508849), (611.971459138, 100.805656833), -0.0836778433323, 0.99649285925, 0 -(618.734287623, 151.6568086), (618.232493996, 101.331410619), -0.104528463268, 0.994521895368, 0 -(623.928893109, 152.313039882), (624.481145148, 101.98817032), -0.125333233564, 0.992114701314, 0 -(629.10861626, 153.077914851), (630.71467173, 102.775647859), -0.146083028562, 0.989272332963, 0 -(634.27118508, 153.951098008), (636.930339512, 103.693497821), -0.166768746716, 0.985996037071, 0 -(639.414335095, 154.932206345), (643.125422096, 104.741317609), -0.187381314586, 0.982287250729, 0 -(644.535810349, 156.020809515), (649.297202114, 105.918647613), -0.207911690818, 0.978147600734, 0 -(649.633364395, 157.216430023), (655.442972419, 107.224971418), -0.228350870111, 0.973578902873, 0 -(654.704761276, 158.518543428), (661.560037274, 108.659716027), -0.248689887165, 0.968583161129, 0 -(659.74777651, 159.926578581), (667.645713531, 110.222252113), -0.268919820615, 0.963162566798, 0 -(664.760198064, 161.439917871), (673.697331812, 111.911894297), -0.289031796944, 0.957319497532, 0 -(669.739827325, 163.057897498), (679.712237677, 113.727901445), -0.309016994375, 0.951056516295, 0 -(674.684480061, 164.779807761), (685.687792789, 115.669476997), -0.328866646739, 0.944376370237, 0 -(679.591987386, 166.604893376), (691.621376074, 117.735769314), -0.348572047322, 0.937281989492, 0 -(684.460196705, 168.532353798), (697.510384864, 119.925872051), -0.368124552685, 0.929776485888, 0 -(689.286972659, 170.561343579), (703.352236046, 122.238824557), -0.387515586452, 0.921863151589, 0 -(694.070198065, 172.690972738), (709.14436719, 124.673612295), -0.406736643076, 0.913545457643, 0 -(698.807774843, 174.920307149), (714.884237678, 127.229167286), -0.425779291565, 0.904827052466, 0 -(703.497624935, 177.248368953), (720.569329812, 129.904368579), -0.444635179185, 0.895711760239, 0 -(708.137691217, 179.674136984), (726.197149922, 132.698042743), -0.46329603512, 0.886203579231, 0 -(712.725938404, 182.19654722), (731.765229461, 135.608964381), -0.481753674102, 0.876306680044, 0 -(717.260353938, 184.814493249), (737.271126085, 138.635856664), -0.5, 0.866025403784, 0 -(721.738948874, 187.526826753), (742.712424725, 141.777391899), -0.518027009373, 0.855364260161, 0 -(726.159758754, 190.332358014), (748.086738649, 145.032192104), -0.535826794979, 0.844327925502, 0 -(730.520844463, 193.229856431), (753.391710505, 148.398829616), -0.553391549243, 0.83292124071, 0 -(734.820293086, 196.218051068), (758.625013356, 151.875827718), -0.570713567684, 0.821149209134, 0 -(739.056218741, 199.295631202), (763.784351703, 155.461661281), -0.587785252292, 0.809016994375, 0 -(743.226763413, 202.461246906), (768.86746249, 159.154757443), -0.604599114862, 0.796529918024, 0 -(747.330097762, 205.713509636), (773.872116096, 162.953496287), -0.621147780278, 0.783693457326, 0 -(751.364421931, 209.050992841), (778.796117315, 166.856211563), -0.637423989749, 0.770513242776, 0 -(755.327966331, 212.472232592), (783.637306317, 170.86119141), -0.65342060399, 0.756995055652, 0 -(759.218992421, 215.97572822), (788.393559597, 174.966679111), -0.669130606359, 0.743144825477, 0 -(763.035793468, 219.559942975), (793.062790905, 179.170873864), -0.684547105929, 0.728968627421, 0 -(766.776695297, 223.223304703), (797.642952161, 183.47193157), -0.699663340513, 0.714472679633, 0 -(770.440057025, 226.964206532), (802.132034356, 187.867965644), -0.714472679633, 0.699663340513, 0 -(774.02427178, 230.781007579), (806.52806843, 192.357047839), -0.728968627421, 0.684547105929, 0 -(777.527767408, 234.672033669), (810.829126136, 196.937209095), -0.743144825477, 0.669130606359, 0 -(780.949007159, 238.635578069), (815.033320889, 201.606440403), -0.756995055652, 0.65342060399, 0 -(784.286490364, 242.669902238), (819.13880859, 206.362693683), -0.770513242776, 0.637423989749, 0 -(787.538753094, 246.773236587), (823.143788437, 211.203882685), -0.783693457326, 0.621147780278, 0 -(790.704368798, 250.943781259), (827.046503713, 216.127883904), -0.796529918024, 0.604599114862, 0 -(793.781948932, 255.179706914), (830.845242557, 221.13253751), -0.809016994375, 0.587785252292, 0 -(796.770143569, 259.479155537), (834.538338719, 226.215648297), -0.821149209134, 0.570713567684, 0 -(799.667641986, 263.840241246), (838.124172282, 231.374986644), -0.83292124071, 0.553391549243, 0 -(802.473173247, 268.261051126), (841.601170384, 236.608289495), -0.844327925502, 0.535826794979, 0 -(805.185506751, 272.739646062), (844.967807896, 241.913261351), -0.855364260161, 0.518027009373, 0 -(807.80345278, 277.274061596), (848.222608101, 247.287575275), -0.866025403784, 0.5, 0 -(810.325863016, 281.862308783), (851.364143336, 252.728873915), -0.876306680044, 0.481753674102, 0 -(812.751631047, 286.502375065), (854.391035619, 258.234770539), -0.886203579231, 0.46329603512, 0 -(815.079692851, 291.192225157), (857.301957257, 263.802850078), -0.895711760239, 0.444635179185, 0 -(817.309027262, 295.929801935), (860.095631421, 269.430670188), -0.904827052466, 0.425779291565, 0 -(819.438656421, 300.713027341), (862.770832714, 275.115762322), -0.913545457643, 0.406736643076, 0 -(821.467646202, 305.539803295), (865.326387705, 280.85563281), -0.921863151589, 0.387515586452, 0 -(823.395106624, 310.408012614), (867.761175443, 286.647763954), -0.929776485888, 0.368124552685, 0 -(825.220192239, 315.315519939), (870.074127949, 292.489615136), -0.937281989492, 0.348572047322, 0 -(826.942102502, 320.260172675), (872.264230686, 298.378623926), -0.944376370237, 0.328866646739, 0 -(828.560082129, 325.239801936), (874.330523003, 304.312207211), -0.951056516295, 0.309016994375, 0 -(830.073421419, 330.25222349), (876.272098555, 310.287762323), -0.957319497532, 0.289031796944, 0 -(831.481456572, 335.295238724), (878.088105703, 316.302668188), -0.963162566798, 0.268919820615, 0 -(832.783569977, 340.366635605), (879.777747887, 322.354286469), -0.968583161129, 0.248689887165, 0 -(833.979190485, 345.464189651), (881.340283973, 328.439962726), -0.973578902873, 0.228350870111, 0 -(835.067793655, 350.585664905), (882.775028582, 334.557027581), -0.978147600734, 0.207911690818, 0 -(836.048901992, 355.72881492), (884.081352387, 340.702797886), -0.982287250729, 0.187381314586, 0 -(836.922085149, 360.89138374), (885.258682391, 346.874577904), -0.985996037071, 0.166768746716, 0 -(837.686960118, 366.071106891), (886.306502179, 353.069660488), -0.989272332963, 0.146083028562, 0 -(838.3431914, 371.265712377), (887.224352141, 359.28532827), -0.992114701314, 0.125333233564, 0 -(838.890491151, 376.47292167), (888.01182968, 365.518854852), -0.994521895368, 0.104528463268, 0 -(839.328619306, 381.690450718), (888.668589381, 371.767506004), -0.99649285925, 0.0836778433323, 0 -(839.657383689, 386.916010939), (889.194343167, 378.028540862), -0.998026728428, 0.0627905195293, 0 -(839.876640091, 392.14731023), (889.588860426, 384.299213127), -0.999122830099, 0.0418756537292, 0 -(839.986292341, 397.382053971), (889.85196811, 390.576772277), -0.999780683475, 0.0209424198834, 0 -(689.987663248, 398.429268269), (739.981494872, 402.356097597), 0.5, 0.0, 1 -(689.987663248, 401.570731731), (739.833481244, 407.065967606), 0.499753280183, 0.0157053795391, 1 -(689.888987496, 404.710645071), (739.53760006, 411.768864359), 0.499013364214, 0.0313952597647, 1 -(689.691733373, 407.845909573), (739.094143318, 416.460146664), 0.497780982302, 0.0470541566593, 1 -(689.396095546, 410.973431109), (738.503548657, 421.135184791), 0.496057350657, 0.0626666167822, 1 -(689.002365772, 414.090123194), (737.766398923, 425.789365042), 0.493844170298, 0.0782172325201, 1 -(688.510932615, 417.192910028), (736.883421593, 430.418094303), 0.491143625364, 0.0936906572929, 1 -(687.922281062, 420.278729536), (735.85548806, 435.016804578), 0.487958380969, 0.109071620698, 1 -(687.23699204, 423.344536386), (734.683612769, 439.580957495), 0.484291580564, 0.124344943582, 1 -(686.455741846, 426.387304997), (733.36895222, 444.106048785), 0.480146842838, 0.13949555302, 1 -(685.57930148, 429.404032523), (731.912803824, 448.58761273), 0.475528258148, 0.154508497187, 1 -(684.608535883, 432.39174182), (730.316604624, 453.021226567), 0.470440384477, 0.169368960123, 1 -(683.544403083, 435.347484378), (728.581929877, 457.402514855), 0.464888242944, 0.184062276342, 1 -(682.387953251, 438.268343237), (726.710491495, 461.727153791), 0.458877312842, 0.198573945317, 1 -(681.140327664, 441.151435861), (724.704136364, 465.990875478), 0.452413526233, 0.212889645783, 1 -(679.802757576, 443.993916986), (722.564844513, 470.189472139), 0.445503262094, 0.22699524987, 1 -(678.376563009, 446.792981426), (720.294727166, 474.318800265), 0.438153340022, 0.240876837051, 1 -(676.863151444, 449.545866843), (717.896024653, 478.374784707), 0.430371013502, 0.254520707875, 1 -(675.264016435, 452.249856472), (715.371104205, 482.3534227), 0.422163962751, 0.267913397489, 1 -(673.580736137, 454.9022818), (712.722457614, 486.250787806), 0.413540287137, 0.281041688926, 1 -(671.814971743, 457.500525204), (709.952698773, 490.063033799), 0.404508497187, 0.293892626146, 1 -(669.968465849, 460.042022533), (707.064561101, 493.78639845), 0.395077506188, 0.306453526826, 1 -(668.043040734, 462.524265634), (704.06089484, 497.41720725), 0.385256621388, 0.318711994874, 1 -(666.04059656, 464.944804833), (700.944664247, 500.951877026), 0.375055534815, 0.330655932662, 1 -(663.963109498, 467.301251351), (697.718944664, 504.386919489), 0.364484313711, 0.342273552964, 1 -(661.812629776, 469.591279659), (694.386919489, 507.718944664), 0.353553390593, 0.353553390593, 1 -(659.591279659, 471.812629776), (690.951877026, 510.944664247), 0.342273552964, 0.364484313711, 1 -(657.301251351, 473.963109498), (687.41720725, 514.06089484), 0.330655932662, 0.375055534815, 1 -(654.944804833, 476.04059656), (683.78639845, 517.064561101), 0.318711994874, 0.385256621388, 1 -(652.524265634, 478.043040734), (680.063033799, 519.952698773), 0.306453526826, 0.395077506188, 1 -(650.042022533, 479.968465849), (676.250787806, 522.722457614), 0.293892626146, 0.404508497187, 1 -(647.500525204, 481.814971743), (672.3534227, 525.371104205), 0.281041688926, 0.413540287137, 1 -(644.9022818, 483.580736137), (668.374784707, 527.896024653), 0.267913397489, 0.422163962751, 1 -(642.249856472, 485.264016435), (664.318800265, 530.294727166), 0.254520707875, 0.430371013502, 1 -(639.545866843, 486.863151444), (660.189472139, 532.564844513), 0.240876837051, 0.438153340022, 1 -(636.792981426, 488.376563009), (655.990875478, 534.704136364), 0.22699524987, 0.445503262094, 1 -(633.993916986, 489.802757576), (651.727153791, 536.710491495), 0.212889645783, 0.452413526233, 1 -(631.151435861, 491.140327664), (647.402514855, 538.581929877), 0.198573945317, 0.458877312842, 1 -(628.268343237, 492.387953251), (643.021226567, 540.316604624), 0.184062276342, 0.464888242944, 1 -(625.347484378, 493.544403083), (638.58761273, 541.912803824), 0.169368960123, 0.470440384477, 1 -(622.39174182, 494.608535883), (634.106048785, 543.36895222), 0.154508497187, 0.475528258148, 1 -(619.404032523, 495.57930148), (629.580957495, 544.683612769), 0.13949555302, 0.480146842838, 1 -(616.387304997, 496.455741846), (625.016804578, 545.85548806), 0.124344943582, 0.484291580564, 1 -(613.344536386, 497.23699204), (620.418094303, 546.883421593), 0.109071620698, 0.487958380969, 1 -(610.278729536, 497.922281062), (615.789365042, 547.766398923), 0.0936906572929, 0.491143625364, 1 -(607.192910028, 498.510932615), (611.135184791, 548.503548657), 0.0782172325201, 0.493844170298, 1 -(604.090123194, 499.002365772), (606.460146664, 549.094143318), 0.0626666167822, 0.496057350657, 1 -(600.973431109, 499.396095546), (601.768864359, 549.53760006), 0.0470541566593, 0.497780982302, 1 -(597.845909573, 499.691733373), (597.065967606, 549.833481244), 0.0313952597647, 0.499013364214, 1 -(594.710645071, 499.888987496), (592.356097597, 549.981494872), 0.0157053795391, 0.499753280183, 1 -(591.570731731, 499.987663248), (587.643902403, 549.981494872), 3.06161699787e-17, 0.5, 1 -(588.429268269, 499.987663248), (582.934032394, 549.833481244), -0.0157053795391, 0.499753280183, 1 -(585.289354929, 499.888987496), (578.231135641, 549.53760006), -0.0313952597647, 0.499013364214, 1 -(582.154090427, 499.691733373), (573.539853336, 549.094143318), -0.0470541566593, 0.497780982302, 1 -(579.026568891, 499.396095546), (568.864815209, 548.503548657), -0.0626666167822, 0.496057350657, 1 -(575.909876806, 499.002365772), (564.210634958, 547.766398923), -0.0782172325201, 0.493844170298, 1 -(572.807089972, 498.510932615), (559.581905697, 546.883421593), -0.0936906572929, 0.491143625364, 1 -(569.721270464, 497.922281062), (554.983195422, 545.85548806), -0.109071620698, 0.487958380969, 1 -(566.655463614, 497.23699204), (550.419042505, 544.683612769), -0.124344943582, 0.484291580564, 1 -(563.612695003, 496.455741846), (545.893951215, 543.36895222), -0.13949555302, 0.480146842838, 1 -(560.595967477, 495.57930148), (541.41238727, 541.912803824), -0.154508497187, 0.475528258148, 1 -(557.60825818, 494.608535883), (536.978773433, 540.316604624), -0.169368960123, 0.470440384477, 1 -(554.652515622, 493.544403083), (532.597485145, 538.581929877), -0.184062276342, 0.464888242944, 1 -(551.731656763, 492.387953251), (528.272846209, 536.710491495), -0.198573945317, 0.458877312842, 1 -(548.848564139, 491.140327664), (524.009124522, 534.704136364), -0.212889645783, 0.452413526233, 1 -(546.006083014, 489.802757576), (519.810527861, 532.564844513), -0.22699524987, 0.445503262094, 1 -(543.207018574, 488.376563009), (515.681199735, 530.294727166), -0.240876837051, 0.438153340022, 1 -(540.454133157, 486.863151444), (511.625215293, 527.896024653), -0.254520707875, 0.430371013502, 1 -(537.750143528, 485.264016435), (507.6465773, 525.371104205), -0.267913397489, 0.422163962751, 1 -(535.0977182, 483.580736137), (503.749212194, 522.722457614), -0.281041688926, 0.413540287137, 1 -(532.499474796, 481.814971743), (499.936966201, 519.952698773), -0.293892626146, 0.404508497187, 1 -(529.957977467, 479.968465849), (496.21360155, 517.064561101), -0.306453526826, 0.395077506188, 1 -(527.475734366, 478.043040734), (492.58279275, 514.06089484), -0.318711994874, 0.385256621388, 1 -(525.055195167, 476.04059656), (489.048122974, 510.944664247), -0.330655932662, 0.375055534815, 1 -(522.698748649, 473.963109498), (485.613080511, 507.718944664), -0.342273552964, 0.364484313711, 1 -(520.408720341, 471.812629776), (482.281055336, 504.386919489), -0.353553390593, 0.353553390593, 1 -(518.187370224, 469.591279659), (479.055335753, 500.951877026), -0.364484313711, 0.342273552964, 1 -(516.036890502, 467.301251351), (475.93910516, 497.41720725), -0.375055534815, 0.330655932662, 1 -(513.95940344, 464.944804833), (472.935438899, 493.78639845), -0.385256621388, 0.318711994874, 1 -(511.956959266, 462.524265634), (470.047301227, 490.063033799), -0.395077506188, 0.306453526826, 1 -(510.031534151, 460.042022533), (467.277542386, 486.250787806), -0.404508497187, 0.293892626146, 1 -(508.185028257, 457.500525204), (464.628895795, 482.3534227), -0.413540287137, 0.281041688926, 1 -(506.419263863, 454.9022818), (462.103975347, 478.374784707), -0.422163962751, 0.267913397489, 1 -(504.735983565, 452.249856472), (459.705272834, 474.318800265), -0.430371013502, 0.254520707875, 1 -(503.136848556, 449.545866843), (457.435155487, 470.189472139), -0.438153340022, 0.240876837051, 1 -(501.623436991, 446.792981426), (455.295863636, 465.990875478), -0.445503262094, 0.22699524987, 1 -(500.197242424, 443.993916986), (453.289508505, 461.727153791), -0.452413526233, 0.212889645783, 1 -(498.859672336, 441.151435861), (451.418070123, 457.402514855), -0.458877312842, 0.198573945317, 1 -(497.612046749, 438.268343237), (449.683395376, 453.021226567), -0.464888242944, 0.184062276342, 1 -(496.455596917, 435.347484378), (448.087196176, 448.58761273), -0.470440384477, 0.169368960123, 1 -(495.391464117, 432.39174182), (446.63104778, 444.106048785), -0.475528258148, 0.154508497187, 1 -(494.42069852, 429.404032523), (445.316387231, 439.580957495), -0.480146842838, 0.13949555302, 1 -(493.544258154, 426.387304997), (444.14451194, 435.016804578), -0.484291580564, 0.124344943582, 1 -(492.76300796, 423.344536386), (443.116578407, 430.418094303), -0.487958380969, 0.109071620698, 1 -(492.077718938, 420.278729536), (442.233601077, 425.789365042), -0.491143625364, 0.0936906572929, 1 -(491.489067385, 417.192910028), (441.496451343, 421.135184791), -0.493844170298, 0.0782172325201, 1 -(490.997634228, 414.090123194), (440.905856682, 416.460146664), -0.496057350657, 0.0626666167822, 1 -(490.603904454, 410.973431109), (440.46239994, 411.768864359), -0.497780982302, 0.0470541566593, 1 -(490.308266627, 407.845909573), (440.166518756, 407.065967606), -0.499013364214, 0.0313952597647, 1 -(490.111012504, 404.710645071), (440.018505128, 402.356097597), -0.499753280183, 0.0157053795391, 1 -(490.012336752, 401.570731731), (440.018505128, 397.643902403), -0.5, 6.12323399574e-17, 1 -(490.012336752, 398.429268269), (440.166518756, 392.934032394), -0.499753280183, -0.0157053795391, 1 -(490.111012504, 395.289354929), (440.46239994, 388.231135641), -0.499013364214, -0.0313952597647, 1 -(490.308266627, 392.154090427), (440.905856682, 383.539853336), -0.497780982302, -0.0470541566593, 1 -(490.603904454, 389.026568891), (441.496451343, 378.864815209), -0.496057350657, -0.0626666167822, 1 -(490.997634228, 385.909876806), (442.233601077, 374.210634958), -0.493844170298, -0.0782172325201, 1 -(491.489067385, 382.807089972), (443.116578407, 369.581905697), -0.491143625364, -0.0936906572929, 1 -(492.077718938, 379.721270464), (444.14451194, 364.983195422), -0.487958380969, -0.109071620698, 1 -(492.76300796, 376.655463614), (445.316387231, 360.419042505), -0.484291580564, -0.124344943582, 1 -(493.544258154, 373.612695003), (446.63104778, 355.893951215), -0.480146842838, -0.13949555302, 1 -(494.42069852, 370.595967477), (448.087196176, 351.41238727), -0.475528258148, -0.154508497187, 1 -(495.391464117, 367.60825818), (449.683395376, 346.978773433), -0.470440384477, -0.169368960123, 1 -(496.455596917, 364.652515622), (451.418070123, 342.597485145), -0.464888242944, -0.184062276342, 1 -(497.612046749, 361.731656763), (453.289508505, 338.272846209), -0.458877312842, -0.198573945317, 1 -(498.859672336, 358.848564139), (455.295863636, 334.009124522), -0.452413526233, -0.212889645783, 1 -(500.197242424, 356.006083014), (457.435155487, 329.810527861), -0.445503262094, -0.22699524987, 1 -(501.623436991, 353.207018574), (459.705272834, 325.681199735), -0.438153340022, -0.240876837051, 1 -(503.136848556, 350.454133157), (462.103975347, 321.625215293), -0.430371013502, -0.254520707875, 1 -(504.735983565, 347.750143528), (464.628895795, 317.6465773), -0.422163962751, -0.267913397489, 1 -(506.419263863, 345.0977182), (467.277542386, 313.749212194), -0.413540287137, -0.281041688926, 1 -(508.185028257, 342.499474796), (470.047301227, 309.936966201), -0.404508497187, -0.293892626146, 1 -(510.031534151, 339.957977467), (472.935438899, 306.21360155), -0.395077506188, -0.306453526826, 1 -(511.956959266, 337.475734366), (475.93910516, 302.58279275), -0.385256621388, -0.318711994874, 1 -(513.95940344, 335.055195167), (479.055335753, 299.048122974), -0.375055534815, -0.330655932662, 1 -(516.036890502, 332.698748649), (482.281055336, 295.613080511), -0.364484313711, -0.342273552964, 1 -(518.187370224, 330.408720341), (485.613080511, 292.281055336), -0.353553390593, -0.353553390593, 1 -(520.408720341, 328.187370224), (489.048122974, 289.055335753), -0.342273552964, -0.364484313711, 1 -(522.698748649, 326.036890502), (492.58279275, 285.93910516), -0.330655932662, -0.375055534815, 1 -(525.055195167, 323.95940344), (496.21360155, 282.935438899), -0.318711994874, -0.385256621388, 1 -(527.475734366, 321.956959266), (499.936966201, 280.047301227), -0.306453526826, -0.395077506188, 1 -(529.957977467, 320.031534151), (503.749212194, 277.277542386), -0.293892626146, -0.404508497187, 1 -(532.499474796, 318.185028257), (507.6465773, 274.628895795), -0.281041688926, -0.413540287137, 1 -(535.0977182, 316.419263863), (511.625215293, 272.103975347), -0.267913397489, -0.422163962751, 1 -(537.750143528, 314.735983565), (515.681199735, 269.705272834), -0.254520707875, -0.430371013502, 1 -(540.454133157, 313.136848556), (519.810527861, 267.435155487), -0.240876837051, -0.438153340022, 1 -(543.207018574, 311.623436991), (524.009124522, 265.295863636), -0.22699524987, -0.445503262094, 1 -(546.006083014, 310.197242424), (528.272846209, 263.289508505), -0.212889645783, -0.452413526233, 1 -(548.848564139, 308.859672336), (532.597485145, 261.418070123), -0.198573945317, -0.458877312842, 1 -(551.731656763, 307.612046749), (536.978773433, 259.683395376), -0.184062276342, -0.464888242944, 1 -(554.652515622, 306.455596917), (541.41238727, 258.087196176), -0.169368960123, -0.470440384477, 1 -(557.60825818, 305.391464117), (545.893951215, 256.63104778), -0.154508497187, -0.475528258148, 1 -(560.595967477, 304.42069852), (550.419042505, 255.316387231), -0.13949555302, -0.480146842838, 1 -(563.612695003, 303.544258154), (554.983195422, 254.14451194), -0.124344943582, -0.484291580564, 1 -(566.655463614, 302.76300796), (559.581905697, 253.116578407), -0.109071620698, -0.487958380969, 1 -(569.721270464, 302.077718938), (564.210634958, 252.233601077), -0.0936906572929, -0.491143625364, 1 -(572.807089972, 301.489067385), (568.864815209, 251.496451343), -0.0782172325201, -0.493844170298, 1 -(575.909876806, 300.997634228), (573.539853336, 250.905856682), -0.0626666167822, -0.496057350657, 1 -(579.026568891, 300.603904454), (578.231135641, 250.46239994), -0.0470541566593, -0.497780982302, 1 -(582.154090427, 300.308266627), (582.934032394, 250.166518756), -0.0313952597647, -0.499013364214, 1 -(585.289354929, 300.111012504), (587.643902403, 250.018505128), -0.0157053795391, -0.499753280183, 1 -(588.429268269, 300.012336752), (592.356097597, 250.018505128), -9.18485099361e-17, -0.5, 1 -(591.570731731, 300.012336752), (597.065967606, 250.166518756), 0.0157053795391, -0.499753280183, 1 -(594.710645071, 300.111012504), (601.768864359, 250.46239994), 0.0313952597647, -0.499013364214, 1 -(597.845909573, 300.308266627), (606.460146664, 250.905856682), 0.0470541566593, -0.497780982302, 1 -(600.973431109, 300.603904454), (611.135184791, 251.496451343), 0.0626666167822, -0.496057350657, 1 -(604.090123194, 300.997634228), (615.789365042, 252.233601077), 0.0782172325201, -0.493844170298, 1 -(607.192910028, 301.489067385), (620.418094303, 253.116578407), 0.0936906572929, -0.491143625364, 1 -(610.278729536, 302.077718938), (625.016804578, 254.14451194), 0.109071620698, -0.487958380969, 1 -(613.344536386, 302.76300796), (629.580957495, 255.316387231), 0.124344943582, -0.484291580564, 1 -(616.387304997, 303.544258154), (634.106048785, 256.63104778), 0.13949555302, -0.480146842838, 1 -(619.404032523, 304.42069852), (638.58761273, 258.087196176), 0.154508497187, -0.475528258148, 1 -(622.39174182, 305.391464117), (643.021226567, 259.683395376), 0.169368960123, -0.470440384477, 1 -(625.347484378, 306.455596917), (647.402514855, 261.418070123), 0.184062276342, -0.464888242944, 1 -(628.268343237, 307.612046749), (651.727153791, 263.289508505), 0.198573945317, -0.458877312842, 1 -(631.151435861, 308.859672336), (655.990875478, 265.295863636), 0.212889645783, -0.452413526233, 1 -(633.993916986, 310.197242424), (660.189472139, 267.435155487), 0.22699524987, -0.445503262094, 1 -(636.792981426, 311.623436991), (664.318800265, 269.705272834), 0.240876837051, -0.438153340022, 1 -(639.545866843, 313.136848556), (668.374784707, 272.103975347), 0.254520707875, -0.430371013502, 1 -(642.249856472, 314.735983565), (672.3534227, 274.628895795), 0.267913397489, -0.422163962751, 1 -(644.9022818, 316.419263863), (676.250787806, 277.277542386), 0.281041688926, -0.413540287137, 1 -(647.500525204, 318.185028257), (680.063033799, 280.047301227), 0.293892626146, -0.404508497187, 1 -(650.042022533, 320.031534151), (683.78639845, 282.935438899), 0.306453526826, -0.395077506188, 1 -(652.524265634, 321.956959266), (687.41720725, 285.93910516), 0.318711994874, -0.385256621388, 1 -(654.944804833, 323.95940344), (690.951877026, 289.055335753), 0.330655932662, -0.375055534815, 1 -(657.301251351, 326.036890502), (694.386919489, 292.281055336), 0.342273552964, -0.364484313711, 1 -(659.591279659, 328.187370224), (697.718944664, 295.613080511), 0.353553390593, -0.353553390593, 1 -(661.812629776, 330.408720341), (700.944664247, 299.048122974), 0.364484313711, -0.342273552964, 1 -(663.963109498, 332.698748649), (704.06089484, 302.58279275), 0.375055534815, -0.330655932662, 1 -(666.04059656, 335.055195167), (707.064561101, 306.21360155), 0.385256621388, -0.318711994874, 1 -(668.043040734, 337.475734366), (709.952698773, 309.936966201), 0.395077506188, -0.306453526826, 1 -(669.968465849, 339.957977467), (712.722457614, 313.749212194), 0.404508497187, -0.293892626146, 1 -(671.814971743, 342.499474796), (715.371104205, 317.6465773), 0.413540287137, -0.281041688926, 1 -(673.580736137, 345.0977182), (717.896024653, 321.625215293), 0.422163962751, -0.267913397489, 1 -(675.264016435, 347.750143528), (720.294727166, 325.681199735), 0.430371013502, -0.254520707875, 1 -(676.863151444, 350.454133157), (722.564844513, 329.810527861), 0.438153340022, -0.240876837051, 1 -(678.376563009, 353.207018574), (724.704136364, 334.009124522), 0.445503262094, -0.22699524987, 1 -(679.802757576, 356.006083014), (726.710491495, 338.272846209), 0.452413526233, -0.212889645783, 1 -(681.140327664, 358.848564139), (728.581929877, 342.597485145), 0.458877312842, -0.198573945317, 1 -(682.387953251, 361.731656763), (730.316604624, 346.978773433), 0.464888242944, -0.184062276342, 1 -(683.544403083, 364.652515622), (731.912803824, 351.41238727), 0.470440384477, -0.169368960123, 1 -(684.608535883, 367.60825818), (733.36895222, 355.893951215), 0.475528258148, -0.154508497187, 1 -(685.57930148, 370.595967477), (734.683612769, 360.419042505), 0.480146842838, -0.13949555302, 1 -(686.455741846, 373.612695003), (735.85548806, 364.983195422), 0.484291580564, -0.124344943582, 1 -(687.23699204, 376.655463614), (736.883421593, 369.581905697), 0.487958380969, -0.109071620698, 1 -(687.922281062, 379.721270464), (737.766398923, 374.210634958), 0.491143625364, -0.0936906572929, 1 -(688.510932615, 382.807089972), (738.503548657, 378.864815209), 0.493844170298, -0.0782172325201, 1 -(689.002365772, 385.909876806), (739.094143318, 383.539853336), 0.496057350657, -0.0626666167822, 1 -(689.396095546, 389.026568891), (739.53760006, 388.231135641), 0.497780982302, -0.0470541566593, 1 -(689.691733373, 392.154090427), (739.833481244, 392.934032394), 0.499013364214, -0.0313952597647, 1 -(689.888987496, 395.289354929), (739.981494872, 397.643902403), 0.499753280183, -0.0157053795391, 1 -(610.225424859, 385.305368693), (650.676274578, 444.083893922), 0.0, 0.0, 0 -(611.108198138, 386.604330126), (647.788493208, 447.806799231), 0.0, 0.0, 0 -(611.907667001, 387.956158147), (644.672647057, 451.341032945), 0.0, 0.0, 0 -(612.620676312, 389.355517711), (641.341032945, 454.672647057), 0.0, 0.0, 0 -(613.244412147, 390.796886183), (637.806799231, 457.788493208), 0.0, 0.0, 0 -(613.776412907, 392.274575141), (634.083893922, 460.676274578), 0.0, 0.0, 0 -(614.214579028, 393.782752821), (630.187009623, 463.324594413), 0.0, 0.0, 0 -(614.557181268, 395.315467135), (626.131525558, 465.723001003), 0.0, 0.0, 0 -(614.802867533, 396.866669161), (621.933446867, 467.862028935), 0.0, 0.0, 0 -(614.950668211, 398.430237012), (617.609341451, 469.733236442), 0.0, 0.0, 0 -(615.0, 400.0), (613.176274578, 471.329238722), 0.0, 0.0, 0 -(614.950668211, 401.569762988), (608.651741537, 472.643737085), 0.0, 0.0, 0 -(614.802867533, 403.133330839), (604.053598594, 473.671543805), 0.0, 0.0, 0 -(614.557181268, 404.684532865), (599.399992517, 474.408602599), 0.0, 0.0, 0 -(614.214579028, 406.217247179), (594.709288965, 474.852004632), 0.0, 0.0, 0 -(613.776412907, 407.725424859), (590.0, 475.0), 0.0, 0.0, 0 -(613.244412147, 409.203113817), (585.290711035, 474.852004632), 0.0, 0.0, 0 -(612.620676312, 410.644482289), (580.600007483, 474.408602599), 0.0, 0.0, 0 -(611.907667001, 412.043841853), (575.946401406, 473.671543805), 0.0, 0.0, 0 -(611.108198138, 413.395669874), (571.348258463, 472.643737085), 0.0, 0.0, 0 -(610.225424859, 414.694631307), (566.823725422, 471.329238722), 0.0, 0.0, 0 -(609.262831069, 415.935599744), (562.390658549, 469.733236442), 0.0, 0.0, 0 -(608.224215686, 417.113677648), (558.066553133, 467.862028935), 0.0, 0.0, 0 -(607.113677648, 418.224215686), (553.868474442, 465.723001003), 0.0, 0.0, 0 -(605.935599744, 419.262831069), (549.812990377, 463.324594413), 0.0, 0.0, 0 -(604.694631307, 420.225424859), (545.916106078, 460.676274578), 0.0, 0.0, 0 -(603.395669874, 421.108198138), (542.193200769, 457.788493208), -0.0, 0.0, 0 -(602.043841853, 421.907667001), (538.658967055, 454.672647057), -0.0, 0.0, 0 -(600.644482289, 422.620676312), (535.327352943, 451.341032945), -0.0, 0.0, 0 -(599.203113817, 423.244412147), (532.211506792, 447.806799231), -0.0, 0.0, 0 -(597.725424859, 423.776412907), (529.323725422, 444.083893922), -0.0, 0.0, 0 -(596.217247179, 424.214579028), (526.675405587, 440.187009623), -0.0, 0.0, 0 -(594.684532865, 424.557181268), (524.276998997, 436.131525558), -0.0, 0.0, 0 -(593.133330839, 424.802867533), (522.137971065, 431.933446867), -0.0, 0.0, 0 -(591.569762988, 424.950668211), (520.266763558, 427.609341451), -0.0, 0.0, 0 -(590.0, 425.0), (518.670761278, 423.176274578), -0.0, 0.0, 0 -(588.430237012, 424.950668211), (517.356262915, 418.651741537), -0.0, 0.0, 0 -(586.866669161, 424.802867533), (516.328456195, 414.053598594), -0.0, 0.0, 0 -(585.315467135, 424.557181268), (515.591397401, 409.399992517), -0.0, 0.0, 0 -(583.782752821, 424.214579028), (515.147995368, 404.709288965), -0.0, 0.0, 0 -(582.274575141, 423.776412907), (515.0, 400.0), -0.0, 0.0, 0 -(580.796886183, 423.244412147), (515.147995368, 395.290711035), -0.0, 0.0, 0 -(579.355517711, 422.620676312), (515.591397401, 390.600007483), -0.0, 0.0, 0 -(577.956158147, 421.907667001), (516.328456195, 385.946401406), -0.0, 0.0, 0 -(576.604330126, 421.108198138), (517.356262915, 381.348258463), -0.0, 0.0, 0 -(575.305368693, 420.225424859), (518.670761278, 376.823725422), -0.0, 0.0, 0 -(574.064400256, 419.262831069), (520.266763558, 372.390658549), -0.0, 0.0, 0 -(572.886322352, 418.224215686), (522.137971065, 368.066553133), -0.0, 0.0, 0 -(571.775784314, 417.113677648), (524.276998997, 363.868474442), -0.0, 0.0, 0 -(570.737168931, 415.935599744), (526.675405587, 359.812990377), -0.0, 0.0, 0 -(569.774575141, 414.694631307), (529.323725422, 355.916106078), -0.0, 0.0, 0 -(568.891801862, 413.395669874), (532.211506792, 352.193200769), -0.0, -0.0, 0 -(568.092332999, 412.043841853), (535.327352943, 348.658967055), -0.0, -0.0, 0 -(567.379323688, 410.644482289), (538.658967055, 345.327352943), -0.0, -0.0, 0 -(566.755587853, 409.203113817), (542.193200769, 342.211506792), -0.0, -0.0, 0 -(566.223587093, 407.725424859), (545.916106078, 339.323725422), -0.0, -0.0, 0 -(565.785420972, 406.217247179), (549.812990377, 336.675405587), -0.0, -0.0, 0 -(565.442818732, 404.684532865), (553.868474442, 334.276998997), -0.0, -0.0, 0 -(565.197132467, 403.133330839), (558.066553133, 332.137971065), -0.0, -0.0, 0 -(565.049331789, 401.569762988), (562.390658549, 330.266763558), -0.0, -0.0, 0 -(565.0, 400.0), (566.823725422, 328.670761278), -0.0, -0.0, 0 -(565.049331789, 398.430237012), (571.348258463, 327.356262915), -0.0, -0.0, 0 -(565.197132467, 396.866669161), (575.946401406, 326.328456195), -0.0, -0.0, 0 -(565.442818732, 395.315467135), (580.600007483, 325.591397401), -0.0, -0.0, 0 -(565.785420972, 393.782752821), (585.290711035, 325.147995368), -0.0, -0.0, 0 -(566.223587093, 392.274575141), (590.0, 325.0), -0.0, -0.0, 0 -(566.755587853, 390.796886183), (594.709288965, 325.147995368), -0.0, -0.0, 0 -(567.379323688, 389.355517711), (599.399992517, 325.591397401), -0.0, -0.0, 0 -(568.092332999, 387.956158147), (604.053598594, 326.328456195), -0.0, -0.0, 0 -(568.891801862, 386.604330126), (608.651741537, 327.356262915), -0.0, -0.0, 0 -(569.774575141, 385.305368693), (613.176274578, 328.670761278), -0.0, -0.0, 0 -(570.737168931, 384.064400256), (617.609341451, 330.266763558), -0.0, -0.0, 0 -(571.775784314, 382.886322352), (621.933446867, 332.137971065), -0.0, -0.0, 0 -(572.886322352, 381.775784314), (626.131525558, 334.276998997), -0.0, -0.0, 0 -(574.064400256, 380.737168931), (630.187009623, 336.675405587), -0.0, -0.0, 0 -(575.305368693, 379.774575141), (634.083893922, 339.323725422), -0.0, -0.0, 0 -(576.604330126, 378.891801862), (637.806799231, 342.211506792), 0.0, -0.0, 0 -(577.956158147, 378.092332999), (641.341032945, 345.327352943), 0.0, -0.0, 0 -(579.355517711, 377.379323688), (644.672647057, 348.658967055), 0.0, -0.0, 0 -(580.796886183, 376.755587853), (647.788493208, 352.193200769), 0.0, -0.0, 0 -(582.274575141, 376.223587093), (650.676274578, 355.916106078), 0.0, -0.0, 0 -(583.782752821, 375.785420972), (653.324594413, 359.812990377), 0.0, -0.0, 0 -(585.315467135, 375.442818732), (655.723001003, 363.868474442), 0.0, -0.0, 0 -(586.866669161, 375.197132467), (657.862028935, 368.066553133), 0.0, -0.0, 0 -(588.430237012, 375.049331789), (659.733236442, 372.390658549), 0.0, -0.0, 0 -(590.0, 375.0), (661.329238722, 376.823725422), 0.0, -0.0, 0 -(591.569762988, 375.049331789), (662.643737085, 381.348258463), 0.0, -0.0, 0 -(593.133330839, 375.197132467), (663.671543805, 385.946401406), 0.0, -0.0, 0 -(594.684532865, 375.442818732), (664.408602599, 390.600007483), 0.0, -0.0, 0 -(596.217247179, 375.785420972), (664.852004632, 395.290711035), 0.0, -0.0, 0 -(597.725424859, 376.223587093), (665.0, 400.0), 0.0, -0.0, 0 -(599.203113817, 376.755587853), (664.852004632, 404.709288965), 0.0, -0.0, 0 -(600.644482289, 377.379323688), (664.408602599, 409.399992517), 0.0, -0.0, 0 -(602.043841853, 378.092332999), (663.671543805, 414.053598594), 0.0, -0.0, 0 -(603.395669874, 378.891801862), (662.643737085, 418.651741537), 0.0, -0.0, 0 -(604.694631307, 379.774575141), (661.329238722, 423.176274578), 0.0, -0.0, 0 -(605.935599744, 380.737168931), (659.733236442, 427.609341451), 0.0, -0.0, 0 -(607.113677648, 381.775784314), (657.862028935, 431.933446867), 0.0, -0.0, 0 -(608.224215686, 382.886322352), (655.723001003, 436.131525558), 0.0, -0.0, 0 -(609.262831069, 384.064400256), (653.324594413, 440.187009623), 0.0, -0.0, 0 diff --git a/reducer_bench/quad_tree/input/mit.in b/reducer_bench/quad_tree/input/mit.in deleted file mode 100644 index 969392ad..00000000 --- a/reducer_bench/quad_tree/input/mit.in +++ /dev/null @@ -1,810 +0,0 @@ -809 -(300.000000, 300.000000), (344.000000, 344.000000), -0.266432, -0.262006, 0 -(302.000000, 300.000000), (344.000000, 342.000000), -0.261668, -0.265758, 0 -(304.000000, 300.000000), (344.000000, 340.000000), -0.258761, -0.268917, 0 -(306.000000, 300.000000), (344.000000, 338.000000), -0.249487, -0.269045, 0 -(308.000000, 300.000000), (344.000000, 336.000000), -0.243579, -0.264545, 0 -(310.000000, 300.000000), (344.000000, 334.000000), -0.237645, -0.265553, 0 -(312.000000, 300.000000), (344.000000, 332.000000), -0.235607, -0.265965, 0 -(314.000000, 300.000000), (344.000000, 330.000000), -0.234118, -0.263122, 0 -(316.000000, 300.000000), (344.000000, 328.000000), -0.217047, -0.267011, 0 -(318.000000, 300.000000), (344.000000, 326.000000), -0.224407, -0.252430, 0 -(320.000000, 300.000000), (344.000000, 324.000000), -0.206892, -0.259447, 0 -(322.000000, 300.000000), (344.000000, 322.000000), -0.204883, -0.251686, 0 -(324.000000, 300.000000), (344.000000, 320.000000), -0.206238, -0.267617, 0 -(326.000000, 300.000000), (344.000000, 318.000000), -0.203838, -0.255601, 0 -(328.000000, 300.000000), (344.000000, 316.000000), -0.187249, -0.252383, 0 -(330.000000, 300.000000), (344.000000, 314.000000), -0.186759, -0.253681, 0 -(332.000000, 300.000000), (344.000000, 312.000000), -0.184390, -0.258427, 0 -(334.000000, 300.000000), (344.000000, 310.000000), -0.184439, -0.263151, 0 -(336.000000, 300.000000), (344.000000, 308.000000), -0.167344, -0.263926, 0 -(338.000000, 300.000000), (344.000000, 306.000000), -0.167196, -0.250923, 0 -(340.000000, 300.000000), (344.000000, 304.000000), -0.158471, -0.254841, 0 -(342.000000, 300.000000), (344.000000, 302.000000), -0.161476, -0.254078, 0 -(300.000000, 302.000000), (342.000000, 344.000000), -0.250806, -0.260594, 0 -(300.000000, 304.000000), (340.000000, 344.000000), -0.267199, -0.247853, 0 -(300.000000, 306.000000), (338.000000, 344.000000), -0.262604, -0.251606, 0 -(300.000000, 308.000000), (336.000000, 344.000000), -0.260283, -0.249496, 0 -(300.000000, 310.000000), (334.000000, 344.000000), -0.256053, -0.225166, 0 -(300.000000, 312.000000), (332.000000, 344.000000), -0.251182, -0.222292, 0 -(300.000000, 314.000000), (330.000000, 344.000000), -0.267783, -0.215020, 0 -(300.000000, 316.000000), (328.000000, 344.000000), -0.257893, -0.215032, 0 -(300.000000, 318.000000), (326.000000, 344.000000), -0.252403, -0.224652, 0 -(300.000000, 320.000000), (324.000000, 344.000000), -0.258714, -0.216793, 0 -(300.000000, 322.000000), (322.000000, 344.000000), -0.258079, -0.203153, 0 -(300.000000, 324.000000), (320.000000, 344.000000), -0.259944, -0.205422, 0 -(300.000000, 326.000000), (318.000000, 344.000000), -0.252078, -0.187139, 0 -(300.000000, 328.000000), (316.000000, 344.000000), -0.266346, -0.190549, 0 -(300.000000, 330.000000), (314.000000, 344.000000), -0.256980, -0.187821, 0 -(300.000000, 332.000000), (312.000000, 344.000000), -0.264627, -0.177786, 0 -(300.000000, 334.000000), (310.000000, 344.000000), -0.258415, -0.176827, 0 -(300.000000, 336.000000), (308.000000, 344.000000), -0.265639, -0.161019, 0 -(300.000000, 338.000000), (306.000000, 344.000000), -0.258433, -0.160923, 0 -(300.000000, 340.000000), (304.000000, 344.000000), -0.250515, -0.164486, 0 -(300.000000, 342.000000), (302.000000, 344.000000), -0.256089, -0.146697, 0 -(300.000000, 346.000000), (300.000000, 390.000000), -0.266777, -0.138872, 0 -(302.000000, 346.000000), (302.000000, 390.000000), -0.246717, -0.139670, 0 -(304.000000, 346.000000), (304.000000, 390.000000), -0.248904, -0.139120, 0 -(306.000000, 346.000000), (306.000000, 390.000000), -0.239322, -0.152618, 0 -(308.000000, 346.000000), (308.000000, 390.000000), -0.230913, -0.147401, 0 -(310.000000, 346.000000), (310.000000, 390.000000), -0.230770, -0.145857, 0 -(312.000000, 346.000000), (312.000000, 390.000000), -0.227823, -0.142849, 0 -(314.000000, 346.000000), (314.000000, 390.000000), -0.227996, -0.139168, 0 -(316.000000, 346.000000), (316.000000, 390.000000), -0.228398, -0.154976, 0 -(318.000000, 346.000000), (318.000000, 390.000000), -0.221990, -0.148025, 0 -(320.000000, 346.000000), (320.000000, 390.000000), -0.207762, -0.140405, 0 -(322.000000, 346.000000), (322.000000, 390.000000), -0.199851, -0.138402, 0 -(324.000000, 346.000000), (324.000000, 390.000000), -0.196424, -0.148284, 0 -(326.000000, 346.000000), (326.000000, 390.000000), -0.194324, -0.141939, 0 -(328.000000, 346.000000), (328.000000, 390.000000), -0.187770, -0.150413, 0 -(330.000000, 346.000000), (330.000000, 390.000000), -0.183636, -0.139547, 0 -(332.000000, 346.000000), (332.000000, 390.000000), -0.189285, -0.145353, 0 -(334.000000, 346.000000), (334.000000, 390.000000), -0.174217, -0.143189, 0 -(336.000000, 346.000000), (336.000000, 390.000000), -0.174474, -0.148539, 0 -(338.000000, 346.000000), (338.000000, 390.000000), -0.160807, -0.150387, 0 -(340.000000, 346.000000), (340.000000, 390.000000), -0.155940, -0.146577, 0 -(342.000000, 346.000000), (342.000000, 390.000000), -0.151243, -0.148763, 0 -(344.000000, 346.000000), (344.000000, 390.000000), -0.159425, -0.154239, 0 -(300.000000, 436.000000), (344.000000, 392.000000), -0.267931, 0.072177, 0 -(300.000000, 434.000000), (342.000000, 392.000000), -0.269215, 0.070079, 0 -(300.000000, 432.000000), (340.000000, 392.000000), -0.260848, 0.073023, 0 -(300.000000, 430.000000), (338.000000, 392.000000), -0.250326, 0.059300, 0 -(300.000000, 428.000000), (336.000000, 392.000000), -0.260379, 0.063250, 0 -(300.000000, 426.000000), (334.000000, 392.000000), -0.258984, 0.045297, 0 -(300.000000, 424.000000), (332.000000, 392.000000), -0.263689, 0.043246, 0 -(300.000000, 422.000000), (330.000000, 392.000000), -0.265116, 0.052675, 0 -(300.000000, 420.000000), (328.000000, 392.000000), -0.251301, 0.035599, 0 -(300.000000, 418.000000), (326.000000, 392.000000), -0.262678, 0.034482, 0 -(300.000000, 416.000000), (324.000000, 392.000000), -0.252590, 0.032848, 0 -(300.000000, 414.000000), (322.000000, 392.000000), -0.254057, 0.026603, 0 -(300.000000, 412.000000), (320.000000, 392.000000), -0.252539, 0.020003, 0 -(300.000000, 410.000000), (318.000000, 392.000000), -0.269973, 0.016218, 0 -(300.000000, 408.000000), (316.000000, 392.000000), -0.253760, 0.000601, 0 -(300.000000, 406.000000), (314.000000, 392.000000), -0.258021, 0.013309, 0 -(300.000000, 404.000000), (312.000000, 392.000000), -0.267222, 0.002764, 0 -(300.000000, 402.000000), (310.000000, 392.000000), -0.266612, -0.003070, 0 -(300.000000, 400.000000), (308.000000, 392.000000), -0.264213, -0.016938, 0 -(300.000000, 398.000000), (306.000000, 392.000000), -0.253770, -0.009592, 0 -(300.000000, 396.000000), (304.000000, 392.000000), -0.253688, -0.022754, 0 -(300.000000, 394.000000), (302.000000, 392.000000), -0.254295, -0.032377, 0 -(302.000000, 436.000000), (344.000000, 394.000000), -0.254507, 0.070589, 0 -(304.000000, 436.000000), (344.000000, 396.000000), -0.259702, 0.079192, 0 -(306.000000, 436.000000), (344.000000, 398.000000), -0.248812, 0.077620, 0 -(308.000000, 436.000000), (344.000000, 400.000000), -0.231326, 0.073598, 0 -(310.000000, 436.000000), (344.000000, 402.000000), -0.244532, 0.084617, 0 -(312.000000, 436.000000), (344.000000, 404.000000), -0.224799, 0.087930, 0 -(314.000000, 436.000000), (344.000000, 406.000000), -0.230380, 0.085228, 0 -(316.000000, 436.000000), (344.000000, 408.000000), -0.220852, 0.070860, 0 -(318.000000, 436.000000), (344.000000, 410.000000), -0.209171, 0.071127, 0 -(320.000000, 436.000000), (344.000000, 412.000000), -0.200830, 0.088607, 0 -(322.000000, 436.000000), (344.000000, 414.000000), -0.201109, 0.072558, 0 -(324.000000, 436.000000), (344.000000, 416.000000), -0.199464, 0.089678, 0 -(326.000000, 436.000000), (344.000000, 418.000000), -0.199380, 0.076766, 0 -(328.000000, 436.000000), (344.000000, 420.000000), -0.184914, 0.071932, 0 -(330.000000, 436.000000), (344.000000, 422.000000), -0.180988, 0.080791, 0 -(332.000000, 436.000000), (344.000000, 424.000000), -0.185444, 0.074505, 0 -(334.000000, 436.000000), (344.000000, 426.000000), -0.173620, 0.074854, 0 -(336.000000, 436.000000), (344.000000, 428.000000), -0.166303, 0.087568, 0 -(338.000000, 436.000000), (344.000000, 430.000000), -0.162526, 0.082371, 0 -(340.000000, 436.000000), (344.000000, 432.000000), -0.168834, 0.082942, 0 -(342.000000, 436.000000), (344.000000, 434.000000), -0.158012, 0.086367, 0 -(300.000000, 438.000000), (344.000000, 438.000000), -0.259128, 0.086608, 0 -(300.000000, 440.000000), (344.000000, 440.000000), -0.258405, 0.080020, 0 -(300.000000, 442.000000), (344.000000, 442.000000), -0.257532, 0.092424, 0 -(300.000000, 444.000000), (344.000000, 444.000000), -0.268854, 0.101638, 0 -(300.000000, 446.000000), (344.000000, 446.000000), -0.263970, 0.110037, 0 -(300.000000, 448.000000), (344.000000, 448.000000), -0.255804, 0.116566, 0 -(300.000000, 450.000000), (344.000000, 450.000000), -0.255284, 0.124816, 0 -(300.000000, 452.000000), (344.000000, 452.000000), -0.266668, 0.119802, 0 -(300.000000, 454.000000), (344.000000, 454.000000), -0.268252, 0.132344, 0 -(300.000000, 456.000000), (344.000000, 456.000000), -0.269407, 0.126304, 0 -(300.000000, 458.000000), (344.000000, 458.000000), -0.268151, 0.136973, 0 -(300.000000, 460.000000), (344.000000, 460.000000), -0.258842, 0.145546, 0 -(300.000000, 462.000000), (344.000000, 462.000000), -0.260459, 0.138632, 0 -(300.000000, 464.000000), (344.000000, 464.000000), -0.262083, 0.150707, 0 -(300.000000, 466.000000), (344.000000, 466.000000), -0.253426, 0.159904, 0 -(300.000000, 468.000000), (344.000000, 468.000000), -0.262926, 0.157446, 0 -(300.000000, 470.000000), (344.000000, 470.000000), -0.263488, 0.173669, 0 -(300.000000, 472.000000), (344.000000, 472.000000), -0.262535, 0.178980, 0 -(300.000000, 474.000000), (344.000000, 474.000000), -0.263908, 0.173612, 0 -(300.000000, 476.000000), (344.000000, 476.000000), -0.259382, 0.182122, 0 -(300.000000, 478.000000), (344.000000, 478.000000), -0.266351, 0.179814, 0 -(300.000000, 480.000000), (344.000000, 480.000000), -0.261312, 0.198365, 0 -(300.000000, 482.000000), (344.000000, 482.000000), -0.265371, 0.197021, 0 -(300.000000, 484.000000), (344.000000, 528.000000), -0.261833, 0.196377, 0 -(302.000000, 484.000000), (344.000000, 526.000000), -0.255635, 0.198760, 0 -(304.000000, 484.000000), (344.000000, 524.000000), -0.247319, 0.201214, 0 -(306.000000, 484.000000), (344.000000, 522.000000), -0.254267, 0.193839, 0 -(308.000000, 484.000000), (344.000000, 520.000000), -0.243240, 0.200275, 0 -(310.000000, 484.000000), (344.000000, 518.000000), -0.237529, 0.204676, 0 -(312.000000, 484.000000), (344.000000, 516.000000), -0.239018, 0.194045, 0 -(314.000000, 484.000000), (344.000000, 514.000000), -0.225419, 0.198056, 0 -(316.000000, 484.000000), (344.000000, 512.000000), -0.218509, 0.206093, 0 -(318.000000, 484.000000), (344.000000, 510.000000), -0.218276, 0.208956, 0 -(320.000000, 484.000000), (344.000000, 508.000000), -0.204927, 0.202817, 0 -(322.000000, 484.000000), (344.000000, 506.000000), -0.207432, 0.195692, 0 -(324.000000, 484.000000), (344.000000, 504.000000), -0.205061, 0.201217, 0 -(326.000000, 484.000000), (344.000000, 502.000000), -0.194495, 0.203627, 0 -(328.000000, 484.000000), (344.000000, 500.000000), -0.190418, 0.205135, 0 -(330.000000, 484.000000), (344.000000, 498.000000), -0.189352, 0.207748, 0 -(332.000000, 484.000000), (344.000000, 496.000000), -0.188488, 0.205013, 0 -(334.000000, 484.000000), (344.000000, 494.000000), -0.178492, 0.204193, 0 -(336.000000, 484.000000), (344.000000, 492.000000), -0.173773, 0.197242, 0 -(338.000000, 484.000000), (344.000000, 490.000000), -0.156968, 0.202986, 0 -(340.000000, 484.000000), (344.000000, 488.000000), -0.152484, 0.195502, 0 -(342.000000, 484.000000), (344.000000, 486.000000), -0.157338, 0.208498, 0 -(300.000000, 486.000000), (342.000000, 528.000000), -0.260453, 0.212243, 0 -(300.000000, 488.000000), (340.000000, 528.000000), -0.263446, 0.201038, 0 -(300.000000, 490.000000), (338.000000, 528.000000), -0.256664, 0.218278, 0 -(300.000000, 492.000000), (336.000000, 528.000000), -0.250006, 0.218409, 0 -(300.000000, 494.000000), (334.000000, 528.000000), -0.263905, 0.222562, 0 -(300.000000, 496.000000), (332.000000, 528.000000), -0.255899, 0.231034, 0 -(300.000000, 498.000000), (330.000000, 528.000000), -0.251221, 0.229606, 0 -(300.000000, 500.000000), (328.000000, 528.000000), -0.265339, 0.238361, 0 -(300.000000, 502.000000), (326.000000, 528.000000), -0.250259, 0.245309, 0 -(300.000000, 504.000000), (324.000000, 528.000000), -0.263891, 0.241253, 0 -(300.000000, 506.000000), (322.000000, 528.000000), -0.264678, 0.257617, 0 -(300.000000, 508.000000), (320.000000, 528.000000), -0.254553, 0.261548, 0 -(300.000000, 510.000000), (318.000000, 528.000000), -0.250141, 0.268478, 0 -(300.000000, 512.000000), (316.000000, 528.000000), -0.265466, 0.277375, 0 -(300.000000, 514.000000), (314.000000, 528.000000), -0.251019, 0.277197, 0 -(300.000000, 516.000000), (312.000000, 528.000000), -0.254126, 0.278528, 0 -(300.000000, 518.000000), (310.000000, 528.000000), -0.260560, 0.277428, 0 -(300.000000, 520.000000), (308.000000, 528.000000), -0.260434, 0.282775, 0 -(300.000000, 522.000000), (306.000000, 528.000000), -0.254294, 0.294560, 0 -(300.000000, 524.000000), (304.000000, 528.000000), -0.258816, 0.291801, 0 -(300.000000, 526.000000), (302.000000, 528.000000), -0.252878, 0.300285, 0 -(400.000000, 344.000000), (444.000000, 300.000000), -0.007166, -0.144100, 0 -(400.000000, 342.000000), (442.000000, 300.000000), -0.010109, -0.147505, 0 -(400.000000, 340.000000), (440.000000, 300.000000), -0.015739, -0.160368, 0 -(400.000000, 338.000000), (438.000000, 300.000000), -0.012196, -0.164630, 0 -(400.000000, 336.000000), (436.000000, 300.000000), -0.009115, -0.166874, 0 -(400.000000, 334.000000), (434.000000, 300.000000), -0.017012, -0.178668, 0 -(400.000000, 332.000000), (432.000000, 300.000000), -0.015326, -0.187153, 0 -(400.000000, 330.000000), (430.000000, 300.000000), -0.000190, -0.185792, 0 -(400.000000, 328.000000), (428.000000, 300.000000), -0.019778, -0.181209, 0 -(400.000000, 326.000000), (426.000000, 300.000000), -0.018595, -0.188904, 0 -(400.000000, 324.000000), (424.000000, 300.000000), -0.012681, -0.199155, 0 -(400.000000, 322.000000), (422.000000, 300.000000), -0.001477, -0.198115, 0 -(400.000000, 320.000000), (420.000000, 300.000000), -0.006380, -0.205771, 0 -(400.000000, 318.000000), (418.000000, 300.000000), -0.013555, -0.220195, 0 -(400.000000, 316.000000), (416.000000, 300.000000), -0.003970, -0.226434, 0 -(400.000000, 314.000000), (414.000000, 300.000000), -0.009910, -0.226135, 0 -(400.000000, 312.000000), (412.000000, 300.000000), -0.000533, -0.220019, 0 -(400.000000, 310.000000), (410.000000, 300.000000), -0.013640, -0.241272, 0 -(400.000000, 308.000000), (408.000000, 300.000000), -0.010387, -0.235836, 0 -(400.000000, 306.000000), (406.000000, 300.000000), -0.005901, -0.254502, 0 -(400.000000, 304.000000), (404.000000, 300.000000), -0.012710, -0.242914, 0 -(400.000000, 302.000000), (402.000000, 300.000000), -0.013170, -0.253037, 0 -(402.000000, 344.000000), (444.000000, 302.000000), 0.004933, -0.153360, 0 -(404.000000, 344.000000), (444.000000, 304.000000), -0.008828, -0.159844, 0 -(406.000000, 344.000000), (444.000000, 306.000000), 0.000431, -0.157423, 0 -(408.000000, 344.000000), (444.000000, 308.000000), 0.016252, -0.147249, 0 -(410.000000, 344.000000), (444.000000, 310.000000), 0.018421, -0.145225, 0 -(412.000000, 344.000000), (444.000000, 312.000000), 0.019636, -0.152958, 0 -(414.000000, 344.000000), (444.000000, 314.000000), 0.024004, -0.143919, 0 -(416.000000, 344.000000), (444.000000, 316.000000), 0.031846, -0.154966, 0 -(418.000000, 344.000000), (444.000000, 318.000000), 0.044647, -0.158064, 0 -(420.000000, 344.000000), (444.000000, 320.000000), 0.043899, -0.140886, 0 -(422.000000, 344.000000), (444.000000, 322.000000), 0.036917, -0.159741, 0 -(424.000000, 344.000000), (444.000000, 324.000000), 0.042842, -0.148471, 0 -(426.000000, 344.000000), (444.000000, 326.000000), 0.059423, -0.143059, 0 -(428.000000, 344.000000), (444.000000, 328.000000), 0.062027, -0.158287, 0 -(430.000000, 344.000000), (444.000000, 330.000000), 0.069028, -0.141143, 0 -(432.000000, 344.000000), (444.000000, 332.000000), 0.073676, -0.146039, 0 -(434.000000, 344.000000), (444.000000, 334.000000), 0.070497, -0.145152, 0 -(436.000000, 344.000000), (444.000000, 336.000000), 0.084117, -0.149071, 0 -(438.000000, 344.000000), (444.000000, 338.000000), 0.092424, -0.149632, 0 -(440.000000, 344.000000), (444.000000, 340.000000), 0.083679, -0.149155, 0 -(442.000000, 344.000000), (444.000000, 342.000000), 0.090143, -0.146685, 0 -(400.000000, 346.000000), (400.000000, 390.000000), -0.002113, -0.140853, 0 -(402.000000, 346.000000), (402.000000, 390.000000), -0.005604, -0.145267, 0 -(404.000000, 346.000000), (404.000000, 390.000000), 0.009182, -0.145957, 0 -(406.000000, 346.000000), (406.000000, 390.000000), 0.006669, -0.141919, 0 -(408.000000, 346.000000), (408.000000, 390.000000), 0.008157, -0.141414, 0 -(410.000000, 346.000000), (410.000000, 390.000000), 0.018339, -0.144000, 0 -(412.000000, 346.000000), (412.000000, 390.000000), 0.015115, -0.147238, 0 -(414.000000, 346.000000), (414.000000, 390.000000), 0.022941, -0.137857, 0 -(416.000000, 346.000000), (416.000000, 390.000000), 0.029475, -0.153032, 0 -(418.000000, 346.000000), (418.000000, 390.000000), 0.041000, -0.151849, 0 -(420.000000, 346.000000), (420.000000, 390.000000), 0.045929, -0.153503, 0 -(422.000000, 346.000000), (422.000000, 390.000000), 0.052998, -0.144954, 0 -(424.000000, 346.000000), (424.000000, 390.000000), 0.052426, -0.139577, 0 -(426.000000, 346.000000), (426.000000, 390.000000), 0.045414, -0.138895, 0 -(428.000000, 346.000000), (428.000000, 390.000000), 0.056268, -0.149443, 0 -(430.000000, 346.000000), (430.000000, 390.000000), 0.064420, -0.150845, 0 -(432.000000, 346.000000), (432.000000, 390.000000), 0.079704, -0.136184, 0 -(434.000000, 346.000000), (434.000000, 390.000000), 0.078888, -0.136114, 0 -(436.000000, 346.000000), (436.000000, 390.000000), 0.077859, -0.149443, 0 -(438.000000, 346.000000), (438.000000, 390.000000), 0.086966, -0.138984, 0 -(440.000000, 346.000000), (440.000000, 390.000000), 0.099143, -0.149694, 0 -(442.000000, 346.000000), (442.000000, 390.000000), 0.092016, -0.150742, 0 -(444.000000, 346.000000), (444.000000, 390.000000), 0.103068, -0.140043, 0 -(400.000000, 392.000000), (444.000000, 436.000000), -0.018599, -0.037457, 0 -(402.000000, 392.000000), (444.000000, 434.000000), 0.001925, -0.022599, 0 -(404.000000, 392.000000), (444.000000, 432.000000), -0.004306, -0.027145, 0 -(406.000000, 392.000000), (444.000000, 430.000000), 0.013898, -0.036308, 0 -(408.000000, 392.000000), (444.000000, 428.000000), 0.002901, -0.028677, 0 -(410.000000, 392.000000), (444.000000, 426.000000), 0.024115, -0.036685, 0 -(412.000000, 392.000000), (444.000000, 424.000000), 0.017428, -0.034617, 0 -(414.000000, 392.000000), (444.000000, 422.000000), 0.023872, -0.023152, 0 -(416.000000, 392.000000), (444.000000, 420.000000), 0.029538, -0.031424, 0 -(418.000000, 392.000000), (444.000000, 418.000000), 0.040664, -0.036574, 0 -(420.000000, 392.000000), (444.000000, 416.000000), 0.037462, -0.036477, 0 -(422.000000, 392.000000), (444.000000, 414.000000), 0.043984, -0.020572, 0 -(424.000000, 392.000000), (444.000000, 412.000000), 0.059540, -0.031873, 0 -(426.000000, 392.000000), (444.000000, 410.000000), 0.049734, -0.033444, 0 -(428.000000, 392.000000), (444.000000, 408.000000), 0.062385, -0.022198, 0 -(430.000000, 392.000000), (444.000000, 406.000000), 0.056513, -0.026214, 0 -(432.000000, 392.000000), (444.000000, 404.000000), 0.060345, -0.021561, 0 -(434.000000, 392.000000), (444.000000, 402.000000), 0.076187, -0.033961, 0 -(436.000000, 392.000000), (444.000000, 400.000000), 0.081293, -0.029915, 0 -(438.000000, 392.000000), (444.000000, 398.000000), 0.084731, -0.025806, 0 -(440.000000, 392.000000), (444.000000, 396.000000), 0.081408, -0.031154, 0 -(442.000000, 392.000000), (444.000000, 394.000000), 0.102508, -0.031163, 0 -(400.000000, 394.000000), (442.000000, 436.000000), -0.005771, -0.028620, 0 -(400.000000, 396.000000), (440.000000, 436.000000), -0.014315, -0.026233, 0 -(400.000000, 398.000000), (438.000000, 436.000000), -0.005044, -0.023651, 0 -(400.000000, 400.000000), (436.000000, 436.000000), -0.012807, -0.017582, 0 -(400.000000, 402.000000), (434.000000, 436.000000), -0.015127, 0.001177, 0 -(400.000000, 404.000000), (432.000000, 436.000000), -0.018154, -0.005588, 0 -(400.000000, 406.000000), (430.000000, 436.000000), -0.015696, 0.001580, 0 -(400.000000, 408.000000), (428.000000, 436.000000), -0.009032, 0.016689, 0 -(400.000000, 410.000000), (426.000000, 436.000000), -0.015617, 0.017482, 0 -(400.000000, 412.000000), (424.000000, 436.000000), -0.009524, 0.014728, 0 -(400.000000, 414.000000), (422.000000, 436.000000), -0.009080, 0.016663, 0 -(400.000000, 416.000000), (420.000000, 436.000000), -0.009233, 0.022213, 0 -(400.000000, 418.000000), (418.000000, 436.000000), -0.008253, 0.025499, 0 -(400.000000, 420.000000), (416.000000, 436.000000), -0.003593, 0.043156, 0 -(400.000000, 422.000000), (414.000000, 436.000000), -0.010655, 0.048915, 0 -(400.000000, 424.000000), (412.000000, 436.000000), -0.018008, 0.043574, 0 -(400.000000, 426.000000), (410.000000, 436.000000), -0.019705, 0.052677, 0 -(400.000000, 428.000000), (408.000000, 436.000000), -0.012659, 0.065251, 0 -(400.000000, 430.000000), (406.000000, 436.000000), -0.010974, 0.069535, 0 -(400.000000, 432.000000), (404.000000, 436.000000), -0.002331, 0.073899, 0 -(400.000000, 434.000000), (402.000000, 436.000000), -0.009288, 0.084515, 0 -(500.000000, 344.000000), (544.000000, 300.000000), 0.248311, -0.144985, 0 -(500.000000, 342.000000), (542.000000, 300.000000), 0.236096, -0.155720, 0 -(500.000000, 340.000000), (540.000000, 300.000000), 0.241705, -0.159521, 0 -(500.000000, 338.000000), (538.000000, 300.000000), 0.231761, -0.172820, 0 -(500.000000, 336.000000), (536.000000, 300.000000), 0.245207, -0.167319, 0 -(500.000000, 334.000000), (534.000000, 300.000000), 0.233843, -0.179026, 0 -(500.000000, 332.000000), (532.000000, 300.000000), 0.244895, -0.174410, 0 -(500.000000, 330.000000), (530.000000, 300.000000), 0.236473, -0.183698, 0 -(500.000000, 328.000000), (528.000000, 300.000000), 0.238746, -0.184182, 0 -(500.000000, 326.000000), (526.000000, 300.000000), 0.235217, -0.194262, 0 -(500.000000, 324.000000), (524.000000, 300.000000), 0.249392, -0.204488, 0 -(500.000000, 322.000000), (522.000000, 300.000000), 0.248415, -0.208266, 0 -(500.000000, 320.000000), (520.000000, 300.000000), 0.230763, -0.212559, 0 -(500.000000, 318.000000), (518.000000, 300.000000), 0.231268, -0.206568, 0 -(500.000000, 316.000000), (516.000000, 300.000000), 0.231340, -0.218020, 0 -(500.000000, 314.000000), (514.000000, 300.000000), 0.247948, -0.215349, 0 -(500.000000, 312.000000), (512.000000, 300.000000), 0.236995, -0.235957, 0 -(500.000000, 310.000000), (510.000000, 300.000000), 0.238931, -0.226300, 0 -(500.000000, 308.000000), (508.000000, 300.000000), 0.244522, -0.239308, 0 -(500.000000, 306.000000), (506.000000, 300.000000), 0.230880, -0.245271, 0 -(500.000000, 304.000000), (504.000000, 300.000000), 0.233374, -0.255277, 0 -(500.000000, 302.000000), (502.000000, 300.000000), 0.245703, -0.246731, 0 -(502.000000, 344.000000), (544.000000, 302.000000), 0.235313, -0.157824, 0 -(504.000000, 344.000000), (544.000000, 304.000000), 0.249570, -0.150941, 0 -(506.000000, 344.000000), (544.000000, 306.000000), 0.262994, -0.145213, 0 -(508.000000, 344.000000), (544.000000, 308.000000), 0.269797, -0.142614, 0 -(510.000000, 344.000000), (544.000000, 310.000000), 0.255299, -0.141788, 0 -(512.000000, 344.000000), (544.000000, 312.000000), 0.264120, -0.158937, 0 -(514.000000, 344.000000), (544.000000, 314.000000), 0.270653, -0.154612, 0 -(516.000000, 344.000000), (544.000000, 316.000000), 0.289495, -0.153007, 0 -(518.000000, 344.000000), (544.000000, 318.000000), 0.292368, -0.142557, 0 -(520.000000, 344.000000), (544.000000, 320.000000), 0.286644, -0.155636, 0 -(522.000000, 344.000000), (544.000000, 322.000000), 0.286486, -0.144425, 0 -(524.000000, 344.000000), (544.000000, 324.000000), 0.293064, -0.143991, 0 -(526.000000, 344.000000), (544.000000, 326.000000), 0.301267, -0.156056, 0 -(528.000000, 344.000000), (544.000000, 328.000000), 0.305737, -0.150359, 0 -(530.000000, 344.000000), (544.000000, 330.000000), 0.313667, -0.158560, 0 -(532.000000, 344.000000), (544.000000, 332.000000), 0.317910, -0.151020, 0 -(534.000000, 344.000000), (544.000000, 334.000000), 0.318616, -0.142520, 0 -(536.000000, 344.000000), (544.000000, 336.000000), 0.338039, -0.158390, 0 -(538.000000, 344.000000), (544.000000, 338.000000), 0.337267, -0.142165, 0 -(540.000000, 344.000000), (544.000000, 340.000000), 0.348996, -0.147433, 0 -(542.000000, 344.000000), (544.000000, 342.000000), 0.351047, -0.156884, 0 -(500.000000, 346.000000), (544.000000, 346.000000), 0.243630, -0.153300, 0 -(500.000000, 348.000000), (544.000000, 348.000000), 0.238505, -0.136875, 0 -(500.000000, 350.000000), (544.000000, 350.000000), 0.238692, -0.139127, 0 -(500.000000, 352.000000), (544.000000, 352.000000), 0.240568, -0.124664, 0 -(500.000000, 354.000000), (544.000000, 354.000000), 0.240237, -0.122946, 0 -(500.000000, 356.000000), (544.000000, 356.000000), 0.240911, -0.116699, 0 -(500.000000, 358.000000), (544.000000, 358.000000), 0.238063, -0.107822, 0 -(500.000000, 360.000000), (544.000000, 360.000000), 0.247244, -0.106200, 0 -(500.000000, 362.000000), (544.000000, 362.000000), 0.236820, -0.109089, 0 -(500.000000, 364.000000), (544.000000, 364.000000), 0.245240, -0.095271, 0 -(500.000000, 366.000000), (544.000000, 366.000000), 0.244891, -0.086144, 0 -(500.000000, 368.000000), (544.000000, 368.000000), 0.242209, -0.087070, 0 -(500.000000, 370.000000), (544.000000, 370.000000), 0.230466, -0.090523, 0 -(500.000000, 372.000000), (544.000000, 372.000000), 0.240765, -0.070538, 0 -(500.000000, 374.000000), (544.000000, 374.000000), 0.247043, -0.078188, 0 -(500.000000, 376.000000), (544.000000, 376.000000), 0.232578, -0.069327, 0 -(500.000000, 378.000000), (544.000000, 378.000000), 0.238512, -0.063917, 0 -(500.000000, 380.000000), (544.000000, 380.000000), 0.233798, -0.052796, 0 -(500.000000, 382.000000), (544.000000, 382.000000), 0.246956, -0.050634, 0 -(500.000000, 384.000000), (544.000000, 384.000000), 0.242540, -0.052807, 0 -(500.000000, 386.000000), (544.000000, 386.000000), 0.236420, -0.051549, 0 -(500.000000, 388.000000), (544.000000, 388.000000), 0.230493, -0.035517, 0 -(500.000000, 390.000000), (544.000000, 390.000000), 0.230629, -0.027262, 0 -(500.000000, 392.000000), (544.000000, 436.000000), 0.238284, -0.032551, 0 -(502.000000, 392.000000), (544.000000, 434.000000), 0.238649, -0.036476, 0 -(504.000000, 392.000000), (544.000000, 432.000000), 0.242178, -0.021460, 0 -(506.000000, 392.000000), (544.000000, 430.000000), 0.247380, -0.025613, 0 -(508.000000, 392.000000), (544.000000, 428.000000), 0.261470, -0.037154, 0 -(510.000000, 392.000000), (544.000000, 426.000000), 0.273864, -0.037765, 0 -(512.000000, 392.000000), (544.000000, 424.000000), 0.262308, -0.024093, 0 -(514.000000, 392.000000), (544.000000, 422.000000), 0.274048, -0.035113, 0 -(516.000000, 392.000000), (544.000000, 420.000000), 0.276580, -0.022441, 0 -(518.000000, 392.000000), (544.000000, 418.000000), 0.290969, -0.029622, 0 -(520.000000, 392.000000), (544.000000, 416.000000), 0.294763, -0.027075, 0 -(522.000000, 392.000000), (544.000000, 414.000000), 0.289744, -0.032697, 0 -(524.000000, 392.000000), (544.000000, 412.000000), 0.290118, -0.028835, 0 -(526.000000, 392.000000), (544.000000, 410.000000), 0.305754, -0.039388, 0 -(528.000000, 392.000000), (544.000000, 408.000000), 0.305648, -0.028616, 0 -(530.000000, 392.000000), (544.000000, 406.000000), 0.323349, -0.026068, 0 -(532.000000, 392.000000), (544.000000, 404.000000), 0.328832, -0.038002, 0 -(534.000000, 392.000000), (544.000000, 402.000000), 0.332456, -0.038990, 0 -(536.000000, 392.000000), (544.000000, 400.000000), 0.320538, -0.020164, 0 -(538.000000, 392.000000), (544.000000, 398.000000), 0.340398, -0.027991, 0 -(540.000000, 392.000000), (544.000000, 396.000000), 0.332682, -0.025738, 0 -(542.000000, 392.000000), (544.000000, 394.000000), 0.349244, -0.035009, 0 -(500.000000, 394.000000), (542.000000, 436.000000), 0.240169, -0.031709, 0 -(500.000000, 396.000000), (540.000000, 436.000000), 0.239877, -0.013250, 0 -(500.000000, 398.000000), (538.000000, 436.000000), 0.230851, -0.019153, 0 -(500.000000, 400.000000), (536.000000, 436.000000), 0.237128, -0.004386, 0 -(500.000000, 402.000000), (534.000000, 436.000000), 0.248772, -0.003127, 0 -(500.000000, 404.000000), (532.000000, 436.000000), 0.232918, 0.008890, 0 -(500.000000, 406.000000), (530.000000, 436.000000), 0.233037, 0.008672, 0 -(500.000000, 408.000000), (528.000000, 436.000000), 0.249502, 0.008686, 0 -(500.000000, 410.000000), (526.000000, 436.000000), 0.235056, 0.022851, 0 -(500.000000, 412.000000), (524.000000, 436.000000), 0.232618, 0.013888, 0 -(500.000000, 414.000000), (522.000000, 436.000000), 0.249849, 0.015073, 0 -(500.000000, 416.000000), (520.000000, 436.000000), 0.234898, 0.020388, 0 -(500.000000, 418.000000), (518.000000, 436.000000), 0.249909, 0.025296, 0 -(500.000000, 420.000000), (516.000000, 436.000000), 0.242396, 0.032592, 0 -(500.000000, 422.000000), (514.000000, 436.000000), 0.244558, 0.041640, 0 -(500.000000, 424.000000), (512.000000, 436.000000), 0.237582, 0.044727, 0 -(500.000000, 426.000000), (510.000000, 436.000000), 0.239932, 0.062460, 0 -(500.000000, 428.000000), (508.000000, 436.000000), 0.231476, 0.060782, 0 -(500.000000, 430.000000), (506.000000, 436.000000), 0.233306, 0.063605, 0 -(500.000000, 432.000000), (504.000000, 436.000000), 0.236397, 0.062078, 0 -(500.000000, 434.000000), (502.000000, 436.000000), 0.230477, 0.074315, 0 -(500.000000, 438.000000), (500.000000, 482.000000), 0.230968, 0.078514, 0 -(502.000000, 438.000000), (502.000000, 482.000000), 0.237987, 0.075470, 0 -(504.000000, 438.000000), (504.000000, 482.000000), 0.252200, 0.083042, 0 -(506.000000, 438.000000), (506.000000, 482.000000), 0.263321, 0.089818, 0 -(508.000000, 438.000000), (508.000000, 482.000000), 0.261930, 0.093170, 0 -(510.000000, 438.000000), (510.000000, 482.000000), 0.269891, 0.091829, 0 -(512.000000, 438.000000), (512.000000, 482.000000), 0.278558, 0.089801, 0 -(514.000000, 438.000000), (514.000000, 482.000000), 0.282125, 0.085954, 0 -(516.000000, 438.000000), (516.000000, 482.000000), 0.287392, 0.086682, 0 -(518.000000, 438.000000), (518.000000, 482.000000), 0.292594, 0.079975, 0 -(520.000000, 438.000000), (520.000000, 482.000000), 0.296409, 0.082526, 0 -(522.000000, 438.000000), (522.000000, 482.000000), 0.287434, 0.092886, 0 -(524.000000, 438.000000), (524.000000, 482.000000), 0.308308, 0.080740, 0 -(526.000000, 438.000000), (526.000000, 482.000000), 0.301490, 0.079705, 0 -(528.000000, 438.000000), (528.000000, 482.000000), 0.307818, 0.081967, 0 -(530.000000, 438.000000), (530.000000, 482.000000), 0.319020, 0.083787, 0 -(532.000000, 438.000000), (532.000000, 482.000000), 0.320482, 0.092006, 0 -(534.000000, 438.000000), (534.000000, 482.000000), 0.324256, 0.077682, 0 -(536.000000, 438.000000), (536.000000, 482.000000), 0.325049, 0.082577, 0 -(538.000000, 438.000000), (538.000000, 482.000000), 0.342500, 0.091979, 0 -(540.000000, 438.000000), (540.000000, 482.000000), 0.335747, 0.087391, 0 -(542.000000, 438.000000), (542.000000, 482.000000), 0.348808, 0.079305, 0 -(544.000000, 438.000000), (544.000000, 482.000000), 0.347191, 0.085933, 0 -(500.000000, 528.000000), (544.000000, 484.000000), 0.245259, 0.304584, 0 -(500.000000, 526.000000), (542.000000, 484.000000), 0.232615, 0.307854, 0 -(500.000000, 524.000000), (540.000000, 484.000000), 0.239558, 0.309024, 0 -(500.000000, 522.000000), (538.000000, 484.000000), 0.230380, 0.296993, 0 -(500.000000, 520.000000), (536.000000, 484.000000), 0.246910, 0.298688, 0 -(500.000000, 518.000000), (534.000000, 484.000000), 0.247733, 0.278400, 0 -(500.000000, 516.000000), (532.000000, 484.000000), 0.233393, 0.275552, 0 -(500.000000, 514.000000), (530.000000, 484.000000), 0.240368, 0.282413, 0 -(500.000000, 512.000000), (528.000000, 484.000000), 0.244338, 0.260849, 0 -(500.000000, 510.000000), (526.000000, 484.000000), 0.244419, 0.258595, 0 -(500.000000, 508.000000), (524.000000, 484.000000), 0.233531, 0.269468, 0 -(500.000000, 506.000000), (522.000000, 484.000000), 0.241172, 0.246031, 0 -(500.000000, 504.000000), (520.000000, 484.000000), 0.246447, 0.256919, 0 -(500.000000, 502.000000), (518.000000, 484.000000), 0.243421, 0.245255, 0 -(500.000000, 500.000000), (516.000000, 484.000000), 0.231225, 0.230613, 0 -(500.000000, 498.000000), (514.000000, 484.000000), 0.231187, 0.241484, 0 -(500.000000, 496.000000), (512.000000, 484.000000), 0.235196, 0.223802, 0 -(500.000000, 494.000000), (510.000000, 484.000000), 0.239338, 0.229755, 0 -(500.000000, 492.000000), (508.000000, 484.000000), 0.232827, 0.219717, 0 -(500.000000, 490.000000), (506.000000, 484.000000), 0.236747, 0.224736, 0 -(500.000000, 488.000000), (504.000000, 484.000000), 0.238405, 0.204480, 0 -(500.000000, 486.000000), (502.000000, 484.000000), 0.233137, 0.206798, 0 -(502.000000, 528.000000), (544.000000, 486.000000), 0.245032, 0.313504, 0 -(504.000000, 528.000000), (544.000000, 488.000000), 0.249211, 0.304370, 0 -(506.000000, 528.000000), (544.000000, 490.000000), 0.259353, 0.303630, 0 -(508.000000, 528.000000), (544.000000, 492.000000), 0.257965, 0.317885, 0 -(510.000000, 528.000000), (544.000000, 494.000000), 0.258098, 0.319137, 0 -(512.000000, 528.000000), (544.000000, 496.000000), 0.278915, 0.319545, 0 -(514.000000, 528.000000), (544.000000, 498.000000), 0.281056, 0.312336, 0 -(516.000000, 528.000000), (544.000000, 500.000000), 0.279800, 0.317281, 0 -(518.000000, 528.000000), (544.000000, 502.000000), 0.287949, 0.310987, 0 -(520.000000, 528.000000), (544.000000, 504.000000), 0.293765, 0.318145, 0 -(522.000000, 528.000000), (544.000000, 506.000000), 0.299790, 0.303102, 0 -(524.000000, 528.000000), (544.000000, 508.000000), 0.302900, 0.317616, 0 -(526.000000, 528.000000), (544.000000, 510.000000), 0.307820, 0.319647, 0 -(528.000000, 528.000000), (544.000000, 512.000000), 0.317353, 0.301225, 0 -(530.000000, 528.000000), (544.000000, 514.000000), 0.309127, 0.300489, 0 -(532.000000, 528.000000), (544.000000, 516.000000), 0.323024, 0.314159, 0 -(534.000000, 528.000000), (544.000000, 518.000000), 0.328994, 0.302235, 0 -(536.000000, 528.000000), (544.000000, 520.000000), 0.338529, 0.308347, 0 -(538.000000, 528.000000), (544.000000, 522.000000), 0.330865, 0.306494, 0 -(540.000000, 528.000000), (544.000000, 524.000000), 0.336232, 0.308963, 0 -(542.000000, 528.000000), (544.000000, 526.000000), 0.340631, 0.305147, 0 -(600.000000, 344.000000), (644.000000, 300.000000), 0.488509, -0.158313, 0 -(600.000000, 342.000000), (642.000000, 300.000000), 0.497483, -0.146691, 0 -(600.000000, 340.000000), (640.000000, 300.000000), 0.498967, -0.159568, 0 -(600.000000, 338.000000), (638.000000, 300.000000), 0.489296, -0.162268, 0 -(600.000000, 336.000000), (636.000000, 300.000000), 0.488577, -0.175914, 0 -(600.000000, 334.000000), (634.000000, 300.000000), 0.495835, -0.183523, 0 -(600.000000, 332.000000), (632.000000, 300.000000), 0.481702, -0.181346, 0 -(600.000000, 330.000000), (630.000000, 300.000000), 0.481124, -0.175946, 0 -(600.000000, 328.000000), (628.000000, 300.000000), 0.489879, -0.194749, 0 -(600.000000, 326.000000), (626.000000, 300.000000), 0.499544, -0.202097, 0 -(600.000000, 324.000000), (624.000000, 300.000000), 0.499410, -0.196463, 0 -(600.000000, 322.000000), (622.000000, 300.000000), 0.485138, -0.197061, 0 -(600.000000, 320.000000), (620.000000, 300.000000), 0.481884, -0.208997, 0 -(600.000000, 318.000000), (618.000000, 300.000000), 0.484433, -0.216884, 0 -(600.000000, 316.000000), (616.000000, 300.000000), 0.499966, -0.219936, 0 -(600.000000, 314.000000), (614.000000, 300.000000), 0.493263, -0.226525, 0 -(600.000000, 312.000000), (612.000000, 300.000000), 0.491750, -0.229254, 0 -(600.000000, 310.000000), (610.000000, 300.000000), 0.486784, -0.234282, 0 -(600.000000, 308.000000), (608.000000, 300.000000), 0.481178, -0.233920, 0 -(600.000000, 306.000000), (606.000000, 300.000000), 0.483450, -0.245245, 0 -(600.000000, 304.000000), (604.000000, 300.000000), 0.480165, -0.240715, 0 -(600.000000, 302.000000), (602.000000, 300.000000), 0.491233, -0.263133, 0 -(602.000000, 344.000000), (644.000000, 302.000000), 0.492939, -0.147644, 0 -(604.000000, 344.000000), (644.000000, 304.000000), 0.490921, -0.142182, 0 -(606.000000, 344.000000), (644.000000, 306.000000), 0.512608, -0.159535, 0 -(608.000000, 344.000000), (644.000000, 308.000000), 0.500721, -0.142982, 0 -(610.000000, 344.000000), (644.000000, 310.000000), 0.519002, -0.154141, 0 -(612.000000, 344.000000), (644.000000, 312.000000), 0.524957, -0.144114, 0 -(614.000000, 344.000000), (644.000000, 314.000000), 0.531862, -0.140610, 0 -(616.000000, 344.000000), (644.000000, 316.000000), 0.524002, -0.143172, 0 -(618.000000, 344.000000), (644.000000, 318.000000), 0.534454, -0.142735, 0 -(620.000000, 344.000000), (644.000000, 320.000000), 0.535303, -0.158796, 0 -(622.000000, 344.000000), (644.000000, 322.000000), 0.543011, -0.147913, 0 -(624.000000, 344.000000), (644.000000, 324.000000), 0.551922, -0.150811, 0 -(626.000000, 344.000000), (644.000000, 326.000000), 0.553166, -0.144628, 0 -(628.000000, 344.000000), (644.000000, 328.000000), 0.568944, -0.151668, 0 -(630.000000, 344.000000), (644.000000, 330.000000), 0.569656, -0.149823, 0 -(632.000000, 344.000000), (644.000000, 332.000000), 0.570199, -0.157405, 0 -(634.000000, 344.000000), (644.000000, 334.000000), 0.567533, -0.148880, 0 -(636.000000, 344.000000), (644.000000, 336.000000), 0.570413, -0.159859, 0 -(638.000000, 344.000000), (644.000000, 338.000000), 0.586585, -0.158865, 0 -(640.000000, 344.000000), (644.000000, 340.000000), 0.597158, -0.154413, 0 -(642.000000, 344.000000), (644.000000, 342.000000), 0.591994, -0.147885, 0 -(600.000000, 392.000000), (644.000000, 392.000000), 0.481473, -0.036145, 1 -(600.000000, 394.000000), (644.000000, 394.000000), 0.491505, -0.029524, 1 -(600.000000, 396.000000), (644.000000, 396.000000), 0.480683, -0.029041, 1 -(600.000000, 398.000000), (644.000000, 398.000000), 0.482740, -0.019013, 1 -(600.000000, 400.000000), (644.000000, 400.000000), 0.482163, -0.009249, 1 -(600.000000, 402.000000), (644.000000, 402.000000), 0.498073, -0.000915, 1 -(600.000000, 404.000000), (644.000000, 404.000000), 0.499939, -0.003760, 1 -(600.000000, 406.000000), (644.000000, 406.000000), 0.489457, 0.013883, 1 -(600.000000, 408.000000), (644.000000, 408.000000), 0.494571, 0.004113, 1 -(600.000000, 410.000000), (644.000000, 410.000000), 0.489060, 0.009770, 1 -(600.000000, 412.000000), (644.000000, 412.000000), 0.486708, 0.021593, 1 -(600.000000, 414.000000), (644.000000, 414.000000), 0.495890, 0.022122, 1 -(600.000000, 416.000000), (644.000000, 416.000000), 0.491734, 0.027474, 1 -(600.000000, 418.000000), (644.000000, 418.000000), 0.488256, 0.033892, 1 -(600.000000, 420.000000), (644.000000, 420.000000), 0.493061, 0.045250, 1 -(600.000000, 422.000000), (644.000000, 422.000000), 0.481007, 0.049535, 1 -(600.000000, 424.000000), (644.000000, 424.000000), 0.499105, 0.052512, 1 -(600.000000, 426.000000), (644.000000, 426.000000), 0.480010, 0.064789, 1 -(600.000000, 428.000000), (644.000000, 428.000000), 0.493471, 0.052750, 1 -(600.000000, 430.000000), (644.000000, 430.000000), 0.485775, 0.070634, 1 -(600.000000, 432.000000), (644.000000, 432.000000), 0.493501, 0.063849, 1 -(600.000000, 434.000000), (644.000000, 434.000000), 0.489718, 0.078441, 1 -(600.000000, 436.000000), (644.000000, 436.000000), 0.490088, 0.089175, 1 -(600.000000, 438.000000), (600.000000, 482.000000), 0.492324, 0.079660, 1 -(602.000000, 438.000000), (602.000000, 482.000000), 0.488288, 0.076384, 1 -(604.000000, 438.000000), (604.000000, 482.000000), 0.499429, 0.084996, 1 -(606.000000, 438.000000), (606.000000, 482.000000), 0.507977, 0.080319, 1 -(608.000000, 438.000000), (608.000000, 482.000000), 0.517118, 0.079711, 1 -(610.000000, 438.000000), (610.000000, 482.000000), 0.517793, 0.080374, 1 -(612.000000, 438.000000), (612.000000, 482.000000), 0.523603, 0.080855, 1 -(614.000000, 438.000000), (614.000000, 482.000000), 0.515624, 0.089611, 1 -(616.000000, 438.000000), (616.000000, 482.000000), 0.520389, 0.094729, 1 -(618.000000, 438.000000), (618.000000, 482.000000), 0.532123, 0.075399, 1 -(620.000000, 438.000000), (620.000000, 482.000000), 0.549518, 0.075594, 1 -(622.000000, 438.000000), (622.000000, 482.000000), 0.538150, 0.080293, 1 -(624.000000, 438.000000), (624.000000, 482.000000), 0.556227, 0.091651, 1 -(626.000000, 438.000000), (626.000000, 482.000000), 0.554141, 0.080946, 1 -(628.000000, 438.000000), (628.000000, 482.000000), 0.560092, 0.094230, 1 -(630.000000, 438.000000), (630.000000, 482.000000), 0.560121, 0.077416, 1 -(632.000000, 438.000000), (632.000000, 482.000000), 0.563889, 0.083409, 1 -(634.000000, 438.000000), (634.000000, 482.000000), 0.568800, 0.088319, 1 -(636.000000, 438.000000), (636.000000, 482.000000), 0.588405, 0.091777, 1 -(638.000000, 438.000000), (638.000000, 482.000000), 0.593637, 0.090522, 1 -(640.000000, 438.000000), (640.000000, 482.000000), 0.581488, 0.086431, 1 -(642.000000, 438.000000), (642.000000, 482.000000), 0.585896, 0.090092, 1 -(644.000000, 438.000000), (644.000000, 482.000000), 0.607285, 0.076520, 1 -(600.000000, 484.000000), (644.000000, 528.000000), 0.489702, 0.207675, 1 -(602.000000, 484.000000), (644.000000, 526.000000), 0.486249, 0.206825, 1 -(604.000000, 484.000000), (644.000000, 524.000000), 0.508074, 0.190766, 1 -(606.000000, 484.000000), (644.000000, 522.000000), 0.512419, 0.191224, 1 -(608.000000, 484.000000), (644.000000, 520.000000), 0.506059, 0.203646, 1 -(610.000000, 484.000000), (644.000000, 518.000000), 0.522875, 0.205201, 1 -(612.000000, 484.000000), (644.000000, 516.000000), 0.529592, 0.197967, 1 -(614.000000, 484.000000), (644.000000, 514.000000), 0.529430, 0.194713, 1 -(616.000000, 484.000000), (644.000000, 512.000000), 0.530383, 0.208320, 1 -(618.000000, 484.000000), (644.000000, 510.000000), 0.538122, 0.204183, 1 -(620.000000, 484.000000), (644.000000, 508.000000), 0.541638, 0.201526, 1 -(622.000000, 484.000000), (644.000000, 506.000000), 0.545960, 0.200276, 1 -(624.000000, 484.000000), (644.000000, 504.000000), 0.547048, 0.202448, 1 -(626.000000, 484.000000), (644.000000, 502.000000), 0.546706, 0.197944, 1 -(628.000000, 484.000000), (644.000000, 500.000000), 0.557540, 0.208992, 1 -(630.000000, 484.000000), (644.000000, 498.000000), 0.564464, 0.207242, 1 -(632.000000, 484.000000), (644.000000, 496.000000), 0.576666, 0.200713, 1 -(634.000000, 484.000000), (644.000000, 494.000000), 0.579068, 0.204740, 1 -(636.000000, 484.000000), (644.000000, 492.000000), 0.581479, 0.201486, 1 -(638.000000, 484.000000), (644.000000, 490.000000), 0.590964, 0.207538, 1 -(640.000000, 484.000000), (644.000000, 488.000000), 0.585133, 0.203839, 1 -(642.000000, 484.000000), (644.000000, 486.000000), 0.597739, 0.194725, 1 -(600.000000, 486.000000), (642.000000, 528.000000), 0.481806, 0.202169, 1 -(600.000000, 488.000000), (640.000000, 528.000000), 0.489438, 0.212189, 1 -(600.000000, 490.000000), (638.000000, 528.000000), 0.485489, 0.207559, 1 -(600.000000, 492.000000), (636.000000, 528.000000), 0.486372, 0.227127, 1 -(600.000000, 494.000000), (634.000000, 528.000000), 0.494085, 0.232331, 1 -(600.000000, 496.000000), (632.000000, 528.000000), 0.487402, 0.221134, 1 -(600.000000, 498.000000), (630.000000, 528.000000), 0.489780, 0.234108, 1 -(600.000000, 500.000000), (628.000000, 528.000000), 0.489078, 0.247320, 1 -(600.000000, 502.000000), (626.000000, 528.000000), 0.488100, 0.253542, 1 -(600.000000, 504.000000), (624.000000, 528.000000), 0.494562, 0.244766, 1 -(600.000000, 506.000000), (622.000000, 528.000000), 0.489255, 0.253630, 1 -(600.000000, 508.000000), (620.000000, 528.000000), 0.499506, 0.250734, 1 -(600.000000, 510.000000), (618.000000, 528.000000), 0.480117, 0.270471, 1 -(600.000000, 512.000000), (616.000000, 528.000000), 0.498273, 0.265249, 1 -(600.000000, 514.000000), (614.000000, 528.000000), 0.489310, 0.276011, 1 -(600.000000, 516.000000), (612.000000, 528.000000), 0.489974, 0.281116, 1 -(600.000000, 518.000000), (610.000000, 528.000000), 0.498180, 0.294412, 1 -(600.000000, 520.000000), (608.000000, 528.000000), 0.483305, 0.283669, 1 -(600.000000, 522.000000), (606.000000, 528.000000), 0.481972, 0.294677, 1 -(600.000000, 524.000000), (604.000000, 528.000000), 0.480795, 0.306057, 1 -(600.000000, 526.000000), (602.000000, 528.000000), 0.487008, 0.303198, 1 -(700.000000, 344.000000), (744.000000, 300.000000), 0.747191, -0.143212, 0 -(700.000000, 342.000000), (742.000000, 300.000000), 0.747306, -0.158731, 0 -(700.000000, 340.000000), (740.000000, 300.000000), 0.744108, -0.164594, 0 -(700.000000, 338.000000), (738.000000, 300.000000), 0.734812, -0.166329, 0 -(700.000000, 336.000000), (736.000000, 300.000000), 0.740172, -0.165933, 0 -(700.000000, 334.000000), (734.000000, 300.000000), 0.747301, -0.175322, 0 -(700.000000, 332.000000), (732.000000, 300.000000), 0.744801, -0.172583, 0 -(700.000000, 330.000000), (730.000000, 300.000000), 0.735149, -0.181926, 0 -(700.000000, 328.000000), (728.000000, 300.000000), 0.732667, -0.185541, 0 -(700.000000, 326.000000), (726.000000, 300.000000), 0.734085, -0.192359, 0 -(700.000000, 324.000000), (724.000000, 300.000000), 0.735575, -0.207735, 0 -(700.000000, 322.000000), (722.000000, 300.000000), 0.742053, -0.206119, 0 -(700.000000, 320.000000), (720.000000, 300.000000), 0.735934, -0.205975, 0 -(700.000000, 318.000000), (718.000000, 300.000000), 0.748557, -0.218270, 0 -(700.000000, 316.000000), (716.000000, 300.000000), 0.740082, -0.224434, 0 -(700.000000, 314.000000), (714.000000, 300.000000), 0.744927, -0.227727, 0 -(700.000000, 312.000000), (712.000000, 300.000000), 0.732354, -0.227767, 0 -(700.000000, 310.000000), (710.000000, 300.000000), 0.743542, -0.228538, 0 -(700.000000, 308.000000), (708.000000, 300.000000), 0.747639, -0.231646, 0 -(700.000000, 306.000000), (706.000000, 300.000000), 0.735133, -0.247189, 0 -(700.000000, 304.000000), (704.000000, 300.000000), 0.742420, -0.257567, 0 -(700.000000, 302.000000), (702.000000, 300.000000), 0.747490, -0.257778, 0 -(702.000000, 344.000000), (744.000000, 302.000000), 0.754851, -0.157361, 0 -(704.000000, 344.000000), (744.000000, 304.000000), 0.740295, -0.157483, 0 -(706.000000, 344.000000), (744.000000, 306.000000), 0.762098, -0.155620, 0 -(708.000000, 344.000000), (744.000000, 308.000000), 0.765158, -0.157327, 0 -(710.000000, 344.000000), (744.000000, 310.000000), 0.761646, -0.152788, 0 -(712.000000, 344.000000), (744.000000, 312.000000), 0.771553, -0.147420, 0 -(714.000000, 344.000000), (744.000000, 314.000000), 0.766237, -0.149889, 0 -(716.000000, 344.000000), (744.000000, 316.000000), 0.789310, -0.148681, 0 -(718.000000, 344.000000), (744.000000, 318.000000), 0.790676, -0.145763, 0 -(720.000000, 344.000000), (744.000000, 320.000000), 0.798592, -0.141970, 0 -(722.000000, 344.000000), (744.000000, 322.000000), 0.791470, -0.147866, 0 -(724.000000, 344.000000), (744.000000, 324.000000), 0.804492, -0.155890, 0 -(726.000000, 344.000000), (744.000000, 326.000000), 0.805487, -0.140375, 0 -(728.000000, 344.000000), (744.000000, 328.000000), 0.811921, -0.157092, 0 -(730.000000, 344.000000), (744.000000, 330.000000), 0.807058, -0.150590, 0 -(732.000000, 344.000000), (744.000000, 332.000000), 0.820129, -0.158092, 0 -(734.000000, 344.000000), (744.000000, 334.000000), 0.827049, -0.149575, 0 -(736.000000, 344.000000), (744.000000, 336.000000), 0.824426, -0.150853, 0 -(738.000000, 344.000000), (744.000000, 338.000000), 0.839805, -0.140416, 0 -(740.000000, 344.000000), (744.000000, 340.000000), 0.841820, -0.158549, 0 -(742.000000, 344.000000), (744.000000, 342.000000), 0.841796, -0.156627, 0 -(746.000000, 300.000000), (790.000000, 300.000000), 0.859031, -0.261967, 0 -(746.000000, 302.000000), (790.000000, 302.000000), 0.858484, -0.251659, 0 -(746.000000, 304.000000), (790.000000, 304.000000), 0.864351, -0.250840, 0 -(746.000000, 306.000000), (790.000000, 306.000000), 0.852578, -0.237057, 0 -(746.000000, 308.000000), (790.000000, 308.000000), 0.852190, -0.235952, 0 -(746.000000, 310.000000), (790.000000, 310.000000), 0.855077, -0.243318, 0 -(746.000000, 312.000000), (790.000000, 312.000000), 0.863158, -0.239436, 0 -(746.000000, 314.000000), (790.000000, 314.000000), 0.846307, -0.224921, 0 -(746.000000, 316.000000), (790.000000, 316.000000), 0.848472, -0.226635, 0 -(746.000000, 318.000000), (790.000000, 318.000000), 0.864489, -0.211399, 0 -(746.000000, 320.000000), (790.000000, 320.000000), 0.850273, -0.208462, 0 -(746.000000, 322.000000), (790.000000, 322.000000), 0.849026, -0.205301, 0 -(746.000000, 324.000000), (790.000000, 324.000000), 0.845685, -0.191169, 0 -(746.000000, 326.000000), (790.000000, 326.000000), 0.854283, -0.192495, 0 -(746.000000, 328.000000), (790.000000, 328.000000), 0.845281, -0.183921, 0 -(746.000000, 330.000000), (790.000000, 330.000000), 0.860878, -0.180688, 0 -(746.000000, 332.000000), (790.000000, 332.000000), 0.849112, -0.180638, 0 -(746.000000, 334.000000), (790.000000, 334.000000), 0.852653, -0.181537, 0 -(746.000000, 336.000000), (790.000000, 336.000000), 0.863522, -0.164769, 0 -(746.000000, 338.000000), (790.000000, 338.000000), 0.846406, -0.169287, 0 -(746.000000, 340.000000), (790.000000, 340.000000), 0.854279, -0.158517, 0 -(746.000000, 342.000000), (790.000000, 342.000000), 0.852395, -0.157563, 0 -(746.000000, 344.000000), (790.000000, 344.000000), 0.857047, -0.151298, 0 -(792.000000, 300.000000), (836.000000, 344.000000), 0.977516, -0.254481, 0 -(794.000000, 300.000000), (836.000000, 342.000000), 0.977067, -0.252995, 0 -(796.000000, 300.000000), (836.000000, 340.000000), 0.979120, -0.252659, 0 -(798.000000, 300.000000), (836.000000, 338.000000), 0.983543, -0.256855, 0 -(800.000000, 300.000000), (836.000000, 336.000000), 0.987040, -0.260771, 0 -(802.000000, 300.000000), (836.000000, 334.000000), 0.996976, -0.253677, 0 -(804.000000, 300.000000), (836.000000, 332.000000), 0.991734, -0.257743, 0 -(806.000000, 300.000000), (836.000000, 330.000000), 1.007402, -0.252388, 0 -(808.000000, 300.000000), (836.000000, 328.000000), 1.006570, -0.253486, 0 -(810.000000, 300.000000), (836.000000, 326.000000), 1.011974, -0.255777, 0 -(812.000000, 300.000000), (836.000000, 324.000000), 1.029978, -0.264504, 0 -(814.000000, 300.000000), (836.000000, 322.000000), 1.024453, -0.268616, 0 -(816.000000, 300.000000), (836.000000, 320.000000), 1.031209, -0.251267, 0 -(818.000000, 300.000000), (836.000000, 318.000000), 1.037866, -0.251396, 0 -(820.000000, 300.000000), (836.000000, 316.000000), 1.036170, -0.265087, 0 -(822.000000, 300.000000), (836.000000, 314.000000), 1.042306, -0.266315, 0 -(824.000000, 300.000000), (836.000000, 312.000000), 1.040432, -0.250627, 0 -(826.000000, 300.000000), (836.000000, 310.000000), 1.045691, -0.260449, 0 -(828.000000, 300.000000), (836.000000, 308.000000), 1.066714, -0.260766, 0 -(830.000000, 300.000000), (836.000000, 306.000000), 1.057697, -0.266246, 0 -(832.000000, 300.000000), (836.000000, 304.000000), 1.078463, -0.255327, 0 -(834.000000, 300.000000), (836.000000, 302.000000), 1.065077, -0.269804, 0 -(792.000000, 302.000000), (834.000000, 344.000000), 0.966930, -0.252521, 0 -(792.000000, 304.000000), (832.000000, 344.000000), 0.977808, -0.246501, 0 -(792.000000, 306.000000), (830.000000, 344.000000), 0.968993, -0.250219, 0 -(792.000000, 308.000000), (828.000000, 344.000000), 0.967722, -0.241029, 0 -(792.000000, 310.000000), (826.000000, 344.000000), 0.970277, -0.227825, 0 -(792.000000, 312.000000), (824.000000, 344.000000), 0.970355, -0.238514, 0 -(792.000000, 314.000000), (822.000000, 344.000000), 0.975908, -0.231779, 0 -(792.000000, 316.000000), (820.000000, 344.000000), 0.960089, -0.227923, 0 -(792.000000, 318.000000), (818.000000, 344.000000), 0.968134, -0.217605, 0 -(792.000000, 320.000000), (816.000000, 344.000000), 0.965763, -0.211434, 0 -(792.000000, 322.000000), (814.000000, 344.000000), 0.966769, -0.208547, 0 -(792.000000, 324.000000), (812.000000, 344.000000), 0.978118, -0.206517, 0 -(792.000000, 326.000000), (810.000000, 344.000000), 0.975687, -0.204186, 0 -(792.000000, 328.000000), (808.000000, 344.000000), 0.967236, -0.185850, 0 -(792.000000, 330.000000), (806.000000, 344.000000), 0.975487, -0.187687, 0 -(792.000000, 332.000000), (804.000000, 344.000000), 0.974346, -0.187583, 0 -(792.000000, 334.000000), (802.000000, 344.000000), 0.979792, -0.172846, 0 -(792.000000, 336.000000), (800.000000, 344.000000), 0.975916, -0.171215, 0 -(792.000000, 338.000000), (798.000000, 344.000000), 0.976935, -0.171362, 0 -(792.000000, 340.000000), (796.000000, 344.000000), 0.977756, -0.162788, 0 -(792.000000, 342.000000), (794.000000, 344.000000), 0.960813, -0.156889, 0 -(746.000000, 436.000000), (790.000000, 392.000000), 0.853698, 0.086721, 0 -(746.000000, 434.000000), (788.000000, 392.000000), 0.856332, 0.073787, 0 -(746.000000, 432.000000), (786.000000, 392.000000), 0.863798, 0.079467, 0 -(746.000000, 430.000000), (784.000000, 392.000000), 0.861182, 0.059561, 0 -(746.000000, 428.000000), (782.000000, 392.000000), 0.853033, 0.052951, 0 -(746.000000, 426.000000), (780.000000, 392.000000), 0.856015, 0.051151, 0 -(746.000000, 424.000000), (778.000000, 392.000000), 0.851434, 0.046702, 0 -(746.000000, 422.000000), (776.000000, 392.000000), 0.851965, 0.048670, 0 -(746.000000, 420.000000), (774.000000, 392.000000), 0.845852, 0.032452, 0 -(746.000000, 418.000000), (772.000000, 392.000000), 0.845982, 0.040198, 0 -(746.000000, 416.000000), (770.000000, 392.000000), 0.849869, 0.020774, 0 -(746.000000, 414.000000), (768.000000, 392.000000), 0.852352, 0.015785, 0 -(746.000000, 412.000000), (766.000000, 392.000000), 0.854560, 0.014287, 0 -(746.000000, 410.000000), (764.000000, 392.000000), 0.849423, 0.012316, 0 -(746.000000, 408.000000), (762.000000, 392.000000), 0.856499, 0.005236, 0 -(746.000000, 406.000000), (760.000000, 392.000000), 0.860427, -0.004803, 0 -(746.000000, 404.000000), (758.000000, 392.000000), 0.846957, -0.003240, 0 -(746.000000, 402.000000), (756.000000, 392.000000), 0.853984, -0.014245, 0 -(746.000000, 400.000000), (754.000000, 392.000000), 0.851226, -0.014834, 0 -(746.000000, 398.000000), (752.000000, 392.000000), 0.850316, -0.010741, 0 -(746.000000, 396.000000), (750.000000, 392.000000), 0.853117, -0.013669, 0 -(746.000000, 394.000000), (748.000000, 392.000000), 0.845410, -0.020449, 0 -(748.000000, 436.000000), (790.000000, 394.000000), 0.853033, 0.077375, 0 -(750.000000, 436.000000), (790.000000, 396.000000), 0.863220, 0.073885, 0 -(752.000000, 436.000000), (790.000000, 398.000000), 0.869827, 0.079203, 0 -(754.000000, 436.000000), (790.000000, 400.000000), 0.884084, 0.084695, 0 -(756.000000, 436.000000), (790.000000, 402.000000), 0.879977, 0.076436, 0 -(758.000000, 436.000000), (790.000000, 404.000000), 0.890480, 0.089537, 0 -(760.000000, 436.000000), (790.000000, 406.000000), 0.890723, 0.089903, 0 -(762.000000, 436.000000), (790.000000, 408.000000), 0.891853, 0.072223, 0 -(764.000000, 436.000000), (790.000000, 410.000000), 0.895138, 0.072280, 0 -(766.000000, 436.000000), (790.000000, 412.000000), 0.897420, 0.077095, 0 -(768.000000, 436.000000), (790.000000, 414.000000), 0.909040, 0.081403, 0 -(770.000000, 436.000000), (790.000000, 416.000000), 0.912850, 0.085266, 0 -(772.000000, 436.000000), (790.000000, 418.000000), 0.926570, 0.083166, 0 -(774.000000, 436.000000), (790.000000, 420.000000), 0.924525, 0.074687, 0 -(776.000000, 436.000000), (790.000000, 422.000000), 0.929497, 0.079935, 0 -(778.000000, 436.000000), (790.000000, 424.000000), 0.944238, 0.082530, 0 -(780.000000, 436.000000), (790.000000, 426.000000), 0.947310, 0.077458, 0 -(782.000000, 436.000000), (790.000000, 428.000000), 0.951415, 0.077136, 0 -(784.000000, 436.000000), (790.000000, 430.000000), 0.956661, 0.085499, 0 -(786.000000, 436.000000), (790.000000, 432.000000), 0.946832, 0.076638, 0 -(788.000000, 436.000000), (790.000000, 434.000000), 0.951935, 0.087312, 0 -(746.000000, 438.000000), (746.000000, 482.000000), 0.851175, 0.087658, 0 -(748.000000, 438.000000), (748.000000, 482.000000), 0.867214, 0.088028, 0 -(750.000000, 438.000000), (750.000000, 482.000000), 0.869881, 0.077352, 0 -(752.000000, 438.000000), (752.000000, 482.000000), 0.875309, 0.092300, 0 -(754.000000, 438.000000), (754.000000, 482.000000), 0.874447, 0.079349, 0 -(756.000000, 438.000000), (756.000000, 482.000000), 0.878704, 0.092297, 0 -(758.000000, 438.000000), (758.000000, 482.000000), 0.894615, 0.080274, 0 -(760.000000, 438.000000), (760.000000, 482.000000), 0.890463, 0.084140, 0 -(762.000000, 438.000000), (762.000000, 482.000000), 0.894961, 0.094960, 0 -(764.000000, 438.000000), (764.000000, 482.000000), 0.909075, 0.084198, 0 -(766.000000, 438.000000), (766.000000, 482.000000), 0.907490, 0.091385, 0 -(768.000000, 438.000000), (768.000000, 482.000000), 0.916656, 0.083905, 0 -(770.000000, 438.000000), (770.000000, 482.000000), 0.908522, 0.088317, 0 -(772.000000, 438.000000), (772.000000, 482.000000), 0.914404, 0.080353, 0 -(774.000000, 438.000000), (774.000000, 482.000000), 0.934956, 0.081339, 0 -(776.000000, 438.000000), (776.000000, 482.000000), 0.922665, 0.081131, 0 -(778.000000, 438.000000), (778.000000, 482.000000), 0.943997, 0.094879, 0 -(780.000000, 438.000000), (780.000000, 482.000000), 0.949159, 0.088878, 0 -(782.000000, 438.000000), (782.000000, 482.000000), 0.937231, 0.089467, 0 -(784.000000, 438.000000), (784.000000, 482.000000), 0.951179, 0.086678, 0 -(786.000000, 438.000000), (786.000000, 482.000000), 0.963816, 0.094883, 0 -(788.000000, 438.000000), (788.000000, 482.000000), 0.958975, 0.093431, 0 -(790.000000, 438.000000), (790.000000, 482.000000), 0.960156, 0.094438, 0 -(746.000000, 484.000000), (790.000000, 528.000000), 0.852572, 0.205117, 0 -(748.000000, 484.000000), (790.000000, 526.000000), 0.869398, 0.196647, 0 -(750.000000, 484.000000), (790.000000, 524.000000), 0.859315, 0.201888, 0 -(752.000000, 484.000000), (790.000000, 522.000000), 0.863032, 0.190972, 0 -(754.000000, 484.000000), (790.000000, 520.000000), 0.865793, 0.196554, 0 -(756.000000, 484.000000), (790.000000, 518.000000), 0.884289, 0.195197, 0 -(758.000000, 484.000000), (790.000000, 516.000000), 0.886907, 0.204245, 0 -(760.000000, 484.000000), (790.000000, 514.000000), 0.891536, 0.204572, 0 -(762.000000, 484.000000), (790.000000, 512.000000), 0.885375, 0.200533, 0 -(764.000000, 484.000000), (790.000000, 510.000000), 0.904451, 0.209534, 0 -(766.000000, 484.000000), (790.000000, 508.000000), 0.899411, 0.206682, 0 -(768.000000, 484.000000), (790.000000, 506.000000), 0.914002, 0.205590, 0 -(770.000000, 484.000000), (790.000000, 504.000000), 0.913361, 0.202818, 0 -(772.000000, 484.000000), (790.000000, 502.000000), 0.925473, 0.207336, 0 -(774.000000, 484.000000), (790.000000, 500.000000), 0.926249, 0.190629, 0 -(776.000000, 484.000000), (790.000000, 498.000000), 0.936774, 0.208821, 0 -(778.000000, 484.000000), (790.000000, 496.000000), 0.940746, 0.206172, 0 -(780.000000, 484.000000), (790.000000, 494.000000), 0.935468, 0.190061, 0 -(782.000000, 484.000000), (790.000000, 492.000000), 0.943060, 0.198500, 0 -(784.000000, 484.000000), (790.000000, 490.000000), 0.941032, 0.198853, 0 -(786.000000, 484.000000), (790.000000, 488.000000), 0.960054, 0.205321, 0 -(788.000000, 484.000000), (790.000000, 486.000000), 0.964050, 0.196961, 0 -(746.000000, 486.000000), (788.000000, 528.000000), 0.854566, 0.200586, 0 -(746.000000, 488.000000), (786.000000, 528.000000), 0.846532, 0.209941, 0 -(746.000000, 490.000000), (784.000000, 528.000000), 0.861119, 0.220983, 0 -(746.000000, 492.000000), (782.000000, 528.000000), 0.854475, 0.210530, 0 -(746.000000, 494.000000), (780.000000, 528.000000), 0.857665, 0.218477, 0 -(746.000000, 496.000000), (778.000000, 528.000000), 0.861120, 0.221026, 0 -(746.000000, 498.000000), (776.000000, 528.000000), 0.861295, 0.236593, 0 -(746.000000, 500.000000), (774.000000, 528.000000), 0.863362, 0.237544, 0 -(746.000000, 502.000000), (772.000000, 528.000000), 0.857222, 0.250136, 0 -(746.000000, 504.000000), (770.000000, 528.000000), 0.851364, 0.247967, 0 -(746.000000, 506.000000), (768.000000, 528.000000), 0.856308, 0.256832, 0 -(746.000000, 508.000000), (766.000000, 528.000000), 0.853028, 0.269368, 0 -(746.000000, 510.000000), (764.000000, 528.000000), 0.845331, 0.264060, 0 -(746.000000, 512.000000), (762.000000, 528.000000), 0.853221, 0.275385, 0 -(746.000000, 514.000000), (760.000000, 528.000000), 0.849382, 0.267271, 0 -(746.000000, 516.000000), (758.000000, 528.000000), 0.847345, 0.283947, 0 -(746.000000, 518.000000), (756.000000, 528.000000), 0.852857, 0.278878, 0 -(746.000000, 520.000000), (754.000000, 528.000000), 0.848889, 0.283976, 0 -(746.000000, 522.000000), (752.000000, 528.000000), 0.864861, 0.298364, 0 -(746.000000, 524.000000), (750.000000, 528.000000), 0.849506, 0.302526, 0 -(746.000000, 526.000000), (748.000000, 528.000000), 0.861841, 0.295626, 0 diff --git a/reducer_bench/quad_tree/input/sin_wave.in b/reducer_bench/quad_tree/input/sin_wave.in deleted file mode 100644 index e43d2f94..00000000 --- a/reducer_bench/quad_tree/input/sin_wave.in +++ /dev/null @@ -1,1181 +0,0 @@ -1180 -(0.000000, 390.000000), (0.000000, 410.000000), 0.000000, 0.000000, 0 -(1.000000, 398.305956), (1.000000, 418.305956), 0.001250, 0.000000, 0 -(2.000000, 406.608144), (2.000000, 426.608144), 0.002500, 0.000000, 0 -(3.000000, 414.902798), (3.000000, 434.902798), 0.003750, 0.000000, 0 -(4.000000, 423.186156), (4.000000, 443.186156), 0.005000, 0.000000, 0 -(5.000000, 431.454459), (5.000000, 451.454459), 0.006250, 0.000000, 0 -(6.000000, 439.703958), (6.000000, 459.703958), 0.007500, 0.000000, 0 -(7.000000, 447.930910), (7.000000, 467.930910), 0.008750, 0.000000, 0 -(8.000000, 456.131582), (8.000000, 476.131582), 0.010000, 0.000000, 0 -(9.000000, 464.302255), (9.000000, 484.302255), 0.011250, 0.000000, 0 -(10.000000, 472.439223), (10.000000, 492.439223), 0.012500, 0.000000, 0 -(11.000000, 480.538794), (11.000000, 500.538794), 0.013750, 0.000000, 0 -(12.000000, 488.597295), (12.000000, 508.597295), 0.015000, 0.000000, 0 -(13.000000, 496.611068), (13.000000, 516.611068), 0.016250, 0.000000, 0 -(14.000000, 504.576481), (14.000000, 524.576481), 0.017500, 0.000000, 0 -(15.000000, 512.489918), (15.000000, 532.489918), 0.018750, 0.000000, 0 -(16.000000, 520.347790), (16.000000, 540.347790), 0.020000, 0.000000, 0 -(17.000000, 528.146533), (17.000000, 548.146533), 0.021250, 0.000000, 0 -(18.000000, 535.882609), (18.000000, 555.882609), 0.022500, 0.000000, 0 -(19.000000, 543.552508), (19.000000, 563.552508), 0.023750, 0.000000, 0 -(20.000000, 551.152752), (20.000000, 571.152752), 0.025000, 0.000000, 0 -(21.000000, 558.679893), (21.000000, 578.679893), 0.026250, 0.000000, 0 -(22.000000, 566.130516), (22.000000, 586.130516), 0.027500, 0.000000, 0 -(23.000000, 573.501241), (23.000000, 593.501241), 0.028750, 0.000000, 0 -(24.000000, 580.788725), (24.000000, 600.788725), 0.030000, 0.000000, 0 -(25.000000, 587.989662), (25.000000, 607.989662), 0.031250, 0.000000, 0 -(26.000000, 595.100786), (26.000000, 615.100786), 0.032500, 0.000000, 0 -(27.000000, 602.118870), (27.000000, 622.118870), 0.033750, 0.000000, 0 -(28.000000, 609.040731), (28.000000, 629.040731), 0.035000, 0.000000, 0 -(29.000000, 615.863229), (29.000000, 635.863229), 0.036250, 0.000000, 0 -(30.000000, 622.583270), (30.000000, 642.583270), 0.037500, 0.000000, 0 -(31.000000, 629.197804), (31.000000, 649.197804), 0.038750, 0.000000, 0 -(32.000000, 635.703832), (32.000000, 655.703832), 0.040000, 0.000000, 0 -(33.000000, 642.098402), (33.000000, 662.098402), 0.041250, 0.000000, 0 -(34.000000, 648.378613), (34.000000, 668.378613), 0.042500, 0.000000, 0 -(35.000000, 654.541616), (35.000000, 674.541616), 0.043750, 0.000000, 0 -(36.000000, 660.584616), (36.000000, 680.584616), 0.045000, 0.000000, 0 -(37.000000, 666.504872), (37.000000, 686.504872), 0.046250, 0.000000, 0 -(38.000000, 672.299697), (38.000000, 692.299697), 0.047500, 0.000000, 0 -(39.000000, 677.966463), (39.000000, 697.966463), 0.048750, 0.000000, 0 -(40.000000, 683.502600), (40.000000, 703.502600), 0.050000, 0.000000, 0 -(41.000000, 688.905596), (41.000000, 708.905596), 0.051250, 0.000000, 0 -(42.000000, 694.173001), (42.000000, 714.173001), 0.052500, 0.000000, 0 -(43.000000, 699.302424), (43.000000, 719.302424), 0.053750, 0.000000, 0 -(44.000000, 704.291539), (44.000000, 724.291539), 0.055000, 0.000000, 0 -(45.000000, 709.138083), (45.000000, 729.138083), 0.056250, 0.000000, 0 -(46.000000, 713.839857), (46.000000, 733.839857), 0.057500, 0.000000, 0 -(47.000000, 718.394728), (47.000000, 738.394728), 0.058750, 0.000000, 0 -(48.000000, 722.800631), (48.000000, 742.800631), 0.060000, 0.000000, 0 -(49.000000, 727.055566), (49.000000, 747.055566), 0.061250, 0.000000, 0 -(50.000000, 731.157603), (50.000000, 751.157603), 0.062500, 0.000000, 0 -(51.000000, 735.104882), (51.000000, 755.104882), 0.063750, 0.000000, 0 -(52.000000, 738.895612), (52.000000, 758.895612), 0.065000, 0.000000, 0 -(53.000000, 742.528073), (53.000000, 762.528073), 0.066250, 0.000000, 0 -(54.000000, 746.000618), (54.000000, 766.000618), 0.067500, 0.000000, 0 -(55.000000, 749.311671), (55.000000, 769.311671), 0.068750, 0.000000, 0 -(56.000000, 752.459731), (56.000000, 772.459731), 0.070000, 0.000000, 0 -(57.000000, 755.443369), (57.000000, 775.443369), 0.071250, 0.000000, 0 -(58.000000, 758.261232), (58.000000, 778.261232), 0.072500, 0.000000, 0 -(59.000000, 760.912041), (59.000000, 780.912041), 0.073750, 0.000000, 0 -(60.000000, 763.394595), (60.000000, 783.394595), 0.075000, 0.000000, 0 -(61.000000, 765.707767), (61.000000, 785.707767), 0.076250, 0.000000, 0 -(62.000000, 767.850507), (62.000000, 787.850507), 0.077500, 0.000000, 0 -(63.000000, 769.821844), (63.000000, 789.821844), 0.078750, 0.000000, 0 -(64.000000, 771.620883), (64.000000, 791.620883), 0.080000, 0.000000, 0 -(65.000000, 773.246809), (65.000000, 793.246809), 0.081250, 0.000000, 0 -(66.000000, 774.698883), (66.000000, 794.698883), 0.082500, 0.000000, 0 -(67.000000, 775.976447), (67.000000, 795.976447), 0.083750, 0.000000, 0 -(68.000000, 777.078922), (68.000000, 797.078922), 0.085000, 0.000000, 0 -(69.000000, 778.005808), (69.000000, 798.005808), 0.086250, 0.000000, 0 -(70.000000, 778.756683), (70.000000, 798.756683), 0.087500, 0.000000, 0 -(71.000000, 779.331207), (71.000000, 799.331207), 0.088750, 0.000000, 0 -(72.000000, 779.729121), (72.000000, 799.729121), 0.090000, 0.000000, 0 -(73.000000, 779.950242), (73.000000, 799.950242), 0.091250, 0.000000, 0 -(74.000000, 779.994471), (74.000000, 799.994471), 0.092500, 0.000000, 0 -(75.000000, 779.861788), (75.000000, 799.861788), 0.093750, 0.000000, 0 -(76.000000, 779.552253), (76.000000, 799.552253), 0.095000, 0.000000, 0 -(77.000000, 779.066007), (77.000000, 799.066007), 0.096250, 0.000000, 0 -(78.000000, 778.403270), (78.000000, 798.403270), 0.097500, 0.000000, 0 -(79.000000, 777.564342), (79.000000, 797.564342), 0.098750, 0.000000, 0 -(80.000000, 776.549604), (80.000000, 796.549604), 0.100000, 0.000000, 0 -(81.000000, 775.359517), (81.000000, 795.359517), 0.101250, 0.000000, 0 -(82.000000, 773.994620), (82.000000, 793.994620), 0.102500, 0.000000, 0 -(83.000000, 772.455533), (83.000000, 792.455533), 0.103750, 0.000000, 0 -(84.000000, 770.742953), (84.000000, 790.742953), 0.105000, 0.000000, 0 -(85.000000, 768.857658), (85.000000, 788.857658), 0.106250, 0.000000, 0 -(86.000000, 766.800503), (86.000000, 786.800503), 0.107500, 0.000000, 0 -(87.000000, 764.572421), (87.000000, 784.572421), 0.108750, 0.000000, 0 -(88.000000, 762.174422), (88.000000, 782.174422), 0.110000, 0.000000, 0 -(89.000000, 759.607595), (89.000000, 779.607595), 0.111250, 0.000000, 0 -(90.000000, 756.873104), (90.000000, 776.873104), 0.112500, 0.000000, 0 -(91.000000, 753.972189), (91.000000, 773.972189), 0.113750, 0.000000, 0 -(92.000000, 750.906166), (92.000000, 770.906166), 0.115000, 0.000000, 0 -(93.000000, 747.676427), (93.000000, 767.676427), 0.116250, 0.000000, 0 -(94.000000, 744.284435), (94.000000, 764.284435), 0.117500, 0.000000, 0 -(95.000000, 740.731731), (95.000000, 760.731731), 0.118750, 0.000000, 0 -(96.000000, 737.019925), (96.000000, 757.019925), 0.120000, 0.000000, 0 -(97.000000, 733.150701), (97.000000, 753.150701), 0.121250, 0.000000, 0 -(98.000000, 729.125814), (98.000000, 749.125814), 0.122500, 0.000000, 0 -(99.000000, 724.947091), (99.000000, 744.947091), 0.123750, 0.000000, 0 -(100.000000, 720.616427), (100.000000, 740.616427), 0.125000, 0.000000, 0 -(101.000000, 716.135786), (101.000000, 736.135786), 0.126250, 0.000000, 0 -(102.000000, 711.507201), (102.000000, 731.507201), 0.127500, 0.000000, 0 -(103.000000, 706.732771), (103.000000, 726.732771), 0.128750, 0.000000, 0 -(104.000000, 701.814663), (104.000000, 721.814663), 0.130000, 0.000000, 0 -(105.000000, 696.755107), (105.000000, 716.755107), 0.131250, 0.000000, 0 -(106.000000, 691.556398), (106.000000, 711.556398), 0.132500, 0.000000, 0 -(107.000000, 686.220896), (107.000000, 706.220896), 0.133750, 0.000000, 0 -(108.000000, 680.751019), (108.000000, 700.751019), 0.135000, 0.000000, 0 -(109.000000, 675.149250), (109.000000, 695.149250), 0.136250, 0.000000, 0 -(110.000000, 669.418129), (110.000000, 689.418129), 0.137500, 0.000000, 0 -(111.000000, 663.560256), (111.000000, 683.560256), 0.138750, 0.000000, 0 -(112.000000, 657.578289), (112.000000, 677.578289), 0.140000, 0.000000, 0 -(113.000000, 651.474941), (113.000000, 671.474941), 0.141250, 0.000000, 0 -(114.000000, 645.252981), (114.000000, 665.252981), 0.142500, 0.000000, 0 -(115.000000, 638.915232), (115.000000, 658.915232), 0.143750, 0.000000, 0 -(116.000000, 632.464567), (116.000000, 652.464567), 0.145000, 0.000000, 0 -(117.000000, 625.903914), (117.000000, 645.903914), 0.146250, 0.000000, 0 -(118.000000, 619.236248), (118.000000, 639.236248), 0.147500, 0.000000, 0 -(119.000000, 612.464595), (119.000000, 632.464595), 0.148750, 0.000000, 0 -(120.000000, 605.592025), (120.000000, 625.592025), 0.150000, 0.000000, 0 -(121.000000, 598.621658), (121.000000, 618.621658), 0.151250, 0.000000, 0 -(122.000000, 591.556653), (122.000000, 611.556653), 0.152500, 0.000000, 0 -(123.000000, 584.400217), (123.000000, 604.400217), 0.153750, 0.000000, 0 -(124.000000, 577.155596), (124.000000, 597.155596), 0.155000, 0.000000, 0 -(125.000000, 569.826076), (125.000000, 589.826076), 0.156250, 0.000000, 0 -(126.000000, 562.414981), (126.000000, 582.414981), 0.157500, 0.000000, 0 -(127.000000, 554.925675), (127.000000, 574.925675), 0.158750, 0.000000, 0 -(128.000000, 547.361554), (128.000000, 567.361554), 0.160000, 0.000000, 0 -(129.000000, 539.726049), (129.000000, 559.726049), 0.161250, 0.000000, 0 -(130.000000, 532.022624), (130.000000, 552.022624), 0.162500, 0.000000, 0 -(131.000000, 524.254774), (131.000000, 544.254774), 0.163750, 0.000000, 0 -(132.000000, 516.426023), (132.000000, 536.426023), 0.165000, 0.000000, 0 -(133.000000, 508.539921), (133.000000, 528.539921), 0.166250, 0.000000, 0 -(134.000000, 500.600046), (134.000000, 520.600046), 0.167500, 0.000000, 0 -(135.000000, 492.610000), (135.000000, 512.610000), 0.168750, 0.000000, 0 -(136.000000, 484.573407), (136.000000, 504.573407), 0.170000, 0.000000, 0 -(137.000000, 476.493913), (137.000000, 496.493913), 0.171250, 0.000000, 0 -(138.000000, 468.375184), (138.000000, 488.375184), 0.172500, 0.000000, 0 -(139.000000, 460.220901), (139.000000, 480.220901), 0.173750, 0.000000, 0 -(140.000000, 452.034763), (140.000000, 472.034763), 0.175000, 0.000000, 0 -(141.000000, 443.820486), (141.000000, 463.820486), 0.176250, 0.000000, 0 -(142.000000, 435.581793), (142.000000, 455.581793), 0.177500, 0.000000, 0 -(143.000000, 427.322424), (143.000000, 447.322424), 0.178750, 0.000000, 0 -(144.000000, 419.046124), (144.000000, 439.046124), 0.180000, 0.000000, 0 -(145.000000, 410.756648), (145.000000, 430.756648), 0.181250, 0.000000, 0 -(146.000000, 402.457756), (146.000000, 422.457756), 0.182500, 0.000000, 0 -(147.000000, 394.153213), (147.000000, 414.153213), 0.183750, 0.000000, 0 -(148.000000, 385.846787), (148.000000, 405.846787), 0.185000, 0.000000, 0 -(149.000000, 377.542244), (149.000000, 397.542244), 0.186250, 0.000000, 0 -(150.000000, 369.243352), (150.000000, 389.243352), 0.187500, 0.000000, 0 -(151.000000, 360.953876), (151.000000, 380.953876), 0.188750, 0.000000, 0 -(152.000000, 352.677576), (152.000000, 372.677576), 0.190000, 0.000000, 0 -(153.000000, 344.418207), (153.000000, 364.418207), 0.191250, 0.000000, 0 -(154.000000, 336.179514), (154.000000, 356.179514), 0.192500, 0.000000, 0 -(155.000000, 327.965237), (155.000000, 347.965237), 0.193750, 0.000000, 0 -(156.000000, 319.779099), (156.000000, 339.779099), 0.195000, 0.000000, 0 -(157.000000, 311.624816), (157.000000, 331.624816), 0.196250, 0.000000, 0 -(158.000000, 303.506087), (158.000000, 323.506087), 0.197500, 0.000000, 0 -(159.000000, 295.426593), (159.000000, 315.426593), 0.198750, 0.000000, 0 -(160.000000, 287.390000), (160.000000, 307.390000), 0.200000, 0.000000, 0 -(161.000000, 279.399954), (161.000000, 299.399954), 0.201250, 0.000000, 0 -(162.000000, 271.460079), (162.000000, 291.460079), 0.202500, 0.000000, 0 -(163.000000, 263.573977), (163.000000, 283.573977), 0.203750, 0.000000, 0 -(164.000000, 255.745226), (164.000000, 275.745226), 0.205000, 0.000000, 0 -(165.000000, 247.977376), (165.000000, 267.977376), 0.206250, 0.000000, 0 -(166.000000, 240.273951), (166.000000, 260.273951), 0.207500, 0.000000, 0 -(167.000000, 232.638446), (167.000000, 252.638446), 0.208750, 0.000000, 0 -(168.000000, 225.074325), (168.000000, 245.074325), 0.210000, 0.000000, 0 -(169.000000, 217.585019), (169.000000, 237.585019), 0.211250, 0.000000, 0 -(170.000000, 210.173924), (170.000000, 230.173924), 0.212500, 0.000000, 0 -(171.000000, 202.844404), (171.000000, 222.844404), 0.213750, 0.000000, 0 -(172.000000, 195.599783), (172.000000, 215.599783), 0.215000, 0.000000, 0 -(173.000000, 188.443347), (173.000000, 208.443347), 0.216250, 0.000000, 0 -(174.000000, 181.378342), (174.000000, 201.378342), 0.217500, 0.000000, 0 -(175.000000, 174.407975), (175.000000, 194.407975), 0.218750, 0.000000, 0 -(176.000000, 167.535405), (176.000000, 187.535405), 0.220000, 0.000000, 0 -(177.000000, 160.763752), (177.000000, 180.763752), 0.221250, 0.000000, 0 -(178.000000, 154.096086), (178.000000, 174.096086), 0.222500, 0.000000, 0 -(179.000000, 147.535433), (179.000000, 167.535433), 0.223750, 0.000000, 0 -(180.000000, 141.084768), (180.000000, 161.084768), 0.225000, 0.000000, 0 -(181.000000, 134.747019), (181.000000, 154.747019), 0.226250, 0.000000, 0 -(182.000000, 128.525059), (182.000000, 148.525059), 0.227500, 0.000000, 0 -(183.000000, 122.421711), (183.000000, 142.421711), 0.228750, 0.000000, 0 -(184.000000, 116.439744), (184.000000, 136.439744), 0.230000, 0.000000, 0 -(185.000000, 110.581871), (185.000000, 130.581871), 0.231250, 0.000000, 0 -(186.000000, 104.850750), (186.000000, 124.850750), 0.232500, 0.000000, 0 -(187.000000, 99.248981), (187.000000, 119.248981), 0.233750, 0.000000, 0 -(188.000000, 93.779104), (188.000000, 113.779104), 0.235000, 0.000000, 0 -(189.000000, 88.443602), (189.000000, 108.443602), 0.236250, 0.000000, 0 -(190.000000, 83.244893), (190.000000, 103.244893), 0.237500, 0.000000, 0 -(191.000000, 78.185337), (191.000000, 98.185337), 0.238750, 0.000000, 0 -(192.000000, 73.267229), (192.000000, 93.267229), 0.240000, 0.000000, 0 -(193.000000, 68.492799), (193.000000, 88.492799), 0.241250, 0.000000, 0 -(194.000000, 63.864214), (194.000000, 83.864214), 0.242500, 0.000000, 0 -(195.000000, 59.383573), (195.000000, 79.383573), 0.243750, 0.000000, 0 -(196.000000, 55.052909), (196.000000, 75.052909), 0.245000, 0.000000, 0 -(197.000000, 50.874186), (197.000000, 70.874186), 0.246250, 0.000000, 0 -(198.000000, 46.849299), (198.000000, 66.849299), 0.247500, 0.000000, 0 -(199.000000, 42.980075), (199.000000, 62.980075), 0.248750, 0.000000, 0 -(200.000000, 39.268269), (200.000000, 59.268269), 0.250000, 0.000000, 0 -(201.000000, 35.715565), (201.000000, 55.715565), 0.251250, 0.000000, 0 -(202.000000, 32.323573), (202.000000, 52.323573), 0.252500, 0.000000, 0 -(203.000000, 29.093834), (203.000000, 49.093834), 0.253750, 0.000000, 0 -(204.000000, 26.027811), (204.000000, 46.027811), 0.255000, 0.000000, 0 -(205.000000, 23.126896), (205.000000, 43.126896), 0.256250, 0.000000, 0 -(206.000000, 20.392405), (206.000000, 40.392405), 0.257500, 0.000000, 0 -(207.000000, 17.825578), (207.000000, 37.825578), 0.258750, 0.000000, 0 -(208.000000, 15.427579), (208.000000, 35.427579), 0.260000, 0.000000, 0 -(209.000000, 13.199497), (209.000000, 33.199497), 0.261250, 0.000000, 0 -(210.000000, 11.142342), (210.000000, 31.142342), 0.262500, 0.000000, 0 -(211.000000, 9.257047), (211.000000, 29.257047), 0.263750, 0.000000, 0 -(212.000000, 7.544467), (212.000000, 27.544467), 0.265000, 0.000000, 0 -(213.000000, 6.005380), (213.000000, 26.005380), 0.266250, 0.000000, 0 -(214.000000, 4.640483), (214.000000, 24.640483), 0.267500, 0.000000, 0 -(215.000000, 3.450396), (215.000000, 23.450396), 0.268750, 0.000000, 0 -(216.000000, 2.435658), (216.000000, 22.435658), 0.270000, 0.000000, 0 -(217.000000, 1.596730), (217.000000, 21.596730), 0.271250, 0.000000, 0 -(218.000000, 0.933993), (218.000000, 20.933993), 0.272500, 0.000000, 0 -(219.000000, 0.447747), (219.000000, 20.447747), 0.273750, 0.000000, 0 -(220.000000, 0.138212), (220.000000, 20.138212), 0.275000, 0.000000, 0 -(221.000000, 0.005529), (221.000000, 20.005529), 0.276250, 0.000000, 0 -(222.000000, 0.049758), (222.000000, 20.049758), 0.277500, 0.000000, 0 -(223.000000, 0.270879), (223.000000, 20.270879), 0.278750, 0.000000, 0 -(224.000000, 0.668793), (224.000000, 20.668793), 0.280000, 0.000000, 0 -(225.000000, 1.243317), (225.000000, 21.243317), 0.281250, 0.000000, 0 -(226.000000, 1.994192), (226.000000, 21.994192), 0.282500, 0.000000, 0 -(227.000000, 2.921078), (227.000000, 22.921078), 0.283750, 0.000000, 0 -(228.000000, 4.023553), (228.000000, 24.023553), 0.285000, 0.000000, 0 -(229.000000, 5.301117), (229.000000, 25.301117), 0.286250, 0.000000, 0 -(230.000000, 6.753191), (230.000000, 26.753191), 0.287500, 0.000000, 0 -(231.000000, 8.379117), (231.000000, 28.379117), 0.288750, 0.000000, 0 -(232.000000, 10.178156), (232.000000, 30.178156), 0.290000, 0.000000, 0 -(233.000000, 12.149493), (233.000000, 32.149493), 0.291250, 0.000000, 0 -(234.000000, 14.292233), (234.000000, 34.292233), 0.292500, 0.000000, 0 -(235.000000, 16.605405), (235.000000, 36.605405), 0.293750, 0.000000, 0 -(236.000000, 19.087959), (236.000000, 39.087959), 0.295000, 0.000000, 0 -(237.000000, 21.738768), (237.000000, 41.738768), 0.296250, 0.000000, 0 -(238.000000, 24.556631), (238.000000, 44.556631), 0.297500, 0.000000, 0 -(239.000000, 27.540269), (239.000000, 47.540269), 0.298750, 0.000000, 0 -(240.000000, 30.688329), (240.000000, 50.688329), 0.300000, 0.000000, 0 -(241.000000, 33.999382), (241.000000, 53.999382), 0.301250, 0.000000, 0 -(242.000000, 37.471927), (242.000000, 57.471927), 0.302500, 0.000000, 0 -(243.000000, 41.104388), (243.000000, 61.104388), 0.303750, 0.000000, 0 -(244.000000, 44.895118), (244.000000, 64.895118), 0.305000, 0.000000, 0 -(245.000000, 48.842397), (245.000000, 68.842397), 0.306250, 0.000000, 0 -(246.000000, 52.944434), (246.000000, 72.944434), 0.307500, 0.000000, 0 -(247.000000, 57.199369), (247.000000, 77.199369), 0.308750, 0.000000, 0 -(248.000000, 61.605272), (248.000000, 81.605272), 0.310000, 0.000000, 0 -(249.000000, 66.160143), (249.000000, 86.160143), 0.311250, 0.000000, 0 -(250.000000, 70.861917), (250.000000, 90.861917), 0.312500, 0.000000, 0 -(251.000000, 75.708461), (251.000000, 95.708461), 0.313750, 0.000000, 0 -(252.000000, 80.697576), (252.000000, 100.697576), 0.315000, 0.000000, 0 -(253.000000, 85.826999), (253.000000, 105.826999), 0.316250, 0.000000, 0 -(254.000000, 91.094404), (254.000000, 111.094404), 0.317500, 0.000000, 0 -(255.000000, 96.497400), (255.000000, 116.497400), 0.318750, 0.000000, 0 -(256.000000, 102.033537), (256.000000, 122.033537), 0.320000, 0.000000, 0 -(257.000000, 107.700303), (257.000000, 127.700303), 0.321250, 0.000000, 0 -(258.000000, 113.495128), (258.000000, 133.495128), 0.322500, 0.000000, 0 -(259.000000, 119.415384), (259.000000, 139.415384), 0.323750, 0.000000, 0 -(260.000000, 125.458384), (260.000000, 145.458384), 0.325000, 0.000000, 0 -(261.000000, 131.621387), (261.000000, 151.621387), 0.326250, 0.000000, 0 -(262.000000, 137.901598), (262.000000, 157.901598), 0.327500, 0.000000, 0 -(263.000000, 144.296168), (263.000000, 164.296168), 0.328750, 0.000000, 0 -(264.000000, 150.802196), (264.000000, 170.802196), 0.330000, 0.000000, 0 -(265.000000, 157.416730), (265.000000, 177.416730), 0.331250, 0.000000, 0 -(266.000000, 164.136771), (266.000000, 184.136771), 0.332500, 0.000000, 0 -(267.000000, 170.959269), (267.000000, 190.959269), 0.333750, 0.000000, 0 -(268.000000, 177.881130), (268.000000, 197.881130), 0.335000, 0.000000, 0 -(269.000000, 184.899214), (269.000000, 204.899214), 0.336250, 0.000000, 0 -(270.000000, 192.010338), (270.000000, 212.010338), 0.337500, 0.000000, 0 -(271.000000, 199.211275), (271.000000, 219.211275), 0.338750, 0.000000, 0 -(272.000000, 206.498759), (272.000000, 226.498759), 0.340000, 0.000000, 0 -(273.000000, 213.869484), (273.000000, 233.869484), 0.341250, 0.000000, 0 -(274.000000, 221.320107), (274.000000, 241.320107), 0.342500, 0.000000, 0 -(275.000000, 228.847248), (275.000000, 248.847248), 0.343750, 0.000000, 0 -(276.000000, 236.447492), (276.000000, 256.447492), 0.345000, 0.000000, 0 -(277.000000, 244.117391), (277.000000, 264.117391), 0.346250, 0.000000, 0 -(278.000000, 251.853467), (278.000000, 271.853467), 0.347500, 0.000000, 0 -(279.000000, 259.652210), (279.000000, 279.652210), 0.348750, 0.000000, 0 -(280.000000, 267.510082), (280.000000, 287.510082), 0.350000, 0.000000, 0 -(281.000000, 275.423519), (281.000000, 295.423519), 0.351250, 0.000000, 0 -(282.000000, 283.388932), (282.000000, 303.388932), 0.352500, 0.000000, 0 -(283.000000, 291.402705), (283.000000, 311.402705), 0.353750, 0.000000, 0 -(284.000000, 299.461206), (284.000000, 319.461206), 0.355000, 0.000000, 0 -(285.000000, 307.560777), (285.000000, 327.560777), 0.356250, 0.000000, 0 -(286.000000, 315.697745), (286.000000, 335.697745), 0.357500, 0.000000, 0 -(287.000000, 323.868418), (287.000000, 343.868418), 0.358750, 0.000000, 0 -(288.000000, 332.069090), (288.000000, 352.069090), 0.360000, 0.000000, 0 -(289.000000, 340.296042), (289.000000, 360.296042), 0.361250, 0.000000, 0 -(290.000000, 348.545541), (290.000000, 368.545541), 0.362500, 0.000000, 0 -(291.000000, 356.813844), (291.000000, 376.813844), 0.363750, 0.000000, 0 -(292.000000, 365.097202), (292.000000, 385.097202), 0.365000, 0.000000, 0 -(293.000000, 373.391856), (293.000000, 393.391856), 0.366250, 0.000000, 0 -(294.000000, 381.694044), (294.000000, 401.694044), 0.367500, 0.000000, 0 -(295.000000, 390.000000), (295.000000, 410.000000), 0.368750, 0.000000, 0 -(296.000000, 398.305956), (296.000000, 418.305956), 0.370000, 0.000000, 0 -(297.000000, 406.608144), (297.000000, 426.608144), 0.371250, 0.000000, 0 -(298.000000, 414.902798), (298.000000, 434.902798), 0.372500, 0.000000, 0 -(299.000000, 423.186156), (299.000000, 443.186156), 0.373750, 0.000000, 0 -(300.000000, 431.454459), (300.000000, 451.454459), 0.375000, 0.000000, 0 -(301.000000, 439.703958), (301.000000, 459.703958), 0.376250, 0.000000, 0 -(302.000000, 447.930910), (302.000000, 467.930910), 0.377500, 0.000000, 0 -(303.000000, 456.131582), (303.000000, 476.131582), 0.378750, 0.000000, 0 -(304.000000, 464.302255), (304.000000, 484.302255), 0.380000, 0.000000, 0 -(305.000000, 472.439223), (305.000000, 492.439223), 0.381250, 0.000000, 0 -(306.000000, 480.538794), (306.000000, 500.538794), 0.382500, 0.000000, 0 -(307.000000, 488.597295), (307.000000, 508.597295), 0.383750, 0.000000, 0 -(308.000000, 496.611068), (308.000000, 516.611068), 0.385000, 0.000000, 0 -(309.000000, 504.576481), (309.000000, 524.576481), 0.386250, 0.000000, 0 -(310.000000, 512.489918), (310.000000, 532.489918), 0.387500, 0.000000, 0 -(311.000000, 520.347790), (311.000000, 540.347790), 0.388750, 0.000000, 0 -(312.000000, 528.146533), (312.000000, 548.146533), 0.390000, 0.000000, 0 -(313.000000, 535.882609), (313.000000, 555.882609), 0.391250, 0.000000, 0 -(314.000000, 543.552508), (314.000000, 563.552508), 0.392500, 0.000000, 0 -(315.000000, 551.152752), (315.000000, 571.152752), 0.393750, 0.000000, 0 -(316.000000, 558.679893), (316.000000, 578.679893), 0.395000, 0.000000, 0 -(317.000000, 566.130516), (317.000000, 586.130516), 0.396250, 0.000000, 0 -(318.000000, 573.501241), (318.000000, 593.501241), 0.397500, 0.000000, 0 -(319.000000, 580.788725), (319.000000, 600.788725), 0.398750, 0.000000, 0 -(320.000000, 587.989662), (320.000000, 607.989662), 0.400000, 0.000000, 0 -(321.000000, 595.100786), (321.000000, 615.100786), 0.401250, 0.000000, 0 -(322.000000, 602.118870), (322.000000, 622.118870), 0.402500, 0.000000, 0 -(323.000000, 609.040731), (323.000000, 629.040731), 0.403750, 0.000000, 0 -(324.000000, 615.863229), (324.000000, 635.863229), 0.405000, 0.000000, 0 -(325.000000, 622.583270), (325.000000, 642.583270), 0.406250, 0.000000, 0 -(326.000000, 629.197804), (326.000000, 649.197804), 0.407500, 0.000000, 0 -(327.000000, 635.703832), (327.000000, 655.703832), 0.408750, 0.000000, 0 -(328.000000, 642.098402), (328.000000, 662.098402), 0.410000, 0.000000, 0 -(329.000000, 648.378613), (329.000000, 668.378613), 0.411250, 0.000000, 0 -(330.000000, 654.541616), (330.000000, 674.541616), 0.412500, 0.000000, 0 -(331.000000, 660.584616), (331.000000, 680.584616), 0.413750, 0.000000, 0 -(332.000000, 666.504872), (332.000000, 686.504872), 0.415000, 0.000000, 0 -(333.000000, 672.299697), (333.000000, 692.299697), 0.416250, 0.000000, 0 -(334.000000, 677.966463), (334.000000, 697.966463), 0.417500, 0.000000, 0 -(335.000000, 683.502600), (335.000000, 703.502600), 0.418750, 0.000000, 0 -(336.000000, 688.905596), (336.000000, 708.905596), 0.420000, 0.000000, 0 -(337.000000, 694.173001), (337.000000, 714.173001), 0.421250, 0.000000, 0 -(338.000000, 699.302424), (338.000000, 719.302424), 0.422500, 0.000000, 0 -(339.000000, 704.291539), (339.000000, 724.291539), 0.423750, 0.000000, 0 -(340.000000, 709.138083), (340.000000, 729.138083), 0.425000, 0.000000, 0 -(341.000000, 713.839857), (341.000000, 733.839857), 0.426250, 0.000000, 0 -(342.000000, 718.394728), (342.000000, 738.394728), 0.427500, 0.000000, 0 -(343.000000, 722.800631), (343.000000, 742.800631), 0.428750, 0.000000, 0 -(344.000000, 727.055566), (344.000000, 747.055566), 0.430000, 0.000000, 0 -(345.000000, 731.157603), (345.000000, 751.157603), 0.431250, 0.000000, 0 -(346.000000, 735.104882), (346.000000, 755.104882), 0.432500, 0.000000, 0 -(347.000000, 738.895612), (347.000000, 758.895612), 0.433750, 0.000000, 0 -(348.000000, 742.528073), (348.000000, 762.528073), 0.435000, 0.000000, 0 -(349.000000, 746.000618), (349.000000, 766.000618), 0.436250, 0.000000, 0 -(350.000000, 749.311671), (350.000000, 769.311671), 0.437500, 0.000000, 0 -(351.000000, 752.459731), (351.000000, 772.459731), 0.438750, 0.000000, 0 -(352.000000, 755.443369), (352.000000, 775.443369), 0.440000, 0.000000, 0 -(353.000000, 758.261232), (353.000000, 778.261232), 0.441250, 0.000000, 0 -(354.000000, 760.912041), (354.000000, 780.912041), 0.442500, 0.000000, 0 -(355.000000, 763.394595), (355.000000, 783.394595), 0.443750, 0.000000, 0 -(356.000000, 765.707767), (356.000000, 785.707767), 0.445000, 0.000000, 0 -(357.000000, 767.850507), (357.000000, 787.850507), 0.446250, 0.000000, 0 -(358.000000, 769.821844), (358.000000, 789.821844), 0.447500, 0.000000, 0 -(359.000000, 771.620883), (359.000000, 791.620883), 0.448750, 0.000000, 0 -(360.000000, 773.246809), (360.000000, 793.246809), 0.450000, 0.000000, 0 -(361.000000, 774.698883), (361.000000, 794.698883), 0.451250, 0.000000, 0 -(362.000000, 775.976447), (362.000000, 795.976447), 0.452500, 0.000000, 0 -(363.000000, 777.078922), (363.000000, 797.078922), 0.453750, 0.000000, 0 -(364.000000, 778.005808), (364.000000, 798.005808), 0.455000, 0.000000, 0 -(365.000000, 778.756683), (365.000000, 798.756683), 0.456250, 0.000000, 0 -(366.000000, 779.331207), (366.000000, 799.331207), 0.457500, 0.000000, 0 -(367.000000, 779.729121), (367.000000, 799.729121), 0.458750, 0.000000, 0 -(368.000000, 779.950242), (368.000000, 799.950242), 0.460000, 0.000000, 0 -(369.000000, 779.994471), (369.000000, 799.994471), 0.461250, 0.000000, 0 -(370.000000, 779.861788), (370.000000, 799.861788), 0.462500, 0.000000, 0 -(371.000000, 779.552253), (371.000000, 799.552253), 0.463750, 0.000000, 0 -(372.000000, 779.066007), (372.000000, 799.066007), 0.465000, 0.000000, 0 -(373.000000, 778.403270), (373.000000, 798.403270), 0.466250, 0.000000, 0 -(374.000000, 777.564342), (374.000000, 797.564342), 0.467500, 0.000000, 0 -(375.000000, 776.549604), (375.000000, 796.549604), 0.468750, 0.000000, 0 -(376.000000, 775.359517), (376.000000, 795.359517), 0.470000, 0.000000, 0 -(377.000000, 773.994620), (377.000000, 793.994620), 0.471250, 0.000000, 0 -(378.000000, 772.455533), (378.000000, 792.455533), 0.472500, 0.000000, 0 -(379.000000, 770.742953), (379.000000, 790.742953), 0.473750, 0.000000, 0 -(380.000000, 768.857658), (380.000000, 788.857658), 0.475000, 0.000000, 0 -(381.000000, 766.800503), (381.000000, 786.800503), 0.476250, 0.000000, 0 -(382.000000, 764.572421), (382.000000, 784.572421), 0.477500, 0.000000, 0 -(383.000000, 762.174422), (383.000000, 782.174422), 0.478750, 0.000000, 0 -(384.000000, 759.607595), (384.000000, 779.607595), 0.480000, 0.000000, 0 -(385.000000, 756.873104), (385.000000, 776.873104), 0.481250, 0.000000, 0 -(386.000000, 753.972189), (386.000000, 773.972189), 0.482500, 0.000000, 0 -(387.000000, 750.906166), (387.000000, 770.906166), 0.483750, 0.000000, 0 -(388.000000, 747.676427), (388.000000, 767.676427), 0.485000, 0.000000, 0 -(389.000000, 744.284435), (389.000000, 764.284435), 0.486250, 0.000000, 0 -(390.000000, 740.731731), (390.000000, 760.731731), 0.487500, 0.000000, 0 -(391.000000, 737.019925), (391.000000, 757.019925), 0.488750, 0.000000, 0 -(392.000000, 733.150701), (392.000000, 753.150701), 0.490000, 0.000000, 0 -(393.000000, 729.125814), (393.000000, 749.125814), 0.491250, 0.000000, 0 -(394.000000, 724.947091), (394.000000, 744.947091), 0.492500, 0.000000, 0 -(395.000000, 720.616427), (395.000000, 740.616427), 0.493750, 0.000000, 0 -(396.000000, 716.135786), (396.000000, 736.135786), 0.495000, 0.000000, 0 -(397.000000, 711.507201), (397.000000, 731.507201), 0.496250, 0.000000, 0 -(398.000000, 706.732771), (398.000000, 726.732771), 0.497500, 0.000000, 0 -(399.000000, 701.814663), (399.000000, 721.814663), 0.498750, 0.000000, 0 -(400.000000, 696.755107), (400.000000, 716.755107), 0.500000, 0.000000, 0 -(401.000000, 691.556398), (401.000000, 711.556398), 0.501250, 0.000000, 0 -(402.000000, 686.220896), (402.000000, 706.220896), 0.502500, 0.000000, 0 -(403.000000, 680.751019), (403.000000, 700.751019), 0.503750, 0.000000, 0 -(404.000000, 675.149250), (404.000000, 695.149250), 0.505000, 0.000000, 0 -(405.000000, 669.418129), (405.000000, 689.418129), 0.506250, 0.000000, 0 -(406.000000, 663.560256), (406.000000, 683.560256), 0.507500, 0.000000, 0 -(407.000000, 657.578289), (407.000000, 677.578289), 0.508750, 0.000000, 0 -(408.000000, 651.474941), (408.000000, 671.474941), 0.510000, 0.000000, 0 -(409.000000, 645.252981), (409.000000, 665.252981), 0.511250, 0.000000, 0 -(410.000000, 638.915232), (410.000000, 658.915232), 0.512500, 0.000000, 0 -(411.000000, 632.464567), (411.000000, 652.464567), 0.513750, 0.000000, 0 -(412.000000, 625.903914), (412.000000, 645.903914), 0.515000, 0.000000, 0 -(413.000000, 619.236248), (413.000000, 639.236248), 0.516250, 0.000000, 0 -(414.000000, 612.464595), (414.000000, 632.464595), 0.517500, 0.000000, 0 -(415.000000, 605.592025), (415.000000, 625.592025), 0.518750, 0.000000, 0 -(416.000000, 598.621658), (416.000000, 618.621658), 0.520000, 0.000000, 0 -(417.000000, 591.556653), (417.000000, 611.556653), 0.521250, 0.000000, 0 -(418.000000, 584.400217), (418.000000, 604.400217), 0.522500, 0.000000, 0 -(419.000000, 577.155596), (419.000000, 597.155596), 0.523750, 0.000000, 0 -(420.000000, 569.826076), (420.000000, 589.826076), 0.525000, 0.000000, 0 -(421.000000, 562.414981), (421.000000, 582.414981), 0.526250, 0.000000, 0 -(422.000000, 554.925675), (422.000000, 574.925675), 0.527500, 0.000000, 0 -(423.000000, 547.361554), (423.000000, 567.361554), 0.528750, 0.000000, 0 -(424.000000, 539.726049), (424.000000, 559.726049), 0.530000, 0.000000, 0 -(425.000000, 532.022624), (425.000000, 552.022624), 0.531250, 0.000000, 0 -(426.000000, 524.254774), (426.000000, 544.254774), 0.532500, 0.000000, 0 -(427.000000, 516.426023), (427.000000, 536.426023), 0.533750, 0.000000, 0 -(428.000000, 508.539921), (428.000000, 528.539921), 0.535000, 0.000000, 0 -(429.000000, 500.600046), (429.000000, 520.600046), 0.536250, 0.000000, 0 -(430.000000, 492.610000), (430.000000, 512.610000), 0.537500, 0.000000, 0 -(431.000000, 484.573407), (431.000000, 504.573407), 0.538750, 0.000000, 0 -(432.000000, 476.493913), (432.000000, 496.493913), 0.540000, 0.000000, 0 -(433.000000, 468.375184), (433.000000, 488.375184), 0.541250, 0.000000, 0 -(434.000000, 460.220901), (434.000000, 480.220901), 0.542500, 0.000000, 0 -(435.000000, 452.034763), (435.000000, 472.034763), 0.543750, 0.000000, 0 -(436.000000, 443.820486), (436.000000, 463.820486), 0.545000, 0.000000, 0 -(437.000000, 435.581793), (437.000000, 455.581793), 0.546250, 0.000000, 0 -(438.000000, 427.322424), (438.000000, 447.322424), 0.547500, 0.000000, 0 -(439.000000, 419.046124), (439.000000, 439.046124), 0.548750, 0.000000, 0 -(440.000000, 410.756648), (440.000000, 430.756648), 0.550000, 0.000000, 0 -(441.000000, 402.457756), (441.000000, 422.457756), 0.551250, 0.000000, 0 -(442.000000, 394.153213), (442.000000, 414.153213), 0.552500, 0.000000, 0 -(443.000000, 385.846787), (443.000000, 405.846787), 0.553750, 0.000000, 0 -(444.000000, 377.542244), (444.000000, 397.542244), 0.555000, 0.000000, 0 -(445.000000, 369.243352), (445.000000, 389.243352), 0.556250, 0.000000, 0 -(446.000000, 360.953876), (446.000000, 380.953876), 0.557500, 0.000000, 0 -(447.000000, 352.677576), (447.000000, 372.677576), 0.558750, 0.000000, 0 -(448.000000, 344.418207), (448.000000, 364.418207), 0.560000, 0.000000, 0 -(449.000000, 336.179514), (449.000000, 356.179514), 0.561250, 0.000000, 0 -(450.000000, 327.965237), (450.000000, 347.965237), 0.562500, 0.000000, 0 -(451.000000, 319.779099), (451.000000, 339.779099), 0.563750, 0.000000, 0 -(452.000000, 311.624816), (452.000000, 331.624816), 0.565000, 0.000000, 0 -(453.000000, 303.506087), (453.000000, 323.506087), 0.566250, 0.000000, 0 -(454.000000, 295.426593), (454.000000, 315.426593), 0.567500, 0.000000, 0 -(455.000000, 287.390000), (455.000000, 307.390000), 0.568750, 0.000000, 0 -(456.000000, 279.399954), (456.000000, 299.399954), 0.570000, 0.000000, 0 -(457.000000, 271.460079), (457.000000, 291.460079), 0.571250, 0.000000, 0 -(458.000000, 263.573977), (458.000000, 283.573977), 0.572500, 0.000000, 0 -(459.000000, 255.745226), (459.000000, 275.745226), 0.573750, 0.000000, 0 -(460.000000, 247.977376), (460.000000, 267.977376), 0.575000, 0.000000, 0 -(461.000000, 240.273951), (461.000000, 260.273951), 0.576250, 0.000000, 0 -(462.000000, 232.638446), (462.000000, 252.638446), 0.577500, 0.000000, 0 -(463.000000, 225.074325), (463.000000, 245.074325), 0.578750, 0.000000, 0 -(464.000000, 217.585019), (464.000000, 237.585019), 0.580000, 0.000000, 0 -(465.000000, 210.173924), (465.000000, 230.173924), 0.581250, 0.000000, 0 -(466.000000, 202.844404), (466.000000, 222.844404), 0.582500, 0.000000, 0 -(467.000000, 195.599783), (467.000000, 215.599783), 0.583750, 0.000000, 0 -(468.000000, 188.443347), (468.000000, 208.443347), 0.585000, 0.000000, 0 -(469.000000, 181.378342), (469.000000, 201.378342), 0.586250, 0.000000, 0 -(470.000000, 174.407975), (470.000000, 194.407975), 0.587500, 0.000000, 0 -(471.000000, 167.535405), (471.000000, 187.535405), 0.588750, 0.000000, 0 -(472.000000, 160.763752), (472.000000, 180.763752), 0.590000, 0.000000, 0 -(473.000000, 154.096086), (473.000000, 174.096086), 0.591250, 0.000000, 0 -(474.000000, 147.535433), (474.000000, 167.535433), 0.592500, 0.000000, 0 -(475.000000, 141.084768), (475.000000, 161.084768), 0.593750, 0.000000, 0 -(476.000000, 134.747019), (476.000000, 154.747019), 0.595000, 0.000000, 0 -(477.000000, 128.525059), (477.000000, 148.525059), 0.596250, 0.000000, 0 -(478.000000, 122.421711), (478.000000, 142.421711), 0.597500, 0.000000, 0 -(479.000000, 116.439744), (479.000000, 136.439744), 0.598750, 0.000000, 0 -(480.000000, 110.581871), (480.000000, 130.581871), 0.600000, 0.000000, 0 -(481.000000, 104.850750), (481.000000, 124.850750), 0.601250, 0.000000, 0 -(482.000000, 99.248981), (482.000000, 119.248981), 0.602500, 0.000000, 0 -(483.000000, 93.779104), (483.000000, 113.779104), 0.603750, 0.000000, 0 -(484.000000, 88.443602), (484.000000, 108.443602), 0.605000, 0.000000, 0 -(485.000000, 83.244893), (485.000000, 103.244893), 0.606250, 0.000000, 0 -(486.000000, 78.185337), (486.000000, 98.185337), 0.607500, 0.000000, 0 -(487.000000, 73.267229), (487.000000, 93.267229), 0.608750, 0.000000, 0 -(488.000000, 68.492799), (488.000000, 88.492799), 0.610000, 0.000000, 0 -(489.000000, 63.864214), (489.000000, 83.864214), 0.611250, 0.000000, 0 -(490.000000, 59.383573), (490.000000, 79.383573), 0.612500, 0.000000, 0 -(491.000000, 55.052909), (491.000000, 75.052909), 0.613750, 0.000000, 0 -(492.000000, 50.874186), (492.000000, 70.874186), 0.615000, 0.000000, 0 -(493.000000, 46.849299), (493.000000, 66.849299), 0.616250, 0.000000, 0 -(494.000000, 42.980075), (494.000000, 62.980075), 0.617500, 0.000000, 0 -(495.000000, 39.268269), (495.000000, 59.268269), 0.618750, 0.000000, 0 -(496.000000, 35.715565), (496.000000, 55.715565), 0.620000, 0.000000, 0 -(497.000000, 32.323573), (497.000000, 52.323573), 0.621250, 0.000000, 0 -(498.000000, 29.093834), (498.000000, 49.093834), 0.622500, 0.000000, 0 -(499.000000, 26.027811), (499.000000, 46.027811), 0.623750, 0.000000, 0 -(500.000000, 23.126896), (500.000000, 43.126896), 0.625000, 0.000000, 0 -(501.000000, 20.392405), (501.000000, 40.392405), 0.626250, 0.000000, 0 -(502.000000, 17.825578), (502.000000, 37.825578), 0.627500, 0.000000, 0 -(503.000000, 15.427579), (503.000000, 35.427579), 0.628750, 0.000000, 0 -(504.000000, 13.199497), (504.000000, 33.199497), 0.630000, 0.000000, 0 -(505.000000, 11.142342), (505.000000, 31.142342), 0.631250, 0.000000, 0 -(506.000000, 9.257047), (506.000000, 29.257047), 0.632500, 0.000000, 0 -(507.000000, 7.544467), (507.000000, 27.544467), 0.633750, 0.000000, 0 -(508.000000, 6.005380), (508.000000, 26.005380), 0.635000, 0.000000, 0 -(509.000000, 4.640483), (509.000000, 24.640483), 0.636250, 0.000000, 0 -(510.000000, 3.450396), (510.000000, 23.450396), 0.637500, 0.000000, 0 -(511.000000, 2.435658), (511.000000, 22.435658), 0.638750, 0.000000, 0 -(512.000000, 1.596730), (512.000000, 21.596730), 0.640000, 0.000000, 0 -(513.000000, 0.933993), (513.000000, 20.933993), 0.641250, 0.000000, 0 -(514.000000, 0.447747), (514.000000, 20.447747), 0.642500, 0.000000, 0 -(515.000000, 0.138212), (515.000000, 20.138212), 0.643750, 0.000000, 0 -(516.000000, 0.005529), (516.000000, 20.005529), 0.645000, 0.000000, 0 -(517.000000, 0.049758), (517.000000, 20.049758), 0.646250, 0.000000, 0 -(518.000000, 0.270879), (518.000000, 20.270879), 0.647500, 0.000000, 0 -(519.000000, 0.668793), (519.000000, 20.668793), 0.648750, 0.000000, 0 -(520.000000, 1.243317), (520.000000, 21.243317), 0.650000, 0.000000, 0 -(521.000000, 1.994192), (521.000000, 21.994192), 0.651250, 0.000000, 0 -(522.000000, 2.921078), (522.000000, 22.921078), 0.652500, 0.000000, 0 -(523.000000, 4.023553), (523.000000, 24.023553), 0.653750, 0.000000, 0 -(524.000000, 5.301117), (524.000000, 25.301117), 0.655000, 0.000000, 0 -(525.000000, 6.753191), (525.000000, 26.753191), 0.656250, 0.000000, 0 -(526.000000, 8.379117), (526.000000, 28.379117), 0.657500, 0.000000, 0 -(527.000000, 10.178156), (527.000000, 30.178156), 0.658750, 0.000000, 0 -(528.000000, 12.149493), (528.000000, 32.149493), 0.660000, 0.000000, 0 -(529.000000, 14.292233), (529.000000, 34.292233), 0.661250, 0.000000, 0 -(530.000000, 16.605405), (530.000000, 36.605405), 0.662500, 0.000000, 0 -(531.000000, 19.087959), (531.000000, 39.087959), 0.663750, 0.000000, 0 -(532.000000, 21.738768), (532.000000, 41.738768), 0.665000, 0.000000, 0 -(533.000000, 24.556631), (533.000000, 44.556631), 0.666250, 0.000000, 0 -(534.000000, 27.540269), (534.000000, 47.540269), 0.667500, 0.000000, 0 -(535.000000, 30.688329), (535.000000, 50.688329), 0.668750, 0.000000, 0 -(536.000000, 33.999382), (536.000000, 53.999382), 0.670000, 0.000000, 0 -(537.000000, 37.471927), (537.000000, 57.471927), 0.671250, 0.000000, 0 -(538.000000, 41.104388), (538.000000, 61.104388), 0.672500, 0.000000, 0 -(539.000000, 44.895118), (539.000000, 64.895118), 0.673750, 0.000000, 0 -(540.000000, 48.842397), (540.000000, 68.842397), 0.675000, 0.000000, 0 -(541.000000, 52.944434), (541.000000, 72.944434), 0.676250, 0.000000, 0 -(542.000000, 57.199369), (542.000000, 77.199369), 0.677500, 0.000000, 0 -(543.000000, 61.605272), (543.000000, 81.605272), 0.678750, 0.000000, 0 -(544.000000, 66.160143), (544.000000, 86.160143), 0.680000, 0.000000, 0 -(545.000000, 70.861917), (545.000000, 90.861917), 0.681250, 0.000000, 0 -(546.000000, 75.708461), (546.000000, 95.708461), 0.682500, 0.000000, 0 -(547.000000, 80.697576), (547.000000, 100.697576), 0.683750, 0.000000, 0 -(548.000000, 85.826999), (548.000000, 105.826999), 0.685000, 0.000000, 0 -(549.000000, 91.094404), (549.000000, 111.094404), 0.686250, 0.000000, 0 -(550.000000, 96.497400), (550.000000, 116.497400), 0.687500, 0.000000, 0 -(551.000000, 102.033537), (551.000000, 122.033537), 0.688750, 0.000000, 0 -(552.000000, 107.700303), (552.000000, 127.700303), 0.690000, 0.000000, 0 -(553.000000, 113.495128), (553.000000, 133.495128), 0.691250, 0.000000, 0 -(554.000000, 119.415384), (554.000000, 139.415384), 0.692500, 0.000000, 0 -(555.000000, 125.458384), (555.000000, 145.458384), 0.693750, 0.000000, 0 -(556.000000, 131.621387), (556.000000, 151.621387), 0.695000, 0.000000, 0 -(557.000000, 137.901598), (557.000000, 157.901598), 0.696250, 0.000000, 0 -(558.000000, 144.296168), (558.000000, 164.296168), 0.697500, 0.000000, 0 -(559.000000, 150.802196), (559.000000, 170.802196), 0.698750, 0.000000, 0 -(560.000000, 157.416730), (560.000000, 177.416730), 0.700000, 0.000000, 0 -(561.000000, 164.136771), (561.000000, 184.136771), 0.701250, 0.000000, 0 -(562.000000, 170.959269), (562.000000, 190.959269), 0.702500, 0.000000, 0 -(563.000000, 177.881130), (563.000000, 197.881130), 0.703750, 0.000000, 0 -(564.000000, 184.899214), (564.000000, 204.899214), 0.705000, 0.000000, 0 -(565.000000, 192.010338), (565.000000, 212.010338), 0.706250, 0.000000, 0 -(566.000000, 199.211275), (566.000000, 219.211275), 0.707500, 0.000000, 0 -(567.000000, 206.498759), (567.000000, 226.498759), 0.708750, 0.000000, 0 -(568.000000, 213.869484), (568.000000, 233.869484), 0.710000, 0.000000, 0 -(569.000000, 221.320107), (569.000000, 241.320107), 0.711250, 0.000000, 0 -(570.000000, 228.847248), (570.000000, 248.847248), 0.712500, 0.000000, 0 -(571.000000, 236.447492), (571.000000, 256.447492), 0.713750, 0.000000, 0 -(572.000000, 244.117391), (572.000000, 264.117391), 0.715000, 0.000000, 0 -(573.000000, 251.853467), (573.000000, 271.853467), 0.716250, 0.000000, 0 -(574.000000, 259.652210), (574.000000, 279.652210), 0.717500, 0.000000, 0 -(575.000000, 267.510082), (575.000000, 287.510082), 0.718750, 0.000000, 0 -(576.000000, 275.423519), (576.000000, 295.423519), 0.720000, 0.000000, 0 -(577.000000, 283.388932), (577.000000, 303.388932), 0.721250, 0.000000, 0 -(578.000000, 291.402705), (578.000000, 311.402705), 0.722500, 0.000000, 0 -(579.000000, 299.461206), (579.000000, 319.461206), 0.723750, 0.000000, 0 -(580.000000, 307.560777), (580.000000, 327.560777), 0.725000, 0.000000, 0 -(581.000000, 315.697745), (581.000000, 335.697745), 0.726250, 0.000000, 0 -(582.000000, 323.868418), (582.000000, 343.868418), 0.727500, 0.000000, 0 -(583.000000, 332.069090), (583.000000, 352.069090), 0.728750, 0.000000, 0 -(584.000000, 340.296042), (584.000000, 360.296042), 0.730000, 0.000000, 0 -(585.000000, 348.545541), (585.000000, 368.545541), 0.731250, 0.000000, 0 -(586.000000, 356.813844), (586.000000, 376.813844), 0.732500, 0.000000, 0 -(587.000000, 365.097202), (587.000000, 385.097202), 0.733750, 0.000000, 0 -(588.000000, 373.391856), (588.000000, 393.391856), 0.735000, 0.000000, 0 -(589.000000, 381.694044), (589.000000, 401.694044), 0.736250, 0.000000, 0 -(590.000000, 390.000000), (590.000000, 410.000000), 0.737500, 0.000000, 0 -(591.000000, 398.305956), (591.000000, 418.305956), 0.738750, 0.000000, 0 -(592.000000, 406.608144), (592.000000, 426.608144), 0.740000, 0.000000, 0 -(593.000000, 414.902798), (593.000000, 434.902798), 0.741250, 0.000000, 0 -(594.000000, 423.186156), (594.000000, 443.186156), 0.742500, 0.000000, 0 -(595.000000, 431.454459), (595.000000, 451.454459), 0.743750, 0.000000, 0 -(596.000000, 439.703958), (596.000000, 459.703958), 0.745000, 0.000000, 0 -(597.000000, 447.930910), (597.000000, 467.930910), 0.746250, 0.000000, 0 -(598.000000, 456.131582), (598.000000, 476.131582), 0.747500, 0.000000, 0 -(599.000000, 464.302255), (599.000000, 484.302255), 0.748750, 0.000000, 0 -(600.000000, 472.439223), (600.000000, 492.439223), 0.750000, 0.000000, 0 -(601.000000, 480.538794), (601.000000, 500.538794), 0.751250, 0.000000, 0 -(602.000000, 488.597295), (602.000000, 508.597295), 0.752500, 0.000000, 0 -(603.000000, 496.611068), (603.000000, 516.611068), 0.753750, 0.000000, 0 -(604.000000, 504.576481), (604.000000, 524.576481), 0.755000, 0.000000, 0 -(605.000000, 512.489918), (605.000000, 532.489918), 0.756250, 0.000000, 0 -(606.000000, 520.347790), (606.000000, 540.347790), 0.757500, 0.000000, 0 -(607.000000, 528.146533), (607.000000, 548.146533), 0.758750, 0.000000, 0 -(608.000000, 535.882609), (608.000000, 555.882609), 0.760000, 0.000000, 0 -(609.000000, 543.552508), (609.000000, 563.552508), 0.761250, 0.000000, 0 -(610.000000, 551.152752), (610.000000, 571.152752), 0.762500, 0.000000, 0 -(611.000000, 558.679893), (611.000000, 578.679893), 0.763750, 0.000000, 0 -(612.000000, 566.130516), (612.000000, 586.130516), 0.765000, 0.000000, 0 -(613.000000, 573.501241), (613.000000, 593.501241), 0.766250, 0.000000, 0 -(614.000000, 580.788725), (614.000000, 600.788725), 0.767500, 0.000000, 0 -(615.000000, 587.989662), (615.000000, 607.989662), 0.768750, 0.000000, 0 -(616.000000, 595.100786), (616.000000, 615.100786), 0.770000, 0.000000, 0 -(617.000000, 602.118870), (617.000000, 622.118870), 0.771250, 0.000000, 0 -(618.000000, 609.040731), (618.000000, 629.040731), 0.772500, 0.000000, 0 -(619.000000, 615.863229), (619.000000, 635.863229), 0.773750, 0.000000, 0 -(620.000000, 622.583270), (620.000000, 642.583270), 0.775000, 0.000000, 0 -(621.000000, 629.197804), (621.000000, 649.197804), 0.776250, 0.000000, 0 -(622.000000, 635.703832), (622.000000, 655.703832), 0.777500, 0.000000, 0 -(623.000000, 642.098402), (623.000000, 662.098402), 0.778750, 0.000000, 0 -(624.000000, 648.378613), (624.000000, 668.378613), 0.780000, 0.000000, 0 -(625.000000, 654.541616), (625.000000, 674.541616), 0.781250, 0.000000, 0 -(626.000000, 660.584616), (626.000000, 680.584616), 0.782500, 0.000000, 0 -(627.000000, 666.504872), (627.000000, 686.504872), 0.783750, 0.000000, 0 -(628.000000, 672.299697), (628.000000, 692.299697), 0.785000, 0.000000, 0 -(629.000000, 677.966463), (629.000000, 697.966463), 0.786250, 0.000000, 0 -(630.000000, 683.502600), (630.000000, 703.502600), 0.787500, 0.000000, 0 -(631.000000, 688.905596), (631.000000, 708.905596), 0.788750, 0.000000, 0 -(632.000000, 694.173001), (632.000000, 714.173001), 0.790000, 0.000000, 0 -(633.000000, 699.302424), (633.000000, 719.302424), 0.791250, 0.000000, 0 -(634.000000, 704.291539), (634.000000, 724.291539), 0.792500, 0.000000, 0 -(635.000000, 709.138083), (635.000000, 729.138083), 0.793750, 0.000000, 0 -(636.000000, 713.839857), (636.000000, 733.839857), 0.795000, 0.000000, 0 -(637.000000, 718.394728), (637.000000, 738.394728), 0.796250, 0.000000, 0 -(638.000000, 722.800631), (638.000000, 742.800631), 0.797500, 0.000000, 0 -(639.000000, 727.055566), (639.000000, 747.055566), 0.798750, 0.000000, 0 -(640.000000, 731.157603), (640.000000, 751.157603), 0.800000, 0.000000, 0 -(641.000000, 735.104882), (641.000000, 755.104882), 0.801250, 0.000000, 0 -(642.000000, 738.895612), (642.000000, 758.895612), 0.802500, 0.000000, 0 -(643.000000, 742.528073), (643.000000, 762.528073), 0.803750, 0.000000, 0 -(644.000000, 746.000618), (644.000000, 766.000618), 0.805000, 0.000000, 0 -(645.000000, 749.311671), (645.000000, 769.311671), 0.806250, 0.000000, 0 -(646.000000, 752.459731), (646.000000, 772.459731), 0.807500, 0.000000, 0 -(647.000000, 755.443369), (647.000000, 775.443369), 0.808750, 0.000000, 0 -(648.000000, 758.261232), (648.000000, 778.261232), 0.810000, 0.000000, 0 -(649.000000, 760.912041), (649.000000, 780.912041), 0.811250, 0.000000, 0 -(650.000000, 763.394595), (650.000000, 783.394595), 0.812500, 0.000000, 0 -(651.000000, 765.707767), (651.000000, 785.707767), 0.813750, 0.000000, 0 -(652.000000, 767.850507), (652.000000, 787.850507), 0.815000, 0.000000, 0 -(653.000000, 769.821844), (653.000000, 789.821844), 0.816250, 0.000000, 0 -(654.000000, 771.620883), (654.000000, 791.620883), 0.817500, 0.000000, 0 -(655.000000, 773.246809), (655.000000, 793.246809), 0.818750, 0.000000, 0 -(656.000000, 774.698883), (656.000000, 794.698883), 0.820000, 0.000000, 0 -(657.000000, 775.976447), (657.000000, 795.976447), 0.821250, 0.000000, 0 -(658.000000, 777.078922), (658.000000, 797.078922), 0.822500, 0.000000, 0 -(659.000000, 778.005808), (659.000000, 798.005808), 0.823750, 0.000000, 0 -(660.000000, 778.756683), (660.000000, 798.756683), 0.825000, 0.000000, 0 -(661.000000, 779.331207), (661.000000, 799.331207), 0.826250, 0.000000, 0 -(662.000000, 779.729121), (662.000000, 799.729121), 0.827500, 0.000000, 0 -(663.000000, 779.950242), (663.000000, 799.950242), 0.828750, 0.000000, 0 -(664.000000, 779.994471), (664.000000, 799.994471), 0.830000, 0.000000, 0 -(665.000000, 779.861788), (665.000000, 799.861788), 0.831250, 0.000000, 0 -(666.000000, 779.552253), (666.000000, 799.552253), 0.832500, 0.000000, 0 -(667.000000, 779.066007), (667.000000, 799.066007), 0.833750, 0.000000, 0 -(668.000000, 778.403270), (668.000000, 798.403270), 0.835000, 0.000000, 0 -(669.000000, 777.564342), (669.000000, 797.564342), 0.836250, 0.000000, 0 -(670.000000, 776.549604), (670.000000, 796.549604), 0.837500, 0.000000, 0 -(671.000000, 775.359517), (671.000000, 795.359517), 0.838750, 0.000000, 0 -(672.000000, 773.994620), (672.000000, 793.994620), 0.840000, 0.000000, 0 -(673.000000, 772.455533), (673.000000, 792.455533), 0.841250, 0.000000, 0 -(674.000000, 770.742953), (674.000000, 790.742953), 0.842500, 0.000000, 0 -(675.000000, 768.857658), (675.000000, 788.857658), 0.843750, 0.000000, 0 -(676.000000, 766.800503), (676.000000, 786.800503), 0.845000, 0.000000, 0 -(677.000000, 764.572421), (677.000000, 784.572421), 0.846250, 0.000000, 0 -(678.000000, 762.174422), (678.000000, 782.174422), 0.847500, 0.000000, 0 -(679.000000, 759.607595), (679.000000, 779.607595), 0.848750, 0.000000, 0 -(680.000000, 756.873104), (680.000000, 776.873104), 0.850000, 0.000000, 0 -(681.000000, 753.972189), (681.000000, 773.972189), 0.851250, 0.000000, 0 -(682.000000, 750.906166), (682.000000, 770.906166), 0.852500, 0.000000, 0 -(683.000000, 747.676427), (683.000000, 767.676427), 0.853750, 0.000000, 0 -(684.000000, 744.284435), (684.000000, 764.284435), 0.855000, 0.000000, 0 -(685.000000, 740.731731), (685.000000, 760.731731), 0.856250, 0.000000, 0 -(686.000000, 737.019925), (686.000000, 757.019925), 0.857500, 0.000000, 0 -(687.000000, 733.150701), (687.000000, 753.150701), 0.858750, 0.000000, 0 -(688.000000, 729.125814), (688.000000, 749.125814), 0.860000, 0.000000, 0 -(689.000000, 724.947091), (689.000000, 744.947091), 0.861250, 0.000000, 0 -(690.000000, 720.616427), (690.000000, 740.616427), 0.862500, 0.000000, 0 -(691.000000, 716.135786), (691.000000, 736.135786), 0.863750, 0.000000, 0 -(692.000000, 711.507201), (692.000000, 731.507201), 0.865000, 0.000000, 0 -(693.000000, 706.732771), (693.000000, 726.732771), 0.866250, 0.000000, 0 -(694.000000, 701.814663), (694.000000, 721.814663), 0.867500, 0.000000, 0 -(695.000000, 696.755107), (695.000000, 716.755107), 0.868750, 0.000000, 0 -(696.000000, 691.556398), (696.000000, 711.556398), 0.870000, 0.000000, 0 -(697.000000, 686.220896), (697.000000, 706.220896), 0.871250, 0.000000, 0 -(698.000000, 680.751019), (698.000000, 700.751019), 0.872500, 0.000000, 0 -(699.000000, 675.149250), (699.000000, 695.149250), 0.873750, 0.000000, 0 -(700.000000, 669.418129), (700.000000, 689.418129), 0.875000, 0.000000, 0 -(701.000000, 663.560256), (701.000000, 683.560256), 0.876250, 0.000000, 0 -(702.000000, 657.578289), (702.000000, 677.578289), 0.877500, 0.000000, 0 -(703.000000, 651.474941), (703.000000, 671.474941), 0.878750, 0.000000, 0 -(704.000000, 645.252981), (704.000000, 665.252981), 0.880000, 0.000000, 0 -(705.000000, 638.915232), (705.000000, 658.915232), 0.881250, 0.000000, 0 -(706.000000, 632.464567), (706.000000, 652.464567), 0.882500, 0.000000, 0 -(707.000000, 625.903914), (707.000000, 645.903914), 0.883750, 0.000000, 0 -(708.000000, 619.236248), (708.000000, 639.236248), 0.885000, 0.000000, 0 -(709.000000, 612.464595), (709.000000, 632.464595), 0.886250, 0.000000, 0 -(710.000000, 605.592025), (710.000000, 625.592025), 0.887500, 0.000000, 0 -(711.000000, 598.621658), (711.000000, 618.621658), 0.888750, 0.000000, 0 -(712.000000, 591.556653), (712.000000, 611.556653), 0.890000, 0.000000, 0 -(713.000000, 584.400217), (713.000000, 604.400217), 0.891250, 0.000000, 0 -(714.000000, 577.155596), (714.000000, 597.155596), 0.892500, 0.000000, 0 -(715.000000, 569.826076), (715.000000, 589.826076), 0.893750, 0.000000, 0 -(716.000000, 562.414981), (716.000000, 582.414981), 0.895000, 0.000000, 0 -(717.000000, 554.925675), (717.000000, 574.925675), 0.896250, 0.000000, 0 -(718.000000, 547.361554), (718.000000, 567.361554), 0.897500, 0.000000, 0 -(719.000000, 539.726049), (719.000000, 559.726049), 0.898750, 0.000000, 0 -(720.000000, 532.022624), (720.000000, 552.022624), 0.900000, 0.000000, 0 -(721.000000, 524.254774), (721.000000, 544.254774), 0.901250, 0.000000, 0 -(722.000000, 516.426023), (722.000000, 536.426023), 0.902500, 0.000000, 0 -(723.000000, 508.539921), (723.000000, 528.539921), 0.903750, 0.000000, 0 -(724.000000, 500.600046), (724.000000, 520.600046), 0.905000, 0.000000, 0 -(725.000000, 492.610000), (725.000000, 512.610000), 0.906250, 0.000000, 0 -(726.000000, 484.573407), (726.000000, 504.573407), 0.907500, 0.000000, 0 -(727.000000, 476.493913), (727.000000, 496.493913), 0.908750, 0.000000, 0 -(728.000000, 468.375184), (728.000000, 488.375184), 0.910000, 0.000000, 0 -(729.000000, 460.220901), (729.000000, 480.220901), 0.911250, 0.000000, 0 -(730.000000, 452.034763), (730.000000, 472.034763), 0.912500, 0.000000, 0 -(731.000000, 443.820486), (731.000000, 463.820486), 0.913750, 0.000000, 0 -(732.000000, 435.581793), (732.000000, 455.581793), 0.915000, 0.000000, 0 -(733.000000, 427.322424), (733.000000, 447.322424), 0.916250, 0.000000, 0 -(734.000000, 419.046124), (734.000000, 439.046124), 0.917500, 0.000000, 0 -(735.000000, 410.756648), (735.000000, 430.756648), 0.918750, 0.000000, 0 -(736.000000, 402.457756), (736.000000, 422.457756), 0.920000, 0.000000, 0 -(737.000000, 394.153213), (737.000000, 414.153213), 0.921250, 0.000000, 0 -(738.000000, 385.846787), (738.000000, 405.846787), 0.922500, 0.000000, 0 -(739.000000, 377.542244), (739.000000, 397.542244), 0.923750, 0.000000, 0 -(740.000000, 369.243352), (740.000000, 389.243352), 0.925000, 0.000000, 0 -(741.000000, 360.953876), (741.000000, 380.953876), 0.926250, 0.000000, 0 -(742.000000, 352.677576), (742.000000, 372.677576), 0.927500, 0.000000, 0 -(743.000000, 344.418207), (743.000000, 364.418207), 0.928750, 0.000000, 0 -(744.000000, 336.179514), (744.000000, 356.179514), 0.930000, 0.000000, 0 -(745.000000, 327.965237), (745.000000, 347.965237), 0.931250, 0.000000, 0 -(746.000000, 319.779099), (746.000000, 339.779099), 0.932500, 0.000000, 0 -(747.000000, 311.624816), (747.000000, 331.624816), 0.933750, 0.000000, 0 -(748.000000, 303.506087), (748.000000, 323.506087), 0.935000, 0.000000, 0 -(749.000000, 295.426593), (749.000000, 315.426593), 0.936250, 0.000000, 0 -(750.000000, 287.390000), (750.000000, 307.390000), 0.937500, 0.000000, 0 -(751.000000, 279.399954), (751.000000, 299.399954), 0.938750, 0.000000, 0 -(752.000000, 271.460079), (752.000000, 291.460079), 0.940000, 0.000000, 0 -(753.000000, 263.573977), (753.000000, 283.573977), 0.941250, 0.000000, 0 -(754.000000, 255.745226), (754.000000, 275.745226), 0.942500, 0.000000, 0 -(755.000000, 247.977376), (755.000000, 267.977376), 0.943750, 0.000000, 0 -(756.000000, 240.273951), (756.000000, 260.273951), 0.945000, 0.000000, 0 -(757.000000, 232.638446), (757.000000, 252.638446), 0.946250, 0.000000, 0 -(758.000000, 225.074325), (758.000000, 245.074325), 0.947500, 0.000000, 0 -(759.000000, 217.585019), (759.000000, 237.585019), 0.948750, 0.000000, 0 -(760.000000, 210.173924), (760.000000, 230.173924), 0.950000, 0.000000, 0 -(761.000000, 202.844404), (761.000000, 222.844404), 0.951250, 0.000000, 0 -(762.000000, 195.599783), (762.000000, 215.599783), 0.952500, 0.000000, 0 -(763.000000, 188.443347), (763.000000, 208.443347), 0.953750, 0.000000, 0 -(764.000000, 181.378342), (764.000000, 201.378342), 0.955000, 0.000000, 0 -(765.000000, 174.407975), (765.000000, 194.407975), 0.956250, 0.000000, 0 -(766.000000, 167.535405), (766.000000, 187.535405), 0.957500, 0.000000, 0 -(767.000000, 160.763752), (767.000000, 180.763752), 0.958750, 0.000000, 0 -(768.000000, 154.096086), (768.000000, 174.096086), 0.960000, 0.000000, 0 -(769.000000, 147.535433), (769.000000, 167.535433), 0.961250, 0.000000, 0 -(770.000000, 141.084768), (770.000000, 161.084768), 0.962500, 0.000000, 0 -(771.000000, 134.747019), (771.000000, 154.747019), 0.963750, 0.000000, 0 -(772.000000, 128.525059), (772.000000, 148.525059), 0.965000, 0.000000, 0 -(773.000000, 122.421711), (773.000000, 142.421711), 0.966250, 0.000000, 0 -(774.000000, 116.439744), (774.000000, 136.439744), 0.967500, 0.000000, 0 -(775.000000, 110.581871), (775.000000, 130.581871), 0.968750, 0.000000, 0 -(776.000000, 104.850750), (776.000000, 124.850750), 0.970000, 0.000000, 0 -(777.000000, 99.248981), (777.000000, 119.248981), 0.971250, 0.000000, 0 -(778.000000, 93.779104), (778.000000, 113.779104), 0.972500, 0.000000, 0 -(779.000000, 88.443602), (779.000000, 108.443602), 0.973750, 0.000000, 0 -(780.000000, 83.244893), (780.000000, 103.244893), 0.975000, 0.000000, 0 -(781.000000, 78.185337), (781.000000, 98.185337), 0.976250, 0.000000, 0 -(782.000000, 73.267229), (782.000000, 93.267229), 0.977500, 0.000000, 0 -(783.000000, 68.492799), (783.000000, 88.492799), 0.978750, 0.000000, 0 -(784.000000, 63.864214), (784.000000, 83.864214), 0.980000, 0.000000, 0 -(785.000000, 59.383573), (785.000000, 79.383573), 0.981250, 0.000000, 0 -(786.000000, 55.052909), (786.000000, 75.052909), 0.982500, 0.000000, 0 -(787.000000, 50.874186), (787.000000, 70.874186), 0.983750, 0.000000, 0 -(788.000000, 46.849299), (788.000000, 66.849299), 0.985000, 0.000000, 0 -(789.000000, 42.980075), (789.000000, 62.980075), 0.986250, 0.000000, 0 -(790.000000, 39.268269), (790.000000, 59.268269), 0.987500, 0.000000, 0 -(791.000000, 35.715565), (791.000000, 55.715565), 0.988750, 0.000000, 0 -(792.000000, 32.323573), (792.000000, 52.323573), 0.990000, 0.000000, 0 -(793.000000, 29.093834), (793.000000, 49.093834), 0.991250, 0.000000, 0 -(794.000000, 26.027811), (794.000000, 46.027811), 0.992500, 0.000000, 0 -(795.000000, 23.126896), (795.000000, 43.126896), 0.993750, 0.000000, 0 -(796.000000, 20.392405), (796.000000, 40.392405), 0.995000, 0.000000, 0 -(797.000000, 17.825578), (797.000000, 37.825578), 0.996250, 0.000000, 0 -(798.000000, 15.427579), (798.000000, 35.427579), 0.997500, 0.000000, 0 -(799.000000, 13.199497), (799.000000, 33.199497), 0.998750, 0.000000, 0 -(800.000000, 11.142342), (800.000000, 31.142342), 1.000000, 0.000000, 0 -(801.000000, 9.257047), (801.000000, 29.257047), 1.001250, 0.000000, 0 -(802.000000, 7.544467), (802.000000, 27.544467), 1.002500, 0.000000, 0 -(803.000000, 6.005380), (803.000000, 26.005380), 1.003750, 0.000000, 0 -(804.000000, 4.640483), (804.000000, 24.640483), 1.005000, 0.000000, 0 -(805.000000, 3.450396), (805.000000, 23.450396), 1.006250, 0.000000, 0 -(806.000000, 2.435658), (806.000000, 22.435658), 1.007500, 0.000000, 0 -(807.000000, 1.596730), (807.000000, 21.596730), 1.008750, 0.000000, 0 -(808.000000, 0.933993), (808.000000, 20.933993), 1.010000, 0.000000, 0 -(809.000000, 0.447747), (809.000000, 20.447747), 1.011250, 0.000000, 0 -(810.000000, 0.138212), (810.000000, 20.138212), 1.012500, 0.000000, 0 -(811.000000, 0.005529), (811.000000, 20.005529), 1.013750, 0.000000, 0 -(812.000000, 0.049758), (812.000000, 20.049758), 1.015000, 0.000000, 0 -(813.000000, 0.270879), (813.000000, 20.270879), 1.016250, 0.000000, 0 -(814.000000, 0.668793), (814.000000, 20.668793), 1.017500, 0.000000, 0 -(815.000000, 1.243317), (815.000000, 21.243317), 1.018750, 0.000000, 0 -(816.000000, 1.994192), (816.000000, 21.994192), 1.020000, 0.000000, 0 -(817.000000, 2.921078), (817.000000, 22.921078), 1.021250, 0.000000, 0 -(818.000000, 4.023553), (818.000000, 24.023553), 1.022500, 0.000000, 0 -(819.000000, 5.301117), (819.000000, 25.301117), 1.023750, 0.000000, 0 -(820.000000, 6.753191), (820.000000, 26.753191), 1.025000, 0.000000, 0 -(821.000000, 8.379117), (821.000000, 28.379117), 1.026250, 0.000000, 0 -(822.000000, 10.178156), (822.000000, 30.178156), 1.027500, 0.000000, 0 -(823.000000, 12.149493), (823.000000, 32.149493), 1.028750, 0.000000, 0 -(824.000000, 14.292233), (824.000000, 34.292233), 1.030000, 0.000000, 0 -(825.000000, 16.605405), (825.000000, 36.605405), 1.031250, 0.000000, 0 -(826.000000, 19.087959), (826.000000, 39.087959), 1.032500, 0.000000, 0 -(827.000000, 21.738768), (827.000000, 41.738768), 1.033750, 0.000000, 0 -(828.000000, 24.556631), (828.000000, 44.556631), 1.035000, 0.000000, 0 -(829.000000, 27.540269), (829.000000, 47.540269), 1.036250, 0.000000, 0 -(830.000000, 30.688329), (830.000000, 50.688329), 1.037500, 0.000000, 0 -(831.000000, 33.999382), (831.000000, 53.999382), 1.038750, 0.000000, 0 -(832.000000, 37.471927), (832.000000, 57.471927), 1.040000, 0.000000, 0 -(833.000000, 41.104388), (833.000000, 61.104388), 1.041250, 0.000000, 0 -(834.000000, 44.895118), (834.000000, 64.895118), 1.042500, 0.000000, 0 -(835.000000, 48.842397), (835.000000, 68.842397), 1.043750, 0.000000, 0 -(836.000000, 52.944434), (836.000000, 72.944434), 1.045000, 0.000000, 0 -(837.000000, 57.199369), (837.000000, 77.199369), 1.046250, 0.000000, 0 -(838.000000, 61.605272), (838.000000, 81.605272), 1.047500, 0.000000, 0 -(839.000000, 66.160143), (839.000000, 86.160143), 1.048750, 0.000000, 0 -(840.000000, 70.861917), (840.000000, 90.861917), 1.050000, 0.000000, 0 -(841.000000, 75.708461), (841.000000, 95.708461), 1.051250, 0.000000, 0 -(842.000000, 80.697576), (842.000000, 100.697576), 1.052500, 0.000000, 0 -(843.000000, 85.826999), (843.000000, 105.826999), 1.053750, 0.000000, 0 -(844.000000, 91.094404), (844.000000, 111.094404), 1.055000, 0.000000, 0 -(845.000000, 96.497400), (845.000000, 116.497400), 1.056250, 0.000000, 0 -(846.000000, 102.033537), (846.000000, 122.033537), 1.057500, 0.000000, 0 -(847.000000, 107.700303), (847.000000, 127.700303), 1.058750, 0.000000, 0 -(848.000000, 113.495128), (848.000000, 133.495128), 1.060000, 0.000000, 0 -(849.000000, 119.415384), (849.000000, 139.415384), 1.061250, 0.000000, 0 -(850.000000, 125.458384), (850.000000, 145.458384), 1.062500, 0.000000, 0 -(851.000000, 131.621387), (851.000000, 151.621387), 1.063750, 0.000000, 0 -(852.000000, 137.901598), (852.000000, 157.901598), 1.065000, 0.000000, 0 -(853.000000, 144.296168), (853.000000, 164.296168), 1.066250, 0.000000, 0 -(854.000000, 150.802196), (854.000000, 170.802196), 1.067500, 0.000000, 0 -(855.000000, 157.416730), (855.000000, 177.416730), 1.068750, 0.000000, 0 -(856.000000, 164.136771), (856.000000, 184.136771), 1.070000, 0.000000, 0 -(857.000000, 170.959269), (857.000000, 190.959269), 1.071250, 0.000000, 0 -(858.000000, 177.881130), (858.000000, 197.881130), 1.072500, 0.000000, 0 -(859.000000, 184.899214), (859.000000, 204.899214), 1.073750, 0.000000, 0 -(860.000000, 192.010338), (860.000000, 212.010338), 1.075000, 0.000000, 0 -(861.000000, 199.211275), (861.000000, 219.211275), 1.076250, 0.000000, 0 -(862.000000, 206.498759), (862.000000, 226.498759), 1.077500, 0.000000, 0 -(863.000000, 213.869484), (863.000000, 233.869484), 1.078750, 0.000000, 0 -(864.000000, 221.320107), (864.000000, 241.320107), 1.080000, 0.000000, 0 -(865.000000, 228.847248), (865.000000, 248.847248), 1.081250, 0.000000, 0 -(866.000000, 236.447492), (866.000000, 256.447492), 1.082500, 0.000000, 0 -(867.000000, 244.117391), (867.000000, 264.117391), 1.083750, 0.000000, 0 -(868.000000, 251.853467), (868.000000, 271.853467), 1.085000, 0.000000, 0 -(869.000000, 259.652210), (869.000000, 279.652210), 1.086250, 0.000000, 0 -(870.000000, 267.510082), (870.000000, 287.510082), 1.087500, 0.000000, 0 -(871.000000, 275.423519), (871.000000, 295.423519), 1.088750, 0.000000, 0 -(872.000000, 283.388932), (872.000000, 303.388932), 1.090000, 0.000000, 0 -(873.000000, 291.402705), (873.000000, 311.402705), 1.091250, 0.000000, 0 -(874.000000, 299.461206), (874.000000, 319.461206), 1.092500, 0.000000, 0 -(875.000000, 307.560777), (875.000000, 327.560777), 1.093750, 0.000000, 0 -(876.000000, 315.697745), (876.000000, 335.697745), 1.095000, 0.000000, 0 -(877.000000, 323.868418), (877.000000, 343.868418), 1.096250, 0.000000, 0 -(878.000000, 332.069090), (878.000000, 352.069090), 1.097500, 0.000000, 0 -(879.000000, 340.296042), (879.000000, 360.296042), 1.098750, 0.000000, 0 -(880.000000, 348.545541), (880.000000, 368.545541), 1.100000, 0.000000, 0 -(881.000000, 356.813844), (881.000000, 376.813844), 1.101250, 0.000000, 0 -(882.000000, 365.097202), (882.000000, 385.097202), 1.102500, 0.000000, 0 -(883.000000, 373.391856), (883.000000, 393.391856), 1.103750, 0.000000, 0 -(884.000000, 381.694044), (884.000000, 401.694044), 1.105000, 0.000000, 0 -(885.000000, 390.000000), (885.000000, 410.000000), 1.106250, 0.000000, 0 -(886.000000, 398.305956), (886.000000, 418.305956), 1.107500, 0.000000, 0 -(887.000000, 406.608144), (887.000000, 426.608144), 1.108750, 0.000000, 0 -(888.000000, 414.902798), (888.000000, 434.902798), 1.110000, 0.000000, 0 -(889.000000, 423.186156), (889.000000, 443.186156), 1.111250, 0.000000, 0 -(890.000000, 431.454459), (890.000000, 451.454459), 1.112500, 0.000000, 0 -(891.000000, 439.703958), (891.000000, 459.703958), 1.113750, 0.000000, 0 -(892.000000, 447.930910), (892.000000, 467.930910), 1.115000, 0.000000, 0 -(893.000000, 456.131582), (893.000000, 476.131582), 1.116250, 0.000000, 0 -(894.000000, 464.302255), (894.000000, 484.302255), 1.117500, 0.000000, 0 -(895.000000, 472.439223), (895.000000, 492.439223), 1.118750, 0.000000, 0 -(896.000000, 480.538794), (896.000000, 500.538794), 1.120000, 0.000000, 0 -(897.000000, 488.597295), (897.000000, 508.597295), 1.121250, 0.000000, 0 -(898.000000, 496.611068), (898.000000, 516.611068), 1.122500, 0.000000, 0 -(899.000000, 504.576481), (899.000000, 524.576481), 1.123750, 0.000000, 0 -(900.000000, 512.489918), (900.000000, 532.489918), 1.125000, 0.000000, 0 -(901.000000, 520.347790), (901.000000, 540.347790), 1.126250, 0.000000, 0 -(902.000000, 528.146533), (902.000000, 548.146533), 1.127500, 0.000000, 0 -(903.000000, 535.882609), (903.000000, 555.882609), 1.128750, 0.000000, 0 -(904.000000, 543.552508), (904.000000, 563.552508), 1.130000, 0.000000, 0 -(905.000000, 551.152752), (905.000000, 571.152752), 1.131250, 0.000000, 0 -(906.000000, 558.679893), (906.000000, 578.679893), 1.132500, 0.000000, 0 -(907.000000, 566.130516), (907.000000, 586.130516), 1.133750, 0.000000, 0 -(908.000000, 573.501241), (908.000000, 593.501241), 1.135000, 0.000000, 0 -(909.000000, 580.788725), (909.000000, 600.788725), 1.136250, 0.000000, 0 -(910.000000, 587.989662), (910.000000, 607.989662), 1.137500, 0.000000, 0 -(911.000000, 595.100786), (911.000000, 615.100786), 1.138750, 0.000000, 0 -(912.000000, 602.118870), (912.000000, 622.118870), 1.140000, 0.000000, 0 -(913.000000, 609.040731), (913.000000, 629.040731), 1.141250, 0.000000, 0 -(914.000000, 615.863229), (914.000000, 635.863229), 1.142500, 0.000000, 0 -(915.000000, 622.583270), (915.000000, 642.583270), 1.143750, 0.000000, 0 -(916.000000, 629.197804), (916.000000, 649.197804), 1.145000, 0.000000, 0 -(917.000000, 635.703832), (917.000000, 655.703832), 1.146250, 0.000000, 0 -(918.000000, 642.098402), (918.000000, 662.098402), 1.147500, 0.000000, 0 -(919.000000, 648.378613), (919.000000, 668.378613), 1.148750, 0.000000, 0 -(920.000000, 654.541616), (920.000000, 674.541616), 1.150000, 0.000000, 0 -(921.000000, 660.584616), (921.000000, 680.584616), 1.151250, 0.000000, 0 -(922.000000, 666.504872), (922.000000, 686.504872), 1.152500, 0.000000, 0 -(923.000000, 672.299697), (923.000000, 692.299697), 1.153750, 0.000000, 0 -(924.000000, 677.966463), (924.000000, 697.966463), 1.155000, 0.000000, 0 -(925.000000, 683.502600), (925.000000, 703.502600), 1.156250, 0.000000, 0 -(926.000000, 688.905596), (926.000000, 708.905596), 1.157500, 0.000000, 0 -(927.000000, 694.173001), (927.000000, 714.173001), 1.158750, 0.000000, 0 -(928.000000, 699.302424), (928.000000, 719.302424), 1.160000, 0.000000, 0 -(929.000000, 704.291539), (929.000000, 724.291539), 1.161250, 0.000000, 0 -(930.000000, 709.138083), (930.000000, 729.138083), 1.162500, 0.000000, 0 -(931.000000, 713.839857), (931.000000, 733.839857), 1.163750, 0.000000, 0 -(932.000000, 718.394728), (932.000000, 738.394728), 1.165000, 0.000000, 0 -(933.000000, 722.800631), (933.000000, 742.800631), 1.166250, 0.000000, 0 -(934.000000, 727.055566), (934.000000, 747.055566), 1.167500, 0.000000, 0 -(935.000000, 731.157603), (935.000000, 751.157603), 1.168750, 0.000000, 0 -(936.000000, 735.104882), (936.000000, 755.104882), 1.170000, 0.000000, 0 -(937.000000, 738.895612), (937.000000, 758.895612), 1.171250, 0.000000, 0 -(938.000000, 742.528073), (938.000000, 762.528073), 1.172500, 0.000000, 0 -(939.000000, 746.000618), (939.000000, 766.000618), 1.173750, 0.000000, 0 -(940.000000, 749.311671), (940.000000, 769.311671), 1.175000, 0.000000, 0 -(941.000000, 752.459731), (941.000000, 772.459731), 1.176250, 0.000000, 0 -(942.000000, 755.443369), (942.000000, 775.443369), 1.177500, 0.000000, 0 -(943.000000, 758.261232), (943.000000, 778.261232), 1.178750, 0.000000, 0 -(944.000000, 760.912041), (944.000000, 780.912041), 1.180000, 0.000000, 0 -(945.000000, 763.394595), (945.000000, 783.394595), 1.181250, 0.000000, 0 -(946.000000, 765.707767), (946.000000, 785.707767), 1.182500, 0.000000, 0 -(947.000000, 767.850507), (947.000000, 787.850507), 1.183750, 0.000000, 0 -(948.000000, 769.821844), (948.000000, 789.821844), 1.185000, 0.000000, 0 -(949.000000, 771.620883), (949.000000, 791.620883), 1.186250, 0.000000, 0 -(950.000000, 773.246809), (950.000000, 793.246809), 1.187500, 0.000000, 0 -(951.000000, 774.698883), (951.000000, 794.698883), 1.188750, 0.000000, 0 -(952.000000, 775.976447), (952.000000, 795.976447), 1.190000, 0.000000, 0 -(953.000000, 777.078922), (953.000000, 797.078922), 1.191250, 0.000000, 0 -(954.000000, 778.005808), (954.000000, 798.005808), 1.192500, 0.000000, 0 -(955.000000, 778.756683), (955.000000, 798.756683), 1.193750, 0.000000, 0 -(956.000000, 779.331207), (956.000000, 799.331207), 1.195000, 0.000000, 0 -(957.000000, 779.729121), (957.000000, 799.729121), 1.196250, 0.000000, 0 -(958.000000, 779.950242), (958.000000, 799.950242), 1.197500, 0.000000, 0 -(959.000000, 779.994471), (959.000000, 799.994471), 1.198750, 0.000000, 0 -(960.000000, 779.861788), (960.000000, 799.861788), 1.200000, 0.000000, 0 -(961.000000, 779.552253), (961.000000, 799.552253), 1.201250, 0.000000, 0 -(962.000000, 779.066007), (962.000000, 799.066007), 1.202500, 0.000000, 0 -(963.000000, 778.403270), (963.000000, 798.403270), 1.203750, 0.000000, 0 -(964.000000, 777.564342), (964.000000, 797.564342), 1.205000, 0.000000, 0 -(965.000000, 776.549604), (965.000000, 796.549604), 1.206250, 0.000000, 0 -(966.000000, 775.359517), (966.000000, 795.359517), 1.207500, 0.000000, 0 -(967.000000, 773.994620), (967.000000, 793.994620), 1.208750, 0.000000, 0 -(968.000000, 772.455533), (968.000000, 792.455533), 1.210000, 0.000000, 0 -(969.000000, 770.742953), (969.000000, 790.742953), 1.211250, 0.000000, 0 -(970.000000, 768.857658), (970.000000, 788.857658), 1.212500, 0.000000, 0 -(971.000000, 766.800503), (971.000000, 786.800503), 1.213750, 0.000000, 0 -(972.000000, 764.572421), (972.000000, 784.572421), 1.215000, 0.000000, 0 -(973.000000, 762.174422), (973.000000, 782.174422), 1.216250, 0.000000, 0 -(974.000000, 759.607595), (974.000000, 779.607595), 1.217500, 0.000000, 0 -(975.000000, 756.873104), (975.000000, 776.873104), 1.218750, 0.000000, 0 -(976.000000, 753.972189), (976.000000, 773.972189), 1.220000, 0.000000, 0 -(977.000000, 750.906166), (977.000000, 770.906166), 1.221250, 0.000000, 0 -(978.000000, 747.676427), (978.000000, 767.676427), 1.222500, 0.000000, 0 -(979.000000, 744.284435), (979.000000, 764.284435), 1.223750, 0.000000, 0 -(980.000000, 740.731731), (980.000000, 760.731731), 1.225000, 0.000000, 0 -(981.000000, 737.019925), (981.000000, 757.019925), 1.226250, 0.000000, 0 -(982.000000, 733.150701), (982.000000, 753.150701), 1.227500, 0.000000, 0 -(983.000000, 729.125814), (983.000000, 749.125814), 1.228750, 0.000000, 0 -(984.000000, 724.947091), (984.000000, 744.947091), 1.230000, 0.000000, 0 -(985.000000, 720.616427), (985.000000, 740.616427), 1.231250, 0.000000, 0 -(986.000000, 716.135786), (986.000000, 736.135786), 1.232500, 0.000000, 0 -(987.000000, 711.507201), (987.000000, 731.507201), 1.233750, 0.000000, 0 -(988.000000, 706.732771), (988.000000, 726.732771), 1.235000, 0.000000, 0 -(989.000000, 701.814663), (989.000000, 721.814663), 1.236250, 0.000000, 0 -(990.000000, 696.755107), (990.000000, 716.755107), 1.237500, 0.000000, 0 -(991.000000, 691.556398), (991.000000, 711.556398), 1.238750, 0.000000, 0 -(992.000000, 686.220896), (992.000000, 706.220896), 1.240000, 0.000000, 0 -(993.000000, 680.751019), (993.000000, 700.751019), 1.241250, 0.000000, 0 -(994.000000, 675.149250), (994.000000, 695.149250), 1.242500, 0.000000, 0 -(995.000000, 669.418129), (995.000000, 689.418129), 1.243750, 0.000000, 0 -(996.000000, 663.560256), (996.000000, 683.560256), 1.245000, 0.000000, 0 -(997.000000, 657.578289), (997.000000, 677.578289), 1.246250, 0.000000, 0 -(998.000000, 651.474941), (998.000000, 671.474941), 1.247500, 0.000000, 0 -(999.000000, 645.252981), (999.000000, 665.252981), 1.248750, 0.000000, 0 -(1000.000000, 638.915232), (1000.000000, 658.915232), 1.250000, 0.000000, 0 -(1001.000000, 632.464567), (1001.000000, 652.464567), 1.251250, 0.000000, 0 -(1002.000000, 625.903914), (1002.000000, 645.903914), 1.252500, 0.000000, 0 -(1003.000000, 619.236248), (1003.000000, 639.236248), 1.253750, 0.000000, 0 -(1004.000000, 612.464595), (1004.000000, 632.464595), 1.255000, 0.000000, 0 -(1005.000000, 605.592025), (1005.000000, 625.592025), 1.256250, 0.000000, 0 -(1006.000000, 598.621658), (1006.000000, 618.621658), 1.257500, 0.000000, 0 -(1007.000000, 591.556653), (1007.000000, 611.556653), 1.258750, 0.000000, 0 -(1008.000000, 584.400217), (1008.000000, 604.400217), 1.260000, 0.000000, 0 -(1009.000000, 577.155596), (1009.000000, 597.155596), 1.261250, 0.000000, 0 -(1010.000000, 569.826076), (1010.000000, 589.826076), 1.262500, 0.000000, 0 -(1011.000000, 562.414981), (1011.000000, 582.414981), 1.263750, 0.000000, 0 -(1012.000000, 554.925675), (1012.000000, 574.925675), 1.265000, 0.000000, 0 -(1013.000000, 547.361554), (1013.000000, 567.361554), 1.266250, 0.000000, 0 -(1014.000000, 539.726049), (1014.000000, 559.726049), 1.267500, 0.000000, 0 -(1015.000000, 532.022624), (1015.000000, 552.022624), 1.268750, 0.000000, 0 -(1016.000000, 524.254774), (1016.000000, 544.254774), 1.270000, 0.000000, 0 -(1017.000000, 516.426023), (1017.000000, 536.426023), 1.271250, 0.000000, 0 -(1018.000000, 508.539921), (1018.000000, 528.539921), 1.272500, 0.000000, 0 -(1019.000000, 500.600046), (1019.000000, 520.600046), 1.273750, 0.000000, 0 -(1020.000000, 492.610000), (1020.000000, 512.610000), 1.275000, 0.000000, 0 -(1021.000000, 484.573407), (1021.000000, 504.573407), 1.276250, 0.000000, 0 -(1022.000000, 476.493913), (1022.000000, 496.493913), 1.277500, 0.000000, 0 -(1023.000000, 468.375184), (1023.000000, 488.375184), 1.278750, 0.000000, 0 -(1024.000000, 460.220901), (1024.000000, 480.220901), 1.280000, 0.000000, 0 -(1025.000000, 452.034763), (1025.000000, 472.034763), 1.281250, 0.000000, 0 -(1026.000000, 443.820486), (1026.000000, 463.820486), 1.282500, 0.000000, 0 -(1027.000000, 435.581793), (1027.000000, 455.581793), 1.283750, 0.000000, 0 -(1028.000000, 427.322424), (1028.000000, 447.322424), 1.285000, 0.000000, 0 -(1029.000000, 419.046124), (1029.000000, 439.046124), 1.286250, 0.000000, 0 -(1030.000000, 410.756648), (1030.000000, 430.756648), 1.287500, 0.000000, 0 -(1031.000000, 402.457756), (1031.000000, 422.457756), 1.288750, 0.000000, 0 -(1032.000000, 394.153213), (1032.000000, 414.153213), 1.290000, 0.000000, 0 -(1033.000000, 385.846787), (1033.000000, 405.846787), 1.291250, 0.000000, 0 -(1034.000000, 377.542244), (1034.000000, 397.542244), 1.292500, 0.000000, 0 -(1035.000000, 369.243352), (1035.000000, 389.243352), 1.293750, 0.000000, 0 -(1036.000000, 360.953876), (1036.000000, 380.953876), 1.295000, 0.000000, 0 -(1037.000000, 352.677576), (1037.000000, 372.677576), 1.296250, 0.000000, 0 -(1038.000000, 344.418207), (1038.000000, 364.418207), 1.297500, 0.000000, 0 -(1039.000000, 336.179514), (1039.000000, 356.179514), 1.298750, 0.000000, 0 -(1040.000000, 327.965237), (1040.000000, 347.965237), 1.300000, 0.000000, 0 -(1041.000000, 319.779099), (1041.000000, 339.779099), 1.301250, 0.000000, 0 -(1042.000000, 311.624816), (1042.000000, 331.624816), 1.302500, 0.000000, 0 -(1043.000000, 303.506087), (1043.000000, 323.506087), 1.303750, 0.000000, 0 -(1044.000000, 295.426593), (1044.000000, 315.426593), 1.305000, 0.000000, 0 -(1045.000000, 287.390000), (1045.000000, 307.390000), 1.306250, 0.000000, 0 -(1046.000000, 279.399954), (1046.000000, 299.399954), 1.307500, 0.000000, 0 -(1047.000000, 271.460079), (1047.000000, 291.460079), 1.308750, 0.000000, 0 -(1048.000000, 263.573977), (1048.000000, 283.573977), 1.310000, 0.000000, 0 -(1049.000000, 255.745226), (1049.000000, 275.745226), 1.311250, 0.000000, 0 -(1050.000000, 247.977376), (1050.000000, 267.977376), 1.312500, 0.000000, 0 -(1051.000000, 240.273951), (1051.000000, 260.273951), 1.313750, 0.000000, 0 -(1052.000000, 232.638446), (1052.000000, 252.638446), 1.315000, 0.000000, 0 -(1053.000000, 225.074325), (1053.000000, 245.074325), 1.316250, 0.000000, 0 -(1054.000000, 217.585019), (1054.000000, 237.585019), 1.317500, 0.000000, 0 -(1055.000000, 210.173924), (1055.000000, 230.173924), 1.318750, 0.000000, 0 -(1056.000000, 202.844404), (1056.000000, 222.844404), 1.320000, 0.000000, 0 -(1057.000000, 195.599783), (1057.000000, 215.599783), 1.321250, 0.000000, 0 -(1058.000000, 188.443347), (1058.000000, 208.443347), 1.322500, 0.000000, 0 -(1059.000000, 181.378342), (1059.000000, 201.378342), 1.323750, 0.000000, 0 -(1060.000000, 174.407975), (1060.000000, 194.407975), 1.325000, 0.000000, 0 -(1061.000000, 167.535405), (1061.000000, 187.535405), 1.326250, 0.000000, 0 -(1062.000000, 160.763752), (1062.000000, 180.763752), 1.327500, 0.000000, 0 -(1063.000000, 154.096086), (1063.000000, 174.096086), 1.328750, 0.000000, 0 -(1064.000000, 147.535433), (1064.000000, 167.535433), 1.330000, 0.000000, 0 -(1065.000000, 141.084768), (1065.000000, 161.084768), 1.331250, 0.000000, 0 -(1066.000000, 134.747019), (1066.000000, 154.747019), 1.332500, 0.000000, 0 -(1067.000000, 128.525059), (1067.000000, 148.525059), 1.333750, 0.000000, 0 -(1068.000000, 122.421711), (1068.000000, 142.421711), 1.335000, 0.000000, 0 -(1069.000000, 116.439744), (1069.000000, 136.439744), 1.336250, 0.000000, 0 -(1070.000000, 110.581871), (1070.000000, 130.581871), 1.337500, 0.000000, 0 -(1071.000000, 104.850750), (1071.000000, 124.850750), 1.338750, 0.000000, 0 -(1072.000000, 99.248981), (1072.000000, 119.248981), 1.340000, 0.000000, 0 -(1073.000000, 93.779104), (1073.000000, 113.779104), 1.341250, 0.000000, 0 -(1074.000000, 88.443602), (1074.000000, 108.443602), 1.342500, 0.000000, 0 -(1075.000000, 83.244893), (1075.000000, 103.244893), 1.343750, 0.000000, 0 -(1076.000000, 78.185337), (1076.000000, 98.185337), 1.345000, 0.000000, 0 -(1077.000000, 73.267229), (1077.000000, 93.267229), 1.346250, 0.000000, 0 -(1078.000000, 68.492799), (1078.000000, 88.492799), 1.347500, 0.000000, 0 -(1079.000000, 63.864214), (1079.000000, 83.864214), 1.348750, 0.000000, 0 -(1080.000000, 59.383573), (1080.000000, 79.383573), 1.350000, 0.000000, 0 -(1081.000000, 55.052909), (1081.000000, 75.052909), 1.351250, 0.000000, 0 -(1082.000000, 50.874186), (1082.000000, 70.874186), 1.352500, 0.000000, 0 -(1083.000000, 46.849299), (1083.000000, 66.849299), 1.353750, 0.000000, 0 -(1084.000000, 42.980075), (1084.000000, 62.980075), 1.355000, 0.000000, 0 -(1085.000000, 39.268269), (1085.000000, 59.268269), 1.356250, 0.000000, 0 -(1086.000000, 35.715565), (1086.000000, 55.715565), 1.357500, 0.000000, 0 -(1087.000000, 32.323573), (1087.000000, 52.323573), 1.358750, 0.000000, 0 -(1088.000000, 29.093834), (1088.000000, 49.093834), 1.360000, 0.000000, 0 -(1089.000000, 26.027811), (1089.000000, 46.027811), 1.361250, 0.000000, 0 -(1090.000000, 23.126896), (1090.000000, 43.126896), 1.362500, 0.000000, 0 -(1091.000000, 20.392405), (1091.000000, 40.392405), 1.363750, 0.000000, 0 -(1092.000000, 17.825578), (1092.000000, 37.825578), 1.365000, 0.000000, 0 -(1093.000000, 15.427579), (1093.000000, 35.427579), 1.366250, 0.000000, 0 -(1094.000000, 13.199497), (1094.000000, 33.199497), 1.367500, 0.000000, 0 -(1095.000000, 11.142342), (1095.000000, 31.142342), 1.368750, 0.000000, 0 -(1096.000000, 9.257047), (1096.000000, 29.257047), 1.370000, 0.000000, 0 -(1097.000000, 7.544467), (1097.000000, 27.544467), 1.371250, 0.000000, 0 -(1098.000000, 6.005380), (1098.000000, 26.005380), 1.372500, 0.000000, 0 -(1099.000000, 4.640483), (1099.000000, 24.640483), 1.373750, 0.000000, 0 -(1100.000000, 3.450396), (1100.000000, 23.450396), 1.375000, 0.000000, 0 -(1101.000000, 2.435658), (1101.000000, 22.435658), 1.376250, 0.000000, 0 -(1102.000000, 1.596730), (1102.000000, 21.596730), 1.377500, 0.000000, 0 -(1103.000000, 0.933993), (1103.000000, 20.933993), 1.378750, 0.000000, 0 -(1104.000000, 0.447747), (1104.000000, 20.447747), 1.380000, 0.000000, 0 -(1105.000000, 0.138212), (1105.000000, 20.138212), 1.381250, 0.000000, 0 -(1106.000000, 0.005529), (1106.000000, 20.005529), 1.382500, 0.000000, 0 -(1107.000000, 0.049758), (1107.000000, 20.049758), 1.383750, 0.000000, 0 -(1108.000000, 0.270879), (1108.000000, 20.270879), 1.385000, 0.000000, 0 -(1109.000000, 0.668793), (1109.000000, 20.668793), 1.386250, 0.000000, 0 -(1110.000000, 1.243317), (1110.000000, 21.243317), 1.387500, 0.000000, 0 -(1111.000000, 1.994192), (1111.000000, 21.994192), 1.388750, 0.000000, 0 -(1112.000000, 2.921078), (1112.000000, 22.921078), 1.390000, 0.000000, 0 -(1113.000000, 4.023553), (1113.000000, 24.023553), 1.391250, 0.000000, 0 -(1114.000000, 5.301117), (1114.000000, 25.301117), 1.392500, 0.000000, 0 -(1115.000000, 6.753191), (1115.000000, 26.753191), 1.393750, 0.000000, 0 -(1116.000000, 8.379117), (1116.000000, 28.379117), 1.395000, 0.000000, 0 -(1117.000000, 10.178156), (1117.000000, 30.178156), 1.396250, 0.000000, 0 -(1118.000000, 12.149493), (1118.000000, 32.149493), 1.397500, 0.000000, 0 -(1119.000000, 14.292233), (1119.000000, 34.292233), 1.398750, 0.000000, 0 -(1120.000000, 16.605405), (1120.000000, 36.605405), 1.400000, 0.000000, 0 -(1121.000000, 19.087959), (1121.000000, 39.087959), 1.401250, 0.000000, 0 -(1122.000000, 21.738768), (1122.000000, 41.738768), 1.402500, 0.000000, 0 -(1123.000000, 24.556631), (1123.000000, 44.556631), 1.403750, 0.000000, 0 -(1124.000000, 27.540269), (1124.000000, 47.540269), 1.405000, 0.000000, 0 -(1125.000000, 30.688329), (1125.000000, 50.688329), 1.406250, 0.000000, 0 -(1126.000000, 33.999382), (1126.000000, 53.999382), 1.407500, 0.000000, 0 -(1127.000000, 37.471927), (1127.000000, 57.471927), 1.408750, 0.000000, 0 -(1128.000000, 41.104388), (1128.000000, 61.104388), 1.410000, 0.000000, 0 -(1129.000000, 44.895118), (1129.000000, 64.895118), 1.411250, 0.000000, 0 -(1130.000000, 48.842397), (1130.000000, 68.842397), 1.412500, 0.000000, 0 -(1131.000000, 52.944434), (1131.000000, 72.944434), 1.413750, 0.000000, 0 -(1132.000000, 57.199369), (1132.000000, 77.199369), 1.415000, 0.000000, 0 -(1133.000000, 61.605272), (1133.000000, 81.605272), 1.416250, 0.000000, 0 -(1134.000000, 66.160143), (1134.000000, 86.160143), 1.417500, 0.000000, 0 -(1135.000000, 70.861917), (1135.000000, 90.861917), 1.418750, 0.000000, 0 -(1136.000000, 75.708461), (1136.000000, 95.708461), 1.420000, 0.000000, 0 -(1137.000000, 80.697576), (1137.000000, 100.697576), 1.421250, 0.000000, 0 -(1138.000000, 85.826999), (1138.000000, 105.826999), 1.422500, 0.000000, 0 -(1139.000000, 91.094404), (1139.000000, 111.094404), 1.423750, 0.000000, 0 -(1140.000000, 96.497400), (1140.000000, 116.497400), 1.425000, 0.000000, 0 -(1141.000000, 102.033537), (1141.000000, 122.033537), 1.426250, 0.000000, 0 -(1142.000000, 107.700303), (1142.000000, 127.700303), 1.427500, 0.000000, 0 -(1143.000000, 113.495128), (1143.000000, 133.495128), 1.428750, 0.000000, 0 -(1144.000000, 119.415384), (1144.000000, 139.415384), 1.430000, 0.000000, 0 -(1145.000000, 125.458384), (1145.000000, 145.458384), 1.431250, 0.000000, 0 -(1146.000000, 131.621387), (1146.000000, 151.621387), 1.432500, 0.000000, 0 -(1147.000000, 137.901598), (1147.000000, 157.901598), 1.433750, 0.000000, 0 -(1148.000000, 144.296168), (1148.000000, 164.296168), 1.435000, 0.000000, 0 -(1149.000000, 150.802196), (1149.000000, 170.802196), 1.436250, 0.000000, 0 -(1150.000000, 157.416730), (1150.000000, 177.416730), 1.437500, 0.000000, 0 -(1151.000000, 164.136771), (1151.000000, 184.136771), 1.438750, 0.000000, 0 -(1152.000000, 170.959269), (1152.000000, 190.959269), 1.440000, 0.000000, 0 -(1153.000000, 177.881130), (1153.000000, 197.881130), 1.441250, 0.000000, 0 -(1154.000000, 184.899214), (1154.000000, 204.899214), 1.442500, 0.000000, 0 -(1155.000000, 192.010338), (1155.000000, 212.010338), 1.443750, 0.000000, 0 -(1156.000000, 199.211275), (1156.000000, 219.211275), 1.445000, 0.000000, 0 -(1157.000000, 206.498759), (1157.000000, 226.498759), 1.446250, 0.000000, 0 -(1158.000000, 213.869484), (1158.000000, 233.869484), 1.447500, 0.000000, 0 -(1159.000000, 221.320107), (1159.000000, 241.320107), 1.448750, 0.000000, 0 -(1160.000000, 228.847248), (1160.000000, 248.847248), 1.450000, 0.000000, 0 -(1161.000000, 236.447492), (1161.000000, 256.447492), 1.451250, 0.000000, 0 -(1162.000000, 244.117391), (1162.000000, 264.117391), 1.452500, 0.000000, 0 -(1163.000000, 251.853467), (1163.000000, 271.853467), 1.453750, 0.000000, 0 -(1164.000000, 259.652210), (1164.000000, 279.652210), 1.455000, 0.000000, 0 -(1165.000000, 267.510082), (1165.000000, 287.510082), 1.456250, 0.000000, 0 -(1166.000000, 275.423519), (1166.000000, 295.423519), 1.457500, 0.000000, 0 -(1167.000000, 283.388932), (1167.000000, 303.388932), 1.458750, 0.000000, 0 -(1168.000000, 291.402705), (1168.000000, 311.402705), 1.460000, 0.000000, 0 -(1169.000000, 299.461206), (1169.000000, 319.461206), 1.461250, 0.000000, 0 -(1170.000000, 307.560777), (1170.000000, 327.560777), 1.462500, 0.000000, 0 -(1171.000000, 315.697745), (1171.000000, 335.697745), 1.463750, 0.000000, 0 -(1172.000000, 323.868418), (1172.000000, 343.868418), 1.465000, 0.000000, 0 -(1173.000000, 332.069090), (1173.000000, 352.069090), 1.466250, 0.000000, 0 -(1174.000000, 340.296042), (1174.000000, 360.296042), 1.467500, 0.000000, 0 -(1175.000000, 348.545541), (1175.000000, 368.545541), 1.468750, 0.000000, 0 -(1176.000000, 356.813844), (1176.000000, 376.813844), 1.470000, 0.000000, 0 -(1177.000000, 365.097202), (1177.000000, 385.097202), 1.471250, 0.000000, 0 -(1178.000000, 373.391856), (1178.000000, 393.391856), 1.472500, 0.000000, 0 -(1179.000000, 381.694044), (1179.000000, 401.694044), 1.473750, 0.000000, 0 diff --git a/reducer_bench/quad_tree/input/smalllines.in b/reducer_bench/quad_tree/input/smalllines.in deleted file mode 100644 index 27068aca..00000000 --- a/reducer_bench/quad_tree/input/smalllines.in +++ /dev/null @@ -1,530 +0,0 @@ -529 -(8, 16), (16, 8), 5, 5, 1 -(8, 32), (9, 30), 5, 5, 0 -(10, 29), (11, 28), -5, -5, 0 -(12, 27), (14, 26), 5, 5, 0 -(15, 24), (16, 23), -5, -5, 0 -(17, 22), (18, 21), 5, 5, 0 -(20, 20), (21, 18), -5, -5, 0 -(22, 17), (23, 16), 5, 5, 0 -(24, 15), (26, 14), -5, -5, 0 -(27, 12), (28, 11), 5, 5, 0 -(29, 10), (30, 9), -5, -5, 0 -(8, 48), (48, 8), -5, -5, 1 -(8, 64), (10, 61), -5, -5, 0 -(13, 58), (16, 55), 5, 5, 0 -(19, 52), (22, 50), -5, -5, 0 -(24, 47), (27, 44), 5, 5, 0 -(30, 41), (33, 38), -5, -5, 0 -(36, 36), (38, 33), 5, 5, 0 -(41, 30), (44, 27), -5, -5, 0 -(47, 24), (50, 22), 5, 5, 0 -(52, 19), (55, 16), -5, -5, 0 -(58, 13), (61, 10), 5, 5, 0 -(8, 80), (80, 8), 5, 5, 1 -(8, 96), (12, 91), 5, 5, 0 -(16, 87), (21, 82), -5, -5, 0 -(25, 78), (30, 74), 5, 5, 0 -(34, 69), (38, 65), -5, -5, 0 -(43, 60), (47, 56), 5, 5, 0 -(52, 52), (56, 47), -5, -5, 0 -(60, 43), (65, 38), 5, 5, 0 -(69, 34), (74, 30), -5, -5, 0 -(78, 25), (82, 21), 5, 5, 0 -(87, 16), (91, 12), -5, -5, 0 -(8, 112), (112, 8), -5, -5, 1 -(8, 128), (14, 122), -5, -5, 0 -(20, 116), (26, 110), 5, 5, 0 -(32, 104), (38, 98), -5, -5, 0 -(44, 92), (50, 86), 5, 5, 0 -(56, 80), (62, 74), -5, -5, 0 -(68, 68), (74, 62), 5, 5, 0 -(80, 56), (86, 50), -5, -5, 0 -(92, 44), (98, 38), 5, 5, 0 -(104, 32), (110, 26), -5, -5, 0 -(116, 20), (122, 14), 5, 5, 0 -(8, 144), (144, 8), 5, 5, 1 -(8, 160), (15, 152), 5, 5, 0 -(23, 144), (30, 137), -5, -5, 0 -(38, 129), (46, 122), 5, 5, 0 -(53, 114), (61, 106), -5, -5, 0 -(68, 99), (76, 91), 5, 5, 0 -(84, 84), (91, 76), -5, -5, 0 -(99, 68), (106, 61), 5, 5, 0 -(114, 53), (122, 46), -5, -5, 0 -(129, 38), (137, 30), 5, 5, 0 -(144, 23), (152, 15), -5, -5, 0 -(8, 176), (176, 8), -5, -5, 1 -(8, 192), (17, 182), -5, -5, 0 -(26, 173), (35, 164), 5, 5, 0 -(44, 155), (54, 146), -5, -5, 0 -(63, 136), (72, 127), 5, 5, 0 -(81, 118), (90, 109), -5, -5, 0 -(100, 100), (109, 90), 5, 5, 0 -(118, 81), (127, 72), -5, -5, 0 -(136, 63), (146, 54), 5, 5, 0 -(155, 44), (164, 35), -5, -5, 0 -(173, 26), (182, 17), 5, 5, 0 -(8, 208), (208, 8), 5, 5, 1 -(8, 224), (18, 213), 5, 5, 0 -(29, 202), (40, 191), -5, -5, 0 -(51, 180), (62, 170), 5, 5, 0 -(72, 159), (83, 148), -5, -5, 0 -(94, 137), (105, 126), 5, 5, 0 -(116, 116), (126, 105), -5, -5, 0 -(137, 94), (148, 83), 5, 5, 0 -(159, 72), (170, 62), -5, -5, 0 -(180, 51), (191, 40), 5, 5, 0 -(202, 29), (213, 18), -5, -5, 0 -(8, 240), (240, 8), -5, -5, 1 -(8, 256), (20, 243), -5, -5, 0 -(32, 231), (45, 218), 5, 5, 0 -(57, 206), (70, 194), -5, -5, 0 -(82, 181), (94, 169), 5, 5, 0 -(107, 156), (119, 144), -5, -5, 0 -(132, 132), (144, 119), 5, 5, 0 -(156, 107), (169, 94), -5, -5, 0 -(181, 82), (194, 70), 5, 5, 0 -(206, 57), (218, 45), -5, -5, 0 -(231, 32), (243, 20), 5, 5, 0 -(8, 272), (272, 8), 5, 5, 1 -(8, 288), (22, 274), 5, 5, 0 -(36, 260), (50, 246), -5, -5, 0 -(64, 232), (78, 218), 5, 5, 0 -(92, 204), (106, 190), -5, -5, 0 -(120, 176), (134, 162), 5, 5, 0 -(148, 148), (162, 134), -5, -5, 0 -(176, 120), (190, 106), 5, 5, 0 -(204, 92), (218, 78), -5, -5, 0 -(232, 64), (246, 50), 5, 5, 0 -(260, 36), (274, 22), -5, -5, 0 -(8, 304), (304, 8), -5, -5, 1 -(8, 320), (23, 304), -5, -5, 0 -(39, 288), (54, 273), 5, 5, 0 -(70, 257), (86, 242), -5, -5, 0 -(101, 226), (117, 210), 5, 5, 0 -(132, 195), (148, 179), -5, -5, 0 -(164, 164), (179, 148), 5, 5, 0 -(195, 132), (210, 117), -5, -5, 0 -(226, 101), (242, 86), 5, 5, 0 -(257, 70), (273, 54), -5, -5, 0 -(288, 39), (304, 23), 5, 5, 0 -(8, 336), (336, 8), 5, 5, 1 -(8, 352), (25, 334), 5, 5, 0 -(42, 317), (59, 300), -5, -5, 0 -(76, 283), (94, 266), 5, 5, 0 -(111, 248), (128, 231), -5, -5, 0 -(145, 214), (162, 197), 5, 5, 0 -(180, 180), (197, 162), -5, -5, 0 -(214, 145), (231, 128), 5, 5, 0 -(248, 111), (266, 94), -5, -5, 0 -(283, 76), (300, 59), 5, 5, 0 -(317, 42), (334, 25), -5, -5, 0 -(8, 368), (368, 8), -5, -5, 1 -(8, 384), (26, 365), -5, -5, 0 -(45, 346), (64, 327), 5, 5, 0 -(83, 308), (102, 290), -5, -5, 0 -(120, 271), (139, 252), 5, 5, 0 -(158, 233), (177, 214), -5, -5, 0 -(196, 196), (214, 177), 5, 5, 0 -(233, 158), (252, 139), -5, -5, 0 -(271, 120), (290, 102), 5, 5, 0 -(308, 83), (327, 64), -5, -5, 0 -(346, 45), (365, 26), 5, 5, 0 -(8, 400), (400, 8), 5, 5, 1 -(8, 416), (28, 395), 5, 5, 0 -(48, 375), (69, 354), -5, -5, 0 -(89, 334), (110, 314), 5, 5, 0 -(130, 293), (150, 273), -5, -5, 0 -(171, 252), (191, 232), 5, 5, 0 -(212, 212), (232, 191), -5, -5, 0 -(252, 171), (273, 150), 5, 5, 0 -(293, 130), (314, 110), -5, -5, 0 -(334, 89), (354, 69), 5, 5, 0 -(375, 48), (395, 28), -5, -5, 0 -(8, 432), (432, 8), -5, -5, 1 -(8, 448), (30, 426), -5, -5, 0 -(52, 404), (74, 382), 5, 5, 0 -(96, 360), (118, 338), -5, -5, 0 -(140, 316), (162, 294), 5, 5, 0 -(184, 272), (206, 250), -5, -5, 0 -(228, 228), (250, 206), 5, 5, 0 -(272, 184), (294, 162), -5, -5, 0 -(316, 140), (338, 118), 5, 5, 0 -(360, 96), (382, 74), -5, -5, 0 -(404, 52), (426, 30), 5, 5, 0 -(8, 464), (464, 8), 5, 5, 1 -(8, 480), (31, 456), 5, 5, 0 -(55, 432), (78, 409), -5, -5, 0 -(102, 385), (126, 362), 5, 5, 0 -(149, 338), (173, 314), -5, -5, 0 -(196, 291), (220, 267), 5, 5, 0 -(244, 244), (267, 220), -5, -5, 0 -(291, 196), (314, 173), 5, 5, 0 -(338, 149), (362, 126), -5, -5, 0 -(385, 102), (409, 78), 5, 5, 0 -(432, 55), (456, 31), -5, -5, 0 -(8, 496), (496, 8), -5, -5, 1 -(8, 512), (33, 486), -5, -5, 0 -(58, 461), (83, 436), 5, 5, 0 -(108, 411), (134, 386), -5, -5, 0 -(159, 360), (184, 335), 5, 5, 0 -(209, 310), (234, 285), -5, -5, 0 -(260, 260), (285, 234), 5, 5, 0 -(310, 209), (335, 184), -5, -5, 0 -(360, 159), (386, 134), 5, 5, 0 -(411, 108), (436, 83), -5, -5, 0 -(461, 58), (486, 33), 5, 5, 0 -(8, 528), (528, 8), 5, 5, 1 -(8, 544), (34, 517), 5, 5, 0 -(61, 490), (88, 463), -5, -5, 0 -(115, 436), (142, 410), 5, 5, 0 -(168, 383), (195, 356), -5, -5, 0 -(222, 329), (249, 302), 5, 5, 0 -(276, 276), (302, 249), -5, -5, 0 -(329, 222), (356, 195), 5, 5, 0 -(383, 168), (410, 142), -5, -5, 0 -(436, 115), (463, 88), 5, 5, 0 -(490, 61), (517, 34), -5, -5, 0 -(8, 560), (560, 8), -5, -5, 1 -(8, 576), (36, 547), -5, -5, 0 -(64, 519), (93, 490), 5, 5, 0 -(121, 462), (150, 434), -5, -5, 0 -(178, 405), (206, 377), 5, 5, 0 -(235, 348), (263, 320), -5, -5, 0 -(292, 292), (320, 263), 5, 5, 0 -(348, 235), (377, 206), -5, -5, 0 -(405, 178), (434, 150), 5, 5, 0 -(462, 121), (490, 93), -5, -5, 0 -(519, 64), (547, 36), 5, 5, 0 -(8, 592), (592, 8), 5, 5, 1 -(8, 608), (38, 578), 5, 5, 0 -(68, 548), (98, 518), -5, -5, 0 -(128, 488), (158, 458), 5, 5, 0 -(188, 428), (218, 398), -5, -5, 0 -(248, 368), (278, 338), 5, 5, 0 -(308, 308), (338, 278), -5, -5, 0 -(368, 248), (398, 218), 5, 5, 0 -(428, 188), (458, 158), -5, -5, 0 -(488, 128), (518, 98), 5, 5, 0 -(548, 68), (578, 38), -5, -5, 0 -(8, 624), (624, 8), -5, -5, 1 -(8, 640), (39, 608), -5, -5, 0 -(71, 576), (102, 545), 5, 5, 0 -(134, 513), (166, 482), -5, -5, 0 -(197, 450), (229, 418), 5, 5, 0 -(260, 387), (292, 355), -5, -5, 0 -(324, 324), (355, 292), 5, 5, 0 -(387, 260), (418, 229), -5, -5, 0 -(450, 197), (482, 166), 5, 5, 0 -(513, 134), (545, 102), -5, -5, 0 -(576, 71), (608, 39), 5, 5, 0 -(8, 656), (656, 8), 5, 5, 1 -(8, 672), (41, 638), 5, 5, 0 -(74, 605), (107, 572), -5, -5, 0 -(140, 539), (174, 506), 5, 5, 0 -(207, 472), (240, 439), -5, -5, 0 -(273, 406), (306, 373), 5, 5, 0 -(340, 340), (373, 306), -5, -5, 0 -(406, 273), (439, 240), 5, 5, 0 -(472, 207), (506, 174), -5, -5, 0 -(539, 140), (572, 107), 5, 5, 0 -(605, 74), (638, 41), -5, -5, 0 -(8, 688), (688, 8), -5, -5, 1 -(8, 704), (42, 669), -5, -5, 0 -(77, 634), (112, 599), 5, 5, 0 -(147, 564), (182, 530), -5, -5, 0 -(216, 495), (251, 460), 5, 5, 0 -(286, 425), (321, 390), -5, -5, 0 -(356, 356), (390, 321), 5, 5, 0 -(425, 286), (460, 251), -5, -5, 0 -(495, 216), (530, 182), 5, 5, 0 -(564, 147), (599, 112), -5, -5, 0 -(634, 77), (669, 42), 5, 5, 0 -(8, 720), (720, 8), 5, 5, 1 -(8, 736), (44, 699), 5, 5, 0 -(80, 663), (117, 626), -5, -5, 0 -(153, 590), (190, 554), 5, 5, 0 -(226, 517), (262, 481), -5, -5, 0 -(299, 444), (335, 408), 5, 5, 0 -(372, 372), (408, 335), -5, -5, 0 -(444, 299), (481, 262), 5, 5, 0 -(517, 226), (554, 190), -5, -5, 0 -(590, 153), (626, 117), 5, 5, 0 -(663, 80), (699, 44), -5, -5, 0 -(8, 752), (752, 8), -5, -5, 1 -(8, 768), (46, 730), -5, -5, 0 -(84, 692), (122, 654), 5, 5, 0 -(160, 616), (198, 578), -5, -5, 0 -(236, 540), (274, 502), 5, 5, 0 -(312, 464), (350, 426), -5, -5, 0 -(388, 388), (426, 350), 5, 5, 0 -(464, 312), (502, 274), -5, -5, 0 -(540, 236), (578, 198), 5, 5, 0 -(616, 160), (654, 122), -5, -5, 0 -(692, 84), (730, 46), 5, 5, 0 -(8, 784), (784, 8), 5, 5, 1 -(792, 784), (791, 784), 5, 5, 0 -(791, 784), (790, 785), -5, -5, 0 -(790, 785), (790, 786), 5, 5, 0 -(789, 786), (789, 786), -5, -5, 0 -(788, 787), (788, 787), 5, 5, 0 -(788, 788), (787, 788), -5, -5, 0 -(787, 788), (786, 789), 5, 5, 0 -(786, 789), (786, 790), -5, -5, 0 -(785, 790), (785, 790), 5, 5, 0 -(784, 791), (784, 791), -5, -5, 0 -(792, 768), (768, 792), -5, -5, 1 -(792, 752), (790, 754), -5, -5, 0 -(788, 756), (786, 758), 5, 5, 0 -(784, 760), (782, 762), -5, -5, 0 -(780, 764), (778, 766), 5, 5, 0 -(776, 768), (774, 770), -5, -5, 0 -(772, 772), (770, 774), 5, 5, 0 -(768, 776), (766, 778), -5, -5, 0 -(764, 780), (762, 782), 5, 5, 0 -(760, 784), (758, 786), -5, -5, 0 -(756, 788), (754, 790), 5, 5, 0 -(792, 736), (736, 792), 5, 5, 1 -(792, 720), (788, 723), 5, 5, 0 -(784, 727), (781, 730), -5, -5, 0 -(777, 734), (774, 738), 5, 5, 0 -(770, 741), (766, 745), -5, -5, 0 -(763, 748), (759, 752), 5, 5, 0 -(756, 756), (752, 759), -5, -5, 0 -(748, 763), (745, 766), 5, 5, 0 -(741, 770), (738, 774), -5, -5, 0 -(734, 777), (730, 781), 5, 5, 0 -(727, 784), (723, 788), -5, -5, 0 -(792, 704), (704, 792), -5, -5, 1 -(792, 688), (786, 693), -5, -5, 0 -(781, 698), (776, 703), 5, 5, 0 -(771, 708), (766, 714), -5, -5, 0 -(760, 719), (755, 724), 5, 5, 0 -(750, 729), (745, 734), -5, -5, 0 -(740, 740), (734, 745), 5, 5, 0 -(729, 750), (724, 755), -5, -5, 0 -(719, 760), (714, 766), 5, 5, 0 -(708, 771), (703, 776), -5, -5, 0 -(698, 781), (693, 786), 5, 5, 0 -(792, 672), (672, 792), 5, 5, 1 -(792, 656), (785, 662), 5, 5, 0 -(778, 669), (771, 676), -5, -5, 0 -(764, 683), (758, 690), 5, 5, 0 -(751, 696), (744, 703), -5, -5, 0 -(737, 710), (730, 717), 5, 5, 0 -(724, 724), (717, 730), -5, -5, 0 -(710, 737), (703, 744), 5, 5, 0 -(696, 751), (690, 758), -5, -5, 0 -(683, 764), (676, 771), 5, 5, 0 -(669, 778), (662, 785), -5, -5, 0 -(792, 640), (640, 792), -5, -5, 1 -(792, 624), (783, 632), -5, -5, 0 -(775, 640), (766, 649), 5, 5, 0 -(758, 657), (750, 666), -5, -5, 0 -(741, 674), (733, 682), 5, 5, 0 -(724, 691), (716, 699), -5, -5, 0 -(708, 708), (699, 716), 5, 5, 0 -(691, 724), (682, 733), -5, -5, 0 -(674, 741), (666, 750), 5, 5, 0 -(657, 758), (649, 766), -5, -5, 0 -(640, 775), (632, 783), 5, 5, 0 -(792, 608), (608, 792), 5, 5, 1 -(792, 592), (782, 602), 5, 5, 0 -(772, 612), (762, 622), -5, -5, 0 -(752, 632), (742, 642), 5, 5, 0 -(732, 652), (722, 662), -5, -5, 0 -(712, 672), (702, 682), 5, 5, 0 -(692, 692), (682, 702), -5, -5, 0 -(672, 712), (662, 722), 5, 5, 0 -(652, 732), (642, 742), -5, -5, 0 -(632, 752), (622, 762), 5, 5, 0 -(612, 772), (602, 782), -5, -5, 0 -(792, 576), (576, 792), -5, -5, 1 -(792, 560), (780, 571), -5, -5, 0 -(768, 583), (757, 594), 5, 5, 0 -(745, 606), (734, 618), -5, -5, 0 -(722, 629), (710, 641), 5, 5, 0 -(699, 652), (687, 664), -5, -5, 0 -(676, 676), (664, 687), 5, 5, 0 -(652, 699), (641, 710), -5, -5, 0 -(629, 722), (618, 734), 5, 5, 0 -(606, 745), (594, 757), -5, -5, 0 -(583, 768), (571, 780), 5, 5, 0 -(792, 544), (544, 792), 5, 5, 1 -(792, 528), (778, 541), 5, 5, 0 -(765, 554), (752, 567), -5, -5, 0 -(739, 580), (726, 594), 5, 5, 0 -(712, 607), (699, 620), -5, -5, 0 -(686, 633), (673, 646), 5, 5, 0 -(660, 660), (646, 673), -5, -5, 0 -(633, 686), (620, 699), 5, 5, 0 -(607, 712), (594, 726), -5, -5, 0 -(580, 739), (567, 752), 5, 5, 0 -(554, 765), (541, 778), -5, -5, 0 -(792, 512), (512, 792), -5, -5, 1 -(792, 496), (777, 510), -5, -5, 0 -(762, 525), (747, 540), 5, 5, 0 -(732, 555), (718, 570), -5, -5, 0 -(703, 584), (688, 599), 5, 5, 0 -(673, 614), (658, 629), -5, -5, 0 -(644, 644), (629, 658), 5, 5, 0 -(614, 673), (599, 688), -5, -5, 0 -(584, 703), (570, 718), 5, 5, 0 -(555, 732), (540, 747), -5, -5, 0 -(525, 762), (510, 777), 5, 5, 0 -(792, 480), (480, 792), 5, 5, 1 -(792, 464), (775, 480), 5, 5, 0 -(759, 496), (742, 513), -5, -5, 0 -(726, 529), (710, 546), 5, 5, 0 -(693, 562), (677, 578), -5, -5, 0 -(660, 595), (644, 611), 5, 5, 0 -(628, 628), (611, 644), -5, -5, 0 -(595, 660), (578, 677), 5, 5, 0 -(562, 693), (546, 710), -5, -5, 0 -(529, 726), (513, 742), 5, 5, 0 -(496, 759), (480, 775), -5, -5, 0 -(792, 448), (448, 792), -5, -5, 1 -(792, 432), (774, 450), -5, -5, 0 -(756, 468), (738, 486), 5, 5, 0 -(720, 504), (702, 522), -5, -5, 0 -(684, 540), (666, 558), 5, 5, 0 -(648, 576), (630, 594), -5, -5, 0 -(612, 612), (594, 630), 5, 5, 0 -(576, 648), (558, 666), -5, -5, 0 -(540, 684), (522, 702), 5, 5, 0 -(504, 720), (486, 738), -5, -5, 0 -(468, 756), (450, 774), 5, 5, 0 -(792, 416), (416, 792), 5, 5, 1 -(792, 400), (772, 419), 5, 5, 0 -(752, 439), (733, 458), -5, -5, 0 -(713, 478), (694, 498), 5, 5, 0 -(674, 517), (654, 537), -5, -5, 0 -(635, 556), (615, 576), 5, 5, 0 -(596, 596), (576, 615), -5, -5, 0 -(556, 635), (537, 654), 5, 5, 0 -(517, 674), (498, 694), -5, -5, 0 -(478, 713), (458, 733), 5, 5, 0 -(439, 752), (419, 772), -5, -5, 0 -(792, 384), (384, 792), -5, -5, 1 -(792, 368), (770, 389), -5, -5, 0 -(749, 410), (728, 431), 5, 5, 0 -(707, 452), (686, 474), -5, -5, 0 -(664, 495), (643, 516), 5, 5, 0 -(622, 537), (601, 558), -5, -5, 0 -(580, 580), (558, 601), 5, 5, 0 -(537, 622), (516, 643), -5, -5, 0 -(495, 664), (474, 686), 5, 5, 0 -(452, 707), (431, 728), -5, -5, 0 -(410, 749), (389, 770), 5, 5, 0 -(792, 352), (352, 792), 5, 5, 1 -(792, 336), (769, 358), 5, 5, 0 -(746, 381), (723, 404), -5, -5, 0 -(700, 427), (678, 450), 5, 5, 0 -(655, 472), (632, 495), -5, -5, 0 -(609, 518), (586, 541), 5, 5, 0 -(564, 564), (541, 586), -5, -5, 0 -(518, 609), (495, 632), 5, 5, 0 -(472, 655), (450, 678), -5, -5, 0 -(427, 700), (404, 723), 5, 5, 0 -(381, 746), (358, 769), -5, -5, 0 -(792, 320), (320, 792), -5, -5, 1 -(792, 304), (767, 328), -5, -5, 0 -(743, 352), (718, 377), 5, 5, 0 -(694, 401), (670, 426), -5, -5, 0 -(645, 450), (621, 474), 5, 5, 0 -(596, 499), (572, 523), -5, -5, 0 -(548, 548), (523, 572), 5, 5, 0 -(499, 596), (474, 621), -5, -5, 0 -(450, 645), (426, 670), 5, 5, 0 -(401, 694), (377, 718), -5, -5, 0 -(352, 743), (328, 767), 5, 5, 0 -(792, 288), (288, 792), 5, 5, 1 -(792, 272), (766, 298), 5, 5, 0 -(740, 324), (714, 350), -5, -5, 0 -(688, 376), (662, 402), 5, 5, 0 -(636, 428), (610, 454), -5, -5, 0 -(584, 480), (558, 506), 5, 5, 0 -(532, 532), (506, 558), -5, -5, 0 -(480, 584), (454, 610), 5, 5, 0 -(428, 636), (402, 662), -5, -5, 0 -(376, 688), (350, 714), 5, 5, 0 -(324, 740), (298, 766), -5, -5, 0 -(792, 256), (256, 792), -5, -5, 1 -(792, 240), (764, 267), -5, -5, 0 -(736, 295), (709, 322), 5, 5, 0 -(681, 350), (654, 378), -5, -5, 0 -(626, 405), (598, 433), 5, 5, 0 -(571, 460), (543, 488), -5, -5, 0 -(516, 516), (488, 543), 5, 5, 0 -(460, 571), (433, 598), -5, -5, 0 -(405, 626), (378, 654), 5, 5, 0 -(350, 681), (322, 709), -5, -5, 0 -(295, 736), (267, 764), 5, 5, 0 -(792, 224), (224, 792), 5, 5, 1 -(792, 208), (762, 237), 5, 5, 0 -(733, 266), (704, 295), -5, -5, 0 -(675, 324), (646, 354), 5, 5, 0 -(616, 383), (587, 412), -5, -5, 0 -(558, 441), (529, 470), 5, 5, 0 -(500, 500), (470, 529), -5, -5, 0 -(441, 558), (412, 587), 5, 5, 0 -(383, 616), (354, 646), -5, -5, 0 -(324, 675), (295, 704), 5, 5, 0 -(266, 733), (237, 762), -5, -5, 0 -(792, 192), (192, 792), -5, -5, 1 -(792, 176), (761, 206), -5, -5, 0 -(730, 237), (699, 268), 5, 5, 0 -(668, 299), (638, 330), -5, -5, 0 -(607, 360), (576, 391), 5, 5, 0 -(545, 422), (514, 453), -5, -5, 0 -(484, 484), (453, 514), 5, 5, 0 -(422, 545), (391, 576), -5, -5, 0 -(360, 607), (330, 638), 5, 5, 0 -(299, 668), (268, 699), -5, -5, 0 -(237, 730), (206, 761), 5, 5, 0 -(792, 160), (160, 792), 5, 5, 1 -(792, 144), (759, 176), 5, 5, 0 -(727, 208), (694, 241), -5, -5, 0 -(662, 273), (630, 306), 5, 5, 0 -(597, 338), (565, 370), -5, -5, 0 -(532, 403), (500, 435), 5, 5, 0 -(468, 468), (435, 500), -5, -5, 0 -(403, 532), (370, 565), 5, 5, 0 -(338, 597), (306, 630), -5, -5, 0 -(273, 662), (241, 694), 5, 5, 0 -(208, 727), (176, 759), -5, -5, 0 -(792, 128), (128, 792), -5, -5, 1 -(792, 112), (758, 146), -5, -5, 0 -(724, 180), (690, 214), 5, 5, 0 -(656, 248), (622, 282), -5, -5, 0 -(588, 316), (554, 350), 5, 5, 0 -(520, 384), (486, 418), -5, -5, 0 -(452, 452), (418, 486), 5, 5, 0 -(384, 520), (350, 554), -5, -5, 0 -(316, 588), (282, 622), 5, 5, 0 -(248, 656), (214, 690), -5, -5, 0 -(180, 724), (146, 758), 5, 5, 0 -(792, 96), (96, 792), 5, 5, 1 -(792, 80), (756, 115), 5, 5, 0 -(720, 151), (685, 186), -5, -5, 0 -(649, 222), (614, 258), 5, 5, 0 -(578, 293), (542, 329), -5, -5, 0 -(507, 364), (471, 400), 5, 5, 0 -(436, 436), (400, 471), -5, -5, 0 -(364, 507), (329, 542), 5, 5, 0 -(293, 578), (258, 614), -5, -5, 0 -(222, 649), (186, 685), 5, 5, 0 -(151, 720), (115, 756), -5, -5, 0 -(792, 64), (64, 792), -5, -5, 1 -(792, 48), (754, 85), -5, -5, 0 -(717, 122), (680, 159), 5, 5, 0 -(643, 196), (606, 234), -5, -5, 0 -(568, 271), (531, 308), 5, 5, 0 -(494, 345), (457, 382), -5, -5, 0 -(420, 420), (382, 457), 5, 5, 0 -(345, 494), (308, 531), -5, -5, 0 -(271, 568), (234, 606), 5, 5, 0 -(196, 643), (159, 680), -5, -5, 0 -(122, 717), (85, 754), 5, 5, 0 -(792, 32), (32, 792), 5, 5, 1 diff --git a/reducer_bench/quad_tree/intersection_detection.c b/reducer_bench/quad_tree/intersection_detection.c deleted file mode 100644 index 92b8b7dd..00000000 --- a/reducer_bench/quad_tree/intersection_detection.c +++ /dev/null @@ -1,157 +0,0 @@ -/** - * Copyright (c) 2012 the Massachusetts Institute of Technology - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - **/ - -#include "./intersection_detection.h" - -#include - -#include "./line.h" -#include "./vec.h" - -// Detect if lines l1 and l2 will intersect between now and the next time step. -IntersectionType intersect(Line *l1, Line *l2, double time) { - assert(compareLines(l1, l2) < 0); - - Vec disp; - Vec p1; - Vec p2; - - // Get relative velocity. - disp = Vec_multiply(Vec_subtract(l2->velocity, l1->velocity), time); - - // Get the parallelogram. - p1 = Vec_add(l2->p1, disp); - p2 = Vec_add(l2->p2, disp); - - int num_line_intersections = 0; - bool top_intersected = false; - bool bottom_intersected = false; - - if (intersectLines(l1->p1, l1->p2, l2->p1, l2->p2)) { - return ALREADY_INTERSECTED; - } - if (intersectLines(l1->p1, l1->p2, p1, p2)) { - num_line_intersections++; - } - if (intersectLines(l1->p1, l1->p2, p1, l2->p1)) { - num_line_intersections++; - top_intersected = true; - } - if (intersectLines(l1->p1, l1->p2, p2, l2->p2)) { - num_line_intersections++; - bottom_intersected = true; - } - - if (num_line_intersections == 2) { - return L2_WITH_L1; - } - - if (pointInParallelogram(l1->p1, l2->p1, l2->p2, p1, p2) - && pointInParallelogram(l1->p2, l2->p1, l2->p2, p1, p2)) { - return L1_WITH_L2; - } - - if (num_line_intersections == 0) { - return NO_INTERSECTION; - } - - Vec v1 = Vec_makeFromLine(*l1); - Vec v2 = Vec_makeFromLine(*l2); - double angle = Vec_angle(v1, v2); - - if (top_intersected) { - if (angle < 0) { - return L2_WITH_L1; - } else { - return L1_WITH_L2; - } - } - - if (bottom_intersected) { - if (angle > 0) { - return L2_WITH_L1; - } else { - return L1_WITH_L2; - } - } - - return L1_WITH_L2; -} - -// Check if a point is in the parallelogram. -bool pointInParallelogram(Vec point, Vec p1, Vec p2, Vec p3, Vec p4) { - double d1 = direction(p1, p2, point); - double d2 = direction(p3, p4, point); - double d3 = direction(p1, p3, point); - double d4 = direction(p2, p4, point); - - return ((d1 > 0 && d2 < 0) || (d1 < 0 && d2 > 0)) && ((d3 > 0 && d4 < 0) || (d3 < 0 && d4 > 0)); -} - -// Check if two lines intersect. -bool intersectLines(Vec p1, Vec p2, Vec p3, Vec p4) { - // Relative orientation - double d1 = direction(p3, p4, p1); - double d2 = direction(p3, p4, p2); - double d3 = direction(p1, p2, p3); - double d4 = direction(p1, p2, p4); - - // If (p1, p2) and (p3, p4) straddle each other, the line segments must - // intersect. - bool b = ((d1 > 0 && d2 < 0) || (d1 < 0 && d2 > 0)) && ((d3 > 0 && d4 < 0) || (d3 < 0 && d4 > 0)); - b = b || (d1 == 0 && onSegment(p3, p4, p1)); - b = b || (d2 == 0 && onSegment(p3, p4, p2)); - b = b || (d3 == 0 && onSegment(p1, p2, p3)); - b = b || (d4 == 0 && onSegment(p1, p2, p4)); - return b; -} - -// Obtain the intersection point for two intersecting line segments. -Vec getIntersectionPoint(Vec p1, Vec p2, Vec p3, Vec p4) { - double u; - - u = ((p4.x - p3.x) * (p1.y - p3.y) - (p4.y - p3.y) * (p1.x - p3.x)) - / ((p4.y - p3.y) * (p2.x - p1.x) - (p4.x - p3.x) * (p2.y - p1.y)); - - return Vec_add(p1, Vec_multiply(Vec_subtract(p2, p1), u)); -} - -// Check the direction of two lines (pi, pj) and (pi, pk). -double direction(Vec pi, Vec pj, Vec pk) { - return crossProduct(pk.x - pi.x, pk.y - pi.y, pj.x - pi.x, pj.y - pi.y); -} - -// Check if a point pk is in the line segment (pi, pj). -// pi, pj, and pk must be collinear. -bool onSegment(Vec pi, Vec pj, Vec pk) { - if (((pi.x <= pk.x && pk.x <= pj.x) || (pj.x <= pk.x && pk.x <= pi.x)) - && ((pi.y <= pk.y && pk.y <= pj.y) || (pj.y <= pk.y && pk.y <= pi.y))) { - return true; - } - return false; -} - -// Calculate the cross product. -double crossProduct(double x1, double y1, double x2, double y2) { - return x1 * y2 - x2 * y1; -} - diff --git a/reducer_bench/quad_tree/intersection_detection.h b/reducer_bench/quad_tree/intersection_detection.h deleted file mode 100644 index 66926c00..00000000 --- a/reducer_bench/quad_tree/intersection_detection.h +++ /dev/null @@ -1,58 +0,0 @@ -/** - * Copyright (c) 2012 the Massachusetts Institute of Technology - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - **/ - -#ifndef INTERSECTIONDETECTION_H_ -#define INTERSECTIONDETECTION_H_ - -#include "./line.h" -#include "./vec.h" - -typedef enum { - NO_INTERSECTION, - L1_WITH_L2, - L2_WITH_L1, - ALREADY_INTERSECTED -} IntersectionType; - -// Detect if line l1 and l2 will be intersected in the next time step. -// Precondition: compareLines(l1, l2) < 0 must be true. -IntersectionType intersect(Line *l1, Line *l2, double time); - -// Check if a point is in the parallelogram. -bool pointInParallelogram(Vec point, Vec p1, Vec p2, Vec p3, Vec p4); - -// Check if two lines intersect. -bool intersectLines(Vec p1, Vec p2, Vec p3, Vec p4); - -// Check the direction of two lines (pi, pj) and (pi, pk). -double direction(Vec pi, Vec pj, Vec pk); - -// Check if a point pk is in the line segment (pi, pj). -bool onSegment(Vec pi, Vec pj, Vec pk); - -// Calculate the cross product. -double crossProduct(double x1, double y1, double x2, double y2); - -// Obtain the intersection point for two intersecting line segments. -Vec getIntersectionPoint(Vec p1, Vec p2, Vec p3, Vec p4); - -#endif // INTERSECTIONDETECTION_H_ diff --git a/reducer_bench/quad_tree/intersection_event_list.c b/reducer_bench/quad_tree/intersection_event_list.c deleted file mode 100644 index 07cd987f..00000000 --- a/reducer_bench/quad_tree/intersection_event_list.c +++ /dev/null @@ -1,107 +0,0 @@ -/** - * Copyright (c) 2013 the Massachusetts Institute of Technology - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - **/ - -#include "./intersection_event_list.h" - -#include -#include - -int IntersectionEventNode_compareData(IntersectionEventNode* node1, - IntersectionEventNode* node2) { - if (compareLines(node1->l1, node2->l1) < 0) { - return -1; - } else if (compareLines(node1->l1, node2->l1) == 0) { - if (compareLines(node1->l2, node2->l2) < 0) { - return -1; - } else if (compareLines(node1->l2, node2->l2) == 0) { - return 0; - } else { - return 1; - } - } else { - return 1; - } -} - -void IntersectionEventNode_swapData(IntersectionEventNode* node1, - IntersectionEventNode* node2) { - { - Line* temp = node1->l1; - node1->l1 = node2->l1; - node2->l1 = temp; - } - { - Line* temp = node1->l2; - node1->l2 = node2->l2; - node2->l2 = temp; - } - { - IntersectionType temp = node1->intersectionType; - node1->intersectionType = node2->intersectionType; - node2->intersectionType = temp; - } -} - -IntersectionEventList IntersectionEventList_make() { - IntersectionEventList intersectionEventList; - intersectionEventList.head = NULL; - intersectionEventList.tail = NULL; - intersectionEventList.size = 0; - return intersectionEventList; -} - -void IntersectionEventList_appendNode( - IntersectionEventList* intersectionEventList, Line* l1, Line* l2, - IntersectionType intersectionType) { - assert(compareLines(l1, l2) < 0); - - IntersectionEventNode* newNode = malloc(sizeof(IntersectionEventNode)); - if (newNode == NULL) { - return; - } - - newNode->l1 = l1; - newNode->l2 = l2; - newNode->intersectionType = intersectionType; - newNode->next = NULL; - if (intersectionEventList->head == NULL) { - intersectionEventList->head = newNode; - } else { - intersectionEventList->tail->next = newNode; - } - intersectionEventList->tail = newNode; - intersectionEventList->size++; -} - -void IntersectionEventList_deleteNodes( - IntersectionEventList* intersectionEventList) { - IntersectionEventNode* curNode = intersectionEventList->head; - IntersectionEventNode* nextNode = NULL; - while (curNode != NULL) { - nextNode = curNode->next; - free(curNode); - curNode = nextNode; - } - intersectionEventList->head = NULL; - intersectionEventList->tail = NULL; - intersectionEventList->size = 0; -} diff --git a/reducer_bench/quad_tree/intersection_event_list.h b/reducer_bench/quad_tree/intersection_event_list.h deleted file mode 100644 index 9fa2c882..00000000 --- a/reducer_bench/quad_tree/intersection_event_list.h +++ /dev/null @@ -1,69 +0,0 @@ -/** - * Copyright (c) 2013 the Massachusetts Institute of Technology - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - **/ - -#ifndef INTERSECTIONEVENTLIST_H_ -#define INTERSECTIONEVENTLIST_H_ - -#include "./line.h" -#include "./intersection_detection.h" - -struct IntersectionEventNode { - // This IntersectionEventNode does not own these Line* lines. - Line* l1; - Line* l2; - IntersectionType intersectionType; - struct IntersectionEventNode* next; -}; -typedef struct IntersectionEventNode IntersectionEventNode; - -// Compares the nodes by l1's line ID, then l1's line ID. -// -1 <=> node1 ordered before node2 -// 0 <=> node1 ordered the same as node2 -// 1 <=> node1 ordered after node2 -int IntersectionEventNode_compareData(IntersectionEventNode* node1, - IntersectionEventNode* node2); - -// Swaps the node1's and node2's data (l1, l2, intersectionType). -void IntersectionEventNode_swapData(IntersectionEventNode* node1, - IntersectionEventNode* node2); - -struct IntersectionEventList { - IntersectionEventNode* head; - IntersectionEventNode* tail; - int size; -}; -typedef struct IntersectionEventList IntersectionEventList; - -// Returns an empty list. -IntersectionEventList IntersectionEventList_make(); - -// Appends a new node to the list with the data (l1, l2, intersectionType). -// Precondition: compareLines(l1, l2) < 0 must be true. -void IntersectionEventList_appendNode( - IntersectionEventList* intersectionEventList, Line* l1, Line* l2, - IntersectionType intersectionType); - -// Deletes all the nodes in the list. -void IntersectionEventList_deleteNodes( - IntersectionEventList* intersectionEventList); - -#endif // INTERSECTIONEVENTLIST_H_ diff --git a/reducer_bench/quad_tree/line.h b/reducer_bench/quad_tree/line.h deleted file mode 100644 index dca7a371..00000000 --- a/reducer_bench/quad_tree/line.h +++ /dev/null @@ -1,111 +0,0 @@ -/** - * Copyright (c) 2012 the Massachusetts Institute of Technology - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - **/ - -// Two-dimensional lines -#ifndef LINE_H_ -#define LINE_H_ - -#include "./graphic_stuff.h" -#include "./vec.h" - -// Lines' coordinates are stored in a box with these bounds -// We choose box coordinates in [.5, 1) to simulate fixed -// point floating point accuracy to mitigate issues with -// associativity of coordinate updates -#define BOX_XMIN .5 -#define BOX_XMAX 1 -#define BOX_YMIN .5 -#define BOX_YMAX 1 - -// Graphics are displayed in a box of this size. -#define WINDOW_WIDTH 1180 -#define WINDOW_HEIGHT 800 - -typedef double window_dimension; -typedef vec_dimension box_dimension; - -// The allowable colors for a line. -typedef enum { - RED = 0, - GRAY = 1 -} Color; - -// A two-dimensional line. -struct Line { - Vec p1; // One endpoint of the line. - Vec p2; // The other endpoint of the line. - - /* - uint16_t xmin_cell; - uint16_t xmax_cell; - uint16_t ymin_cell; - uint16_t ymax_cell; - */ - - // The line's current velocity, in units of pixels per time step. - Vec velocity; - - // double length; - int ind; - - Color color; // The line's color. - - unsigned int id; // Unique line ID. -}; -typedef struct Line Line; - -// Compares the lines by line ID. -// -1 <=> line1 ordered before line2 -// 0 <=> line1 ordered the same as line2 -// 1 <=> line1 ordered after line2 -static inline int compareLines(Line *line1, Line *line2) { - if (line1->id < line2->id) { - return -1; - } else if (line1->id == line2->id) { - return 0; - } else { - return 1; - } -} - -// Convert graphical window coordinates to box coordinates. -static inline void windowToBox(box_dimension *xout, box_dimension *yout, - window_dimension x, window_dimension y) { - *xout = x / WINDOW_WIDTH * ((double) BOX_XMAX - BOX_XMIN) + BOX_XMIN; - *yout = y / WINDOW_HEIGHT * ((double) BOX_YMAX - BOX_YMIN) + BOX_YMIN; -} - -// Convert box coordinates to graphical window coordinates. -static inline void boxToWindow(window_dimension *xout, window_dimension *yout, - box_dimension x, box_dimension y) { - *xout = (x - BOX_XMIN) / ((double) BOX_XMAX - BOX_XMIN) * WINDOW_WIDTH; - *yout = (y - BOX_YMIN) / ((double) BOX_YMAX - BOX_YMIN) * WINDOW_HEIGHT; -} - -// Convert graphical window velocity to box velocity. -static inline void velocityWindowToBox(box_dimension *xout, box_dimension *yout, - window_dimension x, window_dimension y) { - *xout = x / WINDOW_WIDTH * ((double) BOX_XMAX - BOX_XMIN); - *yout = y / WINDOW_HEIGHT * ((double) BOX_YMAX - BOX_YMIN); -} - -#endif // LINE_H_ diff --git a/reducer_bench/quad_tree/line_demo.c b/reducer_bench/quad_tree/line_demo.c deleted file mode 100644 index 5d196f0e..00000000 --- a/reducer_bench/quad_tree/line_demo.c +++ /dev/null @@ -1,137 +0,0 @@ -/** - * LineDemo.c -- main driver for the line simulation - * Copyright (c) 2012 the Massachusetts Institute of Technology - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - **/ - -#include "./line_demo.h" - -#include -#include -#include -#include - -#include "./graphic_stuff.h" -#include "./line.h" - -static char* LineDemo_input_file_path; - -void LineDemo_setInputFile(char* input_file_path) { - LineDemo_input_file_path = input_file_path; -} - -LineDemo* LineDemo_new() { - LineDemo* lineDemo = malloc(sizeof(LineDemo)); - if (lineDemo == NULL) { - return NULL; - } - - lineDemo->count = 0; - lineDemo->numFrames = 0; - lineDemo->collisionWorld = NULL; - return lineDemo; -} - -void LineDemo_delete(LineDemo* lineDemo) { - CollisionWorld_delete(lineDemo->collisionWorld); - free(lineDemo); -} - -// Read in lines from line.in and add them into collision world for simulation. -void LineDemo_createLines(LineDemo* lineDemo) { - unsigned int lineId = 0; - unsigned int numOfLines; - window_dimension px1; - window_dimension py1; - window_dimension px2; - window_dimension py2; - window_dimension vx; - window_dimension vy; - int isGray; - FILE *fin; - fin = fopen(LineDemo_input_file_path, "r"); - if (fin == NULL) { - fprintf(stderr, "Input file not found (%s)\n", LineDemo_input_file_path); - exit(1); - } - - fscanf(fin, "%d\n", &numOfLines); - lineDemo->collisionWorld = CollisionWorld_new(numOfLines); - - while (EOF - != fscanf(fin, "(%lf, %lf), (%lf, %lf), %lf, %lf, %d\n", &px1, &py1, &px2, - &py2, &vx, &vy, &isGray)) { - Line *line = malloc(sizeof(Line)); - - // convert window coordinates to box coordinates - windowToBox(&line->p1.x, &line->p1.y, px1, py1); - windowToBox(&line->p2.x, &line->p2.y, px2, py2); - - // line->length = Vec_length(Vec_subtract(line->p1, line->p2)); - - // convert window velocity to box velocity - velocityWindowToBox(&line->velocity.x, &line->velocity.y, vx, vy); - - // store color - line->color = (Color) isGray; - - // store line ID - line->id = lineId; - lineId++; - - // transfer ownership of line to collisionWorld - CollisionWorld_addLine(lineDemo->collisionWorld, line); - } - fclose(fin); -} - -void LineDemo_setNumFrames(LineDemo* lineDemo, const unsigned int numFrames) { - lineDemo->numFrames = numFrames; -} - -void LineDemo_initLine(LineDemo* lineDemo) { - LineDemo_createLines(lineDemo); -} - -Line* LineDemo_getLine(LineDemo* lineDemo, const unsigned int index) { - return CollisionWorld_getLine(lineDemo->collisionWorld, index); -} - -unsigned int LineDemo_getNumOfLines(LineDemo* lineDemo) { - return CollisionWorld_getNumOfLines(lineDemo->collisionWorld); -} - -unsigned int LineDemo_getNumLineWallCollisions(LineDemo* lineDemo) { - return CollisionWorld_getNumLineWallCollisions(lineDemo->collisionWorld); -} - -unsigned int LineDemo_getNumLineLineCollisions(LineDemo* lineDemo) { - return CollisionWorld_getNumLineLineCollisions(lineDemo->collisionWorld); -} - -// The main simulation loop -bool LineDemo_update(LineDemo* lineDemo) { - lineDemo->count++; - CollisionWorld_updateLines(lineDemo->collisionWorld); - if (lineDemo->count > lineDemo->numFrames) { - return false; - } - return true; -} diff --git a/reducer_bench/quad_tree/line_demo.h b/reducer_bench/quad_tree/line_demo.h deleted file mode 100644 index fc9bba44..00000000 --- a/reducer_bench/quad_tree/line_demo.h +++ /dev/null @@ -1,71 +0,0 @@ -/** - * Copyright (c) 2012 the Massachusetts Institute of Technology - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - **/ - -// LineDemo.h -- main driver for the line simulation -#ifndef LINEDEMO_H_ -#define LINEDEMO_H_ - -#include "./line.h" -#include "./collision_world.h" - -struct LineDemo { - // Iteration counter - unsigned int count; - - // Number of frames to compute - unsigned int numFrames; - - // Objects for line simulation - CollisionWorld* collisionWorld; -}; -typedef struct LineDemo LineDemo; - -LineDemo* LineDemo_new(); -void LineDemo_delete(LineDemo* lineDemo); - -// Add lines for line simulation at beginning. -void LineDemo_createLines(LineDemo* lineDemo); - -// Set number of frames to compute. -void LineDemo_setNumFrames(LineDemo* lineDemo, const unsigned int numFrames); - -// Initialize line simulation. -void LineDemo_initLine(LineDemo* lineDemo); - -// Get ith line. -Line* LineDemo_getLine(LineDemo* lineDemo, const unsigned int index); - -// Get num of lines. -unsigned int LineDemo_getNumOfLines(LineDemo* lineDemo); - -// Get number of line-wall collisions. -unsigned int LineDemo_getNumLineWallCollisions(LineDemo* lineDemo); - -// Get number of line-line collisions. -unsigned int LineDemo_getNumLineLineCollisions(LineDemo* lineDemo); - -// Line simulation update function. -bool LineDemo_update(LineDemo* lineDemo); - -void LineDemo_setInputFile(char* input_file_path); - -#endif // LINEDEMO_H_ diff --git a/reducer_bench/quad_tree/qtree.c b/reducer_bench/quad_tree/qtree.c deleted file mode 100644 index 00b77697..00000000 --- a/reducer_bench/quad_tree/qtree.c +++ /dev/null @@ -1,232 +0,0 @@ -#include "./qtree.h" - - -#include "./vec.h" -#include "./line.h" -#include "./collision_world.h" -#include "./intersection_event_list.h" -#include "./intersection_detection.h" - -qtree * qtree_new(box_dimension xmin, box_dimension xmax, box_dimension ymin, box_dimension ymax, int depth) { - qtree * q = (qtree *)malloc(sizeof(qtree)); - q->xmin = xmin; - q->xmax = xmax; - q->ymin = ymin; - q->ymax = ymax; - - q->depth = depth; - q->cap = 0; - q->sz = 0; - - q->dat = NULL; - - q->ne = NULL; - q->nw = NULL; - q->se = NULL; - q->sw = NULL; - - // q->parent = NULL; - - return q; -} - -void qtree_free(qtree * q) { - if (q == NULL) return; - - free(q->dat); - - qtree_free(q->ne); - qtree_free(q->nw); - qtree_free(q->se); - qtree_free(q->sw); - - // qtree_free(q->parent); - - free(q); -} - - -uint8_t qtree_in(qtree * q, Vec p1, Vec p2, Vec p3, Vec p4) { - // We use < to deal with degenerate parallelograms lying on box boundaries - uint8_t ret = q->xmin < p1.x && p1.x < q->xmax && q->ymin < p1.y && p1.y < q->ymax && - q->xmin < p2.x && p2.x < q->xmax && q->ymin < p2.y && p2.y < q->ymax && - q->xmin < p3.x && p3.x < q->xmax && q->ymin < p3.y && p3.y < q->ymax && - q->xmin < p4.x && p4.x < q->xmax && q->ymin < p4.y && p4.y < q->ymax; - return ret; -} - -void qtree_add(qtree * q, ssize_t ind, CollisionWorld * cw) { - if(q->depth < MAX_DEPTH && q->ne == NULL && q->sz >= MAX_SIZE) qtree_split(q, cw); - - // Get the displacement parallelogram - Line * l = cw->lines[ind]; - Vec p1 = l->p1; - Vec p2 = l->p2; - Vec p3 = Vec_add(p1, Vec_multiply(l->velocity, cw->timeStep)); - Vec p4 = Vec_add(p2, Vec_multiply(l->velocity, cw->timeStep)); - - // Test variable for which quadrant it's in - uint8_t ne = (q->ne != NULL && qtree_in(q->ne, p1, p2, p3, p4)); - uint8_t nw = (q->nw != NULL && qtree_in(q->nw, p1, p2, p3, p4)); - uint8_t se = (q->se != NULL && qtree_in(q->se, p1, p2, p3, p4)); - uint8_t sw = (q->sw != NULL && qtree_in(q->sw, p1, p2, p3, p4)); - uint8_t test = (ne << 3) | (nw << 2) | (se << 1) | sw; - - switch(test) { - case 8: - qtree_add(q->ne, ind, cw); - break; - case 4: - qtree_add(q->nw, ind, cw); - break; - case 2: - qtree_add(q->se, ind, cw); - break; - case 1: - qtree_add(q->sw, ind, cw); - break; - default: - // Add to our list of lines - if (q->cap == q->sz) { - q->cap = (q->cap == 0) ? MAX_SIZE : 1 + 2 * q->cap; - q->dat = (ssize_t *)realloc(q->dat, q->cap * sizeof(ssize_t)); - } - q->dat[q->sz] = ind; - q->sz++; - break; - } -} - -void qtree_split(qtree * q, CollisionWorld * cw) { - box_dimension xmid = (q->xmin + q->xmax) / 2; - box_dimension ymid = (q->ymin + q->ymax) / 2; - int d = q->depth + 1; - - // Assuming q->ne et al are NULL - q->ne = qtree_new(xmid, q->xmax, ymid, q->ymax, d); - // q->ne->parent = q; - q->nw = qtree_new(xmid, q->xmax, q->ymin, ymid, d); - // q->nw->parent = q; - q->se = qtree_new(q->xmin, xmid, ymid, q->ymax, d); - // q->se->parent = q; - q->sw = qtree_new(q->xmin, xmid, q->ymin, ymid, d); - // q->sw->parent = q; - - // Iterate through lines in q; try to move them to q->ne et al - for(ssize_t i = q->sz - 1; i >= 0; i--) { - ssize_t ind = q->dat[i]; - - Line * l = cw->lines[ind]; - Vec p1 = l->p1; - Vec p2 = l->p2; - Vec p3 = Vec_add(p1, Vec_multiply(l->velocity, cw->timeStep)); - Vec p4 = Vec_add(p2, Vec_multiply(l->velocity, cw->timeStep)); - - uint8_t ne = (q->ne != NULL && qtree_in(q->ne, p1, p2, p3, p4)); - uint8_t nw = (q->nw != NULL && qtree_in(q->nw, p1, p2, p3, p4)); - uint8_t se = (q->se != NULL && qtree_in(q->se, p1, p2, p3, p4)); - uint8_t sw = (q->sw != NULL && qtree_in(q->sw, p1, p2, p3, p4)); - uint8_t test = (ne << 3) | (nw << 2) | (se << 1) | sw; - - switch(test) { - case 8: - qtree_add(q->ne, ind, cw); - // Swap the element to be removed with the last element - q->dat[i] ^= q->dat[q->sz - 1]; - q->dat[q->sz - 1] ^= q->dat[i]; - q->dat[i] ^= q->dat[q->sz - 1]; - // Make the new last element junk - q->sz--; - break; - case 4: - qtree_add(q->nw, ind, cw); - q->dat[i] ^= q->dat[q->sz - 1]; - q->dat[q->sz - 1] ^= q->dat[i]; - q->dat[i] ^= q->dat[q->sz - 1]; - q->sz--; - break; - case 2: - qtree_add(q->se, ind, cw); - q->dat[i] ^= q->dat[q->sz - 1]; - q->dat[q->sz - 1] ^= q->dat[i]; - q->dat[i] ^= q->dat[q->sz - 1]; - q->sz--; - break; - case 1: - qtree_add(q->sw, ind, cw); - q->dat[i] ^= q->dat[q->sz - 1]; - q->dat[q->sz - 1] ^= q->dat[i]; - q->dat[i] ^= q->dat[q->sz - 1]; - q->sz--; - break; - default: - break; - } - } - - // if q->dat is too large, free some space - if (q->sz < q->cap / 3 && q->cap > MAX_SIZE) { - q->cap = 1 + 2 * q->sz; - q->dat = (ssize_t *)realloc(q->dat, q->cap * sizeof(ssize_t)); - } -} - -unsigned int qtree_intersect(qtree * q, ssize_t * dats, ssize_t len, IntersectionEventList * iel, CollisionWorld * cw) { - unsigned int numLineLineCollisions = 0; - - // Test info in dats vs q->dat lines - for (ssize_t i = 0; i < len; i++) { - for (ssize_t j = 0; j < q->sz; j++) { - Line * l1 = cw->lines[dats[i]]; - Line * l2 = cw->lines[q->dat[j]]; - - if (compareLines(l1, l2) >= 0) { - Line *temp = l1; - l1 = l2; - l2 = temp; - } - - IntersectionType intersectionType = - intersect(l1, l2, cw->timeStep); - if (intersectionType != NO_INTERSECTION) { - IntersectionEventList_appendNode(iel, l1, l2, - intersectionType); - numLineLineCollisions++; - } - } - } - - // Test within q->dat for collisions - for (ssize_t i = 0; i < q->sz; i++) { - for (ssize_t j = i + 1; j < q->sz; j++) { - Line * l1 = cw->lines[q->dat[i]]; - Line * l2 = cw->lines[q->dat[j]]; - - if (compareLines(l1, l2) >= 0) { - Line *temp = l1; - l1 = l2; - l2 = temp; - } - - IntersectionType intersectionType = - intersect(l1, l2, cw->timeStep); - if (intersectionType != NO_INTERSECTION) { - IntersectionEventList_appendNode(iel, l1, l2, - intersectionType); - numLineLineCollisions++; - } - } - } - - for (ssize_t i = 0; i < q->sz; i++) { - dats[len + i] = q->dat[i]; - } - - // Recursions - if (q->ne != NULL) numLineLineCollisions += qtree_intersect(q->ne, dats, len + q->sz, iel, cw); - if (q->nw != NULL) numLineLineCollisions += qtree_intersect(q->nw, dats, len + q->sz, iel, cw); - if (q->se != NULL) numLineLineCollisions += qtree_intersect(q->se, dats, len + q->sz, iel, cw); - if (q->sw != NULL) numLineLineCollisions += qtree_intersect(q->sw, dats, len + q->sz, iel, cw); - - return numLineLineCollisions; -} diff --git a/reducer_bench/quad_tree/qtree.h b/reducer_bench/quad_tree/qtree.h deleted file mode 100644 index 942f7d8f..00000000 --- a/reducer_bench/quad_tree/qtree.h +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef QTREE_H_ -#define QTREE_H_ - -#ifndef MAX_SIZE -#define MAX_SIZE 3 -#endif - -#ifndef MAX_DEPTH -#define MAX_DEPTH 3000000 -#endif - - -#include -#include - -#include "./vec.h" -#include "./line.h" -#include "./collision_world.h" -#include "./intersection_event_list.h" - -// The quadtree data structure -struct qtree { - box_dimension xmin; - box_dimension xmax; - box_dimension ymin; - box_dimension ymax; - - int depth; - - // Info for the lines stored at this node - ssize_t cap; - ssize_t sz; - ssize_t * dat; - - struct qtree * ne; - struct qtree * nw; - struct qtree * se; - struct qtree * sw; - - // struct qtree * parent; -}; -typedef struct qtree qtree; - -// allocate a new qtree -qtree * qtree_new(box_dimension xmin, box_dimension xmax, box_dimension ymin, box_dimension ymax, int depth); - -// free a new qtree -void qtree_free(qtree * q); - -// See if p1 through p4 are within q's bounds. We treat p1 through p4 as a parallelogram -uint8_t qtree_in(qtree * q, Vec p1, Vec p2, Vec p3, Vec p4); - -// Add cw->lines[ind] to q -void qtree_add(qtree * q, ssize_t ind, CollisionWorld * cw); - -// Create the children of q and place q's lines in the children -void qtree_split(qtree * q, CollisionWorld * cw); - -// Find collisions in q; store them in iel. dats is used in the recursion to store lines from parents of q. -unsigned int qtree_intersect(qtree * q, ssize_t * dats, ssize_t len, IntersectionEventList * iel, CollisionWorld * cw); - -#endif diff --git a/reducer_bench/quad_tree/reducer_defs.c b/reducer_bench/quad_tree/reducer_defs.c deleted file mode 100644 index c53385ea..00000000 --- a/reducer_bench/quad_tree/reducer_defs.c +++ /dev/null @@ -1,23 +0,0 @@ -#include "./reducer_defs.h" - -// Evaluates *left = *left OPERATOR *right -void IEL_merge(IntersectionEventList * left, IntersectionEventList * right) { - if (right->head == NULL) return; - if (left->head == NULL) left->head = right->head; - else left->tail->next = right->head; - left->tail = right->tail; - left->size += right->size; -} - -// Evaluates *left = *left OPERATOR *right -void IEL_list_reduce(void * key, void * left, void * right) { - IEL_merge((IntersectionEventList *)left, (IntersectionEventList *)right); -} - -// Sets *value to the the identity value. -void IEL_list_identity(void* key, void* value) { - IntersectionEventList * v = (IntersectionEventList *)value; - v->head = NULL; - v->tail = NULL; - v->size = 0; -} diff --git a/reducer_bench/quad_tree/reducer_defs.h b/reducer_bench/quad_tree/reducer_defs.h deleted file mode 100644 index 62df0432..00000000 --- a/reducer_bench/quad_tree/reducer_defs.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef REDUCER_DEFS_H_ -#define REDUCER_DEFS_H_ - -#include -#include -#include - -#include "./line.h" -#include "./intersection_event_list.h" -#include "./intersection_detection.h" - -//----- IntersectionEventList - -// Evaluates *left = *left OPERATOR *right -void IEL_merge(IntersectionEventList * left, IntersectionEventList * right); - -// Evaluates *left = *left OPERATOR *right -void IEL_list_reduce(void * key, void * left, void * right); - -// Sets *value to the the identity value. -void IEL_list_identity(void* key, void* value); - - - -typedef CILK_C_DECLARE_REDUCER(IntersectionEventList) IELReducer; - -#define IEL_RED CILK_C_INIT_REDUCER(IntersectionEventList, IEL_list_reduce, IEL_list_identity, 0, (IntersectionEventList) { .head = NULL, .tail = NULL }) - -//----- unsigned int - -#define UINT_RED(name) CILK_C_REDUCER_OPADD(name, int, 0) - -//----- Misc. - -#define REGRED(name) CILK_C_REGISTER_REDUCER(name) - -#define REDVAL(name) REDUCER_VIEW(name) - -#define KILLRED(name) CILK_C_UNREGISTER_REDUCER(name) - -#endif diff --git a/reducer_bench/quad_tree/screensaver.c b/reducer_bench/quad_tree/screensaver.c deleted file mode 100644 index 40ccf465..00000000 --- a/reducer_bench/quad_tree/screensaver.c +++ /dev/null @@ -1,132 +0,0 @@ -/** - * Copyright (c) 2012 the Massachusetts Institute of Technology - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - **/ - -#include -#include -#include -#include - -#include "./fasttime.h" -#include "./line.h" -#include "./line_demo.h" - -// The PROFILE_BUILD preprocessor define is used to indicate we are building for -// profiling, so don't include any graphics or Cilk functions. -#ifndef PROFILE_BUILD -#include "./graphic_stuff.h" -#endif -static char* DEFAULT_INPUT_FILE_PATH = "input/mit.in"; -static char* input_file_path; - -// For non-graphic version -void lineMain(LineDemo *lineDemo) { - // Loop for updating line movement simulation - while (true) { - if (!LineDemo_update(lineDemo)) { - break; - } - } -} - -int main(int argc, char *argv[]) { - int optchar; -#ifndef PROFILE_BUILD - bool graphicDemoFlag = false; -#endif - unsigned int numFrames = 1; - extern int optind; - - // Process command line options. - while ((optchar = getopt(argc, argv, "gi")) != -1) { - switch (optchar) { - case 'g': -#ifndef PROFILE_BUILD - graphicDemoFlag = true; -#endif - break; - default: - printf("Ignoring unrecognized option: %c\n", optchar); - continue; - } - } - - // Shift remaining arguments over. - int remaining_args = argc - optind; - for (int i = 1; i <= remaining_args; i++) { - argv[i] = argv[i + optind - 1]; - } - - // Check to make sure number of arguments is correct. - if (remaining_args < 1) { - printf("Usage: %s [-g] [inputfile]\n", argv[0]); - printf(" -g : show graphics\n"); - exit(-1); - } - - numFrames = atoi(argv[1]); - printf("Number of frames = %u\n", numFrames); - - if (remaining_args > 1) { - input_file_path = argv[2]; - } else { - input_file_path = DEFAULT_INPUT_FILE_PATH; - } - printf("Input file path is: %s\n", input_file_path); - - // Create and initialize the Line simulation environment. - LineDemo *lineDemo = LineDemo_new(); - LineDemo_setInputFile(input_file_path); - LineDemo_initLine(lineDemo); - LineDemo_setNumFrames(lineDemo, numFrames); - - const fasttime_t start_time = gettime(); - -#ifndef PROFILE_BUILD - // Run demo. - if (graphicDemoFlag) { - graphicMain(argc, argv, lineDemo, false); - } else { - lineMain(lineDemo); - } -#else - lineMain(lineDemo); -#endif - - const fasttime_t end_time = gettime(); - - // Output results. - printf("---- RESULTS ----\n"); - printf("Elapsed execution time: %fs\n", - tdiff(start_time, end_time)); - printf("%u Line-Wall Collisions\n", - LineDemo_getNumLineWallCollisions(lineDemo)); - printf("%u Line-Line Collisions\n", - LineDemo_getNumLineLineCollisions(lineDemo)); - printf("---- END RESULTS ----\n"); - - // delete objects - LineDemo_delete(lineDemo); -#ifdef CILKSCALE -cilk_tool_print(); -#endif - return 0; -} diff --git a/reducer_bench/quad_tree/vec.c b/reducer_bench/quad_tree/vec.c deleted file mode 100644 index a5f21998..00000000 --- a/reducer_bench/quad_tree/vec.c +++ /dev/null @@ -1,102 +0,0 @@ -/** - * Copyright (c) 2012 the Massachusetts Institute of Technology - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - **/ - -#include "./vec.h" - -#include - -#include "./line.h" - -Vec Vec_make(const vec_dimension x, const vec_dimension y) { - Vec vector; - vector.x = x; - vector.y = y; - return vector; -} - -Vec Vec_makeFromLine(struct Line line) { - return Vec_subtract(line.p1, line.p2); -} - -// ************************* Fundamental attributes ************************** - -vec_dimension Vec_length(Vec vector) { - return hypot(vector.x, vector.y); -} - -double Vec_argument(Vec vector) { - return atan2(vector.y, vector.x); -} - -// **************************** Related vectors ****************************** - -Vec Vec_normalize(Vec vector) { - return Vec_divide(vector, Vec_length(vector)); -} - -Vec Vec_orthogonal(Vec vector) { - return Vec_make(-vector.y, vector.x); -} - -// ******************** Relationships with other vectors ********************* - -double Vec_angle(Vec vector1, Vec vector2) { - return Vec_argument(vector1) - Vec_argument(vector2); -} - -vec_dimension Vec_component(Vec vector1, Vec vector2) { - return Vec_length(vector1) * cos(Vec_angle(vector1, vector2)); -} - -Vec Vec_projectOnto(Vec vector1, Vec vector2) { - return Vec_multiply(Vec_normalize(vector2), Vec_component(vector1, vector2)); -} - -// ******************************* Arithmetic ******************************** - -bool Vec_equals(Vec lhs, Vec rhs) { - return lhs.x == rhs.x && lhs.y == rhs.y; -} - -Vec Vec_add(Vec lhs, Vec rhs) { - return Vec_make(lhs.x + rhs.x, lhs.y + rhs.y); -} - -Vec Vec_subtract(Vec lhs, Vec rhs) { - return Vec_make(lhs.x - rhs.x, lhs.y - rhs.y); -} - -Vec Vec_multiply(Vec vector, const double scalar) { - return Vec_make(vector.x * scalar, vector.y * scalar); -} - -Vec Vec_divide(Vec vector, const double scalar) { - return Vec_make(vector.x / scalar, vector.y / scalar); -} - -vec_dimension Vec_dotProduct(Vec lhs, Vec rhs) { - return lhs.x * rhs.x + lhs.y * rhs.y; -} - -vec_dimension Vec_crossProduct(Vec lhs, Vec rhs) { - return lhs.x * rhs.y - lhs.y * rhs.x; -} diff --git a/reducer_bench/quad_tree/vec.h b/reducer_bench/quad_tree/vec.h deleted file mode 100644 index 434f7bc4..00000000 --- a/reducer_bench/quad_tree/vec.h +++ /dev/null @@ -1,82 +0,0 @@ -/** - * Copyright (c) 2012 the Massachusetts Institute of Technology - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - **/ - -// Simple 2D vector library -#ifndef VEC_H_ -#define VEC_H_ - -#include - -typedef double vec_dimension; - -// Forward definition of Line to avoid needing to circularly include Line.h -struct Line; - -// A two-dimensional vector. -struct Vec { - vec_dimension x; // The x-coordinate of the vector. - vec_dimension y; // The y-coordinate of the vector. -}; -typedef struct Vec Vec; - -// Returns a vector with the specified x and y coordinates. -Vec Vec_make(const vec_dimension x, const vec_dimension y); - -// Returns a vector parallel to the provided Line. The direction of the -// vector is unspecified. -Vec Vec_makeFromLine(struct Line line); - -// Returns the magnitude of the vector. -vec_dimension Vec_length(Vec vector); - -// Returns the argument of the vector - that is, the angle it makes with the -// positive x axis. Units are radians. -double Vec_argument(Vec vector); - -// Returns a unit vector parallel to the vector. -Vec Vec_normalize(Vec vector); - -// Returns a vector identical in magnitude and perpendicular to the vector. -Vec Vec_orthogonal(Vec vector); - -// Computes the angle between vector1 and vector2. -double Vec_angle(Vec vector1, Vec vector2); - -// Computes the scalar component of vector1 onto vector2. -vec_dimension Vec_component(Vec vector1, Vec vector2); - -// Returns the vector projection of vector1 onto vector2. -Vec Vec_projectOnto(Vec vector1, Vec vector2); - -bool Vec_equals(Vec lhs, Vec rhs); -Vec Vec_add(Vec lhs, Vec rhs); -Vec Vec_subtract(Vec lhs, Vec rhs); -Vec Vec_multiply(Vec vector, const double scalar); -Vec Vec_divide(Vec vector, const double scalar); - -// Computes the dot product of two vectors. -vec_dimension Vec_dotProduct(Vec lhs, Vec rhs); - -// Computes the magnitude of the cross product of two vectors. -vec_dimension Vec_crossProduct(Vec lhs, Vec rhs); - -#endif // VEC_H_ diff --git a/reducer_bench/repeatedintsum.c b/reducer_bench/repeatedintsum.c deleted file mode 100644 index 57f1a428..00000000 --- a/reducer_bench/repeatedintsum.c +++ /dev/null @@ -1,59 +0,0 @@ -#include -#include -#include -#include - -#include "ktiming.h" - -void identity_intsum(void *reducer, void *sum) { *((int *)sum) = 0; } - -void reduce_intsum(void *reducer, void *left, void *right) { - *((int *)left) += *((int *)right); -} - -CILK_C_DECLARE_REDUCER(int) -my_int_sum_reducer = CILK_C_INIT_REDUCER(int, reduce_intsum, identity_intsum, - 0, 0); - -void compute_sum(int limit) { - for (int i = 0; i < limit; i++) { - REDUCER_VIEW(my_int_sum_reducer) += 1; - } -} - -void test_reducer(int limit) { - cilk_spawn compute_sum(limit); - compute_sum(limit); - cilk_sync; -} - -int main(int argc, const char **args) { - int i; - int n, res = 0; - clockmark_t begin, end; - uint64_t running_time[TIMING_COUNT * 200]; - - if (argc != 2) { - fprintf(stderr, "Usage: ilist_dac [] \n"); - exit(1); - } - - n = atoi(args[1]); - - for (i = 0; i < TIMING_COUNT * 200; i++) { - begin = ktiming_getmark(); - CILK_C_REGISTER_REDUCER(my_int_sum_reducer); - *(&REDUCER_VIEW(my_int_sum_reducer)) = 0; - test_reducer(n); - int sum = REDUCER_VIEW(my_int_sum_reducer); - res += (sum == 2 * n) ? 1 : 0; - CILK_C_UNREGISTER_REDUCER(my_int_sum_reducer); - end = ktiming_getmark(); - // printf("The final sum is %d\n", sum); - running_time[i] = ktiming_diff_nsec(&begin, &end); - } - printf("Result: %d/%d successes!\n", res, TIMING_COUNT * 200); - // print_runtime(running_time, TIMING_COUNT); - - return 0; -} diff --git a/reducer_bench/serialsum.c b/reducer_bench/serialsum.c deleted file mode 100644 index 63e080fd..00000000 --- a/reducer_bench/serialsum.c +++ /dev/null @@ -1,49 +0,0 @@ -#include -#include -#include -#include - -#include "ktiming.h" - -volatile int my_int_sum = 0; - -void compute_sum(int limit) { - for (int i = 0; i < limit; i++) { - my_int_sum += 1; - } -} - -void test_reducer(int limit) { - cilk_spawn compute_sum(limit); - compute_sum(limit); - cilk_sync; -} - -int main(int argc, const char **args) { - int i; - int n, res = 0; - clockmark_t begin, end; - uint64_t running_time[TIMING_COUNT]; - - if (argc != 2) { - fprintf(stderr, "Usage: ilist_dac [] \n"); - exit(1); - } - - n = atoi(args[1]); - - for (i = 0; i < TIMING_COUNT; i++) { - begin = ktiming_getmark(); - my_int_sum = 0; - test_reducer(n); - int sum = my_int_sum; - res += (sum == 2 * n) ? 1 : 0; - end = ktiming_getmark(); - // printf("The final sum is %d\n", sum); - running_time[i] = ktiming_diff_nsec(&begin, &end); - } - printf("Result: %d/%d successes!\n", res, TIMING_COUNT); - print_runtime(running_time, TIMING_COUNT); - - return 0; -} diff --git a/reducer_bench/setup.sh b/reducer_bench/setup.sh deleted file mode 100755 index 6211ce8b..00000000 --- a/reducer_bench/setup.sh +++ /dev/null @@ -1,29 +0,0 @@ -#!/bin/bash - -#NOTE(TFK): You'll need this if you use GCC. - -export TAPIR_PREFIX=/efs/tools/tapir-csi/src/build - -export PATH=$TAPIR_PREFIX/bin:/efs/tools/protobuf_c4/bin:$PATH - -export CXX=clang++ -export OPENCV_ROOT=/efs/tools/OpenCV3 - -export LD_LIBRARY_PATH=$TAPIR_PREFIX/lib:$OPENCV_ROOT/lib:$LD_LIBRARY_PATH:/usr/local/lib -export OMP_NUM_THREADS=1 -#export EXTRA_CFLAGS="-fcilkplus -Wall" #-Werror" - -export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/efs/home/tfk/archive-linux/lib/:/usr/lib/x86_64-linux-gnu/:/efs/home/tfk/easyjit/build/bin/:$TAPIR_PREFIX/lib:$TAPIR_PREFIX/tools/clang/lib - -#export CPATH=$CPATH:/efs/home/tfk/archive-linux/lib - -#export LD_PRELOAD=/efs/tools/jemalloc/lib/libjemalloc.so - -#export N_TEMPORARY_BYTES=500000000 - -# for wheatman stuff. -export PYTHONPATH=$PYTHONPATH:/efs/python_local/lib/python2.7/site-packages -export LD_LIBRARY_PATH=/efs/tools/protobuf_c4/lib:$LD_LIBRARY_PATH - -mkdir -p build -$@ diff --git a/runtime/CMakeLists.txt b/runtime/CMakeLists.txt index 5c185dea..42235995 100644 --- a/runtime/CMakeLists.txt +++ b/runtime/CMakeLists.txt @@ -6,16 +6,13 @@ set(CHEETAH_SOURCES cilk2c.c cilk2c_inlined.c cilkred_map.c - closure.c debug.c fiber.c fiber-pool.c global.c init.c internal-malloc.c - mutex.c personality.c - readydeque.c reducer_impl.c sched_stats.c scheduler.c @@ -39,16 +36,20 @@ set(CHEETAH_PERSONALITY_CPP_SOURCES personality-cpp.c ) -include_directories(${CHEETAH_SOURCE_DIR}/include) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) -add_library_flags_if(CHEETAH_HAS_PTHREAD_LIB pthread) +# Add dependent libraries +append_list_if(CHEETAH_HAS_PTHREAD_LIB pthread CHEETAH_COMMON_LIBS) +append_list_if(CHEETAH_HAS_DL_LIB dl CHEETAH_COMMON_LIBS) if (CHEETAH_USE_COMPILER_RT) find_compiler_rt_library(builtins CHEETAH_BUILTINS_LIBRARY) - add_library_flags_if(CHEETAH_BUILTINS_LIBRARY "${CHEETAH_BUILTINS_LIBRARY}") + append_list_if(CHEETAH_BUILTINS_LIBRARY "${CHEETAH_BUILTINS_LIBRARY}" CHEETAH_COMMON_LIBS) else() - add_library_flags_if(CHEETAH_HAS_GCC_S_LIB gcc_s) + append_list_if(CHEETAH_HAS_GCC_S_LIB gcc_s CHEETAH_COMMON_LIBS) endif() +set(CHEETAH_DYNAMIC_LIBS ${CHEETAH_COMMON_LIBS}) + add_flags_if_supported(-g3) add_flags_if_supported(-Wno-covered-switch-default) if (CHEETAH_HAS_FOMIT_FRAME_POINTER_FLAG) @@ -72,251 +73,474 @@ set(CHEETAH_BITCODE_ABI_COMPILE_DEFS ${CHEETAH_COMPILE_DEFS} set(CHEETAH_BITCODE_PEDIGREE_ABI_COMPILE_DEFS ${CHEETAH_BITCODE_ABI_COMPILE_DEFS} "ENABLE_CILKRTS_PEDIGREE=1") +# Set compile flags, compile defs, and link flags for ASan build +set(CHEETAH_ASAN_COMPILE_FLAGS ${CHEETAH_COMPILE_FLAGS}) +set(CHEETAH_ASAN_COMPILE_DEFS ${CHEETAH_COMPILE_DEFS} "CILK_ENABLE_ASAN_HOOKS=1") +set(CHEETAH_ASAN_LINK_FLAGS ${CHEETAH_LINK_FLAGS} -fsanitize=address) +set(CHEETAH_BITCODE_ABI_ASAN_COMPILE_FLAGS ${CHEETAH_BITCODE_ABI_COMPILE_FLAGS}) +set(CHEETAH_BITCODE_ABI_ASAN_COMPILE_DEFS ${CHEETAH_BITCODE_ABI_COMPILE_DEFS} + "CILK_ENABLE_ASAN_HOOKS=1") +set(CHEETAH_BITCODE_PEDIGREE_ABI_ASAN_COMPILE_DEFS + ${CHEETAH_BITCODE_PEDIGREE_ABI_COMPILE_DEFS} + "CILK_ENABLE_ASAN_HOOKS=1") + +set(CHEETAH_BUILD_ASAN_VER OFF) +if (CHEETAH_ENABLE_ASAN AND (CHEETAH_HAS_ASAN OR TARGET asan)) + set(CHEETAH_BUILD_ASAN_VER ON) +endif() + # Add compile flags for Cheetah-runtime compilation that should be # excluded from bitcode compilation if (CHEETAH_HAS_MAVX_FLAG) list(APPEND CHEETAH_COMPILE_FLAGS -mavx) endif() -if (CHEETAH_HAS_MARCH_SANDYBRIDGE_FLAG) - list(APPEND CHEETAH_COMPILER_FLAGS -march=sandybridge) -endif() - -split_list(CHEETAH_COMPILE_FLAGS) -split_list(CHEETAH_LINK_FLAGS) -split_list(CHEETAH_BITCODE_ABI_COMPILE_FLAGS) - -# Build the shared library. -if (CHEETAH_ENABLE_SHARED) - add_library(cheetah_shared SHARED ${CHEETAH_SOURCES}) - target_link_libraries(cheetah_shared ${CHEETAH_LIBRARIES}) - set_target_properties(cheetah_shared - PROPERTIES - COMPILE_FLAGS "${CHEETAH_COMPILE_FLAGS}" - COMPILE_DEFINITIONS "${CHEETAH_COMPILE_DEFS}" - LINK_FLAGS "${CHEETAH_LINK_FLAGS}" - OUTPUT_NAME "opencilk" - VERSION "${CHEETAH_ABI_VERSION}.0" - SOVERSION "${CHEETAH_ABI_VERSION}" - ) - target_compile_options(cheetah_shared PUBLIC "$<$:${CHEETAH_DEBUG_OPTIONS}>") - target_compile_options(cheetah_shared PUBLIC "$<$:${CHEETAH_RELEASE_OPTIONS}>") - list(APPEND CHEETAH_BUILD_TARGETS "cheetah_shared") - if (CHEETAH_INSTALL_SHARED_LIBRARY) - list(APPEND CHEETAH_INSTALL_TARGETS "cheetah_shared") - endif() - - # Build the shared libraries for personality functions - add_library(cheetah_personality_c_shared SHARED ${CHEETAH_PERSONALITY_C_SOURCES}) - target_link_libraries(cheetah_personality_c_shared ${CHEETAH_LIBRARIES}) - set_target_properties(cheetah_personality_c_shared - PROPERTIES - COMPILE_FLAGS "${CHEETAH_COMPILE_FLAGS}" - COMPILE_DEFINITIONS "${CHEETAH_COMPILE_DEFS}" - LINK_FLAGS "${CHEETAH_LINK_FLAGS}" - OUTPUT_NAME "opencilk-personality-c" - ) - target_compile_options(cheetah_personality_c_shared PUBLIC "$<$:${CHEETAH_DEBUG_OPTIONS}>") - target_compile_options(cheetah_personality_c_shared PUBLIC "$<$:${CHEETAH_RELEASE_OPTIONS}>") - list(APPEND CHEETAH_BUILD_TARGETS "cheetah_personality_c_shared") - if (CHEETAH_INSTALL_SHARED_LIBRARY) - list(APPEND CHEETAH_INSTALL_TARGETS "cheetah_personality_c_shared") - endif() - add_library(cheetah_personality_cpp_shared SHARED ${CHEETAH_PERSONALITY_CPP_SOURCES}) - target_link_libraries(cheetah_personality_cpp_shared ${CHEETAH_LIBRARIES}) - set_target_properties(cheetah_personality_cpp_shared - PROPERTIES - COMPILE_FLAGS "${CHEETAH_COMPILE_FLAGS}" - COMPILE_DEFINITIONS "${CHEETAH_COMPILE_DEFS}" - LINK_FLAGS "${CHEETAH_LINK_FLAGS}" - OUTPUT_NAME "opencilk-personality-cpp" - ) - target_compile_options(cheetah_personality_cpp_shared PUBLIC "$<$:${CHEETAH_DEBUG_OPTIONS}>") - target_compile_options(cheetah_personality_cpp_shared PUBLIC "$<$:${CHEETAH_RELEASE_OPTIONS}>") - list(APPEND CHEETAH_BUILD_TARGETS "cheetah_personality_cpp_shared") - if (CHEETAH_INSTALL_SHARED_LIBRARY) - list(APPEND CHEETAH_INSTALL_TARGETS "cheetah_personality_cpp_shared") +if (APPLE) + add_cheetah_bitcode(opencilk-abi + OS ${CHEETAH_SUPPORTED_OS} + ARCHS ${CHEETAH_SUPPORTED_ARCH} + SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/${CHEETAH_ABI_SOURCE} + CFLAGS ${CHEETAH_BITCODE_ABI_COMPILE_FLAGS} + DEFS ${CHEETAH_BITCODE_ABI_COMPILE_DEFS} + PARENT_TARGET cheetah) + + add_cheetah_bitcode(opencilk-pedigrees-abi + OS ${CHEETAH_SUPPORTED_OS} + ARCHS ${CHEETAH_SUPPORTED_ARCH} + SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/${CHEETAH_ABI_SOURCE} + CFLAGS ${CHEETAH_BITCODE_ABI_COMPILE_FLAGS} + DEFS ${CHEETAH_BITCODE_PEDIGREE_ABI_COMPILE_DEFS} + PARENT_TARGET cheetah) + + if (CHEETAH_BUILD_ASAN_VER) + add_cheetah_bitcode(opencilk-asan-abi + OS ${CHEETAH_SUPPORTED_OS} + ARCHS ${CHEETAH_SUPPORTED_ARCH} + SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/${CHEETAH_ABI_SOURCE} + CFLAGS ${CHEETAH_BITCODE_ABI_ASAN_COMPILE_FLAGS} + DEFS ${CHEETAH_BITCODE_ABI_ASAN_COMPILE_DEFS} + PARENT_TARGET cheetah) + + add_cheetah_bitcode(opencilk-pedigrees-asan-abi + OS ${CHEETAH_SUPPORTED_OS} + ARCHS ${CHEETAH_SUPPORTED_ARCH} + SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/${CHEETAH_ABI_SOURCE} + CFLAGS ${CHEETAH_BITCODE_ABI_ASAN_COMPILE_FLAGS} + DEFS ${CHEETAH_BITCODE_PEDIGREE_ABI_ASAN_COMPILE_DEFS} + PARENT_TARGET cheetah) endif() - add_library(cheetah_pedigree_globals_shared SHARED ${CHEETAH_PEDIGREE_GLOBALS_SOURCES}) - target_link_libraries(cheetah_pedigree_globals_shared ${CHEETAH_LIBRARIES}) - set_target_properties(cheetah_pedigree_globals_shared - PROPERTIES - COMPILE_FLAGS "${CHEETAH_COMPILE_FLAGS}" - COMPILE_DEFINITIONS "${CHEETAH_COMPILE_DEFS}" - LINK_FLAGS "${CHEETAH_LINK_FLAGS}" - OUTPUT_NAME "opencilk-pedigrees" - VERSION "${CHEETAH_ABI_VERSION}.0" - SOVERSION "${CHEETAH_ABI_VERSION}" - ) - target_compile_options(cheetah_pedigree_globals_shared PUBLIC "$<$:${CHEETAH_DEBUG_OPTIONS}>") - target_compile_options(cheetah_pedigree_globals_shared PUBLIC "$<$:${CHEETAH_RELEASE_OPTIONS}>") - list(APPEND CHEETAH_BUILD_TARGETS "cheetah_pedigree_globals_shared") - if (CHEETAH_INSTALL_SHARED_LIBRARY) - list(APPEND CHEETAH_INSTALL_TARGETS "cheetah_pedigree_globals_shared") - endif() - -endif() - -# Build the static library. -if (CHEETAH_ENABLE_STATIC) - add_library(cheetah_static STATIC ${CHEETAH_SOURCES}) - target_link_libraries(cheetah_static ${CHEETAH_LIBRARIES}) - set(CMAKE_STATIC_LIBRARY_PREFIX "lib") - set_target_properties(cheetah_static - PROPERTIES - COMPILE_FLAGS "${CHEETAH_COMPILE_FLAGS}" - COMPILE_DEFINITIONS "${CHEETAH_COMPILE_DEFS}" - LINK_FLAGS "${CHEETAH_LINK_FLAGS}" - OUTPUT_NAME "opencilk" - ) - target_compile_options(cheetah_static PUBLIC "$<$:${CHEETAH_DEBUG_OPTIONS}>") - target_compile_options(cheetah_static PUBLIC "$<$:${CHEETAH_RELEASE_OPTIONS}>") - list(APPEND CHEETAH_BUILD_TARGETS "cheetah_static") - if (CHEETAH_INSTALL_STATIC_LIBRARY) - list(APPEND CHEETAH_INSTALL_TARGETS "cheetah_static") - endif() - - # Build the static libraries for personality functions - add_library(cheetah_personality_c_static STATIC ${CHEETAH_PERSONALITY_C_SOURCES}) - target_link_libraries(cheetah_personality_c_static ${CHEETAH_LIBRARIES}) - set_target_properties(cheetah_personality_c_static - PROPERTIES - COMPILE_FLAGS "${CHEETAH_COMPILE_FLAGS}" - COMPILE_DEFINITIONS "${CHEETAH_COMPILE_DEFS}" - LINK_FLAGS "${CHEETAH_LINK_FLAGS}" - OUTPUT_NAME "opencilk-personality-c" - ) - target_compile_options(cheetah_personality_c_static PUBLIC "$<$:${CHEETAH_DEBUG_OPTIONS}>") - target_compile_options(cheetah_personality_c_static PUBLIC "$<$:${CHEETAH_RELEASE_OPTIONS}>") - list(APPEND CHEETAH_BUILD_TARGETS "cheetah_personality_c_static") - if (CHEETAH_INSTALL_SHARED_LIBRARY) - list(APPEND CHEETAH_INSTALL_TARGETS "cheetah_personality_c_static") - endif() - - add_library(cheetah_personality_cpp_static STATIC ${CHEETAH_PERSONALITY_CPP_SOURCES}) - target_link_libraries(cheetah_personality_cpp_static ${CHEETAH_LIBRARIES}) - set_target_properties(cheetah_personality_cpp_static - PROPERTIES - COMPILE_FLAGS "${CHEETAH_COMPILE_FLAGS}" - COMPILE_DEFINITIONS "${CHEETAH_COMPILE_DEFS}" - LINK_FLAGS "${CHEETAH_LINK_FLAGS}" - OUTPUT_NAME "opencilk-personality-cpp" - ) - target_compile_options(cheetah_personality_cpp_static PUBLIC "$<$:${CHEETAH_DEBUG_OPTIONS}>") - target_compile_options(cheetah_personality_cpp_static PUBLIC "$<$:${CHEETAH_RELEASE_OPTIONS}>") - list(APPEND CHEETAH_BUILD_TARGETS "cheetah_personality_cpp_static") - if (CHEETAH_INSTALL_SHARED_LIBRARY) - list(APPEND CHEETAH_INSTALL_TARGETS "cheetah_personality_cpp_static") - endif() -endif() + if (CHEETAH_ENABLE_SHARED) + add_cheetah_runtime(opencilk + SHARED + OS ${CHEETAH_SUPPORTED_OS} + ARCHS ${CHEETAH_SUPPORTED_ARCH} + SOURCES ${CHEETAH_SOURCES} + CFLAGS ${CHEETAH_COMPILE_FLAGS} + LINK_FLAGS ${CHEETAH_LINK_FLAGS} + LINK_LIBS ${CHEETAH_DYNAMIC_LIBS} + DEFS ${CHEETAH_COMPILE_DEFS} + VERSION "${CHEETAH_ABI_VERSION}.0" + SOVERSION ${CHEETAH_ABI_VERSION} + PARENT_TARGET cheetah) + + add_cheetah_runtime(opencilk-personality-c + SHARED + OS ${CHEETAH_SUPPORTED_OS} + ARCHS ${CHEETAH_SUPPORTED_ARCH} + SOURCES ${CHEETAH_PERSONALITY_C_SOURCES} + CFLAGS ${CHEETAH_COMPILE_FLAGS} + LINK_FLAGS ${CHEETAH_LINK_FLAGS} + LINK_LIBS ${CHEETAH_DYNAMIC_LIBS} + DEFS ${CHEETAH_COMPILE_DEFS} + VERSION "${CHEETAH_ABI_VERSION}.0" + SOVERSION ${CHEETAH_ABI_VERSION} + PARENT_TARGET cheetah) + + add_cheetah_runtime(opencilk-personality-cpp + SHARED + OS ${CHEETAH_SUPPORTED_OS} + ARCHS ${CHEETAH_SUPPORTED_ARCH} + SOURCES ${CHEETAH_PERSONALITY_CPP_SOURCES} + CFLAGS ${CHEETAH_COMPILE_FLAGS} + LINK_FLAGS ${CHEETAH_LINK_FLAGS} + LINK_LIBS ${CHEETAH_DYNAMIC_LIBS} + DEFS ${CHEETAH_COMPILE_DEFS} + VERSION "${CHEETAH_ABI_VERSION}.0" + SOVERSION ${CHEETAH_ABI_VERSION} + PARENT_TARGET cheetah) + + add_cheetah_runtime(opencilk-pedigrees + SHARED + OS ${CHEETAH_SUPPORTED_OS} + ARCHS ${CHEETAH_SUPPORTED_ARCH} + SOURCES ${CHEETAH_PEDIGREE_GLOBALS_SOURCES} + CFLAGS ${CHEETAH_COMPILE_FLAGS} + LINK_FLAGS ${CHEETAH_LINK_FLAGS} + LINK_LIBS ${CHEETAH_DYNAMIC_LIBS} + DEFS ${CHEETAH_COMPILE_DEFS} + VERSION "${CHEETAH_ABI_VERSION}.0" + SOVERSION ${CHEETAH_ABI_VERSION} + PARENT_TARGET cheetah) + if (CHEETAH_BUILD_ASAN_VER) + add_cheetah_runtime(opencilk-asan + SHARED + OS ${CHEETAH_SUPPORTED_OS} + ARCHS ${CHEETAH_SUPPORTED_ARCH} + SOURCES ${CHEETAH_SOURCES} + CFLAGS ${CHEETAH_ASAN_COMPILE_FLAGS} + LINK_FLAGS ${CHEETAH_ASAN_LINK_FLAGS} + LINK_LIBS ${CHEETAH_DYNAMIC_LIBS} + DEFS ${CHEETAH_ASAN_COMPILE_DEFS} + VERSION "${CHEETAH_ABI_VERSION}.0" + SOVERSION ${CHEETAH_ABI_VERSION} + PARENT_TARGET cheetah) + + add_cheetah_runtime(opencilk-asan-personality-c + SHARED + OS ${CHEETAH_SUPPORTED_OS} + ARCHS ${CHEETAH_SUPPORTED_ARCH} + SOURCES ${CHEETAH_PERSONALITY_C_SOURCES} + CFLAGS ${CHEETAH_ASAN_COMPILE_FLAGS} + LINK_FLAGS ${CHEETAH_ASAN_LINK_FLAGS} + LINK_LIBS ${CHEETAH_DYNAMIC_LIBS} + DEFS ${CHEETAH_ASAN_COMPILE_DEFS} + VERSION "${CHEETAH_ABI_VERSION}.0" + SOVERSION ${CHEETAH_ABI_VERSION} + PARENT_TARGET cheetah) + + add_cheetah_runtime(opencilk-asan-personality-cpp + SHARED + OS ${CHEETAH_SUPPORTED_OS} + ARCHS ${CHEETAH_SUPPORTED_ARCH} + SOURCES ${CHEETAH_PERSONALITY_CPP_SOURCES} + CFLAGS ${CHEETAH_ASAN_COMPILE_FLAGS} + LINK_FLAGS ${CHEETAH_ASAN_LINK_FLAGS} + LINK_LIBS ${CHEETAH_DYNAMIC_LIBS} + DEFS ${CHEETAH_ASAN_COMPILE_DEFS} + VERSION "${CHEETAH_ABI_VERSION}.0" + SOVERSION ${CHEETAH_ABI_VERSION} + PARENT_TARGET cheetah) + + add_cheetah_runtime(opencilk-pedigrees-asan + SHARED + OS ${CHEETAH_SUPPORTED_OS} + ARCHS ${CHEETAH_SUPPORTED_ARCH} + SOURCES ${CHEETAH_PEDIGREE_GLOBALS_SOURCES} + CFLAGS ${CHEETAH_ASAN_COMPILE_FLAGS} + LINK_FLAGS ${CHEETAH_ASAN_LINK_FLAGS} + LINK_LIBS ${CHEETAH_DYNAMIC_LIBS} + DEFS ${CHEETAH_ASAN_COMPILE_DEFS} + VERSION "${CHEETAH_ABI_VERSION}.0" + SOVERSION ${CHEETAH_ABI_VERSION} + PARENT_TARGET cheetah) + endif() -# Build the Cheetah ABI as LLVM bitcode -if (CHEETAH_ENABLE_BITCODE_ABI AND (CMAKE_C_COMPILER_ID STREQUAL "Clang")) - set(CHEETAH_ABI_BITCODE_FILE "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/libopencilk-abi.bc") - # Commands to compile the source files for the ABI into bitcode. - add_library(cheetah_abi_bc_compile OBJECT ${CHEETAH_ABI_SOURCE}) - - set_target_properties(cheetah_abi_bc_compile - PROPERTIES - COMPILE_FLAGS "${CHEETAH_BITCODE_ABI_COMPILE_FLAGS}" - COMPILE_DEFINITIONS "${CHEETAH_BITCODE_ABI_COMPILE_DEFS}" - ) - target_compile_options(cheetah_abi_bc_compile PUBLIC "$<$:${CHEETAH_DEBUG_OPTIONS}>") - target_compile_options(cheetah_abi_bc_compile PUBLIC "$<$:${CHEETAH_RELEASE_OPTIONS}>") - - # Custom command to generate the ABI bitcode file. We assume that - # cheetah_abi_bc_compile generates just one output, so there's - # nothing to link together. - add_custom_command(OUTPUT ${CHEETAH_ABI_BITCODE_FILE} - DEPENDS cheetah_abi_bc_compile ${CHEETAH_ABI_SOURCE} - COMMAND cp $ ${CHEETAH_ABI_BITCODE_FILE} - COMMENT "Generating ${CHEETAH_ABI_BITCODE_FILE}" - VERBATIM - ) - - # Add a top-level custom target to drive the creation of the ABI - # bitcode file. - add_custom_target(cheetah_abi_bc ALL DEPENDS ${CHEETAH_ABI_BITCODE_FILE}) - list(APPEND CHEETAH_BUILD_TARGETS "cheetah_abi_bc") - # Because the ABI bitcode file is a custom target, we cannot use - # CMake's install(TARGETS) to install it. Instead, we use - # install(FILES) to install bitcode ABI file. - if (CHEETAH_INSTALL_BITCODE_ABI) - list(APPEND CHEETAH_INSTALL_FILES ${CHEETAH_ABI_BITCODE_FILE}) endif() -endif() - -# Build the Cheetah ABI as LLVM bitcode (for pedigrees) -if (CHEETAH_ENABLE_BITCODE_ABI AND (CMAKE_C_COMPILER_ID STREQUAL "Clang")) - set(CHEETAH_PEDIGREE_ABI_BITCODE_FILE "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/libopencilk-pedigrees-abi.bc") - # Commands to compile the source files for the ABI into bitcode. - add_library(cheetah_pedigree_abi_bc_compile OBJECT ${CHEETAH_ABI_SOURCE}) - - set_target_properties(cheetah_pedigree_abi_bc_compile - PROPERTIES - COMPILE_FLAGS "${CHEETAH_BITCODE_ABI_COMPILE_FLAGS}" - COMPILE_DEFINITIONS "${CHEETAH_BITCODE_PEDIGREE_ABI_COMPILE_DEFS}" - ) - target_compile_options(cheetah_pedigree_abi_bc_compile PUBLIC "$<$:${CHEETAH_DEBUG_OPTIONS}>") - target_compile_options(cheetah_pedigree_abi_bc_compile PUBLIC "$<$:${CHEETAH_RELEASE_OPTIONS}>") - - # Custom command to generate the ABI bitcode file. We assume that - # cheetah_abi_bc_compile generates just one output, so there's - # nothing to link together. - add_custom_command(OUTPUT ${CHEETAH_PEDIGREE_ABI_BITCODE_FILE} - DEPENDS cheetah_pedigree_abi_bc_compile ${CHEETAH_ABI_SOURCE} - COMMAND cp $ ${CHEETAH_PEDIGREE_ABI_BITCODE_FILE} - COMMENT "Generating ${CHEETAH_PEDIGREE_ABI_BITCODE_FILE}" - VERBATIM - ) - - # Add a top-level custom target to drive the creation of the ABI - # bitcode file. - add_custom_target(cheetah_pedigree_abi_bc ALL DEPENDS ${CHEETAH_PEDIGREE_ABI_BITCODE_FILE}) - list(APPEND CHEETAH_BUILD_TARGETS "cheetah_pedigree_abi_bc") - # Because the ABI bitcode file is a custom target, we cannot use - # CMake's install(TARGETS) to install it. Instead, we use - # install(FILES) to install bitcode ABI file. - if (CHEETAH_INSTALL_BITCODE_ABI) - list(APPEND CHEETAH_INSTALL_FILES ${CHEETAH_PEDIGREE_ABI_BITCODE_FILE}) + if (CHEETAH_ENABLE_STATIC) + add_cheetah_runtime(opencilk + STATIC + OS ${CHEETAH_SUPPORTED_OS} + ARCHS ${CHEETAH_SUPPORTED_ARCH} + SOURCES ${CHEETAH_SOURCES} + CFLAGS ${CHEETAH_COMPILE_FLAGS} + LINK_FLAGS ${CHEETAH_LINK_FLAGS} + LINK_LIBS ${CHEETAH_COMMON_LIBS} + DEFS ${CHEETAH_COMPILE_DEFS} + PARENT_TARGET cheetah) + + add_cheetah_runtime(opencilk-personality-c + STATIC + OS ${CHEETAH_SUPPORTED_OS} + ARCHS ${CHEETAH_SUPPORTED_ARCH} + SOURCES ${CHEETAH_PERSONALITY_C_SOURCES} + CFLAGS ${CHEETAH_COMPILE_FLAGS} + LINK_FLAGS ${CHEETAH_LINK_FLAGS} + LINK_LIBS ${CHEETAH_COMMON_LIBS} + DEFS ${CHEETAH_COMPILE_DEFS} + PARENT_TARGET cheetah) + + add_cheetah_runtime(opencilk-personality-cpp + STATIC + OS ${CHEETAH_SUPPORTED_OS} + ARCHS ${CHEETAH_SUPPORTED_ARCH} + SOURCES ${CHEETAH_PERSONALITY_CPP_SOURCES} + CFLAGS ${CHEETAH_COMPILE_FLAGS} + LINK_FLAGS ${CHEETAH_LINK_FLAGS} + LINK_LIBS ${CHEETAH_COMMON_LIBS} + DEFS ${CHEETAH_COMPILE_DEFS} + PARENT_TARGET cheetah) + + add_cheetah_runtime(opencilk-pedigrees + STATIC + OS ${CHEETAH_SUPPORTED_OS} + ARCHS ${CHEETAH_SUPPORTED_ARCH} + SOURCES ${CHEETAH_PEDIGREE_GLOBALS_SOURCES} + CFLAGS ${CHEETAH_COMPILE_FLAGS} + LINK_FLAGS ${CHEETAH_LINK_FLAGS} + LINK_LIBS ${CHEETAH_COMMON_LIBS} + DEFS ${CHEETAH_COMPILE_DEFS} + PARENT_TARGET cheetah) + + if (CHEETAH_BUILD_ASAN_VER) + add_cheetah_runtime(opencilk-asan + STATIC + OS ${CHEETAH_SUPPORTED_OS} + ARCHS ${CHEETAH_SUPPORTED_ARCH} + SOURCES ${CHEETAH_SOURCES} + CFLAGS ${CHEETAH_ASAN_COMPILE_FLAGS} + LINK_FLAGS ${CHEETAH_ASAN_LINK_FLAGS} + LINK_LIBS ${CHEETAH_COMMON_LIBS} + DEFS ${CHEETAH_ASAN_COMPILE_DEFS} + PARENT_TARGET cheetah) + + add_cheetah_runtime(opencilk-asan-personality-c + STATIC + OS ${CHEETAH_SUPPORTED_OS} + ARCHS ${CHEETAH_SUPPORTED_ARCH} + SOURCES ${CHEETAH_PERSONALITY_C_SOURCES} + CFLAGS ${CHEETAH_ASAN_COMPILE_FLAGS} + LINK_FLAGS ${CHEETAH_ASAN_LINK_FLAGS} + LINK_LIBS ${CHEETAH_COMMON_LIBS} + DEFS ${CHEETAH_ASAN_COMPILE_DEFS} + PARENT_TARGET cheetah) + + add_cheetah_runtime(opencilk-asan-personality-cpp + STATIC + OS ${CHEETAH_SUPPORTED_OS} + ARCHS ${CHEETAH_SUPPORTED_ARCH} + SOURCES ${CHEETAH_PERSONALITY_CPP_SOURCES} + CFLAGS ${CHEETAH_ASAN_COMPILE_FLAGS} + LINK_FLAGS ${CHEETAH_ASAN_LINK_FLAGS} + LINK_LIBS ${CHEETAH_COMMON_LIBS} + DEFS ${CHEETAH_ASAN_COMPILE_DEFS} + PARENT_TARGET cheetah) + + add_cheetah_runtime(opencilk-pedigrees-asan + STATIC + OS ${CHEETAH_SUPPORTED_OS} + ARCHS ${CHEETAH_SUPPORTED_ARCH} + SOURCES ${CHEETAH_PEDIGREE_GLOBALS_SOURCES} + CFLAGS ${CHEETAH_ASAN_COMPILE_FLAGS} + LINK_FLAGS ${CHEETAH_ASAN_LINK_FLAGS} + LINK_LIBS ${CHEETAH_COMMON_LIBS} + DEFS ${CHEETAH_ASAN_COMPILE_DEFS} + PARENT_TARGET cheetah) + endif() endif() -endif() - - - -if (CHEETAH_INSTALL_LIBRARY) - install(TARGETS ${CHEETAH_INSTALL_TARGETS} - LIBRARY DESTINATION ${CHEETAH_LIBRARY_INSTALL_DIR} COMPONENT cheetah - ARCHIVE DESTINATION ${CHEETAH_LIBRARY_INSTALL_DIR} COMPONENT cheetah - ) - install(FILES ${CHEETAH_INSTALL_FILES} - DESTINATION ${CHEETAH_LIBRARY_INSTALL_DIR} COMPONENT cheetah - ) -endif() - -# Add a meta-target for both libraries. -add_custom_target(cheetah DEPENDS ${CHEETAH_BUILD_TARGETS}) +else() # Not APPLE + foreach (arch ${CHEETAH_SUPPORTED_ARCH}) + add_cheetah_bitcode(opencilk-abi + ARCHS ${arch} + SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/${CHEETAH_ABI_SOURCE} + CFLAGS ${CHEETAH_BITCODE_ABI_COMPILE_FLAGS} + DEFS ${CHEETAH_BITCODE_ABI_COMPILE_DEFS} + PARENT_TARGET cheetah) + + add_cheetah_bitcode(opencilk-pedigrees-abi + ARCHS ${arch} + SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/${CHEETAH_ABI_SOURCE} + CFLAGS ${CHEETAH_BITCODE_ABI_COMPILE_FLAGS} + DEFS ${CHEETAH_BITCODE_PEDIGREE_ABI_COMPILE_DEFS} + PARENT_TARGET cheetah) + + if (CHEETAH_BUILD_ASAN_VER) + add_cheetah_bitcode(opencilk-asan-abi + ARCHS ${arch} + SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/${CHEETAH_ABI_SOURCE} + CFLAGS ${CHEETAH_BITCODE_ABI_ASAN_COMPILE_FLAGS} + DEFS ${CHEETAH_BITCODE_ABI_ASAN_COMPILE_DEFS} + PARENT_TARGET cheetah) + + add_cheetah_bitcode(opencilk-pedigrees-asan-abi + ARCHS ${arch} + SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/${CHEETAH_ABI_SOURCE} + CFLAGS ${CHEETAH_BITCODE_ABI_ASAN_COMPILE_FLAGS} + DEFS ${CHEETAH_BITCODE_PEDIGREE_ABI_ASAN_COMPILE_DEFS} + PARENT_TARGET cheetah) + endif() -if (NOT CMAKE_CONFIGURATION_TYPES AND (CHEETAH_INSTALL_LIBRARY OR - CHEETAH_INSTALL_HEADERS)) - if(CHEETAH_INSTALL_LIBRARY) - set(lib_install_target cheetah) + if (CHEETAH_ENABLE_SHARED) + add_cheetah_runtime(opencilk + SHARED + ARCHS ${arch} + SOURCES ${CHEETAH_SOURCES} + CFLAGS ${CHEETAH_COMPILE_FLAGS} + LINK_FLAGS ${CHEETAH_LINK_FLAGS} + LINK_LIBS ${CHEETAH_DYNAMIC_LIBS} + DEFS ${CHEETAH_COMPILE_DEFS} + VERSION "${CHEETAH_ABI_VERSION}.0" + SOVERSION ${CHEETAH_ABI_VERSION} + PARENT_TARGET cheetah) + + add_cheetah_runtime(opencilk-personality-c + SHARED + ARCHS ${arch} + SOURCES ${CHEETAH_PERSONALITY_C_SOURCES} + CFLAGS ${CHEETAH_COMPILE_FLAGS} + LINK_FLAGS ${CHEETAH_LINK_FLAGS} + LINK_LIBS ${CHEETAH_DYNAMIC_LIBS} + DEFS ${CHEETAH_COMPILE_DEFS} + VERSION "${CHEETAH_ABI_VERSION}.0" + SOVERSION ${CHEETAH_ABI_VERSION} + PARENT_TARGET cheetah) + + add_cheetah_runtime(opencilk-personality-cpp + SHARED + ARCHS ${arch} + SOURCES ${CHEETAH_PERSONALITY_CPP_SOURCES} + CFLAGS ${CHEETAH_COMPILE_FLAGS} + LINK_FLAGS ${CHEETAH_LINK_FLAGS} + LINK_LIBS ${CHEETAH_DYNAMIC_LIBS} + DEFS ${CHEETAH_COMPILE_DEFS} + VERSION "${CHEETAH_ABI_VERSION}.0" + SOVERSION ${CHEETAH_ABI_VERSION} + PARENT_TARGET cheetah) + + add_cheetah_runtime(opencilk-pedigrees + SHARED + ARCHS ${arch} + SOURCES ${CHEETAH_PEDIGREE_GLOBALS_SOURCES} + CFLAGS ${CHEETAH_COMPILE_FLAGS} + LINK_FLAGS ${CHEETAH_LINK_FLAGS} + LINK_LIBS ${CHEETAH_DYNAMIC_LIBS} + DEFS ${CHEETAH_COMPILE_DEFS} + VERSION "${CHEETAH_ABI_VERSION}.0" + SOVERSION ${CHEETAH_ABI_VERSION} + PARENT_TARGET cheetah) + + if (CHEETAH_BUILD_ASAN_VER) + add_cheetah_runtime(opencilk-asan + SHARED + ARCHS ${arch} + SOURCES ${CHEETAH_SOURCES} + CFLAGS ${CHEETAH_ASAN_COMPILE_FLAGS} + LINK_FLAGS ${CHEETAH_ASAN_LINK_FLAGS} + LINK_LIBS ${CHEETAH_DYNAMIC_LIBS} + DEFS ${CHEETAH_ASAN_COMPILE_DEFS} + VERSION "${CHEETAH_ABI_VERSION}.0" + SOVERSION ${CHEETAH_ABI_VERSION} + PARENT_TARGET cheetah) + + add_cheetah_runtime(opencilk-asan-personality-c + SHARED + ARCHS ${arch} + SOURCES ${CHEETAH_PERSONALITY_C_SOURCES} + CFLAGS ${CHEETAH_ASAN_COMPILE_FLAGS} + LINK_FLAGS ${CHEETAH_ASAN_LINK_FLAGS} + LINK_LIBS ${CHEETAH_DYNAMIC_LIBS} + DEFS ${CHEETAH_ASAN_COMPILE_DEFS} + VERSION "${CHEETAH_ABI_VERSION}.0" + SOVERSION ${CHEETAH_ABI_VERSION} + PARENT_TARGET cheetah) + + add_cheetah_runtime(opencilk-asan-personality-cpp + SHARED + ARCHS ${arch} + SOURCES ${CHEETAH_PERSONALITY_CPP_SOURCES} + CFLAGS ${CHEETAH_ASAN_COMPILE_FLAGS} + LINK_FLAGS ${CHEETAH_ASAN_LINK_FLAGS} + LINK_LIBS ${CHEETAH_DYNAMIC_LIBS} + DEFS ${CHEETAH_ASAN_COMPILE_DEFS} + VERSION "${CHEETAH_ABI_VERSION}.0" + SOVERSION ${CHEETAH_ABI_VERSION} + PARENT_TARGET cheetah) + + add_cheetah_runtime(opencilk-pedigrees-asan + SHARED + ARCHS ${arch} + SOURCES ${CHEETAH_PEDIGREE_GLOBALS_SOURCES} + CFLAGS ${CHEETAH_ASAN_COMPILE_FLAGS} + LINK_FLAGS ${CHEETAH_ASAN_LINK_FLAGS} + LINK_LIBS ${CHEETAH_DYNAMIC_LIBS} + DEFS ${CHEETAH_ASAN_COMPILE_DEFS} + VERSION "${CHEETAH_ABI_VERSION}.0" + SOVERSION ${CHEETAH_ABI_VERSION} + PARENT_TARGET cheetah) + endif() endif() - if(CHEETAH_INSTALL_HEADERS) - set(header_install_target install-cheetah-headers) + if (CHEETAH_ENABLE_STATIC) + add_cheetah_runtime(opencilk + STATIC + ARCHS ${arch} + SOURCES ${CHEETAH_SOURCES} + CFLAGS ${CHEETAH_COMPILE_FLAGS} + LINK_FLAGS ${CHEETAH_LINK_FLAGS} + LINK_LIBS ${CHEETAH_COMMON_LIBS} + DEFS ${CHEETAH_COMPILE_DEFS} + PARENT_TARGET cheetah) + + add_cheetah_runtime(opencilk-personality-c + STATIC + ARCHS ${arch} + SOURCES ${CHEETAH_PERSONALITY_C_SOURCES} + CFLAGS ${CHEETAH_COMPILE_FLAGS} + LINK_FLAGS ${CHEETAH_LINK_FLAGS} + LINK_LIBS ${CHEETAH_COMMON_LIBS} + DEFS ${CHEETAH_COMPILE_DEFS} + PARENT_TARGET cheetah) + + add_cheetah_runtime(opencilk-personality-cpp + STATIC + ARCHS ${arch} + SOURCES ${CHEETAH_PERSONALITY_CPP_SOURCES} + CFLAGS ${CHEETAH_COMPILE_FLAGS} + LINK_FLAGS ${CHEETAH_LINK_FLAGS} + LINK_LIBS ${CHEETAH_COMMON_LIBS} + DEFS ${CHEETAH_COMPILE_DEFS} + PARENT_TARGET cheetah) + + add_cheetah_runtime(opencilk-pedigrees + STATIC + ARCHS ${arch} + SOURCES ${CHEETAH_PEDIGREE_GLOBALS_SOURCES} + CFLAGS ${CHEETAH_COMPILE_FLAGS} + LINK_FLAGS ${CHEETAH_LINK_FLAGS} + LINK_LIBS ${CHEETAH_COMMON_LIBS} + DEFS ${CHEETAH_COMPILE_DEFS} + PARENT_TARGET cheetah) + + if (CHEETAH_BUILD_ASAN_VER) + add_cheetah_runtime(opencilk-asan + STATIC + ARCHS ${arch} + SOURCES ${CHEETAH_SOURCES} + CFLAGS ${CHEETAH_ASAN_COMPILE_FLAGS} + LINK_FLAGS ${CHEETAH_ASAN_LINK_FLAGS} + LINK_LIBS ${CHEETAH_COMMON_LIBS} + DEFS ${CHEETAH_ASAN_COMPILE_DEFS} + PARENT_TARGET cheetah) + + add_cheetah_runtime(opencilk-asan-personality-c + STATIC + ARCHS ${arch} + SOURCES ${CHEETAH_PERSONALITY_C_SOURCES} + CFLAGS ${CHEETAH_ASAN_COMPILE_FLAGS} + LINK_FLAGS ${CHEETAH_ASAN_LINK_FLAGS} + LINK_LIBS ${CHEETAH_COMMON_LIBS} + DEFS ${CHEETAH_ASAN_COMPILE_DEFS} + PARENT_TARGET cheetah) + + add_cheetah_runtime(opencilk-asan-personality-cpp + STATIC + ARCHS ${arch} + SOURCES ${CHEETAH_PERSONALITY_CPP_SOURCES} + CFLAGS ${CHEETAH_ASAN_COMPILE_FLAGS} + LINK_FLAGS ${CHEETAH_ASAN_LINK_FLAGS} + LINK_LIBS ${CHEETAH_COMMON_LIBS} + DEFS ${CHEETAH_ASAN_COMPILE_DEFS} + PARENT_TARGET cheetah) + + add_cheetah_runtime(opencilk-pedigrees-asan + STATIC + ARCHS ${arch} + SOURCES ${CHEETAH_PEDIGREE_GLOBALS_SOURCES} + CFLAGS ${CHEETAH_ASAN_COMPILE_FLAGS} + LINK_FLAGS ${CHEETAH_ASAN_LINK_FLAGS} + LINK_LIBS ${CHEETAH_COMMON_LIBS} + DEFS ${CHEETAH_ASAN_COMPILE_DEFS} + PARENT_TARGET cheetah) + endif() endif() - add_custom_target(install-cheetah - DEPENDS ${lib_install_target} - ${header_install_target} - COMMAND "${CMAKE_COMMAND}" - -DCMAKE_INSTALL_COMPONENT=cheetah - -P "${CHEETAH_BINARY_DIR}/cmake_install.cmake") - add_custom_target(install-cheetah-stripped - DEPENDS ${lib_install_target} - ${header_install_target} - COMMAND "${CMAKE_COMMAND}" - -DCMAKE_INSTALL_COMPONENT=cheetah - -DCMAKE_INSTALL_DO_STRIP=1 - -P "${CHEETAH_BINARY_DIR}/cmake_install.cmake") + endforeach() endif() diff --git a/runtime/Makefile b/runtime/Makefile index 764ba0ab..7c8f7947 100644 --- a/runtime/Makefile +++ b/runtime/Makefile @@ -5,7 +5,8 @@ REDUCER_DEF = -DREDUCER_MODULE #ABI_DEF imported from ../config.mk #ALERT_DEF = -DALERT_LVL=0x000 -MAIN = $(RTS_LIB) +RESOURCE_DIR=$(realpath ..) +MAIN = $(RTS_LIBDIR)/$(RTS_LIB) BITCODE_ABI = $(MAIN)-abi.bc SRCS = $(filter-out $(PERSON_C_SRC).c, $(filter-out $(PERSON_CPP_SRC).c, $(wildcard *.c))) HDRS = $(wildcard *.h) @@ -14,20 +15,20 @@ INCLUDES = -I../include/ DEFINES = $(REDUCER_DEF) $(ABI_DEF) $(ALERT_DEF) OPTIONS = $(OPT) $(DBG) $(ARCH) -Werror -Wall -fpic $(DEFINES) $(INCLUDES) -PERSON_C = libopencilk-personality-c -PERSON_CPP = libopencilk-personality-cpp +PERSON_C = $(RTS_LIBDIR)/$(RTS_C_PERSONALITY_LIB) +PERSON_CPP = $(RTS_LIBDIR)/$(RTS_CXX_PERSONALITY_LIB) PERSON_C_SRC = personality-c PERSON_CPP_SRC = personality-cpp .PHONY: all clean build -all: build $(MAIN).a $(MAIN).so $(PERSON_C).a $(PERSON_C).so $(PERSON_CPP).a $(PERSON_CPP).so $(BITCODE_ABI) +all: build $(RTS_LIBDIR) $(MAIN).a $(MAIN).so $(PERSON_C).a $(PERSON_C).so $(PERSON_CPP).a $(PERSON_CPP).so $(BITCODE_ABI) $(MAIN).a: $(OBJS) ar rcs $@ $^ $(MAIN).so: $(OBJS) - $(CC) -shared -o $@ $^ + $(CC) -shared -o $@ $^ -lpthread $(PERSON_C).a: build/$(PERSON_C_SRC).o ar rcs $@ $^ @@ -44,6 +45,9 @@ $(PERSON_CPP).so: ./build/$(PERSON_CPP_SRC).o build: mkdir -p $@ +$(RTS_LIBDIR): + mkdir -p $@ + build/%.o: %.c $(HDRS) $(CC) -c $(OPTIONS) -o $@ $< @@ -55,11 +59,11 @@ build/libpedigree_globals.so: build/pedigree_globals.o $(CC) -shared -o $@ $^ build/cilk2c_inlined.bc: cilk2c_inlined.c $(HDRS) - $(CC) -O3 -DCHEETAH_API="" -DCHEETAH_INTERNAL_NORETURN='__attribute((noreturn))' -DCHEETAH_INTERNAL="" -DCILK_DEBUG=0 -DENABLE_CILKRTS_PEDIGREE=1 -c -emit-llvm $(INCLUDES) -o $@ $< + $(CC) -O3 -DCHEETAH_API="" -DCHEETAH_INTERNAL_NORETURN='__attribute__((noreturn))' -DCHEETAH_INTERNAL="" -DCILK_DEBUG=0 -DENABLE_CILKRTS_PEDIGREE=1 -c -emit-llvm $(INCLUDES) -o $@ $< $(BITCODE_ABI) : build/cilk2c_inlined.bc cp $< $@ clean: - rm -f $(OBJS) $(BITCODE_ABI) *.a *.so *~ + rm -f $(OBJS) build/$(PERSON_C_SRC).o build/$(PERSON_CPP_SRC).o $(RTS_LIBDIR)/*.a $(RTS_LIBDIR)/*.so $(RTS_LIBDIR)/*.bc *~ rm -f build/cilk2c_inlined.bc diff --git a/runtime/TODOS.txt b/runtime/TODOS.txt deleted file mode 100644 index 02dac39f..00000000 --- a/runtime/TODOS.txt +++ /dev/null @@ -1,64 +0,0 @@ -Questions for TB / John: - -Q: Where is __default_cilkrts_startup and __default_cilkrts_shutdown inserted? - Is it inserted by the compiler as a global constructor / destructor? -A: No __default_cilkrts_startup/shutdown are not implicitly inserted by the -compiler. because those functions are marked with __attribute__((constructor))/ -__attribute__((destructor)), the linker and loader know to run those functions -before/after the execution of main (just standard linker / loader features) - -Q: Is __cilkrts_atinit and __cilkrts_atexit currently used? -A: No. Plan to remove. - -Q: using cmake in the runtime didn't work for me - -Q: Why is there a __cilk_personality_c_v0 and a __cilk_personality_cpp_v0? -They all seem to call __cilk_personality_internal anyway? - -Q: There are various ifdef used: CPU_SETSIZE, _SC_NPROCESSORS_ONLN, CHEETAH_SAVE_MXCSR, -Assume compiler generates this: __i386__, __BSD__, __SSE__, __AVX__ - -Q: IS CHECK_CILK_FRAME_MAGIC still necessary now that we have moved to bitcode -based approach? - -Q: What is the purpose of #undef Closure_assert_ownership / Closure_assert_alienation - -Q: Why do we need worker_state_change? Isn't that similar to the sched_state code? - -Q: The cilkified thread, after woken up by the last worker leaving cilkified region, -will execute leave_frame and Cilk_set_return ... why is this OK? - -Q: Do we want to improve the support for reducer? i.e., remove cap limit and -also incur less overhead if the lookup succeeds (need to inline lookup in the -reducer header file), also make the vinfo and log array part of the cilkred_map -and make the map itself a linked list of pages (4K each) - -Q: In the reducer_impl.c, there is a comment that says: -"Special case, if left is leftmost, then always merge into it. - For C reducers this forces lazy creation of the leftmost views." -What's that comment about? (is_leftmost always returns false). -If the leftmost is just a pointer anyway why does it matter? - -Q: Besides LONG_BIT, what else do we need from GNU_SOURCE? Should -we depend on GNU_SOURCE? (How does that work on Mac / Windows?) -(Maybe also __builtin_ctzl?) - -NOTE: -- Remove invoke-main.c entirely (or 'make' won't work) -- Remove cmdline.c entirely (deprecating cmdline arg) -- Currently need to copy over libopencilk-abi.bc into the build ... ideally -it would be nice to provide a compiler flag to specify the right ABI -- Tim is working on Pedigree - - -Check: -- Does __cilkrts_check_excpetion_raise only raises the exception from -a frame where the exception will be handled? (It retrieves t->user_exn -and raises that.) No it doesn't seem so. It seems that this is always -called after a successful non-trivial sync. - -- Change max_fibers to per worker max fibers -- Rethink fiber stats -- Incorporate the timing stats into scheduler -- Clean up the code -- Use struct and not typedef diff --git a/runtime/cilk-internal.h b/runtime/cilk-internal.h index f4519e83..e4371713 100644 --- a/runtime/cilk-internal.h +++ b/runtime/cilk-internal.h @@ -18,6 +18,12 @@ extern "C" { #include "sched_stats.h" #include "types.h" +#if defined __i386__ || defined __x86_64__ +#ifdef __SSE__ +#define CHEETAH_SAVE_MXCSR +#endif +#endif + struct global_state; typedef struct global_state global_state; typedef struct local_state local_state; @@ -49,26 +55,17 @@ struct __cilkrts_stack_frame { // The client copies the worker from TLS here when initializing // the structure. The runtime ensures that the field always points // to the __cilkrts_worker which currently "owns" the frame. + // + // TODO: Remove this pointer? This pointer only seems to be needed for + // debugging purposes. When the worker structure is genuinely needed, it + // seems to be accessible by calling __cilkrts_get_tls_worker(), which will + // be inlined and optimized to a simple move from TLS. _Atomic(__cilkrts_worker *) worker; // Before every spawn and nontrivial sync the client function // saves its continuation here. jmpbuf ctx; - /** - * Architecture-specific floating point state that should be carried - * along with a context from thread to thread. On Win64 this is in - * jmpbuf. - */ -#if defined __i386__ || defined __x86_64__ -#ifdef __SSE__ -#define CHEETAH_SAVE_MXCSR - uint32_t mxcsr; -#else - uint32_t reserved1; -#endif -#endif - #ifdef ENABLE_CILKRTS_PEDIGREE __cilkrts_pedigree pedigree; // Fields for pedigrees. int64_t rank; @@ -125,16 +122,7 @@ static const uint32_t frame_magic = offsetof(struct __cilkrts_stack_frame, flags)) * 13) + offsetof(struct __cilkrts_stack_frame, call_parent)) -#if defined __i386__ || defined __x86_64__ - * 13) -#ifdef __SSE__ - + offsetof(struct __cilkrts_stack_frame, mxcsr)) -#else - + offsetof(struct __cilkrts_stack_frame, reserved1)) -#endif -#else )) -#endif ; #define CHECK_CILK_FRAME_MAGIC(G, F) (frame_magic == (F)->magic) @@ -193,12 +181,6 @@ enum __cilkrts_worker_state { WORKER_RUN }; -/** - * NOTE: if you are using the Tapir compiler, you should not change - * these fields; ok to change for hand-compiled code. - * See Tapir compiler ABI: - * https://github.com/OpenCilk/opencilk-project/blob/release/9.x/llvm/lib/Transforms/Tapir/CilkRABI.cpp - **/ struct __cilkrts_worker { // T and H pointers in the THE protocol _Atomic(__cilkrts_stack_frame **) tail; @@ -222,7 +204,9 @@ struct __cilkrts_worker { // Map from reducer names to reducer values cilkred_map *reducer_map; -}; +} __attribute__((aligned(256))); // This alignment reduces false sharing induced + // by hardware prefetchers on some systems, + // such as Intel CPUs. struct cilkrts_callbacks { unsigned last_init; @@ -234,6 +218,13 @@ struct cilkrts_callbacks { extern CHEETAH_INTERNAL struct cilkrts_callbacks cilkrts_callbacks; +extern __thread __cilkrts_worker *tls_worker; + +static inline __attribute__((always_inline)) __cilkrts_worker * +__cilkrts_get_tls_worker(void) { + return tls_worker; +} + #ifdef __cplusplus } #endif diff --git a/runtime/cilk2c.c b/runtime/cilk2c.c index 353472f2..39a16ada 100644 --- a/runtime/cilk2c.c +++ b/runtime/cilk2c.c @@ -14,11 +14,11 @@ extern void _Unwind_Resume(struct _Unwind_Exception *); extern _Unwind_Reason_Code _Unwind_RaiseException(struct _Unwind_Exception *); -CHEETAH_INTERNAL unsigned cilkg_nproc = 0; - CHEETAH_INTERNAL struct cilkrts_callbacks cilkrts_callbacks = { 0, 0, false, {NULL}, {NULL}}; +unsigned __cilkrts_get_nworkers(void) { return cilkg_nproc; } + // Internal method to get the Cilk worker ID. Intended for debugging purposes. // // TODO: Figure out how we want to support worker-local storage. @@ -34,6 +34,10 @@ unsigned __cilkrts_get_worker_number(void) { // help initialization of libraries that depend on the OpenCilk runtime. int __cilkrts_is_initialized(void) { return NULL != default_cilkrts; } +int __cilkrts_running_on_workers(void) { + return NULL != __cilkrts_get_tls_worker(); +} + // These callback-registration methods can run before the runtime system has // started. // @@ -61,13 +65,15 @@ int __cilkrts_atexit(void (*callback)(void)) { return 0; } -// Called after a normal cilk_sync (i.e. not the cilk_sync called in the -// personality function.) Checks if there is an exception that needs to be +// Called after a normal cilk_sync or a cilk_sync performed within the +// personality function. Checks if there is an exception that needs to be // propagated. This is called from the frame that will handle whatever exception // was thrown. void __cilkrts_check_exception_raise(__cilkrts_stack_frame *sf) { __cilkrts_worker *w = sf->worker; + CILK_ASSERT(w, sf->worker == __cilkrts_get_tls_worker()); + deque_lock_self(w); Closure *t = deque_peek_bottom(w, w->self); Closure_lock(w, t); @@ -87,12 +93,13 @@ void __cilkrts_check_exception_raise(__cilkrts_stack_frame *sf) { return; } -// Called after a cilk_sync in the personality function. Checks if -// there is an exception that needs to be propagated, and if so, +// Checks if there is an exception that needs to be propagated, and if so, // resumes unwinding with that exception. void __cilkrts_check_exception_resume(__cilkrts_stack_frame *sf) { __cilkrts_worker *w = sf->worker; + CILK_ASSERT(w, sf->worker == __cilkrts_get_tls_worker()); + deque_lock_self(w); Closure *t = deque_peek_bottom(w, w->self); Closure_lock(w, t); @@ -118,11 +125,9 @@ void __cilkrts_check_exception_resume(__cilkrts_stack_frame *sf) { // handlers in that frame execute. void __cilkrts_cleanup_fiber(__cilkrts_stack_frame *sf, int32_t sel) { - if (sel == 0) - // Don't do anything during cleanups. - return; - __cilkrts_worker *w = sf->worker; + CILK_ASSERT(w, sf->worker == __cilkrts_get_tls_worker()); + deque_lock_self(w); Closure *t = deque_peek_bottom(w, w->self); @@ -168,78 +173,3 @@ void __cilkrts_sync(__cilkrts_stack_frame *sf) { longjmp_to_runtime(w); } } - -void __cilkrts_pause_frame(__cilkrts_stack_frame *sf, char *exn) { - - __cilkrts_worker *w = sf->worker; - cilkrts_alert(CFRAME, w, "__cilkrts_pause_frame %p", (void *)sf); - - CILK_ASSERT(w, CHECK_CILK_FRAME_MAGIC(w->g, sf)); - CILK_ASSERT(w, sf->worker == __cilkrts_get_tls_worker()); - - CILK_ASSERT(w, sf->flags & CILK_FRAME_DETACHED); - __cilkrts_stack_frame **tail = - atomic_load_explicit(&w->tail, memory_order_relaxed); - --tail; - /* The store of tail must precede the load of exc in global order. - See comment in do_dekker_on. */ - atomic_store_explicit(&w->tail, tail, memory_order_seq_cst); - __cilkrts_stack_frame **exc = - atomic_load_explicit(&w->exc, memory_order_seq_cst); - /* Currently no other modifications of flags are atomic so this - one isn't either. If the thief wins it may run in parallel - with the clear of DETACHED. Does it modify flags too? */ - sf->flags &= ~CILK_FRAME_DETACHED; - if (__builtin_expect(exc > tail, 0)) { - Cilk_exception_handler(exn); - // If Cilk_exception_handler returns this thread won - // the race and can return to the parent function. - } - // CILK_ASSERT(w, *(w->tail) == w->current_stack_frame); -} - -void __cilkrts_leave_frame(__cilkrts_stack_frame *sf) { - __cilkrts_worker *w = sf->worker; - cilkrts_alert(CFRAME, w, "__cilkrts_leave_frame %p", (void *)sf); - - CILK_ASSERT(w, CHECK_CILK_FRAME_MAGIC(w->g, sf)); - CILK_ASSERT(w, sf->worker == __cilkrts_get_tls_worker()); - // WHEN_CILK_DEBUG(sf->magic = ~CILK_STACKFRAME_MAGIC); - - if (sf->flags & CILK_FRAME_DETACHED) { // if this frame is detached - __cilkrts_stack_frame **tail = - atomic_load_explicit(&w->tail, memory_order_relaxed); - --tail; - /* The store of tail must precede the load of exc in global order. - See comment in do_dekker_on. */ - atomic_store_explicit(&w->tail, tail, memory_order_seq_cst); - __cilkrts_stack_frame **exc = - atomic_load_explicit(&w->exc, memory_order_seq_cst); - /* Currently no other modifications of flags are atomic so this - one isn't either. If the thief wins it may run in parallel - with the clear of DETACHED. Does it modify flags too? */ - sf->flags &= ~CILK_FRAME_DETACHED; - if (__builtin_expect(exc > tail, 0)) { - Cilk_exception_handler(NULL); - // If Cilk_exception_handler returns this thread won - // the race and can return to the parent function. - } - // CILK_ASSERT(w, *(w->tail) == w->current_stack_frame); - } else { - // A detached frame would never need to call Cilk_set_return, which - // performs the return protocol of a full frame back to its parent - // when the full frame is called (not spawned). A spawned full - // frame returning is done via a different protocol, which is - // triggered in Cilk_exception_handler. - if (sf->flags & CILK_FRAME_STOLEN) { // if this frame has a full frame - cilkrts_alert(RETURN, w, - "__cilkrts_leave_frame parent is call_parent!"); - // leaving a full frame; need to get the full frame of its call - // parent back onto the deque - Cilk_set_return(w); - CILK_ASSERT(w, CHECK_CILK_FRAME_MAGIC(w->g, sf)); - } - } -} - -unsigned __cilkrts_get_nworkers(void) { return cilkg_nproc; } diff --git a/runtime/cilk2c.h b/runtime/cilk2c.h index b24a9ae5..18b1c9ca 100644 --- a/runtime/cilk2c.h +++ b/runtime/cilk2c.h @@ -4,20 +4,98 @@ #include "cilk-internal.h" #include +// Returns 1 if the current exection is running on Cilk workers, 0 otherwise. +CHEETAH_API int __cilkrts_running_on_workers(void); + // ABI functions inlined by the compiler (provided as a bitcode file after // compiling runtime) are defined in cilk2c_inline.c. // ABI functions not inlined by the compiler are defined in cilk2c.c. -CHEETAH_API void __cilkrts_enter_frame(__cilkrts_stack_frame *sf); -CHEETAH_API void __cilkrts_enter_frame_fast(__cilkrts_stack_frame *sf); -CHEETAH_API void __cilkrts_save_fp_ctrl_state(__cilkrts_stack_frame *sf); -CHEETAH_API void __cilkrts_detach(__cilkrts_stack_frame *self); + +// Inserted at the entry of a spawning function that is not itself a spawn +// helper. Initializes the stack frame sf allocated for that function. +CHEETAH_INTERNAL void __cilkrts_enter_frame(__cilkrts_stack_frame *sf); + +// Inserted at the entry of a spawn helper, i.e., a function that must have been +// spawned. Initializes the stack frame sf allocated for that function. +CHEETAH_INTERNAL void __cilkrts_enter_frame_helper(__cilkrts_stack_frame *sf); + +// Prepare to perform a spawn. This function may return once or twice, +// returning 0 the first time and 1 the second time. This function is intended +// to be used follows: +// +// if (0 == __cilk_spawn_prepare(sf)) { +// spawn_helper(args); +// } +CHEETAH_INTERNAL int __cilk_prepare_spawn(__cilkrts_stack_frame *sf); + +// Called in the spawn helper immediately before the spawned computation. +// Enables the parent function to be stollen. +CHEETAH_INTERNAL void __cilkrts_detach(__cilkrts_stack_frame *sf); + +// Check if the runtime is storing an exception we need to handle later, and +// raises that exception if so. CHEETAH_API void __cilkrts_check_exception_raise(__cilkrts_stack_frame *sf); + +// Check if the runtime is storing an exception we need to handle later, and +// resumes unwinding with that exception if so. CHEETAH_API void __cilkrts_check_exception_resume(__cilkrts_stack_frame *sf); -CHEETAH_API void __cilkrts_cleanup_fiber(__cilkrts_stack_frame *, int32_t sel); + +// Performs runtime operations to handle a cilk_sync. +__attribute__((noreturn, nothrow)) CHEETAH_API void __cilkrts_sync(__cilkrts_stack_frame *sf); -CHEETAH_API void __cilkrts_pop_frame(__cilkrts_stack_frame *sf); -CHEETAH_API void __cilkrts_pause_frame(__cilkrts_stack_frame *sf, char *exn); -CHEETAH_API void __cilkrts_leave_frame(__cilkrts_stack_frame *sf); + +// Implements a cilk_sync when the cilk_sync might produce an exception that +// needs to be handled. +CHEETAH_INTERNAL void __cilk_sync(__cilkrts_stack_frame *sf); + +// Implements a cilk_sync when the cilk_sync is guaranteed not to produce an +// exception that needs to be handled. +CHEETAH_INTERNAL void __cilk_sync_nothrow(__cilkrts_stack_frame *sf); + +// Deprecated? Removes the current stack frame from the bottom of the stack. +// (This logic has been manually inlined into __cilkrts_leave_frame, +// __cilkrts_leave_frame_helper, and __cilkrts_pause_frame.) +CHEETAH_INTERNAL void __cilkrts_pop_frame(__cilkrts_stack_frame *sf); + +// Inserted on return from a spawning function that is not itself a spawn +// helper. Performs Cilk's return protocol for such functions. +CHEETAH_INTERNAL void __cilkrts_leave_frame(__cilkrts_stack_frame *sf); + +// Inserted on return from a spawn-helper function. Performs Cilk's return +// protocol for such functions. +CHEETAH_INTERNAL void __cilkrts_leave_frame_helper(__cilkrts_stack_frame *sf); + +// Performs all necessary operations on return from a spawning function that is +// not itself a spawn helper. +CHEETAH_INTERNAL void __cilk_parent_epilogue(__cilkrts_stack_frame *sf); + +// Performs all necessary operations on return from a spawn-helper function. +CHEETAH_INTERNAL void __cilk_helper_epilogue(__cilkrts_stack_frame *sf); + +// Performs all necessary runtime updates when execution enters a landingpad in +// a spawning function. +CHEETAH_INTERNAL +void __cilkrts_enter_landingpad(__cilkrts_stack_frame *sf, int32_t sel); + +// Called from __cilkrts_enter_landingpad to optionally fix the current stack +// pointer and cleanup a fiber that was previously saved for exception handling. +CHEETAH_API void __cilkrts_cleanup_fiber(__cilkrts_stack_frame *, int32_t sel); + +// Performs Cilk's return protocol on an exceptional return (i.e., a resume) +// from a spawn-helper function. +CHEETAH_INTERNAL void __cilkrts_pause_frame(__cilkrts_stack_frame *sf, char *exn); + +// Inserted on an exceptional return (i.e., a resume) from a spawn-helper +// function. +CHEETAH_INTERNAL void __cilk_pause_frame(__cilkrts_stack_frame *sf, char *exn); + +// Compute the grainsize for a cilk_for loop at runtime, based on the number n +// of loop iterations. +CHEETAH_INTERNAL uint8_t __cilkrts_cilk_for_grainsize_8(uint8_t n); +CHEETAH_INTERNAL uint16_t __cilkrts_cilk_for_grainsize_16(uint16_t n); +CHEETAH_INTERNAL uint32_t __cilkrts_cilk_for_grainsize_32(uint32_t n); +CHEETAH_INTERNAL uint64_t __cilkrts_cilk_for_grainsize_64(uint64_t n); + // Not marked as CHEETAH_API as it may be deprecated soon unsigned __cilkrts_get_nworkers(void); //CHEETAH_API int64_t* __cilkrts_get_pedigree(void); diff --git a/runtime/cilk2c_inlined.c b/runtime/cilk2c_inlined.c index 7fac080b..bc6ece4d 100644 --- a/runtime/cilk2c_inlined.c +++ b/runtime/cilk2c_inlined.c @@ -1,9 +1,8 @@ -// ================================================================ -// This file contains the compiler ABI, which corresponds to -// conceptually what the compiler generates to implement Cilk code. -// They are included here in part as documentation, and in part -// allow one to write and run "hand-compiled" Cilk code. -// ================================================================ +// ============================================================================= +// This file contains the compiler-runtime ABI. This file is compiled to LLVM +// bitcode, which the compiler then includes and inlines when it compiles a Cilk +// program. +// ============================================================================= #include #include @@ -43,11 +42,6 @@ uint64_t __cilkrts_get_dprand(void) { // This routine must be inlined for correctness. static inline __attribute__((always_inline)) void cilkify(global_state *g, __cilkrts_stack_frame *sf) { - // After inlining, orig_rsp will receive the stack pointer in the stack - // frame of the Cilk function instantiation on the Cilkifying thread. - void *orig_rsp = NULL; - ASM_GET_SP(orig_rsp); - #ifdef ENABLE_CILKRTS_PEDIGREE __cilkrts_init_dprng(); #endif @@ -56,18 +50,9 @@ cilkify(global_state *g, __cilkrts_stack_frame *sf) { // pointer, of the Cilk function. if (__builtin_setjmp(sf->ctx) == 0) { sysdep_save_fp_ctrl_state(sf); - invoke_cilkified_root(g, sf); - - wait_until_cilk_done(g); - - // At this point, some Cilk worker must have completed the Cilkified - // region and executed uncilkify at the end of the Cilk function. The - // longjmp will therefore jump to the end of the Cilk function. We need - // only restore the stack pointer to its original value on the - // Cilkifying thread's stack. - SP(sf) = orig_rsp; - sysdep_restore_fp_state(sf); - __builtin_longjmp(sf->ctx, 1); + __cilkrts_internal_invoke_cilkified_root(g, sf); + } else { + sanitizer_finish_switch_fiber(); } } @@ -83,7 +68,9 @@ uncilkify(global_state *g, __cilkrts_stack_frame *sf) { sysdep_save_fp_ctrl_state(sf); // Finish this Cilkified region, and transfer control back to the // original thread that performed cilkify. - exit_cilkified_root(g, sf); + __cilkrts_internal_exit_cilkified_root(g, sf); + } else { + sanitizer_finish_switch_fiber(); } } @@ -156,9 +143,9 @@ __cilkrts_enter_frame(__cilkrts_stack_frame *sf) { // routine will always be executed by a Cilk worker, it is optimized compared to // its counterpart, __cilkrts_enter_frame. __attribute__((always_inline)) void -__cilkrts_enter_frame_fast(__cilkrts_stack_frame *sf) { +__cilkrts_enter_frame_helper(__cilkrts_stack_frame *sf) { __cilkrts_worker *w = __cilkrts_get_tls_worker(); - cilkrts_alert(CFRAME, w, "__cilkrts_enter_frame_fast %p", (void *)sf); + cilkrts_alert(CFRAME, w, "__cilkrts_enter_frame_helper %p", (void *)sf); sf->flags = 0; sf->magic = frame_magic; @@ -186,12 +173,34 @@ __cilkrts_enter_frame_fast(__cilkrts_stack_frame *sf) { #endif } +__attribute__((always_inline)) int +__cilk_prepare_spawn(__cilkrts_stack_frame *sf) { + sysdep_save_fp_ctrl_state(sf); + int res = __builtin_setjmp(sf->ctx); + if (res != 0) { + sanitizer_finish_switch_fiber(); + } + return res; +} + +static inline __cilkrts_worker *get_tls_worker(__cilkrts_stack_frame *sf) { + // In principle, we should be able to get the worker efficiently by calling + // __cilkrts_get_tls_worker(). But code-generation on many systems assumes + // that the thread on which a function runs never changes. As a result, it + // may cache the address returned by __cilkrts_get_tls_worker() during + // enter_frame and load the cached value in later, even though the actual + // result of __cilkrts_get_tls_worker() may change between those two points. + // To avoid this buggy behavior, we therefore get the worker from sf. + // + // TODO: Fix code-generation of TLS lookups on these systems. + return atomic_load_explicit(&sf->worker, memory_order_relaxed); +} + // Detach the given Cilk stack frame, allowing other Cilk workers to steal the // parent frame. -__attribute__((always_inline)) -void __cilkrts_detach(__cilkrts_stack_frame *sf) { - __cilkrts_worker *w = - atomic_load_explicit(&sf->worker, memory_order_relaxed); +__attribute__((always_inline)) void +__cilkrts_detach(__cilkrts_stack_frame *sf) { + __cilkrts_worker *w = get_tls_worker(sf); cilkrts_alert(CFRAME, w, "__cilkrts_detach %p", (void *)sf); CILK_ASSERT(w, CHECK_CILK_FRAME_MAGIC(w->g, sf)); @@ -210,34 +219,197 @@ void __cilkrts_detach(__cilkrts_stack_frame *sf) { atomic_store_explicit(&w->tail, tail, memory_order_release); } -// inlined by the compiler; this implementation is only used in invoke-main.c -__attribute__((always_inline)) -void __cilkrts_save_fp_ctrl_state(__cilkrts_stack_frame *sf) { - sysdep_save_fp_ctrl_state(sf); +__attribute__((always_inline)) void __cilk_sync(__cilkrts_stack_frame *sf) { + if (sf->flags & CILK_FRAME_UNSYNCHED) { + if (__builtin_setjmp(sf->ctx) == 0) { + sysdep_save_fp_ctrl_state(sf); + __cilkrts_sync(sf); + } else { + sanitizer_finish_switch_fiber(); + if (sf->flags & CILK_FRAME_EXCEPTION_PENDING) { + __cilkrts_check_exception_raise(sf); + } + } + } } -// Pop this Cilk stack frame off of the bottom of the linked list of -// __cilkrts_stack_frames, and if popping the last Cilk stack frame, call -// uncilkify to terminate the Cilkified region. This function must be inlined -// for correctness. -__attribute__((always_inline)) -void __cilkrts_pop_frame(__cilkrts_stack_frame *sf) { - __cilkrts_worker *w = - atomic_load_explicit(&sf->worker, memory_order_relaxed); - cilkrts_alert(CFRAME, w, "__cilkrts_pop_frame %p", (void *)sf); +__attribute__((always_inline)) void +__cilk_sync_nothrow(__cilkrts_stack_frame *sf) { + if (sf->flags & CILK_FRAME_UNSYNCHED) { + if (__builtin_setjmp(sf->ctx) == 0) { + sysdep_save_fp_ctrl_state(sf); + __cilkrts_sync(sf); + } else { + sanitizer_finish_switch_fiber(); + } + } +} + +__attribute__((always_inline)) void +__cilkrts_leave_frame(__cilkrts_stack_frame *sf) { + __cilkrts_worker *w = get_tls_worker(sf); + cilkrts_alert(CFRAME, w, "__cilkrts_leave_frame %p", (void *)sf); CILK_ASSERT(w, CHECK_CILK_FRAME_MAGIC(w->g, sf)); CILK_ASSERT(w, sf->worker == __cilkrts_get_tls_worker()); - /* The inlined version in the Tapir compiler uses release - semantics for the store to call_parent, but relaxed - order may be acceptable for both. A thief can't see - these operations until the Dekker protocol with a - memory barrier has run. */ + // WHEN_CILK_DEBUG(sf->magic = ~CILK_STACKFRAME_MAGIC); + + // Pop this frame off the cactus stack. This logic used to be in + // __cilkrts_pop_frame, but has been manually inlined to avoid reloading the + // worker unnecessarily. w->current_stack_frame = sf->call_parent; sf->call_parent = NULL; + // Check if sf is the final stack frame, and if so, terminate the Cilkified // region. - if (sf->flags & CILK_FRAME_LAST) { + uint32_t flags = sf->flags; + if (flags & CILK_FRAME_LAST) { uncilkify(w->g, sf); + flags = sf->flags; + } + + if (flags == 0) { + return; + } + + CILK_ASSERT(w, !(flags & CILK_FRAME_DETACHED)); + + // A detached frame would never need to call Cilk_set_return, which performs + // the return protocol of a full frame back to its parent when the full + // frame is called (not spawned). A spawned full frame returning is done + // via a different protocol, which is triggered in Cilk_exception_handler. + if (flags & CILK_FRAME_STOLEN) { // if this frame has a full frame + cilkrts_alert(RETURN, w, + "__cilkrts_leave_frame parent is call_parent!"); + // leaving a full frame; need to get the full frame of its call + // parent back onto the deque + Cilk_set_return(w); + CILK_ASSERT(w, CHECK_CILK_FRAME_MAGIC(w->g, sf)); + } +} + +__attribute__((always_inline)) void +__cilkrts_leave_frame_helper(__cilkrts_stack_frame *sf) { + __cilkrts_worker *w = get_tls_worker(sf); + cilkrts_alert(CFRAME, w, "__cilkrts_leave_frame_helper %p", (void *)sf); + + CILK_ASSERT(w, CHECK_CILK_FRAME_MAGIC(w->g, sf)); + CILK_ASSERT(w, sf->worker == __cilkrts_get_tls_worker()); + // WHEN_CILK_DEBUG(sf->magic = ~CILK_STACKFRAME_MAGIC); + + // Pop this frame off the cactus stack. This logic used to be in + // __cilkrts_pop_frame, but has been manually inlined to avoid reloading the + // worker unnecessarily. + w->current_stack_frame = sf->call_parent; + sf->call_parent = NULL; + + CILK_ASSERT(w, sf->flags & CILK_FRAME_DETACHED); + + __cilkrts_stack_frame **tail = + atomic_load_explicit(&w->tail, memory_order_relaxed); + --tail; + /* The store of tail must precede the load of exc in global order. See + comment in do_dekker_on. */ + atomic_store_explicit(&w->tail, tail, memory_order_seq_cst); + __cilkrts_stack_frame **exc = + atomic_load_explicit(&w->exc, memory_order_seq_cst); + /* Currently no other modifications of flags are atomic so this one isn't + either. If the thief wins it may run in parallel with the clear of + DETACHED. Does it modify flags too? */ + sf->flags &= ~CILK_FRAME_DETACHED; + if (__builtin_expect(exc > tail, 0)) { + Cilk_exception_handler(NULL); + // If Cilk_exception_handler returns this thread won the race and can + // return to the parent function. } + // CILK_ASSERT(w, *(w->tail) == w->current_stack_frame); +} + +__attribute__((always_inline)) void +__cilk_parent_epilogue(__cilkrts_stack_frame *sf) { + __cilkrts_leave_frame(sf); } + +__attribute__((always_inline)) void +__cilk_helper_epilogue(__cilkrts_stack_frame *sf) { + __cilkrts_leave_frame_helper(sf); +} + +__attribute__((always_inline)) +void __cilkrts_enter_landingpad(__cilkrts_stack_frame *sf, int32_t sel) { + // Don't do anything special during cleanups. + if (sel == 0) + return; + + if (0 == __builtin_setjmp(sf->ctx)) + __cilkrts_cleanup_fiber(sf, sel); +} + +__attribute__((always_inline)) +void __cilkrts_pause_frame(__cilkrts_stack_frame *sf, char *exn) { + __cilkrts_worker *w = get_tls_worker(sf); + cilkrts_alert(CFRAME, w, "__cilkrts_pause_frame %p", (void *)sf); + + CILK_ASSERT(w, CHECK_CILK_FRAME_MAGIC(w->g, sf)); + CILK_ASSERT(w, sf->worker == __cilkrts_get_tls_worker()); + + // Pop this frame off the cactus stack. This logic used to be in + // __cilkrts_pop_frame, but has been manually inlined to avoid reloading the + // worker unnecessarily. + w->current_stack_frame = sf->call_parent; + sf->call_parent = NULL; + + // A __cilkrts_pause_frame may be reached before the spawn-helper frame has + // detached. In that case, THE is not required. + if (sf->flags & CILK_FRAME_DETACHED) { + __cilkrts_stack_frame **tail = + atomic_load_explicit(&w->tail, memory_order_relaxed); + --tail; + /* The store of tail must precede the load of exc in global order. + See comment in do_dekker_on. */ + atomic_store_explicit(&w->tail, tail, memory_order_seq_cst); + __cilkrts_stack_frame **exc = + atomic_load_explicit(&w->exc, memory_order_seq_cst); + /* Currently no other modifications of flags are atomic so this + one isn't either. If the thief wins it may run in parallel + with the clear of DETACHED. Does it modify flags too? */ + sf->flags &= ~CILK_FRAME_DETACHED; + if (__builtin_expect(exc > tail, 0)) { + Cilk_exception_handler(exn); + // If Cilk_exception_handler returns this thread won + // the race and can return to the parent function. + } + // CILK_ASSERT(w, *(w->tail) == w->current_stack_frame); + } +} + +__attribute__((always_inline)) void +__cilk_helper_epilogue_exn(__cilkrts_stack_frame *sf, char *exn) { + __cilkrts_pause_frame(sf, exn); +} + +/// Computes a grainsize for a cilk_for loop, using the following equation: +/// +/// grainsize = min(2048, ceil(n / (8 * nworkers))) +#define __cilkrts_grainsize_fn_impl(NAME, INT_T) \ + __attribute__((always_inline)) INT_T NAME(INT_T n) { \ + INT_T small_loop_grainsize = n / (8 * cilkg_nproc); \ + if (small_loop_grainsize <= 1) \ + return 1; \ + INT_T large_loop_grainsize = 2048; \ + return large_loop_grainsize < small_loop_grainsize \ + ? large_loop_grainsize \ + : small_loop_grainsize; \ + } +#define __cilkrts_grainsize_fn(SZ) \ + __cilkrts_grainsize_fn_impl(__cilkrts_cilk_for_grainsize_##SZ, uint##SZ##_t) + +__attribute__((always_inline)) uint8_t +__cilkrts_cilk_for_grainsize_8(uint8_t n) { + uint8_t small_loop_grainsize = n / (8 * cilkg_nproc); + if (small_loop_grainsize <= 1) + return 1; + return small_loop_grainsize; +} + +__cilkrts_grainsize_fn(16) __cilkrts_grainsize_fn(32) __cilkrts_grainsize_fn(64) diff --git a/runtime/closure-type.h b/runtime/closure-type.h new file mode 100644 index 00000000..d636aea7 --- /dev/null +++ b/runtime/closure-type.h @@ -0,0 +1,115 @@ +#ifndef _CLOSURE_TYPE_H +#define _CLOSURE_TYPE_H + +#include "cilk-internal.h" +#include "cilkred_map.h" +#include "fiber.h" +#include "mutex.h" + +// Forward declaration +typedef struct Closure Closure; + +enum ClosureStatus { + /* Closure.status == 0 is invalid */ + CLOSURE_RUNNING = 42, + CLOSURE_SUSPENDED, + CLOSURE_RETURNING, + CLOSURE_READY, + CLOSURE_PRE_INVALID, /* before first real use */ + CLOSURE_POST_INVALID /* after destruction */ +}; + +/* + * All the data needed to properly handle a thrown exception. + */ +struct closure_exception { + char *exn; +}; + +/* + * the list of children is not distributed among + * the children themselves, in order to avoid extra protocols + * and locking. + */ +struct Closure { + cilk_mutex mutex; /* mutual exclusion lock */ + + __cilkrts_stack_frame *frame; /* rest of the closure */ + + struct cilk_fiber *fiber; + struct cilk_fiber *fiber_child; + + worker_id owner_ready_deque; /* debug only */ + worker_id mutex_owner; /* debug only */ + + enum ClosureStatus status : 8; /* doubles as magic number */ + bool has_cilk_callee; + bool lock_wait; + bool simulated_stolen; + unsigned int join_counter; /* number of outstanding spawned children */ + char *orig_rsp; /* the rsp one should use when sync successfully */ + + Closure *callee; + + Closure *call_parent; /* the "parent" closure that called */ + Closure *spawn_parent; /* the "parent" closure that spawned */ + + Closure *left_sib; // left *spawned* sibling in the closure tree + Closure *right_sib; // right *spawned* sibling in the closur tree + // right most *spawned* child in the closure tree + Closure *right_most_child; + + /* + * stuff related to ready deque. + * + * ANGE: for top of the ReadyDeque, prev_ready = NULL + * for bottom of the ReadyDeque, next_ready = NULL + * next_ready pointing downward, prev_ready pointing upward + * + * top + * next | ^ + * | | prev + * v | + * ... + * next | ^ + * | | prev + * v | + * bottom + */ + Closure *next_ready; + Closure *prev_ready; + + /* Stores of non-null values to right_rmap and child_rmap must + have release ordering to make sure values pointed to by the + map are visible. Loads must have acquire ordering. */ + /* Accumulated reducer maps from right siblings */ + _Atomic(cilkred_map *) volatile right_rmap; + /* Accumulated reducer maps from children */ + _Atomic(cilkred_map *) volatile child_rmap; + /* Reducer map for this closure when suspended at sync */ + cilkred_map *user_rmap; + + // Exceptions (roughly follows the reducer protocol) + + /* Canonical frame address (CFA) of the call-stack frame from which an + exception was rethrown. Used to ensure that the rethrown exception + appears to be rethrown from the correct frame and to avoid repeated calls + to __cilkrts_leave_frame during stack unwinding. */ + char *reraise_cfa; + /* Stack pointer for the parent fiber. used to restore the stack pointer + properly after entering a landingpad. */ + char *parent_rsp; + /* Pointer to a fiber whose destruction was delayed for + exception-handling. */ + struct cilk_fiber *saved_throwing_fiber; + + // exception propagated from our right siblings + struct closure_exception right_exn; + // exception propagated from our children + struct closure_exception child_exn; + // exception thrown from this closure + struct closure_exception user_exn; + +} __attribute__((aligned(CILK_CACHE_LINE))); + +#endif diff --git a/runtime/closure.c b/runtime/closure.c deleted file mode 100644 index 41085837..00000000 --- a/runtime/closure.c +++ /dev/null @@ -1,421 +0,0 @@ -#include "closure.h" -#include "cilk-internal.h" -#include "cilk2c.h" -#include "global.h" -#include "internal-malloc.h" -#include "readydeque.h" - -#undef Closure_assert_ownership -void Closure_assert_ownership(__cilkrts_worker *const w, Closure *t) { - CILK_ASSERT(w, t->mutex_owner == w->self); -} - -#undef Closure_assert_alienation -void Closure_assert_alienation(__cilkrts_worker *const w, Closure *t) { - CILK_ASSERT(w, t->mutex_owner != w->self); -} - -void Closure_checkmagic(__cilkrts_worker *const w, Closure *t) { - switch (t->status) { - case CLOSURE_RUNNING: - case CLOSURE_SUSPENDED: - case CLOSURE_RETURNING: - case CLOSURE_READY: - return; - case CLOSURE_POST_INVALID: - CILK_ABORT(w, "destroyed closure"); - default: - CILK_ABORT(w, "invalid closure"); - } -} - -const char *Closure_status_to_str(enum ClosureStatus status) { - switch (status) { - case CLOSURE_RUNNING: - return "running"; - case CLOSURE_SUSPENDED: - return "suspended"; - case CLOSURE_RETURNING: - return "returning"; - case CLOSURE_READY: - return "ready"; - case CLOSURE_PRE_INVALID: - return "pre-invalid"; - case CLOSURE_POST_INVALID: - return "post-invalid"; - default: - return "unknown"; - } -} - -void clear_closure_exception(struct closure_exception *exn) { exn->exn = NULL; } - -void Closure_change_status(__cilkrts_worker *const w, Closure *t, - enum ClosureStatus old, enum ClosureStatus status) { - CILK_ASSERT(w, t->status == old); - t->status = status; -} - -void Closure_set_status(__cilkrts_worker *const w, Closure *t, - enum ClosureStatus status) { - t->status = status; -} - -int Closure_trylock(__cilkrts_worker *const w, Closure *t) { - Closure_checkmagic(w, t); - int ret = cilk_mutex_try(&(t->mutex)); - if (ret) { - t->mutex_owner = w->self; - } - return ret; -} - -void Closure_lock(__cilkrts_worker *const w, Closure *t) { - Closure_checkmagic(w, t); - t->lock_wait = true; - cilk_mutex_lock(&(t->mutex)); - t->lock_wait = false; - t->mutex_owner = w->self; -} - -void Closure_unlock(__cilkrts_worker *const w, Closure *t) { - Closure_checkmagic(w, t); - Closure_assert_ownership(w, t); - t->mutex_owner = NO_WORKER; - cilk_mutex_unlock(&(t->mutex)); -} - -/******************************************** - * Closure management - ********************************************/ - -// need to be careful when calling this function --- we check whether a -// frame is set stolen (i.e., has a full frame associated with it), but note -// that the setting of this can be delayed. A thief can steal a spawned -// frame, but it cannot fully promote it until it remaps its TLMM stack, -// because the flag field is stored in the frame on the TLMM stack. That -// means, a frame can be stolen, in the process of being promoted, and -// mean while, the stolen flag is not set until finish_promote. -int Closure_at_top_of_stack(__cilkrts_worker *const w) { - __cilkrts_stack_frame **head = - atomic_load_explicit(&w->head, memory_order_relaxed); - __cilkrts_stack_frame **tail = - atomic_load_explicit(&w->tail, memory_order_relaxed); - return (head == tail && __cilkrts_stolen(w->current_stack_frame)); -} - -int Closure_has_children(Closure *cl) { - - return (cl->has_cilk_callee || cl->join_counter != 0); -} - -static inline void Closure_init(Closure *t) { - cilk_mutex_init(&t->mutex); - - t->mutex_owner = NO_WORKER; - t->owner_ready_deque = NO_WORKER; - t->status = CLOSURE_PRE_INVALID; - t->lock_wait = false; - t->has_cilk_callee = false; - t->simulated_stolen = false; - t->join_counter = 0; - - t->frame = NULL; - t->fiber = NULL; - t->fiber_child = NULL; - - t->orig_rsp = NULL; - - t->callee = NULL; - - t->call_parent = NULL; - t->spawn_parent = NULL; - - t->left_sib = NULL; - t->right_sib = NULL; - t->right_most_child = NULL; - - t->next_ready = NULL; - t->prev_ready = NULL; - - clear_closure_exception(&(t->right_exn)); - clear_closure_exception(&(t->child_exn)); - clear_closure_exception(&(t->user_exn)); - t->reraise_cfa = NULL; - t->parent_rsp = NULL; - t->saved_throwing_fiber = NULL; - - atomic_store_explicit(&t->child_rmap, NULL, memory_order_relaxed); - atomic_store_explicit(&t->right_rmap, NULL, memory_order_relaxed); - t->user_rmap = NULL; -} - -Closure *Closure_create(__cilkrts_worker *const w) { - /* cilk_internal_malloc returns sufficiently aligned memory */ - Closure *new_closure = - cilk_internal_malloc(w, sizeof(*new_closure), IM_CLOSURE); - CILK_ASSERT(w, new_closure != NULL); - - Closure_init(new_closure); - - cilkrts_alert(CLOSURE, w, "Allocate closure %p", (void *)new_closure); - - return new_closure; -} - -/* - * ANGE: Same thing as Cilk_Closure_create, except this function uses system - * malloc, while Cilk_Closure_create will eventually use internal_malloc. - * To be used only for creating the initial closure in invoke-main.c. - */ -Closure *Closure_create_main() { - Closure *new_closure = - (Closure *)cilk_aligned_alloc(CILK_CACHE_LINE, sizeof(*new_closure)); - CILK_ASSERT_G(new_closure != NULL); - Closure_init(new_closure); - - return new_closure; -} - -// double linking left and right; the right is always the new child -// Note that we must have the lock on the parent when invoking this function -static inline void double_link_children(__cilkrts_worker *const w, - Closure *left, Closure *right) { - - if (left) { - CILK_ASSERT(w, left->right_sib == (Closure *)NULL); - left->right_sib = right; - } - - if (right) { - CILK_ASSERT(w, right->left_sib == (Closure *)NULL); - right->left_sib = left; - } -} - -// unlink the closure from its left and right siblings -// Note that we must have the lock on the parent when invoking this function -static inline void unlink_child(__cilkrts_worker *const w, Closure *cl) { - - if (cl->left_sib) { - CILK_ASSERT(w, cl->left_sib->right_sib == cl); - cl->left_sib->right_sib = cl->right_sib; - } - if (cl->right_sib) { - CILK_ASSERT(w, cl->right_sib->left_sib == cl); - cl->right_sib->left_sib = cl->left_sib; - } - // used only for error checking - cl->left_sib = (Closure *)NULL; - cl->right_sib = (Closure *)NULL; -} - -/*** - * Only the scheduler is allowed to alter the closure tree. - * Consequently, these operations are private. - * - * Insert the newly created child into the closure tree. - * The child closure is newly created, which makes it the new right - * most child of parent. Setup the left/right sibling for this new - * child, and reset the parent's right most child pointer. - * - * Note that we don't need locks on the children to double link them. - * The old right most child will not follow its right_sib link until - * it's ready to return, and it needs lock on the parent to do so, which - * we are holding. The pointer to new right most child is not visible - * to anyone yet, so we don't need to lock that, either. - ***/ -CHEETAH_INTERNAL -void Closure_add_child(__cilkrts_worker *const w, Closure *parent, - Closure *child) { - - /* ANGE: w must have the lock on parent */ - Closure_assert_ownership(w, parent); - /* ANGE: w must NOT have the lock on child */ - Closure_assert_alienation(w, child); - - // setup sib links between parent's right most child and the new child - double_link_children(w, parent->right_most_child, child); - // now the new child becomes the right most child - parent->right_most_child = child; -} - -/*** - * Remove the child from the closure tree. - * At this point we should already have reduced all rmaps that this - * child has. We need to unlink it from its left/right sibling, and reset - * the right most child pointer in parent if this child is currently the - * right most child. - * - * Note that we need locks both on the parent and the child. - * We always hold lock on the parent when unlinking a child, so only one - * child gets unlinked at a time, and one child gets to modify the steal - * tree at a time. - ***/ -void Closure_remove_child(__cilkrts_worker *const w, Closure *parent, - Closure *child) { - CILK_ASSERT(w, child); - CILK_ASSERT(w, parent == child->spawn_parent); - - Closure_assert_ownership(w, parent); - Closure_assert_ownership(w, child); - - if (child == parent->right_most_child) { - CILK_ASSERT(w, child->right_sib == (Closure *)NULL); - parent->right_most_child = child->left_sib; - } - - CILK_ASSERT(w, child->right_rmap == (cilkred_map *)NULL); - - unlink_child(w, child); -} - -/*** - * This function is called during promote_child, when we know we have multiple - * frames in the stacklet. - * We create a new closure for the new spawn_parent, and temporarily use - * that to represent all frames in between the new spawn_parent and the - * old closure on top of the victim's deque. In case where some other child - * of the old closure returns, it needs to know that the old closure has - * outstanding call children, so it won't resume the suspended old closure - * by mistake. - ***/ -void Closure_add_temp_callee(__cilkrts_worker *const w, Closure *caller, - Closure *callee) { - CILK_ASSERT(w, !(caller->has_cilk_callee)); - CILK_ASSERT(w, callee->spawn_parent == NULL); - - callee->call_parent = caller; - caller->has_cilk_callee = true; -} - -void Closure_add_callee(__cilkrts_worker *const w, Closure *caller, - Closure *callee) { - CILK_ASSERT(w, callee->frame->call_parent == caller->frame); - - // ANGE: instead of checking has_cilk_callee, we just check if callee is - // NULL, because we might have set the has_cilk_callee in - // Closure_add_tmp_callee to prevent the closure from being resumed. - CILK_ASSERT(w, caller->callee == NULL); - CILK_ASSERT(w, callee->spawn_parent == NULL); - CILK_ASSERT(w, (callee->frame->flags & CILK_FRAME_DETACHED) == 0); - - callee->call_parent = caller; - caller->callee = callee; - caller->has_cilk_callee = true; -} - -void Closure_remove_callee(__cilkrts_worker *const w, Closure *caller) { - - // A child is not double linked with siblings if it is called - // so there is no need to unlink it. - CILK_ASSERT(w, caller->status == CLOSURE_SUSPENDED); - CILK_ASSERT(w, caller->has_cilk_callee); - caller->has_cilk_callee = false; - caller->callee = NULL; -} - -/* This function is used for steal, the next function for sync. - The invariants are slightly different. */ -void Closure_suspend_victim(__cilkrts_worker *thief, __cilkrts_worker *victim, - Closure *cl) { - - Closure *cl1; - - CILK_ASSERT(thief, !cl->user_rmap); - - Closure_checkmagic(thief, cl); - Closure_assert_ownership(thief, cl); - deque_assert_ownership(thief, victim->self); - - CILK_ASSERT(thief, cl == thief->g->root_closure || cl->spawn_parent || - cl->call_parent); - - Closure_change_status(thief, cl, CLOSURE_RUNNING, CLOSURE_SUSPENDED); - - cl1 = deque_xtract_bottom(thief, victim->self); - CILK_ASSERT(thief, cl == cl1); - USE_UNUSED(cl1); -} - -void Closure_suspend(__cilkrts_worker *const w, Closure *cl) { - - Closure *cl1; - - CILK_ASSERT(w, !cl->user_rmap); - - cilkrts_alert(SCHED, w, "Closure_suspend %p", (void *)cl); - - Closure_checkmagic(w, cl); - Closure_assert_ownership(w, cl); - deque_assert_ownership(w, w->self); - - CILK_ASSERT(w, cl == w->g->root_closure || cl->spawn_parent || - cl->call_parent); - CILK_ASSERT(w, cl->frame != NULL); - CILK_ASSERT(w, __cilkrts_stolen(cl->frame)); - CILK_ASSERT(w, cl->frame->worker->self == w->self); - - Closure_change_status(w, cl, CLOSURE_RUNNING, CLOSURE_SUSPENDED); - cl->frame->worker = (struct __cilkrts_worker *)0xbfbfbfbfbf; - - cl1 = deque_xtract_bottom(w, w->self); - - CILK_ASSERT(w, cl == cl1); - USE_UNUSED(cl1); -} - -void Closure_make_ready(Closure *cl) { cl->status = CLOSURE_READY; } - -static inline void Closure_clean(__cilkrts_worker *const w, Closure *t) { - CILK_ASSERT(w, !t->lock_wait); - - // sanity checks - if (w) { - CILK_ASSERT(w, t->left_sib == (Closure *)NULL); - CILK_ASSERT(w, t->right_sib == (Closure *)NULL); - CILK_ASSERT(w, t->right_most_child == (Closure *)NULL); - CILK_ASSERT(w, t->user_rmap == (cilkred_map *)NULL); - CILK_ASSERT(w, t->child_rmap == (cilkred_map *)NULL); - CILK_ASSERT(w, t->right_rmap == (cilkred_map *)NULL); - } else { - CILK_ASSERT_G(t->left_sib == (Closure *)NULL); - CILK_ASSERT_G(t->right_sib == (Closure *)NULL); - CILK_ASSERT_G(t->right_most_child == (Closure *)NULL); - CILK_ASSERT_G(t->user_rmap == (cilkred_map *)NULL); - CILK_ASSERT_G(t->child_rmap == (cilkred_map *)NULL); - CILK_ASSERT_G(t->right_rmap == (cilkred_map *)NULL); - } - - cilk_mutex_destroy(&t->mutex); -} - -/* ANGE: destroy the closure and internally free it (put back to global - * pool) - */ -void Closure_destroy_main(Closure *t) { - t->status = CLOSURE_POST_INVALID; - Closure_clean(NULL, t); - free(t); -} - -/* ANGE: destroy the closure and internally free it (put back to global - * pool) - */ -void Closure_destroy(struct __cilkrts_worker *const w, Closure *t) { - cilkrts_alert(CLOSURE, w, "Deallocate closure %p", (void *)t); - Closure_checkmagic(w, t); - t->status = CLOSURE_POST_INVALID; - Closure_clean(w, t); - cilk_internal_free(w, t, sizeof(*t), IM_CLOSURE); -} - -/* Destroy the closure and internally free it (put back to global pool), after - workers have been terminated. - */ -void Closure_destroy_global(struct global_state *const g, Closure *t) { - cilkrts_alert(CLOSURE, NULL, "Deallocate closure %p", (void *)t); - t->status = CLOSURE_POST_INVALID; - Closure_clean(NULL, t); - cilk_internal_free_global(g, t, sizeof(*t), IM_CLOSURE); -} diff --git a/runtime/closure.h b/runtime/closure.h index 9ea14dcb..c0f7b1ce 100644 --- a/runtime/closure.h +++ b/runtime/closure.h @@ -2,6 +2,7 @@ #define _CLOSURE_H // Includes +#include #include "debug.h" #include "cilk-internal.h" @@ -9,20 +10,26 @@ #include "fiber.h" #include "mutex.h" -// Forward declaration -typedef struct Closure Closure; +#include "closure-type.h" -enum ClosureStatus { - /* Closure.status == 0 is invalid */ - CLOSURE_RUNNING = 42, - CLOSURE_SUSPENDED, - CLOSURE_RETURNING, - CLOSURE_READY, - CLOSURE_PRE_INVALID, /* before first real use */ - CLOSURE_POST_INVALID /* after destruction */ -}; - -CHEETAH_INTERNAL const char *Closure_status_to_str(enum ClosureStatus status); +static inline const char *Closure_status_to_str(enum ClosureStatus status) { + switch (status) { + case CLOSURE_RUNNING: + return "running"; + case CLOSURE_SUSPENDED: + return "suspended"; + case CLOSURE_RETURNING: + return "returning"; + case CLOSURE_READY: + return "ready"; + case CLOSURE_PRE_INVALID: + return "pre-invalid"; + case CLOSURE_POST_INVALID: + return "post-invalid"; + default: + return "unknown"; + } +} #if CILK_DEBUG #define Closure_assert_ownership(w, t) Closure_assert_ownership(w, t) @@ -35,100 +42,31 @@ CHEETAH_INTERNAL const char *Closure_status_to_str(enum ClosureStatus status); #define Closure_checkmagic(w, t) #endif -/* - * All the data needed to properly handle a thrown exception. - */ -struct closure_exception { - char *exn; -}; - -/* - * the list of children is not distributed among - * the children themselves, in order to avoid extra protocols - * and locking. - */ -struct Closure { - cilk_mutex mutex; /* mutual exclusion lock */ - - __cilkrts_stack_frame *frame; /* rest of the closure */ - - struct cilk_fiber *fiber; - struct cilk_fiber *fiber_child; - - worker_id owner_ready_deque; /* debug only */ - worker_id mutex_owner; /* debug only */ - - enum ClosureStatus status : 8; /* doubles as magic number */ - bool has_cilk_callee; - bool lock_wait; - bool simulated_stolen; - unsigned int join_counter; /* number of outstanding spawned children */ - char *orig_rsp; /* the rsp one should use when sync successfully */ - - Closure *callee; - - Closure *call_parent; /* the "parent" closure that called */ - Closure *spawn_parent; /* the "parent" closure that spawned */ - - Closure *left_sib; // left *spawned* sibling in the closure tree - Closure *right_sib; // right *spawned* sibling in the closur tree - // right most *spawned* child in the closure tree - Closure *right_most_child; - - /* - * stuff related to ready deque. - * - * ANGE: for top of the ReadyDeque, prev_ready = NULL - * for bottom of the ReadyDeque, next_ready = NULL - * next_ready pointing downward, prev_ready pointing upward - * - * top - * next | ^ - * | | prev - * v | - * ... - * next | ^ - * | | prev - * v | - * bottom - */ - Closure *next_ready; - Closure *prev_ready; - - // Exceptions (roughly follows the reducer protocol) - - // exception propagated from our right siblings - struct closure_exception right_exn; - // exception propagated from our children - struct closure_exception child_exn; - // exception thrown from this closure - struct closure_exception user_exn; - - char *reraise_cfa; - char *parent_rsp; - struct cilk_fiber *saved_throwing_fiber; - - // cilkred_map *children_reducer_map; - // cilkred_map *right_reducer_map; - - /* Stores of non-null values to right_rmap and child_rmap must - have release ordering to make sure values pointed to by the - map are visible. Loads must have acquire ordering. */ - /* Accumulated reducer maps from right siblings */ - _Atomic(cilkred_map *) volatile right_rmap; - /* Accumulated reducer maps from children */ - _Atomic(cilkred_map *) volatile child_rmap; - /* Reducer map for this closure when suspended at sync */ - cilkred_map *user_rmap; - -} __attribute__((aligned(CILK_CACHE_LINE))); - #if CILK_DEBUG -CHEETAH_INTERNAL void Closure_assert_ownership(__cilkrts_worker *const w, - Closure *t); -CHEETAH_INTERNAL void Closure_assert_alienation(__cilkrts_worker *const w, - Closure *t); -CHEETAH_INTERNAL void Closure_checkmagic(__cilkrts_worker *const w, Closure *t); +static inline void Closure_assert_ownership(__cilkrts_worker *const w, + Closure *t) { + CILK_ASSERT(w, t->mutex_owner == w->self); +} + +static inline void Closure_assert_alienation(__cilkrts_worker *const w, + Closure *t) { + CILK_ASSERT(w, t->mutex_owner != w->self); +} + +static inline void Closure_checkmagic(__cilkrts_worker *const w, Closure *t) { + switch (t->status) { + case CLOSURE_RUNNING: + case CLOSURE_SUSPENDED: + case CLOSURE_RETURNING: + case CLOSURE_READY: + return; + case CLOSURE_POST_INVALID: + CILK_ABORT(w, "destroyed closure"); + default: + CILK_ABORT(w, "invalid closure"); + } +} + #define Closure_assert_ownership(w, t) Closure_assert_ownership(w, t) #define Closure_assert_alienation(w, t) Closure_assert_alienation(w, t) #define Closure_checkmagic(w, t) Closure_checkmagic(w, t) @@ -138,45 +76,365 @@ CHEETAH_INTERNAL void Closure_checkmagic(__cilkrts_worker *const w, Closure *t); #define Closure_checkmagic(w, t) #endif // CILK_DEBUG +#include "cilk2c.h" +#include "global.h" +#include "internal-malloc.h" +#include "readydeque.h" + // TODO: maybe make this look more like the other closure functions. -CHEETAH_INTERNAL void clear_closure_exception(struct closure_exception *exn); - -CHEETAH_INTERNAL -void Closure_change_status(__cilkrts_worker *const w, Closure *t, - enum ClosureStatus old, enum ClosureStatus status); -CHEETAH_INTERNAL -void Closure_set_status(__cilkrts_worker *const w, Closure *t, - enum ClosureStatus status); - -CHEETAH_INTERNAL int Closure_trylock(__cilkrts_worker *const w, Closure *t); -CHEETAH_INTERNAL void Closure_lock(__cilkrts_worker *const w, Closure *t); -CHEETAH_INTERNAL void Closure_unlock(__cilkrts_worker *const w, Closure *t); - -CHEETAH_INTERNAL int Closure_at_top_of_stack(__cilkrts_worker *const w); -CHEETAH_INTERNAL int Closure_has_children(Closure *cl); - -CHEETAH_INTERNAL Closure *Closure_create(__cilkrts_worker *const w); -CHEETAH_INTERNAL Closure *Closure_create_main(); - -CHEETAH_INTERNAL void Closure_add_child(__cilkrts_worker *const w, - Closure *parent, Closure *child); -CHEETAH_INTERNAL void Closure_remove_child(__cilkrts_worker *const w, - Closure *parent, Closure *child); -CHEETAH_INTERNAL void Closure_add_temp_callee(__cilkrts_worker *const w, - Closure *caller, Closure *callee); -CHEETAH_INTERNAL void Closure_add_callee(__cilkrts_worker *const w, - Closure *caller, Closure *callee); -CHEETAH_INTERNAL void Closure_remove_callee(__cilkrts_worker *const w, - Closure *caller); - -CHEETAH_INTERNAL void Closure_suspend_victim(__cilkrts_worker *thief, - __cilkrts_worker *victim, - Closure *cl); -CHEETAH_INTERNAL void Closure_suspend(__cilkrts_worker *const w, Closure *cl); - -CHEETAH_INTERNAL void Closure_make_ready(Closure *cl); -CHEETAH_INTERNAL void Closure_destroy(__cilkrts_worker *const w, Closure *t); -CHEETAH_INTERNAL void Closure_destroy_main(Closure *t); -CHEETAH_INTERNAL void Closure_destroy_global(struct global_state *const g, - Closure *t); +static inline void clear_closure_exception(struct closure_exception *exn) { + exn->exn = NULL; +} + +static inline void Closure_change_status(__cilkrts_worker *const w, Closure *t, + enum ClosureStatus old, + enum ClosureStatus status) { + CILK_ASSERT(w, t->status == old); + t->status = status; +} + +static inline void Closure_set_status(__cilkrts_worker *const w, Closure *t, + enum ClosureStatus status) { + t->status = status; +} + +static inline int Closure_trylock(__cilkrts_worker *const w, Closure *t) { + Closure_checkmagic(w, t); + int ret = cilk_mutex_try(&(t->mutex)); + if (ret) { + t->mutex_owner = w->self; + } + return ret; +} + +static inline void Closure_lock(__cilkrts_worker *const w, Closure *t) { + Closure_checkmagic(w, t); + t->lock_wait = true; + cilk_mutex_lock(&(t->mutex)); + t->lock_wait = false; + t->mutex_owner = w->self; +} + +static inline void Closure_unlock(__cilkrts_worker *const w, Closure *t) { + Closure_checkmagic(w, t); + Closure_assert_ownership(w, t); + t->mutex_owner = NO_WORKER; + cilk_mutex_unlock(&(t->mutex)); +} + +// need to be careful when calling this function --- we check whether a +// frame is set stolen (i.e., has a full frame associated with it), but note +// that the setting of this can be delayed. A thief can steal a spawned +// frame, but it cannot fully promote it until it remaps its TLMM stack, +// because the flag field is stored in the frame on the TLMM stack. That +// means, a frame can be stolen, in the process of being promoted, and +// mean while, the stolen flag is not set until finish_promote. +static inline int Closure_at_top_of_stack(__cilkrts_worker *const w) { + __cilkrts_stack_frame **head = + atomic_load_explicit(&w->head, memory_order_relaxed); + __cilkrts_stack_frame **tail = + atomic_load_explicit(&w->tail, memory_order_relaxed); + return (head == tail && __cilkrts_stolen(w->current_stack_frame)); +} + +static inline int Closure_has_children(Closure *cl) { + + return (cl->has_cilk_callee || cl->join_counter != 0); +} + +static inline void Closure_init(Closure *t) { + cilk_mutex_init(&t->mutex); + + t->mutex_owner = NO_WORKER; + t->owner_ready_deque = NO_WORKER; + t->status = CLOSURE_PRE_INVALID; + t->lock_wait = false; + t->has_cilk_callee = false; + t->simulated_stolen = false; + t->join_counter = 0; + + t->frame = NULL; + t->fiber = NULL; + t->fiber_child = NULL; + + t->orig_rsp = NULL; + + t->callee = NULL; + + t->call_parent = NULL; + t->spawn_parent = NULL; + + t->left_sib = NULL; + t->right_sib = NULL; + t->right_most_child = NULL; + + t->next_ready = NULL; + t->prev_ready = NULL; + + clear_closure_exception(&(t->right_exn)); + clear_closure_exception(&(t->child_exn)); + clear_closure_exception(&(t->user_exn)); + t->reraise_cfa = NULL; + t->parent_rsp = NULL; + t->saved_throwing_fiber = NULL; + + atomic_store_explicit(&t->child_rmap, NULL, memory_order_relaxed); + atomic_store_explicit(&t->right_rmap, NULL, memory_order_relaxed); + t->user_rmap = NULL; +} + +static inline Closure *Closure_create(__cilkrts_worker *const w) { + /* cilk_internal_malloc returns sufficiently aligned memory */ + Closure *new_closure = + cilk_internal_malloc(w, sizeof(*new_closure), IM_CLOSURE); + CILK_ASSERT(w, new_closure != NULL); + + Closure_init(new_closure); + + cilkrts_alert(CLOSURE, w, "Allocate closure %p", (void *)new_closure); + + return new_closure; +} + +// double linking left and right; the right is always the new child +// Note that we must have the lock on the parent when invoking this function +static inline void double_link_children(__cilkrts_worker *const w, + Closure *left, Closure *right) { + + if (left) { + CILK_ASSERT(w, left->right_sib == (Closure *)NULL); + left->right_sib = right; + } + + if (right) { + CILK_ASSERT(w, right->left_sib == (Closure *)NULL); + right->left_sib = left; + } +} + +// unlink the closure from its left and right siblings +// Note that we must have the lock on the parent when invoking this function +static inline void unlink_child(__cilkrts_worker *const w, Closure *cl) { + + if (cl->left_sib) { + CILK_ASSERT(w, cl->left_sib->right_sib == cl); + cl->left_sib->right_sib = cl->right_sib; + } + if (cl->right_sib) { + CILK_ASSERT(w, cl->right_sib->left_sib == cl); + cl->right_sib->left_sib = cl->left_sib; + } + // used only for error checking + cl->left_sib = (Closure *)NULL; + cl->right_sib = (Closure *)NULL; +} + +/*** + * Only the scheduler is allowed to alter the closure tree. + * Consequently, these operations are private. + * + * Insert the newly created child into the closure tree. + * The child closure is newly created, which makes it the new right + * most child of parent. Setup the left/right sibling for this new + * child, and reset the parent's right most child pointer. + * + * Note that we don't need locks on the children to double link them. + * The old right most child will not follow its right_sib link until + * it's ready to return, and it needs lock on the parent to do so, which + * we are holding. The pointer to new right most child is not visible + * to anyone yet, so we don't need to lock that, either. + ***/ +static inline +void Closure_add_child(__cilkrts_worker *const w, Closure *parent, + Closure *child) { + + /* ANGE: w must have the lock on parent */ + Closure_assert_ownership(w, parent); + /* ANGE: w must NOT have the lock on child */ + Closure_assert_alienation(w, child); + + // setup sib links between parent's right most child and the new child + double_link_children(w, parent->right_most_child, child); + // now the new child becomes the right most child + parent->right_most_child = child; +} + +/*** + * Remove the child from the closure tree. + * At this point we should already have reduced all rmaps that this + * child has. We need to unlink it from its left/right sibling, and reset + * the right most child pointer in parent if this child is currently the + * right most child. + * + * Note that we need locks both on the parent and the child. + * We always hold lock on the parent when unlinking a child, so only one + * child gets unlinked at a time, and one child gets to modify the steal + * tree at a time. + ***/ +static inline +void Closure_remove_child(__cilkrts_worker *const w, Closure *parent, + Closure *child) { + CILK_ASSERT(w, child); + CILK_ASSERT(w, parent == child->spawn_parent); + + Closure_assert_ownership(w, parent); + Closure_assert_ownership(w, child); + + if (child == parent->right_most_child) { + CILK_ASSERT(w, child->right_sib == (Closure *)NULL); + parent->right_most_child = child->left_sib; + } + + CILK_ASSERT(w, child->right_rmap == (cilkred_map *)NULL); + + unlink_child(w, child); +} + +/*** + * This function is called during promote_child, when we know we have multiple + * frames in the stacklet. + * We create a new closure for the new spawn_parent, and temporarily use + * that to represent all frames in between the new spawn_parent and the + * old closure on top of the victim's deque. In case where some other child + * of the old closure returns, it needs to know that the old closure has + * outstanding call children, so it won't resume the suspended old closure + * by mistake. + ***/ +static inline +void Closure_add_temp_callee(__cilkrts_worker *const w, Closure *caller, + Closure *callee) { + CILK_ASSERT(w, !(caller->has_cilk_callee)); + CILK_ASSERT(w, callee->spawn_parent == NULL); + + callee->call_parent = caller; + caller->has_cilk_callee = true; +} + +static inline +void Closure_add_callee(__cilkrts_worker *const w, Closure *caller, + Closure *callee) { + CILK_ASSERT(w, callee->frame->call_parent == caller->frame); + + // ANGE: instead of checking has_cilk_callee, we just check if callee is + // NULL, because we might have set the has_cilk_callee in + // Closure_add_tmp_callee to prevent the closure from being resumed. + CILK_ASSERT(w, caller->callee == NULL); + CILK_ASSERT(w, callee->spawn_parent == NULL); + CILK_ASSERT(w, (callee->frame->flags & CILK_FRAME_DETACHED) == 0); + + callee->call_parent = caller; + caller->callee = callee; + caller->has_cilk_callee = true; +} + +static inline +void Closure_remove_callee(__cilkrts_worker *const w, Closure *caller) { + + // A child is not double linked with siblings if it is called + // so there is no need to unlink it. + CILK_ASSERT(w, caller->status == CLOSURE_SUSPENDED); + CILK_ASSERT(w, caller->has_cilk_callee); + caller->has_cilk_callee = false; + caller->callee = NULL; +} + +/* This function is used for steal, the next function for sync. + The invariants are slightly different. */ +static inline +void Closure_suspend_victim(__cilkrts_worker *thief, __cilkrts_worker *victim, + Closure *cl) { + + Closure *cl1; + + CILK_ASSERT(thief, !cl->user_rmap); + + Closure_checkmagic(thief, cl); + Closure_assert_ownership(thief, cl); + deque_assert_ownership(thief, victim->self); + + CILK_ASSERT(thief, cl == thief->g->root_closure || cl->spawn_parent || + cl->call_parent); + + Closure_change_status(thief, cl, CLOSURE_RUNNING, CLOSURE_SUSPENDED); + + cl1 = deque_xtract_bottom(thief, victim->self); + CILK_ASSERT(thief, cl == cl1); + USE_UNUSED(cl1); +} + +static inline +void Closure_suspend(__cilkrts_worker *const w, Closure *cl) { + + Closure *cl1; + + CILK_ASSERT(w, !cl->user_rmap); + + cilkrts_alert(SCHED, w, "Closure_suspend %p", (void *)cl); + + Closure_checkmagic(w, cl); + Closure_assert_ownership(w, cl); + deque_assert_ownership(w, w->self); + + CILK_ASSERT(w, cl == w->g->root_closure || cl->spawn_parent || + cl->call_parent); + CILK_ASSERT(w, cl->frame != NULL); + CILK_ASSERT(w, __cilkrts_stolen(cl->frame)); + CILK_ASSERT(w, cl->frame->worker->self == w->self); + + Closure_change_status(w, cl, CLOSURE_RUNNING, CLOSURE_SUSPENDED); + atomic_store_explicit(&cl->frame->worker, INVALID, memory_order_relaxed); + + cl1 = deque_xtract_bottom(w, w->self); + + CILK_ASSERT(w, cl == cl1); + USE_UNUSED(cl1); +} + +static inline void Closure_make_ready(Closure *cl) { cl->status = CLOSURE_READY; } + +static inline void Closure_clean(__cilkrts_worker *const w, Closure *t) { + CILK_ASSERT(w, !t->lock_wait); + + // sanity checks + if (w) { + CILK_ASSERT(w, t->left_sib == (Closure *)NULL); + CILK_ASSERT(w, t->right_sib == (Closure *)NULL); + CILK_ASSERT(w, t->right_most_child == (Closure *)NULL); + CILK_ASSERT(w, t->user_rmap == (cilkred_map *)NULL); + CILK_ASSERT(w, t->child_rmap == (cilkred_map *)NULL); + CILK_ASSERT(w, t->right_rmap == (cilkred_map *)NULL); + } else { + CILK_ASSERT_G(t->left_sib == (Closure *)NULL); + CILK_ASSERT_G(t->right_sib == (Closure *)NULL); + CILK_ASSERT_G(t->right_most_child == (Closure *)NULL); + CILK_ASSERT_G(t->user_rmap == (cilkred_map *)NULL); + CILK_ASSERT_G(t->child_rmap == (cilkred_map *)NULL); + CILK_ASSERT_G(t->right_rmap == (cilkred_map *)NULL); + } + + cilk_mutex_destroy(&t->mutex); +} + +/* ANGE: destroy the closure and internally free it (put back to global + pool) */ +static inline void Closure_destroy(struct __cilkrts_worker *const w, + Closure *t) { + cilkrts_alert(CLOSURE, w, "Deallocate closure %p", (void *)t); + Closure_checkmagic(w, t); + CILK_ASSERT(w, NULL == t->saved_throwing_fiber); + t->status = CLOSURE_POST_INVALID; + Closure_clean(w, t); + cilk_internal_free(w, t, sizeof(*t), IM_CLOSURE); +} + +/* Destroy the closure and internally free it (put back to global pool), after + workers have been terminated. */ +static inline void Closure_destroy_global(struct global_state *const g, + Closure *t) { + cilkrts_alert(CLOSURE, NULL, "Deallocate closure %p", (void *)t); + t->status = CLOSURE_POST_INVALID; + Closure_clean(NULL, t); + cilk_internal_free_global(g, t, sizeof(*t), IM_CLOSURE); +} + #endif diff --git a/runtime/debug.h b/runtime/debug.h index 6edf6c59..c3a8ec84 100644 --- a/runtime/debug.h +++ b/runtime/debug.h @@ -125,7 +125,11 @@ CHEETAH_INTERNAL extern const char *const __cilkrts_assertion_failed; #else #define CILK_ASSERT(w, ex) +#define CILK_ASSERT_POINTER_EQUAL(w, P1, P2) +#define CILK_ASSERT_ZERO(w, ex, FMT) +#define CILK_ASSERT_INDEX_ZERO(w, LEFT, I, RIGHT, FMT) #define CILK_ASSERT_G(ex) +#define CILK_ASSERT_G_LE(A, B, FMT) #define CILK_ABORT(w, msg) #define CILK_ABORT_G(msg) #define WHEN_CILK_DEBUG(ex) diff --git a/runtime/fiber-pool.c b/runtime/fiber-pool.c index a9dedeed..8d3ae800 100644 --- a/runtime/fiber-pool.c +++ b/runtime/fiber-pool.c @@ -343,6 +343,7 @@ struct cilk_fiber *cilk_fiber_allocate_from_pool(__cilkrts_worker *w) { */ void cilk_fiber_deallocate_to_pool(__cilkrts_worker *w, struct cilk_fiber *fiber_to_return) { + sanitizer_fiber_deallocate(fiber_to_return); struct cilk_fiber_pool *pool = &(w->l->fiber_pool); if (pool->size == pool->capacity) { fiber_pool_free_batch(w, pool, pool->capacity / BATCH_FRACTION); diff --git a/runtime/fiber.c b/runtime/fiber.c index a3e890c7..acc067ea 100644 --- a/runtime/fiber.c +++ b/runtime/fiber.c @@ -1,3 +1,8 @@ +#ifndef _GNU_SOURCE +#define _GNU_SOURCE // For RTLD_DEFAULT from dlfcn.h +#endif + +#include // For dynamically loading ASan functions #include #include #include @@ -17,7 +22,6 @@ struct cilk_fiber { char *stack_low; // lowest usable byte of stack char *stack_high; // one byte above highest usable byte of stack char *alloc_high; // last byte of mmap-ed region - __cilkrts_worker *owner; // worker using this fiber }; #ifndef MAP_GROWSDOWN @@ -39,6 +43,150 @@ struct cilk_fiber { // in this file. //=============================================================== +#if CILK_ENABLE_ASAN_HOOKS +//=============================================================== +// Sanitizer interface, to allow ASan to work on Cilk programs. +//=============================================================== + +static void __sanitizer_start_switch_fiber_weak(void **fake_stack_save, + const void *stack_bottom, + size_t stacksize) + __attribute__((__weakref__("__sanitizer_start_switch_fiber"))); +static void __sanitizer_finish_switch_fiber_weak(void *fake_stack_save, + const void **stack_bottom_old, + size_t *stacksize_old) + __attribute__((__weakref__("__sanitizer_finish_switch_fiber"))); +static void __asan_unpoison_memory_region_weak(const void volatile *addr, + size_t size) + __attribute__((__weakref__("__asan_unpoison_memory_region"))); + +typedef void (*SanitizerStartSwitchFiberFuncPtr)(void **, const void *, size_t); +typedef void (*SanitizerFinishSwitchFiberFuncPtr)(void *, const void **, + size_t *); +typedef void (*AsanUnpoisonMemoryRegionFuncPtr)(const void volatile *, size_t); + +static bool have_sanitizer_start_switch_fiber_fn = false; +static bool have_sanitizer_finish_switch_fiber_fn = false; +static bool have_asan_unpoison_memory_region_fn = false; +static SanitizerStartSwitchFiberFuncPtr sanitizer_start_switch_fiber_fn = NULL; +static SanitizerFinishSwitchFiberFuncPtr sanitizer_finish_switch_fiber_fn = NULL; +static AsanUnpoisonMemoryRegionFuncPtr asan_unpoison_memory_region_fn = NULL; + +__thread void *fake_stack_save = NULL; +const __thread void *old_thread_stack = NULL; +__thread size_t old_thread_stacksize = 0; + +static SanitizerStartSwitchFiberFuncPtr getStartSwitchFiberFunc() { + SanitizerStartSwitchFiberFuncPtr fn = NULL; + + // Check whether weak reference points to statically linked function. + if (NULL != (fn = &__sanitizer_start_switch_fiber_weak)) { + return fn; + } + + // Check whether we can find a dynamically linked function. + if (NULL != (fn = (SanitizerStartSwitchFiberFuncPtr)dlsym( + RTLD_DEFAULT, "__sanitizer_start_switch_fiber"))) { + return fn; + } + + // Couldn't find the function at all. + return NULL; +} + +static SanitizerFinishSwitchFiberFuncPtr getFinishSwitchFiberFunc() { + SanitizerFinishSwitchFiberFuncPtr fn = NULL; + + // Check whether weak reference points to statically linked function. + if (NULL != (fn = &__sanitizer_finish_switch_fiber_weak)) { + return fn; + } + + // Check whether we can find a dynamically linked function. + if (NULL != (fn = (SanitizerFinishSwitchFiberFuncPtr)dlsym( + RTLD_DEFAULT, "__sanitizer_finish_switch_fiber"))) { + return fn; + } + + // Couldn't find the function at all. + return NULL; +} + +static AsanUnpoisonMemoryRegionFuncPtr getUnpoisonMemoryRegionFunc() { + AsanUnpoisonMemoryRegionFuncPtr fn = NULL; + + // Check whether weak reference points to statically linked function. + if (NULL != (fn = &__asan_unpoison_memory_region_weak)) { + return fn; + } + + // Check whether we can find a dynamically linked function. + if (NULL != (fn = (AsanUnpoisonMemoryRegionFuncPtr)dlsym( + RTLD_DEFAULT, "__asan_unpoison_memory_region"))) { + return fn; + } + + // Couldn't find the function at all. + return NULL; +} + +void sanitizer_start_switch_fiber(struct cilk_fiber *fiber) { + if (!have_sanitizer_start_switch_fiber_fn) { + sanitizer_start_switch_fiber_fn = getStartSwitchFiberFunc(); + have_sanitizer_start_switch_fiber_fn = true; + } + if (NULL != sanitizer_start_switch_fiber_fn) { + if (fiber) { + sanitizer_start_switch_fiber_fn( + /* &fake_stack_save */NULL, fiber->stack_low, + (size_t)(fiber->stack_high - fiber->stack_low)); + } else { + sanitizer_start_switch_fiber_fn( + /* &fake_stack_save */NULL, + old_thread_stack, old_thread_stacksize); + } + } +} + +void sanitizer_finish_switch_fiber() { + if (!have_sanitizer_finish_switch_fiber_fn) { + sanitizer_finish_switch_fiber_fn = getFinishSwitchFiberFunc(); + have_sanitizer_finish_switch_fiber_fn = true; + } + if (NULL != sanitizer_finish_switch_fiber_fn) { + sanitizer_finish_switch_fiber_fn(/* fake_stack_save */NULL, + &old_thread_stack, + &old_thread_stacksize); + } +} + +void sanitizer_unpoison_fiber(struct cilk_fiber *fiber) { + if (!have_asan_unpoison_memory_region_fn) { + asan_unpoison_memory_region_fn = getUnpoisonMemoryRegionFunc(); + have_asan_unpoison_memory_region_fn = true; + } + if (NULL != asan_unpoison_memory_region_fn) { + asan_unpoison_memory_region_fn( + fiber->stack_low, (size_t)(fiber->stack_high - fiber->stack_low)); + } +} + +void sanitizer_fiber_deallocate(struct cilk_fiber *fiber) { + if (NULL != fake_stack_save && NULL != sanitizer_start_switch_fiber_fn && + NULL != sanitizer_finish_switch_fiber_fn) { + void *local_fake_stack_save; + const void *stack_bottom; + size_t stacksize; + sanitizer_start_switch_fiber_fn(&local_fake_stack_save, NULL, 0); + sanitizer_finish_switch_fiber_fn(fake_stack_save, &stack_bottom, + &stacksize); + sanitizer_start_switch_fiber_fn(NULL, stack_bottom, stacksize); + sanitizer_finish_switch_fiber_fn(local_fake_stack_save, NULL, 0); + } + sanitizer_unpoison_fiber(fiber); +} +#endif // CILK_ENABLE_ASAN_HOOKS + //=============================================================== // Private helper functions //=============================================================== @@ -102,7 +250,6 @@ static void fiber_init(struct cilk_fiber *fiber) { fiber->stack_low = NULL; fiber->stack_high = NULL; fiber->alloc_high = NULL; - fiber->owner = NULL; } @@ -110,7 +257,6 @@ static void fiber_init(struct cilk_fiber *fiber) { // Supported public functions //=============================================================== - char *sysdep_reset_stack_for_resume(struct cilk_fiber *fiber, __cilkrts_stack_frame *sf) { CILK_ASSERT_G(fiber); @@ -118,9 +264,13 @@ char *sysdep_reset_stack_for_resume(struct cilk_fiber *fiber, boundary just after usable memory. */ /* JFC: This may need to be more than 256 if the stolen function has more than 256 bytes of outgoing arguments. I think - Cilk++ looked at fp-sp in the stolen function. - It should also exceed frame_size in init_fiber_run. */ - size_t align = MAX_STACK_ALIGN > 256 ? MAX_STACK_ALIGN : 256; + Cilk++ looked at fp-sp in the stolen function. */ + /* size_t align = MAX_STACK_ALIGN > 256 ? MAX_STACK_ALIGN : 256; */ + /* TB: The OpenCilk compiler should ensure that sufficient space is + allocated for outgoing arguments of any function, so we don't need any + particular alignment here. We use a positive alignment here for the + subsequent debugging step that checks the stack is accessible. */ + size_t align = 64; char *sp = fiber->stack_high - align; SP(sf) = sp; @@ -171,24 +321,6 @@ void cilk_fiber_deallocate_global(struct global_state *g, cilk_internal_free_global(g, fiber, sizeof(*fiber), IM_FIBER); } -struct cilk_fiber *cilk_main_fiber_allocate() { - struct cilk_fiber *fiber = malloc(sizeof(*fiber)); - fiber_init(fiber); - make_stack(fiber, DEFAULT_STACK_SIZE); // default ~1MB stack - cilkrts_alert(FIBER, NULL, "[?]: Allocate main fiber %p [%p--%p]", - (void *)fiber, (void *)fiber->stack_low, - (void *)fiber->stack_high); - return fiber; -} - -void cilk_main_fiber_deallocate(struct cilk_fiber *fiber) { - cilkrts_alert(FIBER, NULL, "[?]: Deallocate main fiber %p [%p--%p]", - (void *)fiber, (void *)fiber->stack_low, - (void *)fiber->stack_high); - free_stack(fiber); - free(fiber); -} - int in_fiber(struct cilk_fiber *fiber, void *p) { void *low = fiber->stack_low, *high = fiber->stack_high; return p >= low && p < high; diff --git a/runtime/fiber.h b/runtime/fiber.h index 454c1040..f4096d3e 100644 --- a/runtime/fiber.h +++ b/runtime/fiber.h @@ -43,7 +43,7 @@ static inline __attribute__((always_inline)) void sysdep_save_fp_ctrl_state(__cilkrts_stack_frame *sf) { #ifdef CHEETAH_SAVE_MXCSR #if 1 - __asm__("stmxcsr %0" : "=m"(sf->mxcsr)); + __asm__("stmxcsr %0" : "=m"(MXCSR(sf))); #else /* Disabled because LLVM's implementation is bad. */ sf->mxcsr = __builtin_ia32_stmxcsr(); /* aka _mm_setcsr */ @@ -62,7 +62,7 @@ void sysdep_restore_fp_state(__cilkrts_stack_frame *sf) { /* TODO: Find a way to do this only when using floating point. */ #ifdef CHEETAH_SAVE_MXCSR #if 1 - __asm__ volatile("ldmxcsr %0" : : "m"(sf->mxcsr)); + __asm__ volatile("ldmxcsr %0" : : "m"(MXCSR(sf))); #else /* Disabled because LLVM's implementation is bad. */ __builtin_ia32_ldmxcsr(sf->mxcsr); /* aka _mm_getcsr */ @@ -97,11 +97,6 @@ CHEETAH_INTERNAL void cilk_fiber_deallocate(__cilkrts_worker *w, struct cilk_fiber *fiber); CHEETAH_INTERNAL void cilk_fiber_deallocate_global(global_state *, struct cilk_fiber *fiber); -// allocate / deallocate fiber from / back to OS for the invoke-main -CHEETAH_INTERNAL -struct cilk_fiber *cilk_main_fiber_allocate(); -CHEETAH_INTERNAL -void cilk_main_fiber_deallocate(struct cilk_fiber *fiber); // allocate / deallocate one fiber from / back to per-worker pool CHEETAH_INTERNAL struct cilk_fiber *cilk_fiber_allocate_from_pool(__cilkrts_worker *w); @@ -111,4 +106,15 @@ void cilk_fiber_deallocate_to_pool(__cilkrts_worker *w, CHEETAH_INTERNAL int in_fiber(struct cilk_fiber *, void *); +#if CILK_ENABLE_ASAN_HOOKS +void sanitizer_start_switch_fiber(struct cilk_fiber *fiber); +void sanitizer_finish_switch_fiber(); +CHEETAH_INTERNAL void sanitizer_unpoison_fiber(struct cilk_fiber *fiber); +CHEETAH_INTERNAL void sanitizer_fiber_deallocate(struct cilk_fiber *fiber); +#else +static inline void sanitizer_start_switch_fiber(struct cilk_fiber *fiber) {} +static inline void sanitizer_finish_switch_fiber() {} +static inline void sanitizer_unpoison_fiber(struct cilk_fiber *fiber) {} +static inline void sanitizer_fiber_deallocate(struct cilk_fiber *fiber) {} +#endif // CILK_ENABLE_ASAN_HOOKS #endif diff --git a/runtime/global.c b/runtime/global.c index b277391a..e30222d3 100644 --- a/runtime/global.c +++ b/runtime/global.c @@ -16,7 +16,7 @@ global_state *default_cilkrts; -extern CHEETAH_INTERNAL unsigned cilkg_nproc; +unsigned cilkg_nproc = 0; static void set_alert_debug_level() { /* Only the bits also set in ALERT_LVL are used. */ @@ -33,13 +33,20 @@ static global_state *global_state_allocate() { memset(g, 0, sizeof *g); cilk_mutex_init(&g->im_lock); + cilk_mutex_init(&g->index_lock); cilk_mutex_init(&g->print_lock); + atomic_store_explicit(&g->start_root_worker, 0, memory_order_relaxed); + atomic_store_explicit(&g->cilkified_futex, 0, memory_order_relaxed); + // TODO: Convert to cilk_* equivalents pthread_mutex_init(&g->cilkified_lock, NULL); pthread_cond_init(&g->cilkified_cond_var, NULL); - pthread_mutex_init(&g->start_lock, NULL); - pthread_cond_init(&g->start_cond_var, NULL); + pthread_mutex_init(&g->start_root_worker_lock, NULL); + pthread_cond_init(&g->start_root_worker_cond_var, NULL); + + pthread_mutex_init(&g->disengaged_lock, NULL); + pthread_cond_init(&g->disengaged_cond_var, NULL); return g; } @@ -64,7 +71,7 @@ static void set_deqdepth(global_state *g, unsigned int deqdepth) { static void set_fiber_pool_cap(global_state *g, unsigned int fiber_pool_cap) { // TODO: Verify that g has not yet been initialized. CILK_ASSERT_G(!g->workers_started); - CILK_ASSERT_G(fiber_pool_cap >= 8); + CILK_ASSERT_G(fiber_pool_cap >= 2); CILK_ASSERT_G(fiber_pool_cap <= 999999); g->options.fiber_pool_cap = fiber_pool_cap; } @@ -152,7 +159,7 @@ global_state *global_state_init(int argc, char *argv[]) { #ifdef DEBUG setlinebuf(stderr); #endif - + set_alert_debug_level(); // alert / debug used by global_state_allocate global_state *g = global_state_allocate(); @@ -166,18 +173,20 @@ global_state *global_state_init(int argc, char *argv[]) { g->workers_started = false; g->root_closure_initialized = false; - atomic_store_explicit(&g->start, 0, memory_order_relaxed); atomic_store_explicit(&g->done, 0, memory_order_relaxed); atomic_store_explicit(&g->cilkified, 0, memory_order_relaxed); + atomic_store_explicit(&g->disengaged_deprived, 0, memory_order_relaxed); + g->terminate = false; g->exiting_worker = 0; - atomic_store_explicit(&g->reducer_map_count, 0, memory_order_relaxed); g->workers = (__cilkrts_worker **)calloc(active_size, sizeof(__cilkrts_worker *)); g->deques = (ReadyDeque *)cilk_aligned_alloc( __alignof__(ReadyDeque), active_size * sizeof(ReadyDeque)); g->threads = (pthread_t *)calloc(active_size, sizeof(pthread_t)); + g->index_to_worker = (worker_id *)calloc(active_size, sizeof(worker_id)); + g->worker_to_index = (worker_id *)calloc(active_size, sizeof(worker_id)); cilk_internal_malloc_global_init(g); // initialize internal malloc first cilk_fiber_pool_global_init(g); cilk_global_sched_stats_init(&(g->stats)); diff --git a/runtime/global.h b/runtime/global.h index fc982652..e7571a89 100644 --- a/runtime/global.h +++ b/runtime/global.h @@ -10,11 +10,14 @@ #include "debug.h" #include "fiber.h" #include "internal-malloc-impl.h" +#include "jmpbuf.h" #include "mutex.h" #include "rts-config.h" #include "sched_stats.h" #include "types.h" +extern unsigned cilkg_nproc; + struct __cilkrts_worker; struct reducer_id_manager; struct Closure; @@ -56,21 +59,50 @@ struct global_state { struct cilk_im_desc im_desc __attribute__((aligned(CILK_CACHE_LINE))); cilk_mutex im_lock; // lock for accessing global im_desc + // These fields are accessed exclusively by the boss thread. + + jmpbuf boss_ctx __attribute__((aligned(CILK_CACHE_LINE))); + void *orig_rsp; volatile bool workers_started; - volatile bool root_closure_initialized; - volatile atomic_bool start; - volatile atomic_bool done; - volatile atomic_bool cilkified; - volatile bool terminate; - volatile worker_id exiting_worker; - volatile atomic_uint reducer_map_count; - cilk_mutex print_lock; // global lock for printing messages + // These fields are shared between the boss thread and a couple workers. + + _Atomic uint32_t start_root_worker __attribute__((aligned(CILK_CACHE_LINE))); + // NOTE: We can probably update the runtime system so that, when it uses + // cilkified_futex, it does not also use the cilkified field. But the + // cilkified field is helpful for debugging, and it seems unlikely that this + // optimization would improve performance. + _Atomic uint32_t cilkified_futex; + volatile worker_id exiting_worker; + volatile atomic_bool cilkified; + pthread_mutex_t start_root_worker_lock; + pthread_cond_t start_root_worker_cond_var; pthread_mutex_t cilkified_lock; pthread_cond_t cilkified_cond_var; - pthread_mutex_t start_lock; - pthread_cond_t start_cond_var; + + // These fields are shared among all workers in the work-stealing loop. + + volatile atomic_bool done __attribute__((aligned(CILK_CACHE_LINE))); + volatile bool terminate; + volatile bool root_closure_initialized; + + worker_id *index_to_worker __attribute__((aligned(CILK_CACHE_LINE))); + worker_id *worker_to_index; + cilk_mutex index_lock; + + // Count of number of disengaged and deprived workers. Upper 32 bits count + // the disengaged workers. Lower 32 bits count the deprived workers. These + // two counts are stored in a single word to make it easier to update both + // counts atomically. + _Atomic uint64_t disengaged_deprived __attribute__((aligned(CILK_CACHE_LINE))); + + _Atomic uint32_t disengaged_thieves_futex __attribute__((aligned(CILK_CACHE_LINE))); + + pthread_mutex_t disengaged_lock; + pthread_cond_t disengaged_cond_var; + + cilk_mutex print_lock; // global lock for printing messages struct reducer_id_manager *id_manager; /* null while Cilk is running */ diff --git a/runtime/init.c b/runtime/init.c index 4b36ca57..a07f3ad7 100644 --- a/runtime/init.c +++ b/runtime/init.c @@ -27,11 +27,11 @@ #include "readydeque.h" #include "sched_stats.h" #include "scheduler.h" +#include "worker_coord.h" #include "reducer_impl.h" -CHEETAH_INTERNAL -extern void cleanup_invoke_main(Closure *invoke_main); +extern __thread bool is_boss_thread; #ifdef __FreeBSD__ typedef cpuset_t cpu_set_t; @@ -49,6 +49,8 @@ static local_state *worker_local_init(global_state *g) { l->lock_wait = false; l->provably_good_steal = false; l->rand_next = 0; /* will be reset in scheduler loop */ + l->index_to_worker = + (worker_id *)calloc(g->options.nproc, sizeof(worker_id)); cilk_sched_stats_init(&(l->stats)); return l; @@ -84,63 +86,11 @@ static void workers_init(global_state *g) { w->reducer_map = NULL; // initialize internal malloc first cilk_internal_malloc_per_worker_init(w); - cilk_fiber_pool_per_worker_init(w); - } -} - -static void *scheduler_thread_proc(void *arg) { - __cilkrts_worker *w = (__cilkrts_worker *)arg; - cilkrts_alert(BOOT, w, "scheduler_thread_proc"); - __cilkrts_set_tls_worker(w); - - worker_id self = w->self; - - do { - // Wait for g->start == 1 to start executing the work-stealing loop. We - // use a condition variable to wait on g->start, because this approach - // seems to result in better performance. - pthread_mutex_lock(&w->g->start_lock); - while (!atomic_load_explicit(&w->g->start, memory_order_acquire)) { - pthread_cond_wait(&w->g->start_cond_var, &w->g->start_lock); - } - pthread_mutex_unlock(&w->g->start_lock); - // Check if we should exit this scheduling function. - if (w->g->terminate) { - return 0; - } - - /* TODO: Maybe import reducers here? They must be imported - before user code runs. */ - - // Start the new Cilkified region using the last worker that finished a - // Cilkified region. This approach ensures that the new Cilkified - // region starts on an available worker with the worker state that was - // updated by any operations that occurred outside of Cilkified regions. - // Such operations, for example might have updated the left-most view of - // a reducer. - if (self == w->g->exiting_worker) { - worker_scheduler(w, w->g->root_closure); - } else { - worker_scheduler(w, NULL); - } - - // At this point, some worker will have finished the Cilkified region, - // meaning it recordied its ID in g->exiting_worker and set g->done = 1. - // That worker's state accurately reflects the execution of the - // Cilkified region, including all updates to reducers. Wait for that - // worker to exit the work-stealing loop, and use it to wake-up the - // original Cilkifying thread. - if (self == w->g->exiting_worker) { - // Mark the computation as no longer cilkified, to signal the thread - // that originally cilkified the execution. - pthread_mutex_lock(&(w->g->cilkified_lock)); - atomic_store_explicit(&w->g->cilkified, 0, memory_order_release); - pthread_cond_signal(&w->g->cilkified_cond_var); - pthread_mutex_unlock(&(w->g->cilkified_lock)); - } - - } while (true); + // Initialize index-to-worker map entry for this worker. + g->index_to_worker[i] = i; + g->worker_to_index[i] = i; + } } #ifdef CPU_SETSIZE @@ -176,6 +126,9 @@ static void threads_init(global_state *g) { which is in a format compatible with cpulist_parse(). FreeBSD exports sysctl kern.sched.topology_spec, an XML representation of the processor topology. */ + /* TODO: Fix pinning strategy to better utilize cpu architecture. For + example, we probably do not want to pin a worker to cpus on different + NUMA nodes. */ #ifdef __FreeBSD__ int pin_strategy = 1; /* (0, 1), (2, 3), ... */ #else @@ -219,12 +172,18 @@ static void threads_init(global_state *g) { step_out = group_size; } else { step_out = 1; - step_in = group_size; + step_in = n_threads; } } #endif - - for (int w = 0; w < n_threads; w++) { + int worker_start = +#if BOSS_THIEF + 1 +#else + 0 +#endif + ; + for (int w = worker_start; w < n_threads; w++) { int status = pthread_create(&g->threads[w], NULL, scheduler_thread_proc, g->workers[w]); @@ -260,7 +219,6 @@ static void threads_init(global_state *g) { } #endif } - usleep(10); } global_state *__cilkrts_startup(int argc, char *argv[]) { @@ -312,19 +270,29 @@ static void __cilkrts_start_workers(global_state *g) { // Stop the Cilk workers in g, for example, by joining their underlying Pthreads. static void __cilkrts_stop_workers(global_state *g) { - CILK_ASSERT_G(!atomic_load_explicit(&g->start, memory_order_acquire)); - CILK_ASSERT_G(CLOSURE_READY != g->root_closure->status); + /* CILK_ASSERT_G( */ + /* !atomic_load_explicit(&g->start_thieves, memory_order_acquire)); */ // Set g->start and g->terminate, to allow the workers to exit their - // outermost scheduling loop. Wake up any workers waiting on g->start. + // outermost scheduling loop. g->terminate = true; - pthread_mutex_lock(&(g->start_lock)); - atomic_store_explicit(&g->start, 1, memory_order_release); - pthread_cond_broadcast(&g->start_cond_var); - pthread_mutex_unlock(&(g->start_lock)); + + // Wake up all the workers. + // We call wake_all_disengaged, rather than wake_thieves, to properly + // terminate all thieves, whether they're disengaged inside or outside the + // work-stealing loop. + wake_all_disengaged(g); + wake_root_worker(g, (uint32_t)(-1)); // Join the worker pthreads - for (unsigned int i = 0; i < g->nworkers; i++) { + unsigned int worker_start = +#if BOSS_THIEF + 1 +#else + 0 +#endif + ; + for (unsigned int i = worker_start; i < g->nworkers; i++) { int status = pthread_join(g->threads[i], NULL); if (status != 0) cilkrts_bug(NULL, "Cilk runtime error: thread join (%u) failed: %d", @@ -334,14 +302,91 @@ static void __cilkrts_stop_workers(global_state *g) { g->workers_started = false; } +// Block until signaled the Cilkified region is done. Executed by the Cilkfying +// thread. +void wait_until_cilk_done(global_state *g) { + wait_while_cilkified(g); +} + +// Helper method to make the boss thread wait for the cilkified region +// to complete. +static inline __attribute__((noinline)) void boss_wait_helper(void) { + // The setjmp/longjmp to and from user code can invalidate the + // function arguments and local variables in this function. Get + // fresh copies of these arguments from the runtime's global + // state. + global_state *g = tls_worker->g; + __cilkrts_stack_frame *sf = g->root_closure->frame; + CILK_BOSS_START_TIMING(g); + +#if !BOSS_THIEF + worker_id self = tls_worker->self; +#endif + tls_worker = NULL; + +#if !BOSS_THIEF + // Wake up the worker the boss was impersonating, to let it take + // over the computation. + try_wake_root_worker(g, &self, (uint32_t)(-1)); +#endif + + // Wait until the cilkified region is done executing. + wait_until_cilk_done(g); + +#if BOSS_THIEF + g->workers[0]->reducer_map = g->workers[g->exiting_worker]->reducer_map; + g->workers[g->exiting_worker]->reducer_map = NULL; + g->exiting_worker = 0; +#endif + + // At this point, some Cilk worker must have completed the + // Cilkified region and executed uncilkify at the end of the Cilk + // function. The longjmp will therefore jump to the end of the + // Cilk function. We need only restore the stack pointer to its + // original value on the Cilkifying thread's stack. + + CILK_BOSS_STOP_TIMING(g); + + // Restore the boss's original rsp, so the boss completes the Cilk + // function on its original stack. + SP(sf) = g->orig_rsp; + sysdep_restore_fp_state(sf); + sanitizer_start_switch_fiber(NULL); + __builtin_longjmp(sf->ctx, 1); +} + // Setup runtime structures to start a new Cilkified region. Executed by the // Cilkifying thread in cilkify(). -void invoke_cilkified_root(global_state *g, __cilkrts_stack_frame *sf) { +void __cilkrts_internal_invoke_cilkified_root(global_state *g, + __cilkrts_stack_frame *sf) { CILK_ASSERT_G(!__cilkrts_get_tls_worker()); + /* CILK_ASSERT_G( */ + /* !atomic_load_explicit(&g->start_thieves, memory_order_acquire)); */ + /* CILK_ASSERT_G( */ + /* !atomic_load_explicit(&g->start_thieves_futex, memory_order_acquire)); */ // Start the workers if necessary - if (!g->workers_started) + if (__builtin_expect(!g->workers_started, false)) { __cilkrts_start_workers(g); + } + + if (!is_boss_thread) { +#if BOSS_THIEF + cilk_fiber_pool_per_worker_init(g->workers[0]); + // rts_srand(g->workers[0], (0 + 1) * 162347); + g->workers[0]->l->rand_next = 162347; +#endif + is_boss_thread = true; + } + + // The boss thread will impersonate the last exiting worker until it tries + // to become a thief. +#if BOSS_THIEF + tls_worker = g->workers[0]; +#else + tls_worker = g->workers[g->exiting_worker]; +#endif + CILK_START_TIMING(tls_worker, INTERVAL_CILKIFY_ENTER); // Mark the root closure as not initialized g->root_closure_initialized = false; @@ -350,6 +395,7 @@ void invoke_cilkified_root(global_state *g, __cilkrts_stack_frame *sf) { Closure_make_ready(g->root_closure); // Setup the stack pointer to point at the root closure's fiber. + g->orig_rsp = SP(sf); void *new_rsp = (void *)sysdep_reset_stack_for_resume(g->root_closure->fiber, sf); USE_UNUSED(new_rsp); @@ -363,67 +409,78 @@ void invoke_cilkified_root(global_state *g, __cilkrts_stack_frame *sf) { // Associate sf with this root closure g->root_closure->frame = sf; - // Now we kick off execution of the Cilkified region by setting appropriate - // flags: + // Now kick off execution of the Cilkified region by setting appropriate + // flags. + + /* reset_disengaged_var(g); */ + set_cilkified(g); - // Set g->cilkified = 1, so the Cilkifying thread will wait for the - // Cilkified region to finish. - atomic_store_explicit(&g->cilkified, 1, memory_order_release); // Set g->done = 0, so Cilk workers will continue trying to steal. atomic_store_explicit(&g->done, 0, memory_order_release); - // Set g->start = 1 to unleash workers to enter the work-stealing loop. - // Wake up any workers waiting for this flag. - pthread_mutex_lock(&(g->start_lock)); - atomic_store_explicit(&g->start, 1, memory_order_release); - pthread_cond_broadcast(&g->start_cond_var); - pthread_mutex_unlock(&(g->start_lock)); -} -// Block until signaled the Cilkified region is done. Executed by the Cilkfying -// thread. -void wait_until_cilk_done(global_state *g) { - // Wait on g->cilkified to be set to 0, indicating the end of the Cilkified - // region. We use a condition variable to wait on g->cilkified, because - // this approach seems to result in better performance. - - // TODO: Convert pthread_mutex_lock, pthread_mutex_unlock, and - // pthread_cond_wait to cilk_* equivalents. - pthread_mutex_lock(&(g->cilkified_lock)); - - // There may be a *very unlikely* scenario where the Cilk computation has - // already been completed before even starting to wait. In that case, do - // not wait and continue directly. Also handle spurious wakeups with a - // 'while' instead of an 'if'. - while (atomic_load_explicit(&g->cilkified, memory_order_acquire)) { - pthread_cond_wait(&(g->cilkified_cond_var), &(g->cilkified_lock)); + // Wake up the thieves, to allow them to begin work stealing. + // + // NOTE: We might want to wake thieves gradually, as successful steals + // occur, rather than all at once. Initial testing of this approach did not + // seem to perform well, however. One possible reason why could be because + // of the extra kernel interactions involved in waking workers gradually. + wake_thieves(g); + /* request_more_thieves(g, g->nworkers); */ + + if (__builtin_setjmp(g->boss_ctx) == 0) { + CILK_SWITCH_TIMING(tls_worker, INTERVAL_CILKIFY_ENTER, INTERVAL_SCHED); + do_what_it_says_boss(tls_worker, g->root_closure); + } else { + // The stack on which + // __cilkrts_internal_invoke_cilkified_root() was called may + // be corrupted at this point, so we call this helper method, + // marked noinline, to ensure the compiler does not try to use + // any data from the stack. + boss_wait_helper(); } - - pthread_mutex_unlock(&(g->cilkified_lock)); } // Finish the execution of a Cilkified region. Executed by a worker in g. -void exit_cilkified_root(global_state *g, __cilkrts_stack_frame *sf) { - __cilkrts_worker *w = sf->worker; - +void __cilkrts_internal_exit_cilkified_root(global_state *g, + __cilkrts_stack_frame *sf) { + __cilkrts_worker *w = __cilkrts_get_tls_worker(); + CILK_ASSERT(w, w->l->state == WORKER_RUN); + CILK_SWITCH_TIMING(w, INTERVAL_WORK, INTERVAL_CILKIFY_EXIT); // Record this worker as the exiting worker. We keep track of this exiting // worker so that code outside of Cilkified regions can use this worker's // state, specifically, its reducer_map. We make sure to do this before // setting done, so that other workers will properly observe the new // exiting_worker. - g->exiting_worker = w->self; + worker_id self = w->self; + g->exiting_worker = self; - // Mark the computation as done. Also set start to false, so workers who - // exit the work-stealing loop will return to waiting for the start of the - // next Cilkified region. - atomic_store_explicit(&g->start, 0, memory_order_release); + // Mark the computation as done. Also "sleep" the workers: update global + // flags so workers who exit the work-stealing loop will return to waiting + // for the start of the next Cilkified region. + sleep_thieves(g); atomic_store_explicit(&g->done, 1, memory_order_release); + /* wake_all_disengaged(g); */ + +#if !BOSS_THIEF + if (!is_boss_thread && self != atomic_load_explicit(&g->start_root_worker, + memory_order_acquire)) { + // If a thread other than the boss thread finishes the cilkified region, + // make sure that the previous root worker is awake, so that it can + // become a thief and this worker can become the new root worker. + wake_root_worker(g, self); + } +#endif // Clear this worker's deque. Nobody can successfully steal from this deque // at this point, because head == tail, but we still want any subsequent - // Cilkified region to start with an empty deque. + // Cilkified region to start with an empty deque. We go ahead and grab the + // deque lock to make sure no other worker has a lingering pointer to the + // closure. + deque_lock_self(w); g->deques[w->self].bottom = (Closure *)NULL; g->deques[w->self].top = (Closure *)NULL; WHEN_CILK_DEBUG(g->root_closure->owner_ready_deque = NO_WORKER); + deque_unlock_self(w); // Clear the flags in sf. This routine runs before leave_frame in a Cilk // function, but leave_frame is executed conditionally in Cilk functions @@ -432,8 +489,30 @@ void exit_cilkified_root(global_state *g, __cilkrts_stack_frame *sf) { CILK_ASSERT(w, __cilkrts_synced(sf)); sf->flags = 0; - // done; go back to runtime - longjmp_to_runtime(w); + CILK_STOP_TIMING(w, INTERVAL_CILKIFY_EXIT); + if (is_boss_thread) { + // We finished the computation on the boss thread. No need to jump to + // the runtime in this case; just return normally. + /* CILK_ASSERT(w, w->l->fiber_to_free == NULL); */ + if (w->l->fiber_to_free) { + cilk_fiber_deallocate_to_pool(w, w->l->fiber_to_free); + } + w->l->fiber_to_free = NULL; + atomic_store_explicit(&g->cilkified, 0, memory_order_release); + w->l->state = WORKER_IDLE; + tls_worker = NULL; + + // Restore the boss's original rsp, so the boss completes the Cilk + // function on its original stack. + SP(sf) = g->orig_rsp; + sysdep_restore_fp_state(sf); + sanitizer_start_switch_fiber(NULL); + __builtin_longjmp(sf->ctx, 1); + } else { + // done; go back to runtime + CILK_START_TIMING(w, INTERVAL_WORK); + longjmp_to_runtime(w); + } } static void global_state_terminate(global_state *g) { @@ -448,11 +527,16 @@ static void global_state_deinit(global_state *g) { cilk_fiber_pool_global_destroy(g); cilk_internal_malloc_global_destroy(g); // internal malloc last cilk_mutex_destroy(&(g->print_lock)); + cilk_mutex_destroy(&(g->index_lock)); // TODO: Convert to cilk_* equivalents pthread_mutex_destroy(&g->cilkified_lock); pthread_cond_destroy(&g->cilkified_cond_var); - pthread_mutex_destroy(&g->start_lock); - pthread_cond_destroy(&g->start_cond_var); + /* pthread_mutex_destroy(&g->start_thieves_lock); */ + /* pthread_cond_destroy(&g->start_thieves_cond_var); */ + pthread_mutex_destroy(&g->start_root_worker_lock); + pthread_cond_destroy(&g->start_root_worker_cond_var); + pthread_mutex_destroy(&g->disengaged_lock); + pthread_cond_destroy(&g->disengaged_cond_var); free(g->workers); g->workers = NULL; g->nworkers = 0; @@ -460,6 +544,10 @@ static void global_state_deinit(global_state *g) { g->deques = NULL; free(g->threads); g->threads = NULL; + free(g->index_to_worker); + g->index_to_worker = NULL; + free(g->worker_to_index); + g->worker_to_index = NULL; free(g->id_manager); /* XXX Should export this back to global */ g->id_manager = NULL; free(g); @@ -520,6 +608,8 @@ static void workers_deinit(global_state *g) { cilk_internal_malloc_per_worker_destroy(w); // internal malloc last free(w->l->shadow_stack); w->l->shadow_stack = NULL; + free(w->l->index_to_worker); + w->l->index_to_worker = NULL; free(w->l); w->l = NULL; free(w); diff --git a/runtime/init.h b/runtime/init.h index 8bf65d7b..34c55720 100644 --- a/runtime/init.h +++ b/runtime/init.h @@ -3,10 +3,8 @@ #include "cilk-internal.h" -void invoke_cilkified_root(global_state *g, __cilkrts_stack_frame *sf); -void wait_until_cilk_done(global_state *g); -__attribute__((noreturn)) -void exit_cilkified_root(global_state *g, __cilkrts_stack_frame *sf); +void __cilkrts_internal_invoke_cilkified_root(global_state *g, __cilkrts_stack_frame *sf); +void __cilkrts_internal_exit_cilkified_root(global_state *g, __cilkrts_stack_frame *sf); // Used by Cilksan to set nworkers to 1 and force reduction void __cilkrts_internal_set_nworkers(unsigned int nworkers); diff --git a/runtime/internal-malloc.c b/runtime/internal-malloc.c index 33dcfeab..44f45370 100644 --- a/runtime/internal-malloc.c +++ b/runtime/internal-malloc.c @@ -17,6 +17,8 @@ CHEETAH_INTERNAL int cheetah_page_shift = 0; #define SIZE_THRESH bucket_sizes[NUM_BUCKETS - 1] /* TODO: Use sizeof(fiber), sizeof(closure), etc. */ +/* NOTE: Allocator does not currently work with non-power-of-2 bucket sizes in + * the mix. */ static const unsigned int bucket_sizes[NUM_BUCKETS] = {32, 64, 128, 256, 512, 1024, 2048}; static const unsigned int bucket_capacity[NUM_BUCKETS] = { @@ -323,9 +325,13 @@ static void extend_global_pool(__cilkrts_worker *w) { im_pool->mem_list_index++; if (im_pool->mem_list_index >= im_pool->mem_list_size) { - size_t new_list_size = im_pool->mem_list_size + MEM_LIST_SIZE; + CILK_ASSERT(w, im_pool->mem_list_size > 0); + size_t new_list_size = 2 * im_pool->mem_list_size; im_pool->mem_list = realloc(im_pool->mem_list, new_list_size * sizeof(*im_pool->mem_list)); + for (size_t i = im_pool->mem_list_size; i < new_list_size; ++i) { + im_pool->mem_list[i] = 0; + } im_pool->mem_list_size = new_list_size; CILK_CHECK(w->g, im_pool->mem_list, "Failed to extend global memory list by %zu bytes", diff --git a/runtime/jmpbuf.h b/runtime/jmpbuf.h index 91123e98..291ce761 100644 --- a/runtime/jmpbuf.h +++ b/runtime/jmpbuf.h @@ -1,7 +1,6 @@ #ifndef _JMPBUF_H #define _JMPBUF_H -#include #include #include "debug.h" @@ -27,7 +26,16 @@ typedef void *jmpbuf[JMPBUF_SIZE]; * @brief Get stack pointer from jump buffer in__cilkrts_stack_frame. */ #define SP(SF) JMPBUF_SP((SF)->ctx) -// typedef void *__CILK_JUMP_BUFFER[8]; + +#if defined __i386__ || defined __x86_64__ +// We use an otherwise unused entry in the jmpbuf to store MXCSR +#define JMPBUF_MXCSR(ctx) (ctx)[3] +/** + * @brief Get MXCSR from jump buffer in__cilkrts_stack_frame. X86 and X86_64 + * only. + */ +#define MXCSR(SF) JMPBUF_MXCSR((SF)->ctx) +#endif /* These macros are only for debugging. */ #if defined __i386__ diff --git a/runtime/local.h b/runtime/local.h index 1e6cb40f..0be88c9f 100644 --- a/runtime/local.h +++ b/runtime/local.h @@ -10,6 +10,8 @@ struct local_state { bool lock_wait; bool provably_good_steal; unsigned int rand_next; + // Local copy of the index-to-worker map. + worker_id *index_to_worker; jmpbuf rts_ctx; struct cilk_fiber_pool fiber_pool; diff --git a/runtime/mutex.c b/runtime/mutex.c deleted file mode 100644 index b49621ba..00000000 --- a/runtime/mutex.c +++ /dev/null @@ -1,58 +0,0 @@ -#include -#include -#include - -#include "mutex.h" - -void cilk_mutex_init(cilk_mutex *lock) { -#if USE_SPINLOCK - int ret = pthread_spin_init(&(lock->posix), PTHREAD_PROCESS_PRIVATE); - if (ret != 0) { - errno = ret; - perror("Pthread_spin_init failed"); - exit(-1); - } -#else - pthread_mutex_init(&(lock->posix), NULL); -#endif -} - -void cilk_mutex_lock(cilk_mutex *lock) { -#if USE_SPINLOCK - pthread_spin_lock(&(lock->posix)); -#else - pthread_mutex_lock(&(lock->posix)); -#endif -} - -void cilk_mutex_unlock(cilk_mutex *lock) { -#if USE_SPINLOCK - pthread_spin_unlock(&(lock->posix)); -#else - pthread_mutex_unlock(&(lock->posix)); -#endif -} - -int cilk_mutex_try(cilk_mutex *lock) { -#if USE_SPINLOCK - if (pthread_spin_trylock(&(lock->posix)) == 0) { - return 1; - } else { - return 0; - } -#else - if (pthread_mutex_trylock(&(lock->posix)) == 0) { - return 1; - } else { - return 0; - } -#endif -} - -void cilk_mutex_destroy(cilk_mutex *lock) { -#if USE_SPINLOCK - pthread_spin_destroy(&(lock->posix)); -#else - pthread_mutex_destroy(&(lock->posix)); -#endif -} diff --git a/runtime/mutex.h b/runtime/mutex.h index 3f7ad486..5853cc77 100644 --- a/runtime/mutex.h +++ b/runtime/mutex.h @@ -5,7 +5,10 @@ typedef union cilk_mutex cilk_mutex; // Includes +#include #include +#include +#include #include "rts-config.h" @@ -25,13 +28,56 @@ union cilk_mutex { }; #endif -CHEETAH_INTERNAL void cilk_mutex_init(cilk_mutex *lock); +static inline void cilk_mutex_init(cilk_mutex *lock) { +#if USE_SPINLOCK + int ret = pthread_spin_init(&(lock->posix), PTHREAD_PROCESS_PRIVATE); + if (ret != 0) { + errno = ret; + perror("Pthread_spin_init failed"); + exit(-1); + } +#else + pthread_mutex_init(&(lock->posix), NULL); +#endif +} -CHEETAH_INTERNAL void cilk_mutex_lock(cilk_mutex *lock); +static inline void cilk_mutex_lock(cilk_mutex *lock) { +#if USE_SPINLOCK + pthread_spin_lock(&(lock->posix)); +#else + pthread_mutex_lock(&(lock->posix)); +#endif +} -CHEETAH_INTERNAL void cilk_mutex_unlock(cilk_mutex *lock); +static inline void cilk_mutex_unlock(cilk_mutex *lock) { +#if USE_SPINLOCK + pthread_spin_unlock(&(lock->posix)); +#else + pthread_mutex_unlock(&(lock->posix)); +#endif +} -CHEETAH_INTERNAL int cilk_mutex_try(cilk_mutex *lock); +static inline int cilk_mutex_try(cilk_mutex *lock) { +#if USE_SPINLOCK + if (pthread_spin_trylock(&(lock->posix)) == 0) { + return 1; + } else { + return 0; + } +#else + if (pthread_mutex_trylock(&(lock->posix)) == 0) { + return 1; + } else { + return 0; + } +#endif +} -CHEETAH_INTERNAL void cilk_mutex_destroy(cilk_mutex *lock); +static inline void cilk_mutex_destroy(cilk_mutex *lock) { +#if USE_SPINLOCK + pthread_spin_destroy(&(lock->posix)); +#else + pthread_mutex_destroy(&(lock->posix)); +#endif +} #endif diff --git a/runtime/personality.c b/runtime/personality.c index fcca88a6..187bd4f3 100644 --- a/runtime/personality.c +++ b/runtime/personality.c @@ -57,7 +57,7 @@ _Unwind_Reason_Code __cilk_personality_internal( if (sf->flags & CILK_FRAME_UNSYNCHED) { // save floating point state - __cilkrts_save_fp_ctrl_state(sf); + sysdep_save_fp_ctrl_state(sf); if (__builtin_setjmp(sf->ctx) == 0) { deque_lock_self(w); @@ -69,10 +69,6 @@ _Unwind_Reason_Code __cilk_personality_internal( // set closure_exception t->user_exn.exn = (char *)ue_header; - /* - t->user_exn.frame = sf; - t->user_exn.fiber = t->fiber; - */ deque_unlock_self(w); @@ -104,8 +100,6 @@ _Unwind_Reason_Code __cilk_personality_internal( t->reraise_cfa = (char *)get_cfa(context); // Raise the new exception. __cilkrts_check_exception_raise(sf); - // Calling Resume instead of RaiseException also appears to work, - // and is a bit faster. // NOTE: Calling resume does not seem to work on MacOSX. // __cilkrts_check_exception_resume(sf); } @@ -124,11 +118,9 @@ _Unwind_Reason_Code __cilk_personality_internal( _Unwind_Reason_Code cleanup_res = std_lib_personality( version, actions, exception_class, ue_header, context); - // if we need to continue unwinding the stack, pop_frame + leave_frame - // here + // if we need to continue unwinding the stack, leave_frame here if ((cleanup_res == _URC_CONTINUE_UNWIND) && !isSpawnHelper && !skip_leaveframe) { - __cilkrts_pop_frame(sf); __cilkrts_leave_frame(sf); } diff --git a/runtime/readydeque.c b/runtime/readydeque.c deleted file mode 100644 index c8f49c42..00000000 --- a/runtime/readydeque.c +++ /dev/null @@ -1,184 +0,0 @@ -#include "readydeque.h" -#include "closure.h" -#include "debug.h" -#include "global.h" -#include "local.h" - -/********************************************************* - * Management of ReadyDeques - *********************************************************/ - -void deque_assert_ownership(__cilkrts_worker *const w, worker_id pn) { - CILK_ASSERT(w, w->g->deques[pn].mutex_owner == w->self); -} - -void deque_lock_self(__cilkrts_worker *const w) { - struct local_state *l = w->l; - worker_id id = w->self; - global_state *g = w->g; - l->lock_wait = true; - cilk_mutex_lock(&g->deques[id].mutex); - l->lock_wait = false; - g->deques[id].mutex_owner = id; -} - -void deque_unlock_self(__cilkrts_worker *const w) { - worker_id id = w->self; - global_state *g = w->g; - g->deques[id].mutex_owner = NO_WORKER; - cilk_mutex_unlock(&g->deques[id].mutex); -} - -int deque_trylock(__cilkrts_worker *const w, worker_id pn) { - global_state *g = w->g; - int ret = cilk_mutex_try(&g->deques[pn].mutex); - if (ret) { - g->deques[pn].mutex_owner = w->self; - } - return ret; -} - -void deque_lock(__cilkrts_worker *const w, worker_id pn) { - global_state *g = w->g; - struct local_state *l = w->l; - l->lock_wait = true; - cilk_mutex_lock(&g->deques[pn].mutex); - l->lock_wait = false; - g->deques[pn].mutex_owner = w->self; -} - -void deque_unlock(__cilkrts_worker *const w, worker_id pn) { - global_state *g = w->g; - g->deques[pn].mutex_owner = NO_WORKER; - cilk_mutex_unlock(&w->g->deques[pn].mutex); -} - -/* - * functions that add/remove elements from the top/bottom - * of deques - * - * ANGE: the precondition of these functions is that the worker w -> self - * must have locked worker pn's deque before entering the function - */ -Closure *deque_xtract_top(__cilkrts_worker *const w, worker_id pn) { - - Closure *cl; - - /* ANGE: make sure w has the lock on worker pn's deque */ - deque_assert_ownership(w, pn); - - cl = w->g->deques[pn].top; - if (cl) { - CILK_ASSERT(w, cl->owner_ready_deque == pn); - w->g->deques[pn].top = cl->next_ready; - /* ANGE: if there is only one entry in the deque ... */ - if (cl == w->g->deques[pn].bottom) { - CILK_ASSERT(w, cl->next_ready == (Closure *)NULL); - w->g->deques[pn].bottom = (Closure *)NULL; - } else { - CILK_ASSERT(w, cl->next_ready); - (cl->next_ready)->prev_ready = (Closure *)NULL; - } - WHEN_CILK_DEBUG(cl->owner_ready_deque = NO_WORKER); - } else { - CILK_ASSERT(w, w->g->deques[pn].bottom == (Closure *)NULL); - } - - return cl; -} - -Closure *deque_peek_top(__cilkrts_worker *const w, worker_id pn) { - - Closure *cl; - - /* ANGE: make sure w has the lock on worker pn's deque */ - deque_assert_ownership(w, pn); - - /* ANGE: return the top but does not unlink it from the rest */ - cl = w->g->deques[pn].top; - if (cl) { - // If w is stealing, then it may peek the top of the deque of the worker - // who is in the midst of exiting a Cilkified region. In that case, cl - // will be the root closure, and cl->owner_ready_deque is not - // necessarily pn. The steal will subsequently fail do_dekker_on. - CILK_ASSERT(w, cl->owner_ready_deque == pn || - (w->self != pn && cl == w->g->root_closure)); - } else { - CILK_ASSERT(w, w->g->deques[pn].bottom == (Closure *)NULL); - } - - return cl; -} - -Closure *deque_xtract_bottom(__cilkrts_worker *const w, worker_id pn) { - - Closure *cl; - - /* ANGE: make sure w has the lock on worker pn's deque */ - deque_assert_ownership(w, pn); - - cl = w->g->deques[pn].bottom; - if (cl) { - CILK_ASSERT(w, cl->owner_ready_deque == pn); - w->g->deques[pn].bottom = cl->prev_ready; - if (cl == w->g->deques[pn].top) { - CILK_ASSERT(w, cl->prev_ready == (Closure *)NULL); - w->g->deques[pn].top = (Closure *)NULL; - } else { - CILK_ASSERT(w, cl->prev_ready); - (cl->prev_ready)->next_ready = (Closure *)NULL; - } - - WHEN_CILK_DEBUG(cl->owner_ready_deque = NO_WORKER); - } else { - CILK_ASSERT(w, w->g->deques[pn].top == (Closure *)NULL); - } - - return cl; -} - -Closure *deque_peek_bottom(__cilkrts_worker *const w, worker_id pn) { - - Closure *cl; - - /* ANGE: make sure w has the lock on worker pn's deque */ - deque_assert_ownership(w, pn); - - cl = w->g->deques[pn].bottom; - if (cl) { - CILK_ASSERT(w, cl->owner_ready_deque == pn); - } else { - CILK_ASSERT(w, w->g->deques[pn].top == (Closure *)NULL); - } - - return cl; -} - -void deque_assert_is_bottom(__cilkrts_worker *const w, Closure *t) { - - /* ANGE: still need to make sure the worker self has the lock */ - deque_assert_ownership(w, w->self); - CILK_ASSERT(w, t == deque_peek_bottom(w, w->self)); -} - -/* - * ANGE: this allow w -> self to append Closure cl onto worker pn's ready - * deque (i.e. make cl the new bottom). - */ -void deque_add_bottom(__cilkrts_worker *const w, Closure *cl, worker_id pn) { - - deque_assert_ownership(w, pn); - CILK_ASSERT(w, cl->owner_ready_deque == NO_WORKER); - - cl->prev_ready = w->g->deques[pn].bottom; - cl->next_ready = (Closure *)NULL; - w->g->deques[pn].bottom = cl; - WHEN_CILK_DEBUG(cl->owner_ready_deque = pn); - - if (w->g->deques[pn].top) { - CILK_ASSERT(w, cl->prev_ready); - (cl->prev_ready)->next_ready = cl; - } else { - w->g->deques[pn].top = cl; - } -} diff --git a/runtime/readydeque.h b/runtime/readydeque.h index 608c4589..ba48eeb5 100644 --- a/runtime/readydeque.h +++ b/runtime/readydeque.h @@ -1,7 +1,7 @@ #ifndef _READYDEQUE_H #define _READYDEQUE_H -#include "closure.h" +#include "closure-type.h" #include "rts-config.h" // Forward declaration @@ -11,6 +11,10 @@ typedef struct ReadyDeque ReadyDeque; #include "cilk-internal.h" #include "mutex.h" +#include "debug.h" +#include "global.h" +#include "local.h" + // Actual declaration struct ReadyDeque { cilk_mutex mutex; @@ -18,40 +22,195 @@ struct ReadyDeque { worker_id mutex_owner; } __attribute__((aligned(CILK_CACHE_LINE))); -// assert that pn's deque be locked by ourselves -CHEETAH_INTERNAL void deque_assert_ownership(__cilkrts_worker *const w, - worker_id pn); -CHEETAH_INTERNAL void deque_lock_self(__cilkrts_worker *const w); -CHEETAH_INTERNAL void deque_unlock_self(__cilkrts_worker *const w); -CHEETAH_INTERNAL int deque_trylock(__cilkrts_worker *const w, worker_id pn); -CHEETAH_INTERNAL void deque_lock(__cilkrts_worker *const w, worker_id pn); -CHEETAH_INTERNAL void deque_unlock(__cilkrts_worker *const w, worker_id pn); +/********************************************************* + * Management of ReadyDeques + *********************************************************/ + +static inline +void deque_assert_ownership(__cilkrts_worker *const w, worker_id pn) { + CILK_ASSERT(w, w->g->deques[pn].mutex_owner == w->self); +} + +static inline +void deque_lock_self(__cilkrts_worker *const w) { + struct local_state *l = w->l; + worker_id id = w->self; + global_state *g = w->g; + l->lock_wait = true; + cilk_mutex_lock(&g->deques[id].mutex); + l->lock_wait = false; + g->deques[id].mutex_owner = id; +} + +static inline +void deque_unlock_self(__cilkrts_worker *const w) { + worker_id id = w->self; + global_state *g = w->g; + g->deques[id].mutex_owner = NO_WORKER; + cilk_mutex_unlock(&g->deques[id].mutex); +} + +static inline +int deque_trylock(__cilkrts_worker *const w, worker_id pn) { + global_state *g = w->g; + int ret = cilk_mutex_try(&g->deques[pn].mutex); + if (ret) { + g->deques[pn].mutex_owner = w->self; + } + return ret; +} + +static inline +void deque_lock(__cilkrts_worker *const w, worker_id pn) { + global_state *g = w->g; + struct local_state *l = w->l; + l->lock_wait = true; + cilk_mutex_lock(&g->deques[pn].mutex); + l->lock_wait = false; + g->deques[pn].mutex_owner = w->self; +} + +static inline +void deque_unlock(__cilkrts_worker *const w, worker_id pn) { + global_state *g = w->g; + g->deques[pn].mutex_owner = NO_WORKER; + cilk_mutex_unlock(&w->g->deques[pn].mutex); +} /* - * functions that add/remove elements from the top/bottom of deques + * functions that add/remove elements from the top/bottom + * of deques * * ANGE: the precondition of these functions is that the worker w -> self * must have locked worker pn's deque before entering the function */ -CHEETAH_INTERNAL -Closure *deque_xtract_top(__cilkrts_worker *const w, worker_id pn); +static inline +Closure *deque_xtract_top(__cilkrts_worker *const w, worker_id pn) { + + Closure *cl; + + /* ANGE: make sure w has the lock on worker pn's deque */ + deque_assert_ownership(w, pn); + + cl = w->g->deques[pn].top; + if (cl) { + CILK_ASSERT(w, cl->owner_ready_deque == pn); + w->g->deques[pn].top = cl->next_ready; + /* ANGE: if there is only one entry in the deque ... */ + if (cl == w->g->deques[pn].bottom) { + CILK_ASSERT(w, cl->next_ready == (Closure *)NULL); + w->g->deques[pn].bottom = (Closure *)NULL; + } else { + CILK_ASSERT(w, cl->next_ready); + (cl->next_ready)->prev_ready = (Closure *)NULL; + } + WHEN_CILK_DEBUG(cl->owner_ready_deque = NO_WORKER); + } else { + CILK_ASSERT(w, w->g->deques[pn].bottom == (Closure *)NULL); + } + + return cl; +} + +static inline +Closure *deque_peek_top(__cilkrts_worker *const w, worker_id pn) { + + Closure *cl; + + /* ANGE: make sure w has the lock on worker pn's deque */ + deque_assert_ownership(w, pn); + + /* ANGE: return the top but does not unlink it from the rest */ + cl = w->g->deques[pn].top; + if (cl) { + // If w is stealing, then it may peek the top of the deque of the worker + // who is in the midst of exiting a Cilkified region. In that case, cl + // will be the root closure, and cl->owner_ready_deque is not + // necessarily pn. The steal will subsequently fail do_dekker_on. + CILK_ASSERT(w, cl->owner_ready_deque == pn || + (w->self != pn && cl == w->g->root_closure)); + } else { + CILK_ASSERT(w, w->g->deques[pn].bottom == (Closure *)NULL); + } -CHEETAH_INTERNAL -Closure *deque_peek_top(__cilkrts_worker *const w, worker_id pn); + return cl; +} -CHEETAH_INTERNAL -Closure *deque_xtract_bottom(__cilkrts_worker *const w, worker_id pn); +static inline +Closure *deque_xtract_bottom(__cilkrts_worker *const w, worker_id pn) { -CHEETAH_INTERNAL -Closure *deque_peek_bottom(__cilkrts_worker *const w, worker_id pn); + Closure *cl; + + /* ANGE: make sure w has the lock on worker pn's deque */ + deque_assert_ownership(w, pn); + + cl = w->g->deques[pn].bottom; + if (cl) { + CILK_ASSERT(w, cl->owner_ready_deque == pn); + w->g->deques[pn].bottom = cl->prev_ready; + if (cl == w->g->deques[pn].top) { + CILK_ASSERT(w, cl->prev_ready == (Closure *)NULL); + w->g->deques[pn].top = (Closure *)NULL; + } else { + CILK_ASSERT(w, cl->prev_ready); + (cl->prev_ready)->next_ready = (Closure *)NULL; + } + + WHEN_CILK_DEBUG(cl->owner_ready_deque = NO_WORKER); + } else { + CILK_ASSERT(w, w->g->deques[pn].top == (Closure *)NULL); + } + + return cl; +} + +static inline +Closure *deque_peek_bottom(__cilkrts_worker *const w, worker_id pn) { + + Closure *cl; + + /* ANGE: make sure w has the lock on worker pn's deque */ + deque_assert_ownership(w, pn); + + cl = w->g->deques[pn].bottom; + if (cl) { + CILK_ASSERT(w, cl->owner_ready_deque == pn); + } else { + CILK_ASSERT(w, w->g->deques[pn].top == (Closure *)NULL); + } + + return cl; +} + +static inline +void deque_assert_is_bottom(__cilkrts_worker *const w, Closure *t) { + + /* ANGE: still need to make sure the worker self has the lock */ + deque_assert_ownership(w, w->self); + CILK_ASSERT(w, t == deque_peek_bottom(w, w->self)); +} /* * ANGE: this allow w -> self to append Closure cl onto worker pn's ready * deque (i.e. make cl the new bottom). */ -CHEETAH_INTERNAL void deque_add_bottom(__cilkrts_worker *const w, Closure *cl, - worker_id pn); +static inline +void deque_add_bottom(__cilkrts_worker *const w, Closure *cl, worker_id pn) { + + deque_assert_ownership(w, pn); + CILK_ASSERT(w, cl->owner_ready_deque == NO_WORKER); + + cl->prev_ready = w->g->deques[pn].bottom; + cl->next_ready = (Closure *)NULL; + w->g->deques[pn].bottom = cl; + WHEN_CILK_DEBUG(cl->owner_ready_deque = pn); + + if (w->g->deques[pn].top) { + CILK_ASSERT(w, cl->prev_ready); + (cl->prev_ready)->next_ready = cl; + } else { + w->g->deques[pn].top = cl; + } +} -CHEETAH_INTERNAL void deque_assert_is_bottom(__cilkrts_worker *const w, - Closure *t); #endif diff --git a/runtime/rts-config.h b/runtime/rts-config.h index 30a95f5a..63bc2978 100644 --- a/runtime/rts-config.h +++ b/runtime/rts-config.h @@ -22,8 +22,17 @@ #ifndef CILK_DEBUG #define CILK_DEBUG 1 -#endif +#endif + +#ifndef CILK_ENABLE_ASAN_HOOKS +#define CILK_ENABLE_ASAN_HOOKS 0 +#endif + +#ifndef CILK_STATS #define CILK_STATS 0 +#endif + +#define BOSS_THIEF 1 #define CILK_CACHE_LINE 64 @@ -39,7 +48,6 @@ #define MIN_NUM_PAGES_PER_STACK 4 #define MAX_NUM_PAGES_PER_STACK 2000 -#define DEFAULT_STACKSIZE 0x100000 // 1 MBytes /* The largest known stack alignment requirement is for AVX-512 which may access memory in aligned 64 byte units. */ @@ -48,7 +56,7 @@ #define DEFAULT_NPROC 0 // 0 for # of cores available #define DEFAULT_DEQ_DEPTH 1024 #define DEFAULT_STACK_SIZE 0x100000 // 1 MBytes -#define DEFAULT_FIBER_POOL_CAP 128 // initial per-worker fiber pool capacity +#define DEFAULT_FIBER_POOL_CAP 3 // initial per-worker fiber pool capacity #define DEFAULT_REDUCER_LIMIT 1024 #define DEFAULT_FORCE_REDUCE 0 // do not self steal to force reduce diff --git a/runtime/sched_stats.c b/runtime/sched_stats.c index 7195a118..bbf7f116 100644 --- a/runtime/sched_stats.c +++ b/runtime/sched_stats.c @@ -1,7 +1,9 @@ #include +#include #include "cilk-internal.h" #include "debug.h" +#include "global.h" #include "internal-malloc-impl.h" #include "local.h" #include "sched_stats.h" @@ -15,8 +17,16 @@ static const char *enum_to_str(enum timing_type t) { return "scheduling"; case INTERVAL_IDLE: return "idling"; + case INTERVAL_SLEEP: + return "sleep (sched)"; + case INTERVAL_SLEEP_UNCILK: + return "sleep (uncilk)"; + case INTERVAL_CILKIFY_ENTER: + return "cilkify (enter)"; + case INTERVAL_CILKIFY_EXIT: + return "cilkify (exit)"; default: - return "unknonw"; + return "unknown"; } } @@ -49,9 +59,33 @@ static inline uint64_t end_cycle_count() { return ((uint64_t)high << 32) | low; } +static inline double nsec_to_sec(uint64_t nsec) { return nsec / 1.0e9; } + +static inline uint64_t begin_time() { + struct timespec res; + clock_gettime(CLOCK_MONOTONIC, &res); + return (res.tv_sec * 1e9) + (res.tv_nsec); +} + +static inline uint64_t end_time() { + struct timespec res; + clock_gettime(CLOCK_MONOTONIC, &res); + return (res.tv_sec * 1e9) + (res.tv_nsec); +} + +int nr_events = 32; + void cilk_global_sched_stats_init(struct global_sched_stats *s) { + s->boss_waiting = 0; + s->boss_wait_count = 0; + s->boss_begin = 0; + s->boss_end = 0; + s->exit_time = 0; + s->steals = 0; + s->repos = 0; for (int i = 0; i < NUMBER_OF_STATS; ++i) { s->time[i] = 0.0; + s->count[i] = 0; } } @@ -60,7 +94,10 @@ void cilk_sched_stats_init(struct sched_stats *s) { s->begin[i] = 0; s->end[i] = 0; s->time[i] = 0; + s->count[i] = 0; } + s->steals = 0; + s->repos = 0; } void cilk_start_timing(__cilkrts_worker *w, enum timing_type t) { @@ -68,7 +105,7 @@ void cilk_start_timing(__cilkrts_worker *w, enum timing_type t) { struct sched_stats *s = &(w->l->stats); CILK_ASSERT(w, s->begin[t] == 0); s->end[t] = 0; - s->begin[t] = begin_cycle_count(); + s->begin[t] = begin_time(); } } @@ -76,13 +113,33 @@ void cilk_stop_timing(__cilkrts_worker *w, enum timing_type t) { if (w) { struct sched_stats *s = &(w->l->stats); CILK_ASSERT(w, s->end[t] == 0); - s->end[t] = end_cycle_count(); - CILK_ASSERT(w, s->end[t] > s->begin[t]); + s->end[t] = end_time(); + CILK_ASSERT(w, s->end[t] >= s->begin[t]); s->time[t] += (s->end[t] - s->begin[t]); + s->count[t]++; s->begin[t] = 0; } } +void cilk_switch_timing(__cilkrts_worker *w, enum timing_type t1, + enum timing_type t2) { + if (w) { + struct sched_stats *s = &(w->l->stats); + // Stop timer t1 + CILK_ASSERT(w, s->end[t1] == 0); + s->end[t1] = end_time(); + CILK_ASSERT(w, s->end[t1] >= s->begin[t1]); + s->time[t1] += (s->end[t1] - s->begin[t1]); + s->count[t1]++; + s->begin[t1] = 0; + + // Start timer t2 where t1 left off + CILK_ASSERT(w, s->begin[t2] == 0); + s->end[t2] = 0; + s->begin[t2] = begin_time(); + } +} + void cilk_drop_timing(__cilkrts_worker *w, enum timing_type t) { if (w) { struct sched_stats *s = &(w->l->stats); @@ -91,36 +148,95 @@ void cilk_drop_timing(__cilkrts_worker *w, enum timing_type t) { } } +void cilk_boss_start_timing(struct global_state *g) { + struct global_sched_stats *s = &(g->stats); + CILK_ASSERT_G(s->boss_begin == 0); + s->boss_begin = begin_time(); + s->boss_end = 0; +} + +void cilk_boss_stop_timing(struct global_state *g) { + struct global_sched_stats *s = &(g->stats); + CILK_ASSERT_G(s->boss_end == 0); + s->boss_end = end_time(); + CILK_ASSERT_G(s->boss_end >= s->boss_begin); + CILK_ASSERT_G(s->boss_end >= s->exit_time); + uint64_t last = s->exit_time > s->boss_begin ? s->exit_time : s->boss_begin; + s->boss_waiting += (s->boss_end - last); + s->boss_wait_count++; + s->boss_begin = 0; + s->exit_time = 0; +} + +void cilk_exit_worker_timing(struct global_state *g) { + struct global_sched_stats *s = &(g->stats); + CILK_ASSERT_G(s->exit_time == 0); + s->exit_time = begin_time(); +} + +static void sched_stats_reset_worker(__cilkrts_worker *w, + void *data __attribute__((unused))) { + for (int t = 0; t < NUMBER_OF_STATS; t++) { + w->l->stats.time[t] = 0; + w->l->stats.count[t] = 0; + } + w->l->stats.steals = 0; + w->l->stats.repos = 0; +} + +#define COL_DESC "%15s" +#define HDR_DESC "%18s %8s" +#define WORKER_HDR_DESC "%10s %3u:" +#define FIELD_DESC "%18.6f %8ld" + static void sched_stats_print_worker(__cilkrts_worker *w, void *data) { FILE *fp = (FILE *)data; fprintf(fp, WORKER_HDR_DESC, "Worker", w->self); for (int t = 0; t < NUMBER_OF_STATS; t++) { - double tmp = cycles_to_micro_sec(w->l->stats.time[t]); - g->stats.time[t] += (double)tmp; - fprintf(fp, FIELD_DESC, micro_sec_to_sec(tmp)); + double tmp = nsec_to_sec(w->l->stats.time[t]); + w->g->stats.time[t] += (double)tmp; + uint64_t tmp_count = w->l->stats.count[t]; + w->g->stats.count[t] += tmp_count; + fprintf(fp, FIELD_DESC, tmp, tmp_count); } + w->g->stats.steals += w->l->stats.steals; + w->g->stats.repos += w->l->stats.repos; fprintf(fp, "\n"); } void cilk_sched_stats_print(struct global_state *g) { -#define HDR_DESC "%15s" -#define WORKER_HDR_DESC "%10s %3u:" -#define FIELD_DESC "%15.3f" + for (int t = 0; t < NUMBER_OF_STATS; t++) { + g->stats.time[t] = 0.0; + g->stats.count[t] = 0; + } + g->stats.steals = 0; + g->stats.repos = 0; fprintf(stderr, "\nSCHEDULING STATS (SECONDS):\n"); - fprintf(stderr, HDR_DESC, ""); + { + fprintf(stderr, COL_DESC, "Boss waiting:"); + double tmp = nsec_to_sec(g->stats.boss_waiting); + fprintf(stderr, FIELD_DESC, tmp, g->stats.boss_wait_count); + fprintf(stderr, "\n"); + g->stats.boss_waiting = 0; + g->stats.boss_wait_count = 0; + } + fprintf(stderr, COL_DESC, ""); for (int t = 0; t < NUMBER_OF_STATS; t++) { - fprintf(stderr, HDR_DESC, enum_to_str(t)); + fprintf(stderr, HDR_DESC, enum_to_str(t), "count"); } fprintf(stderr, "\n"); for_each_worker(g, &sched_stats_print_worker, stderr); - fprintf(stderr, HDR_DESC, "Total:"); + fprintf(stderr, COL_DESC, "Total:"); for (int t = 0; t < NUMBER_OF_STATS; t++) { - fprintf(stderr, FIELD_DESC, micro_sec_to_sec(g->stats.time[t])); + fprintf(stderr, FIELD_DESC, g->stats.time[t], g->stats.count[t]); } fprintf(stderr, "\n"); + + for_each_worker(g, &sched_stats_reset_worker, NULL); + } /* @@ -142,3 +258,7 @@ void cilk_reset_timing() { } */ #endif + +void __cilkrts_sched_stats_print(void) { + WHEN_SCHED_STATS(cilk_sched_stats_print(default_cilkrts)); +} diff --git a/runtime/sched_stats.h b/runtime/sched_stats.h index f798aa37..a2df087a 100644 --- a/runtime/sched_stats.h +++ b/runtime/sched_stats.h @@ -12,17 +12,34 @@ enum timing_type { INTERVAL_WORK = 0, // work time INTERVAL_SCHED, // scheduling time INTERVAL_IDLE, // idle time + INTERVAL_SLEEP, // spleeing time in work-stealing loop + INTERVAL_SLEEP_UNCILK, // spleeing time outside of work-stealing loop + INTERVAL_CILKIFY_ENTER, // time entering cilkified regions + INTERVAL_CILKIFY_EXIT, // time exiting cilkified regions NUMBER_OF_STATS // must be the very last entry }; struct sched_stats { uint64_t time[NUMBER_OF_STATS]; // Total time measured for all stats + uint64_t count[NUMBER_OF_STATS]; uint64_t begin[NUMBER_OF_STATS]; // Begin time of current measurement uint64_t end[NUMBER_OF_STATS]; // End time of current measurement + + uint64_t steals; + uint64_t repos; }; struct global_sched_stats { + // Stats for the boss thread + uint64_t boss_waiting; + uint64_t boss_wait_count; + uint64_t boss_begin; + uint64_t exit_time; + uint64_t boss_end; + uint64_t steals; + uint64_t repos; double time[NUMBER_OF_STATS]; // Total time measured for all stats + uint64_t count[NUMBER_OF_STATS]; }; #if SCHED_STATS @@ -35,8 +52,17 @@ void cilk_start_timing(__cilkrts_worker *w, enum timing_type t); CHEETAH_INTERNAL void cilk_stop_timing(__cilkrts_worker *w, enum timing_type t); CHEETAH_INTERNAL +void cilk_switch_timing(__cilkrts_worker *w, enum timing_type t1, + enum timing_type t2); +CHEETAH_INTERNAL void cilk_drop_timing(__cilkrts_worker *w, enum timing_type t); CHEETAH_INTERNAL +void cilk_boss_start_timing(struct global_state *g); +CHEETAH_INTERNAL +void cilk_boss_stop_timing(struct global_state *g); +CHEETAH_INTERNAL +void cilk_exit_worker_timing(struct global_state *g); +CHEETAH_INTERNAL void cilk_sched_stats_print(struct global_state *g); // void cilk_reset_timing(__cilkrts_worker *w, enum timing_type t); // FIXME: should have a header file that's user-code interfacing @@ -45,7 +71,11 @@ void cilk_sched_stats_print(struct global_state *g); #define WHEN_SCHED_STATS(ex) ex #define CILK_START_TIMING(w, t) cilk_start_timing(w, t) #define CILK_STOP_TIMING(w, t) cilk_stop_timing(w, t) +#define CILK_SWITCH_TIMING(w, t1, t2) cilk_switch_timing(w, t1, t2) #define CILK_DROP_TIMING(w, t) cilk_drop_timing(w, t) +#define CILK_BOSS_START_TIMING(g) cilk_boss_start_timing(g) +#define CILK_BOSS_STOP_TIMING(g) cilk_boss_stop_timing(g) +#define CILK_EXIT_WORKER_TIMING(g) cilk_exit_worker_timing(g) #else #define cilk_global_sched_stats_init(s) @@ -56,7 +86,11 @@ void cilk_sched_stats_print(struct global_state *g); #define WHEN_SCHED_STATS(ex) #define CILK_START_TIMING(w, t) #define CILK_STOP_TIMING(w, t) +#define CILK_SWITCH_TIMING(w, t1, t2) #define CILK_DROP_TIMING(w, t) +#define CILK_BOSS_START_TIMING(g) +#define CILK_BOSS_STOP_TIMING(g) +#define CILK_EXIT_WORKER_TIMING(g) #endif // SCHED_STATS #endif // __SCHED_STATS_HEADER__ diff --git a/runtime/scheduler.c b/runtime/scheduler.c index 1e7b8dd8..90379d70 100644 --- a/runtime/scheduler.c +++ b/runtime/scheduler.c @@ -4,7 +4,7 @@ #include #endif #include -#include /* usleep */ +#include #include #include "cilk-internal.h" @@ -15,10 +15,12 @@ #include "local.h" #include "readydeque.h" #include "scheduler.h" +#include "worker_coord.h" #include "reducer_impl.h" __thread __cilkrts_worker *tls_worker = NULL; +__thread bool is_boss_thread = false; // ============================================== // Misc. helper functions @@ -27,15 +29,15 @@ __thread __cilkrts_worker *tls_worker = NULL; /*********************************************************** * Internal random number generator. ***********************************************************/ -static unsigned int rts_rand(__cilkrts_worker *const w) { - w->l->rand_next = w->l->rand_next * 1103515245 + 12345; - return (w->l->rand_next >> 16); -} - static void rts_srand(__cilkrts_worker *const w, unsigned int seed) { w->l->rand_next = seed; } +static unsigned int rts_rand(local_state *l) { + l->rand_next = l->rand_next * 1103515245 + 12345; + return (l->rand_next >> 16); +} + static void worker_change_state(__cilkrts_worker *w, enum __cilkrts_worker_state s) { /* TODO: Update statistics based on state change. */ @@ -107,7 +109,7 @@ static void signal_immediate_exception_to_all(__cilkrts_worker *const w) { static void setup_for_execution(__cilkrts_worker *w, Closure *t) { cilkrts_alert(SCHED, w, "(setup_for_execution) closure %p", (void *)t); - t->frame->worker = w; + atomic_store_explicit(&t->frame->worker, w, memory_order_relaxed); Closure_set_status(w, t, CLOSURE_RUNNING); __cilkrts_stack_frame **init = w->l->shadow_stack; @@ -155,7 +157,7 @@ static void setup_for_sync(__cilkrts_worker *w, Closure *t) { SP(t->frame) = (void *)t->orig_rsp; t->orig_rsp = NULL; // unset once we have sync-ed - t->frame->worker = w; + atomic_store_explicit(&t->frame->worker, w, memory_order_relaxed); } // ============================================== @@ -169,10 +171,6 @@ CHEETAH_INTERNAL void __cilkrts_init_tls_variables() { CILK_ASSERT_G(status == 0); } -void *__cilkrts_get_current_thread_id() { return (void *)pthread_self(); } - -__cilkrts_worker *__cilkrts_get_tls_worker() { return tls_worker; } - CHEETAH_INTERNAL void __cilkrts_set_tls_worker(__cilkrts_worker *w) { tls_worker = w; } @@ -189,14 +187,14 @@ static Closure *setup_call_parent_resumption(__cilkrts_worker *const w, Closure_assert_ownership(w, t); CILK_ASSERT_POINTER_EQUAL(w, w, __cilkrts_get_tls_worker()); - CILK_ASSERT(w, __cilkrts_stolen(t->frame) != 0); CILK_ASSERT(w, t->frame != NULL); + CILK_ASSERT(w, __cilkrts_stolen(t->frame) != 0); CILK_ASSERT(w, ((intptr_t)t->frame->worker) & 1); CILK_ASSERT_POINTER_EQUAL(w, w->head, w->tail); CILK_ASSERT_POINTER_EQUAL(w, w->current_stack_frame, t->frame); Closure_change_status(w, t, CLOSURE_SUSPENDED, CLOSURE_RUNNING); - t->frame->worker = w; + atomic_store_explicit(&t->frame->worker, w, memory_order_relaxed); reset_exception_pointer(w, t); return t; @@ -241,6 +239,10 @@ void Cilk_set_return(__cilkrts_worker *const w) { setup_call_parent_resumption(w, call_parent); Closure_unlock(w, call_parent); + if (t->saved_throwing_fiber) { + cilk_fiber_deallocate_to_pool(w, t->saved_throwing_fiber); + t->saved_throwing_fiber = NULL; + } Closure_destroy(w, t); deque_add_bottom(w, call_parent, w->self); @@ -264,7 +266,7 @@ static Closure *unconditional_steal(__cilkrts_worker *const w, CILK_ASSERT(w, parent->status == CLOSURE_SUSPENDED); CILK_ASSERT(w, parent->frame != NULL); - CILK_ASSERT(w, parent->frame->worker == (__cilkrts_worker *)0xbfbfbfbfbf); + CILK_ASSERT(w, parent->frame->worker == INVALID); CILK_ASSERT(w, parent->owner_ready_deque == NO_WORKER); CILK_ASSERT(w, (parent->fiber == NULL) && parent->fiber_child); parent->fiber = parent->fiber_child; @@ -334,8 +336,7 @@ static Closure *provably_good_steal_maybe(__cilkrts_worker *const w, * This function returns a closure to be executed next, or NULL if none. * The child must not be locked by ourselves, and be in no deque. ***/ -CHEETAH_INTERNAL -Closure *Closure_return(__cilkrts_worker *const w, Closure *child) { +static Closure *Closure_return(__cilkrts_worker *const w, Closure *child) { Closure *res = (Closure *)NULL; Closure *const parent = child->spawn_parent; @@ -368,91 +369,84 @@ Closure *Closure_return(__cilkrts_worker *const w, Closure *child) { Closure_lock(w, parent); Closure_lock(w, child); - // "Reduce" exceptions. Deallocate any exception objects and other fibers - // that have been reduced away. - while (1) { + // Deal with reducers and exceptions. We do both in the same loop to ensure + // that we end up with a consistent view of reducers and exceptions in + // parent and sibling closures. To "reduce" exceptions, deallocate any + // exception objects and other fibers that have been reduced away. + while (true) { // invariant: a closure cannot unlink itself w/out lock on parent // so what this points to cannot change while we have lock on parent + // Get the right-sibling hypermap and exception. + cilkred_map *right = + atomic_load_explicit(&child->right_rmap, memory_order_acquire); + atomic_store_explicit(&child->right_rmap, NULL, memory_order_relaxed); struct closure_exception right_exn = child->right_exn; clear_closure_exception(&(child->right_exn)); - struct closure_exception left_exn; + // Get the "left" hypermap and exception, which either belongs to a + // left sibling, if it exists, or the parent, otherwise. + _Atomic(cilkred_map *) volatile *left_ptr; + struct closure_exception *left_exn_ptr; Closure *const left_sib = child->left_sib; - struct closure_exception *left_ptr; if (left_sib != NULL) { - left_exn = left_sib->right_exn; - left_ptr = &(left_sib->right_exn); - clear_closure_exception(left_ptr); + left_ptr = &left_sib->right_rmap; + left_exn_ptr = &left_sib->right_exn; } else { - left_exn = parent->child_exn; - left_ptr = &(parent->child_exn); - clear_closure_exception(left_ptr); + left_ptr = &parent->child_rmap; + left_exn_ptr = &parent->child_exn; } + cilkred_map *left = + atomic_load_explicit(left_ptr, memory_order_acquire); + atomic_store_explicit(left_ptr, NULL, memory_order_relaxed); + struct closure_exception left_exn = *left_exn_ptr; + clear_closure_exception(left_exn_ptr); - struct closure_exception active = child->user_exn; + // Get the current active hypermap and exception. + cilkred_map *active = w->reducer_map; + w->reducer_map = NULL; + struct closure_exception active_exn = child->user_exn; - if (left_exn.exn == NULL && right_exn.exn == NULL) { - *left_ptr = active; + // If we have no hypermaps or exceptions on either the left or right, + // deposit the active hypermap and exception and break from the loop. + if (left == NULL && right == NULL && left_exn.exn == NULL && + right_exn.exn == NULL) { + /* deposit views */ + atomic_store_explicit(left_ptr, active, memory_order_release); + *left_exn_ptr = active_exn; break; } Closure_unlock(w, child); Closure_unlock(w, parent); // clean up exception objects - // TODO: determine exactly when it's safe to clean up exception objects if (left_exn.exn) { - active = left_exn; + active_exn = left_exn; + // can safely delete any exceptions to the right of left_exn. if (child->user_exn.exn) { - // can safely delete this exception. _Unwind_DeleteException( (struct _Unwind_Exception *)child->user_exn.exn); + clear_closure_exception(&child->user_exn); } if (right_exn.exn) { _Unwind_DeleteException( (struct _Unwind_Exception *)right_exn.exn); + clear_closure_exception(&right_exn); } } else if (child->user_exn.exn) { + // can safely delete right_exn. if (right_exn.exn) { _Unwind_DeleteException( (struct _Unwind_Exception *)right_exn.exn); + clear_closure_exception(&right_exn); } - } else { - active = right_exn; + } else if (right_exn.exn) { + // save right_exn. + active_exn = right_exn; } + child->user_exn = active_exn; - child->user_exn = active; - Closure_lock(w, parent); - Closure_lock(w, child); - } - - while (1) { - // invariant: a closure cannot unlink itself w/out lock on parent - // so what this points to cannot change while we have lock on parent - cilkred_map *right = - atomic_load_explicit(&child->right_rmap, memory_order_acquire); - atomic_store_explicit(&child->right_rmap, NULL, memory_order_relaxed); - _Atomic(cilkred_map *) volatile *left_ptr; - Closure *const left_sib = child->left_sib; - if (left_sib != NULL) { - left_ptr = &left_sib->right_rmap; - } else { - left_ptr = &parent->child_rmap; - } - cilkred_map *left = - atomic_load_explicit(left_ptr, memory_order_acquire); - atomic_store_explicit(left_ptr, NULL, memory_order_relaxed); - - cilkred_map *active = w->reducer_map; - w->reducer_map = NULL; - - if (left == NULL && right == NULL) { - /* deposit views */ - atomic_store_explicit(left_ptr, active, memory_order_release); - break; - } - Closure_unlock(w, child); - Closure_unlock(w, parent); + // merge reducers if (left) { active = merge_two_rmaps(w, left, active); } @@ -521,6 +515,7 @@ Closure *Closure_return(__cilkrts_worker *const w, Closure *child) { if (active_exn.exn) { _Unwind_DeleteException( (struct _Unwind_Exception *)active_exn.exn); + clear_closure_exception(&active_exn); } parent->user_exn = child_exn; parent->frame->flags |= CILK_FRAME_EXCEPTION_PENDING; @@ -549,7 +544,7 @@ Closure *Closure_return(__cilkrts_worker *const w, Closure *child) { /* * ANGE: t is returning; call the return protocol; see comments above * Closure_return. res is either the next closure to execute - * (provably-good-steal the parent closure), or NULL is nothing should be + * (provably-good-steal the parent closure), or NULL if nothing should be * executed next. * * Only called from do_what_it_says when the closure->status = @@ -624,6 +619,7 @@ void Cilk_exception_handler(char *exn) { Closure_unlock(w, t); deque_unlock_self(w); + sanitizer_unpoison_fiber(t->fiber); longjmp_to_runtime(w); // NOT returning back to user code } else { // not steal, not abort; false alarm @@ -656,7 +652,7 @@ oldest_non_stolen_frame_in_stacklet(__cilkrts_stack_frame *head) { __cilkrts_stack_frame *cur = head; while (cur && (cur->flags & CILK_FRAME_DETACHED) == 0 && cur->call_parent && - __cilkrts_stolen(cur->call_parent) == 0) { + __cilkrts_not_stolen(cur->call_parent)) { cur = cur->call_parent; } @@ -685,7 +681,8 @@ static Closure *setup_call_parent_closure_helper( CILK_ASSERT(w, call_parent->fiber); Closure_set_status(w, curr_cl, CLOSURE_SUSPENDED); - curr_cl->frame->worker = (__cilkrts_worker *)0xbfbfbfbfbf; + atomic_store_explicit(&curr_cl->frame->worker, INVALID, + memory_order_relaxed); curr_cl->fiber = call_parent->fiber; Closure_add_callee(w, call_parent, curr_cl); @@ -727,7 +724,8 @@ static void setup_closures_in_stacklet(__cilkrts_worker *const w, oldest_cl->frame = oldest; } CILK_ASSERT(w, oldest->worker == victim_w); - oldest_cl->frame->worker = (__cilkrts_worker *)0xbfbfbfbf; + atomic_store_explicit(&oldest_cl->frame->worker, INVALID, + memory_order_relaxed); call_parent = setup_call_parent_closure_helper( w, victim_w, youngest->call_parent, oldest_cl); @@ -827,12 +825,11 @@ static Closure *promote_child(__cilkrts_worker *const w, CILK_ASSERT(w, frame_to_steal != NULL); // ANGE: if cl's frame is set AND equal to the frame at *HEAD, cl must be - // either the root frame (invoke_main) or have been stolen before. - // On the other hand, if cl's frame is not set, the top stacklet may contain - // one frame (the detached spawn helper resulted from spawning an - // expression) or more than one frame, where the right-most (oldest) frame - // is a spawn helper that called a Cilk function (regular cilk_spawn of - // function). + // either the root frame or have been stolen before. On the other hand, if + // cl's frame is not set, the top stacklet may contain one frame (the + // detached spawn helper resulted from spawning an expression) or more than + // one frame, where the right-most (oldest) frame is a spawn helper that + // called a Cilk function (regular cilk_spawn of function). if (cl->frame == frame_to_steal) { // stolen before CILK_ASSERT(w, __cilkrts_stolen(frame_to_steal)); spawn_parent = cl; @@ -953,7 +950,6 @@ static void finish_promote(__cilkrts_worker *const w, static Closure *extract_top_spawning_closure(__cilkrts_worker *const w, __cilkrts_worker *const victim_w, Closure *cl) { - Closure *res = NULL, *child; struct cilk_fiber *parent_fiber = cl->fiber; @@ -1012,8 +1008,9 @@ static Closure *Closure_steal(__cilkrts_worker *const w, int victim) { atomic_load_explicit(&victim_w->head, memory_order_relaxed); __cilkrts_stack_frame **tail = atomic_load_explicit(&victim_w->tail, memory_order_relaxed); - if (head >= tail) + if (head >= tail) { return NULL; + } } //----- EVENT_STEAL_ATTEMPT @@ -1043,7 +1040,7 @@ static Closure *Closure_steal(__cilkrts_worker *const w, int victim) { res = extract_top_spawning_closure(w, victim_w, cl); // at this point, more steals can happen from the victim. - deque_unlock(w, victim_w->self); + deque_unlock(w, victim); CILK_ASSERT(w, res->fiber); CILK_ASSERT(w, res->frame->worker == victim_w); @@ -1138,7 +1135,8 @@ void promote_own_deque(__cilkrts_worker *w) { finish_promote(w, w, res, has_frames_to_promote); Closure_set_status(w, res, CLOSURE_SUSPENDED); - res->frame->worker = (__cilkrts_worker *)0xbfbfbfbfbf; + atomic_store_explicit(&res->frame->worker, INVALID, + memory_order_relaxed); res->simulated_stolen = true; Closure_unlock(w, res); @@ -1184,7 +1182,7 @@ void longjmp_to_user_code(__cilkrts_worker *w, Closure *t) { // region. The closure has been completely setup at this point by // invoke_cilkified_root(). We just need jump to the user code. volatile bool *initialized = &w->g->root_closure_initialized; - if (t == w->g->root_closure && *initialized == 0) { + if (t == w->g->root_closure && *initialized == false) { *initialized = true; } else if (!t->simulated_stolen) { void *new_rsp = sysdep_reset_stack_for_resume(fiber, sf); @@ -1192,18 +1190,18 @@ void longjmp_to_user_code(__cilkrts_worker *w, Closure *t) { CILK_ASSERT(w, SP(sf) == new_rsp); } } - CILK_STOP_TIMING(w, INTERVAL_SCHED); - CILK_START_TIMING(w, INTERVAL_WORK); + CILK_SWITCH_TIMING(w, INTERVAL_SCHED, INTERVAL_WORK); + sanitizer_start_switch_fiber(fiber); sysdep_longjmp_to_sf(sf); } __attribute__((noreturn)) void longjmp_to_runtime(__cilkrts_worker *w) { cilkrts_alert(SCHED | ALERT_FIBER, w, "(longjmp_to_runtime)"); - CILK_STOP_TIMING(w, INTERVAL_WORK); - CILK_START_TIMING(w, INTERVAL_SCHED); + CILK_SWITCH_TIMING(w, INTERVAL_WORK, INTERVAL_SCHED); /* Can't change to WORKER_SCHED yet because the reducer map may still be set. */ + sanitizer_start_switch_fiber(NULL); __builtin_longjmp(w->l->rts_ctx, 1); } @@ -1291,6 +1289,7 @@ int Cilk_sync(__cilkrts_worker *const w, __cilkrts_stack_frame *frame) { if (t->user_exn.exn) { _Unwind_DeleteException( (struct _Unwind_Exception *)t->user_exn.exn); + clear_closure_exception(&t->user_exn); } t->user_exn = child_exn; clear_closure_exception(&(t->child_exn)); @@ -1305,116 +1304,323 @@ int Cilk_sync(__cilkrts_worker *const w, __cilkrts_stack_frame *frame) { } if (t->simulated_stolen) t->simulated_stolen = false; + + sanitizer_start_switch_fiber(t->fiber); } return res; } -static Closure *do_what_it_says(__cilkrts_worker *w, Closure *t) { - - Closure *res = NULL; +static void do_what_it_says(__cilkrts_worker *w, Closure *t) { __cilkrts_stack_frame *f; - cilkrts_alert(SCHED, w, "(do_what_it_says) closure %p", (void *)t); - Closure_lock(w, t); + do { + cilkrts_alert(SCHED, w, "(do_what_it_says) closure %p", (void *)t); + Closure_lock(w, t); + + switch (t->status) { + case CLOSURE_READY: + // ANGE: anything we need to free must have been freed at this point + CILK_ASSERT(w, w->l->fiber_to_free == NULL); + + cilkrts_alert(SCHED, w, "(do_what_it_says) CLOSURE_READY"); + /* just execute it */ + setup_for_execution(w, t); + f = t->frame; + // t->fiber->resume_sf = f; // I THINK this works + cilkrts_alert(SCHED, w, "(do_what_it_says) resume_sf = %p", + (void *)f); + CILK_ASSERT(w, f); + USE_UNUSED(f); + Closure_unlock(w, t); + + // MUST unlock the closure before locking the queue + // (rule A in file PROTOCOLS) + deque_lock_self(w); + deque_add_bottom(w, t, w->self); + deque_unlock_self(w); - switch (t->status) { - case CLOSURE_READY: - // ANGE: anything we need to free must have been freed at this point - CILK_ASSERT(w, w->l->fiber_to_free == NULL); - - cilkrts_alert(SCHED, w, "(do_what_it_says) CLOSURE_READY"); - /* just execute it */ - setup_for_execution(w, t); - f = t->frame; - // t->fiber->resume_sf = f; // I THINK this works - cilkrts_alert(SCHED, w, "(do_what_it_says) resume_sf = %p", (void *)f); - CILK_ASSERT(w, f); - USE_UNUSED(f); - Closure_unlock(w, t); + /* now execute it */ + cilkrts_alert(SCHED, w, "(do_what_it_says) Jump into user code"); + + // CILK_ASSERT(w, w->l->runtime_fiber != t->fiber); + // cilk_fiber_suspend_self_and_resume_other(w->l->runtime_fiber, + // t->fiber); + // cilkrts_alert(SCHED, w, "(do_what_it_says) Back from user + // code"); + // longjmp invalidates non-volatile variables + __cilkrts_worker *volatile w_save = w; + if (__builtin_setjmp(w->l->rts_ctx) == 0) { + worker_change_state(w, WORKER_RUN); + longjmp_to_user_code(w, t); + } else { + w = w_save; + CILK_ASSERT_POINTER_EQUAL(w, w, __cilkrts_get_tls_worker()); + sanitizer_finish_switch_fiber(); + worker_change_state(w, WORKER_SCHED); + // CILK_ASSERT(w, t->fiber == w->l->fiber_to_free); + if (w->l->fiber_to_free) { + cilk_fiber_deallocate_to_pool(w, w->l->fiber_to_free); + } + w->l->fiber_to_free = NULL; + + // Attempt to get a closure from the bottom of our deque. + deque_lock_self(w); + t = deque_xtract_bottom(w, w->self); + deque_unlock_self(w); + } - // MUST unlock the closure before locking the queue - // (rule A in file PROTOCOLS) - deque_lock_self(w); - deque_add_bottom(w, t, w->self); - deque_unlock_self(w); + break; // ? - /* now execute it */ - cilkrts_alert(SCHED, w, "(do_what_it_says) Jump into user code"); - - // CILK_ASSERT(w, w->l->runtime_fiber != t->fiber); - // cilk_fiber_suspend_self_and_resume_other(w->l->runtime_fiber, - // t->fiber); - // cilkrts_alert(SCHED, w, "(do_what_it_says) Back from user - // code"); - // longjmp invalidates non-volatile variables - __cilkrts_worker *volatile w_save = w; - if (__builtin_setjmp(w->l->rts_ctx) == 0) { - worker_change_state(w, WORKER_RUN); - longjmp_to_user_code(w, t); - } else { - w = w_save; - CILK_ASSERT_POINTER_EQUAL(w, w, __cilkrts_get_tls_worker()); - worker_change_state(w, WORKER_SCHED); - // CILK_ASSERT(w, t->fiber == w->l->fiber_to_free); - if (w->l->fiber_to_free) { - cilk_fiber_deallocate_to_pool(w, w->l->fiber_to_free); - } - w->l->fiber_to_free = NULL; + case CLOSURE_RETURNING: + cilkrts_alert(SCHED, w, "(do_what_it_says) CLOSURE_RETURNING"); + // the return protocol assumes t is not locked, and everybody + // will respect the fact that t is returning + Closure_unlock(w, t); + t = return_value(w, t); + + break; // ? + + default: + cilkrts_bug(w, "do_what_it_says invalid status %d", t->status); + cilkrts_bug(w, "do_what_it_says() closure status %s", + Closure_status_to_str(t->status)); + break; } + if (t) { + WHEN_SCHED_STATS(w->l->stats.repos++); + } + } while (t); +} - break; // ? +// Thin wrapper around do_what_it_says to allow the boss thread to execute the +// Cilk computation until it would enter the work-stealing loop. +void do_what_it_says_boss(__cilkrts_worker *w, Closure *t) { - case CLOSURE_RETURNING: - cilkrts_alert(SCHED, w, "(do_what_it_says) CLOSURE_RETURNING"); - // the return protocol assumes t is not locked, and everybody - // will respect the fact that t is returning - Closure_unlock(w, t); - res = return_value(w, t); + do_what_it_says(w, t); - break; // ? + // At this point, the boss has run out of work to do. Rather than become a + // thief itself, the boss wakes up the root worker to become a thief. - default: - cilkrts_bug(w, "do_what_it_says invalid status %d", t->status); - cilkrts_bug(w, "do_what_it_says() closure status %s", - Closure_status_to_str(t->status)); - break; + CILK_STOP_TIMING(w, INTERVAL_SCHED); + worker_change_state(w, WORKER_IDLE); +#if BOSS_THIEF + worker_scheduler(w); +#else + __builtin_longjmp(w->g->boss_ctx, 1); +#endif +} + +// Update the index-to-worker map to swap self with the worker at the target +// index. +static void swap_worker_with_target(global_state *g, worker_id self, + worker_id target_index) { + worker_id self_index = g->worker_to_index[self]; + worker_id target_worker = g->index_to_worker[target_index]; + + // Update the index-to-worker map. + g->index_to_worker[self_index] = target_worker; + g->index_to_worker[target_index] = self; + + // Update the worker-to-index map. + g->worker_to_index[target_worker] = self_index; + g->worker_to_index[self] = target_index; +} + +// Called by a thief thread. Causes the thief thread to try to sleep, that is, +// to wait for a signal to resume work-stealing. +static bool try_to_disengage_thief(global_state *g, worker_id self, + uint64_t disengaged_deprived) { + // Try to grab the lock on the index structure. + if (!cilk_mutex_try(&g->index_lock)) { + return false; } - return res; + // Increment the number of disengaged thieves and decrement number of deprived + // thieves. + const uint64_t disengaged_mask = ((uint64_t)-1) << 32; + uint64_t disengaged = disengaged_deprived & disengaged_mask; + uint64_t new_disengaged_deprived = + ((disengaged + (1UL << 32)) & disengaged_mask) | + ((disengaged_deprived - 1) & ~disengaged_mask); + // Try to update the number of disengaged workers. This step synchronizes + // with parallel calls to reengage thieves, calls to reengage thieves, and + // updates to the number of deprived workers. + // First atomically update the number of disengaged workers. + if (atomic_compare_exchange_strong_explicit( + &g->disengaged_deprived, &disengaged_deprived, + new_disengaged_deprived, memory_order_release, + memory_order_acquire)) { + // Update the index-to-worker map. + worker_id last_index = g->nworkers - (new_disengaged_deprived >> 32); + if (g->worker_to_index[self] < last_index) { + swap_worker_with_target(g, self, last_index); + } + // Release the lock on the index structure + cilk_mutex_unlock(&g->index_lock); + + // Disengage this thread. + thief_disengage(g); + + // The thread is now reengaged. Grab the lock on the index structure. + cilk_mutex_lock(&g->index_lock); + + // Decrement the number of disengaged workers. + while (true) { + // Atomically decrement the number of disengaged workers. + uint64_t disengaged_deprived = atomic_load_explicit( + &g->disengaged_deprived, memory_order_acquire); + disengaged = disengaged_deprived & disengaged_mask; + new_disengaged_deprived = ((disengaged - (1UL << 32)) & disengaged_mask) | + ((disengaged_deprived + 1) & ~disengaged_mask); + if (atomic_compare_exchange_strong_explicit( + &g->disengaged_deprived, &disengaged_deprived, + new_disengaged_deprived, memory_order_release, + memory_order_acquire)) { + // Update the index structure. + last_index = g->nworkers - (disengaged_deprived >> 32); + if (g->worker_to_index[self] > last_index) { + swap_worker_with_target(g, self, last_index); + } + + // Release the lock on the index structure. + cilk_mutex_unlock(&g->index_lock); + return true; + } + } + } else { + // Release the lock on the index structure. + cilk_mutex_unlock(&g->index_lock); + return false; + } } -void worker_scheduler(__cilkrts_worker *w, Closure *t) { +// Attempt to disengage this thief thread. The __cilkrts_worker parameter is only +// used for debugging. +static bool maybe_disengage_thief(global_state *g, worker_id self, + unsigned int nworkers, __cilkrts_worker *w) { + // Check the number of active and deprived workers, and disengage this worker + // if there are too many deprived workers. + while (true) { + // Check if this deprived thread should sleep. + uint64_t disengaged_deprived = + atomic_load_explicit(&g->disengaged_deprived, memory_order_acquire); + const uint64_t disengaged_mask = ((uint64_t)-1) << 32; + uint32_t disengaged = (uint32_t)(disengaged_deprived >> 32); + uint32_t deprived = (uint32_t)(disengaged_deprived & ~disengaged_mask); + + CILK_ASSERT(w, disengaged < nworkers); + CILK_ASSERT(w, deprived < nworkers); + int32_t active = + (int32_t)nworkers - (int32_t)disengaged - (int32_t)deprived; + CILK_ASSERT(w, active >= 1); + // TODO: Investigate whether it's better to keep the number of deprived + // workers less than the number of active workers. + if (active < (int32_t)deprived) { + // Too many deprived thieves. Try to disengage this worker. If it + // fails, repeat the loop. + if (try_to_disengage_thief(g, self, disengaged_deprived)) { + // The thief was successfully disengaged. It has since been + // taken out of disengage. + return true; + } + } else { + // We have enough active workers to keep this worker out of disengage, + // but this worker was still unable to steal work. Put this thief + // to sleep for a while using the conventional way. + // In testing, a nanosleep(0) takes approximately 50 us. + const struct timespec sleeptime = {.tv_sec = 0, .tv_nsec = 50000}; + /* const struct timespec sleeptime = {.tv_sec = 0, .tv_nsec = + * 25000}; */ + nanosleep(&sleeptime, NULL); + break; + } + } + return false; +} +void worker_scheduler(__cilkrts_worker *w) { + Closure *t = NULL; CILK_ASSERT(w, w == __cilkrts_get_tls_worker()); - rts_srand(w, w->self * 162347); CILK_START_TIMING(w, INTERVAL_SCHED); worker_change_state(w, WORKER_SCHED); + global_state *rts = w->g; + worker_id self = w->self; + // Get this worker's local_state pointer, to avoid rereading it + // unnecessarily during the work-stealing loop. This optimization helps + // reduce sharing on the worker structure. + local_state *l = w->l; + // Get the number of workers. We don't currently support changing the + // number of workers dynamically during execution of a Cilkified region. + unsigned int nworkers = rts->nworkers; + // Initialize count of consecutive failed steal attempts. Effectively, + // every worker is active upon entering this routine. + unsigned int fails = 0; + // Get pointers to the local and global copies of the index-to-worker map. + worker_id *local_index_to_worker = w->l->index_to_worker; + + // Threshold for number of consective failed steal attempts to declare a + // thief as deprived. Must be a power of 2. + const unsigned int DEPRIVED_THRESHOLD = 2048; + // Threshold for number of consecutive failed steal attempts to try + // disengaging this worker. Must be a multiple of DEPRIVED_THRESHOLD and a + // power of 2. + const unsigned int DISENGAGE_THRESHOLD = 4 * DEPRIVED_THRESHOLD; + // Threshold for number of failed steal attempts to put this thief to sleep + // for an extended amount of time. Must be larger than DISENGAGE_THRESHOLD. + const unsigned int SLEEP_THRESHOLD = 32 * DEPRIVED_THRESHOLD; + + // Number of attempted steals the thief should do each time it copies the + // worker state. ATTEMPTS must divide DEPRIVED_THRESHOLD. + const int ATTEMPTS = 4; + + while (!atomic_load_explicit(&rts->done, memory_order_acquire)) { + /* A worker entering the steal loop must have saved its reducer map into + the frame to which it belongs. */ + CILK_ASSERT(w, !w->reducer_map); - int fails = 0; - - while (!atomic_load_explicit(&w->g->done, memory_order_acquire)) { - if (!t) { - // try to get work from our local queue - deque_lock_self(w); - t = deque_xtract_bottom(w, w->self); - deque_unlock_self(w); - /* A worker entering the steal loop must have saved its - reducer map into the frame to which it belongs. */ - if (!t) { - CILK_ASSERT(w, !w->reducer_map); - } - } CILK_STOP_TIMING(w, INTERVAL_SCHED); - while (!t && !atomic_load_explicit(&w->g->done, memory_order_acquire)) { + while (!t && !atomic_load_explicit(&rts->done, memory_order_acquire)) { CILK_START_TIMING(w, INTERVAL_SCHED); CILK_START_TIMING(w, INTERVAL_IDLE); - unsigned int victim = rts_rand(w) % w->g->nworkers; - if (victim != w->self) { + // Get the set of workers we can steal from and a local copy of the + // index-to-worker map. We'll attempt a few steals using these + // local copies to minimize memory traffic. + uint64_t disengaged_deprived = atomic_load_explicit( + &rts->disengaged_deprived, memory_order_relaxed); + uint32_t disengaged = (uint32_t)(disengaged_deprived >> 32); + uint32_t stealable = nworkers - disengaged; + // TODO: Technically, ATTEMPTS should scale with the number of + // workers, to amortize the memcpy, which takes O(P)-time. However, + // in testing, ATTEMPTS = 4 works well even on large worker counts + // (e.g., 96) in a NUMA environment. I suspect the total cost of + // the memcpy is too small for such worker counts to worry about. + memcpy(local_index_to_worker, rts->index_to_worker, + sizeof(worker_id) * stealable); + + int attempt = ATTEMPTS; + do { + // Choose a random victim not equal to self. + worker_id victim = + local_index_to_worker[rts_rand(l) % stealable]; + while (victim == self) { + victim = local_index_to_worker[rts_rand(l) % stealable]; + } + // Attempt to steal from that victim. t = Closure_steal(w, victim); - } + if (!t) { + // Pause inside this busy loop. +#ifdef __SSE__ + __builtin_ia32_pause(); +#endif +#ifdef __aarch64__ + __builtin_arm_yield(); +#endif + } + } while (!t && --attempt > 0); + #if SCHED_STATS if (t) { // steal successful CILK_STOP_TIMING(w, INTERVAL_SCHED); @@ -1425,31 +1631,80 @@ void worker_scheduler(__cilkrts_worker *w, Closure *t) { } #endif if (t) { + WHEN_SCHED_STATS(w->l->stats.steals++); + if (fails >= DEPRIVED_THRESHOLD) { + // This thief is no longer deprived. Decrement the number + // of deprived thieves. + atomic_fetch_sub_explicit(&rts->disengaged_deprived, 1, + memory_order_release); + + // Request to reengage at most 2 thieves. + // TODO: Investigate whether it's better to keep the number + // less than the number of active workers. + request_more_thieves(rts, 2); + } fails = 0; break; } - /* TODO: Use condition variables or a similar controlled - blocking mechanism. When a thread finds something to steal - it should wake up another thread to enter the loop. */ - ++fails; - if (fails > 100000) { - usleep(10); - } else if (fails > 10000) { - usleep(1); - } else if (fails > 1000) { -#if defined __APPLE__ || defined __linux__ - sched_yield(); -#else - pthread_yield(); -#endif - } else { -#ifdef __SSE__ - __builtin_ia32_pause(); -#endif -#ifdef __aarch64__ - __builtin_arm_yield(); + CILK_START_TIMING(w, INTERVAL_SLEEP); + fails += ATTEMPTS; + + // Every DEPRIVED_THRESHOLD consecutive failed steal attempts, + // update the set of deprived workers, and maybe disengage this + // worker if there are too many deprived workers. + if (fails % DEPRIVED_THRESHOLD == 0) { + if (fails > (1 << 25)) { + // Prevent the fail count from exceeding this maximum, so we + // don't have to worry about the fail count overflowing. + // + // This maximum bound is chosen based on the maximum sleep + // time when fails > SLEEP_THRESHOLD, which specifies the + // time to sleep in nanoseconds. Because the specification + // to nanosleep() disallows times with more than 1e9 + // nanoseconds, we set the maximum fails value here + // accordinly and, in this case, simply sleep for 1 second. + fails = (1 << 25); + const struct timespec sleeptime = {.tv_sec = 1, + .tv_nsec = 0}; + nanosleep(&sleeptime, NULL); + } else if (DEPRIVED_THRESHOLD == fails) { + // This thief is now considered deprived. Increment the + // number of deprived workers. + atomic_fetch_add_explicit(&rts->disengaged_deprived, 1, + memory_order_release); + } else if (fails % DISENGAGE_THRESHOLD == 0) { +#if BOSS_THIEF + if (is_boss_thread) { + // The boss thread should never disengage. Sleep instead. + const struct timespec sleeptime = {.tv_sec = 0, .tv_nsec = 50000}; + nanosleep(&sleeptime, NULL); + } else #endif + if (maybe_disengage_thief(rts, self, nworkers, w)) { + // The semaphore for reserving workers may have been + // non-zero due to past successful steals, rather than a + // recent successful steal. Decrement fails so we try + // to disengage this again sooner, in case there is + // still nothing to steal. + fails -= (DISENGAGE_THRESHOLD / 2); + } + + } else if (fails > SLEEP_THRESHOLD) { + // This thief has failed a lot of consecutive steal + // attempts, but it's not disengaged. Sleep for increasing + // lengths of time. + const struct timespec sleeptime = {.tv_sec = 0, + .tv_nsec = 16 * fails}; + nanosleep(&sleeptime, NULL); + } else if (fails % DISENGAGE_THRESHOLD != 0) { + // This thief has failed many consecutive steal attempts, + // but it's not disengaged. Sleep for a short time. + const struct timespec sleeptime = {.tv_sec = 0, + .tv_nsec = 50000}; + nanosleep(&sleeptime, NULL); + } } + CILK_STOP_TIMING(w, INTERVAL_SLEEP); } CILK_START_TIMING(w, INTERVAL_SCHED); // If one Cilkified region stops and another one starts, then a worker @@ -1458,9 +1713,116 @@ void worker_scheduler(__cilkrts_worker *w, Closure *t) { if (t) { // if provably-good steal happens, do_what_it_says will return // the next closure to execute - t = do_what_it_says(w, t); + do_what_it_says(w, t); + t = NULL; } } + + if (fails >= DEPRIVED_THRESHOLD) { + // If this worker was deprived, decrement the number of deprived + // workers, essentially making this worker active. + atomic_fetch_sub_explicit(&rts->disengaged_deprived, 1, + memory_order_release); + } CILK_STOP_TIMING(w, INTERVAL_SCHED); worker_change_state(w, WORKER_IDLE); +#if BOSS_THIEF + if (is_boss_thread) { + __builtin_longjmp(w->g->boss_ctx, 1); + } +#endif +} + +void *scheduler_thread_proc(void *arg) { + __cilkrts_worker *w = (__cilkrts_worker *)arg; + cilkrts_alert(BOOT, w, "scheduler_thread_proc"); + __cilkrts_set_tls_worker(w); + +#if BOSS_THIEF + CILK_ASSERT(w, w->self != 0); +#endif + // Initialize the worker's fiber pool. We have each worker do this itself + // to improve the locality of the initial fibers. + cilk_fiber_pool_per_worker_init(w); + + // Avoid redundant lookups of these commonly accessed worker fields. + const worker_id self = w->self; + global_state *rts = w->g; + + // Initialize worker's random-number generator. + rts_srand(w, (self + 1) * 162347); + + CILK_START_TIMING(w, INTERVAL_SLEEP_UNCILK); + do { + // Wait for g->start == 1 to start executing the work-stealing loop. We + // use a condition variable to wait on g->start, because this approach + // seems to result in better performance. +#if !BOSS_THIEF + if (self == rts->exiting_worker) { + root_worker_wait(rts, self); + } else { +#endif + thief_wait(rts); +#if !BOSS_THIEF + } +#endif + CILK_STOP_TIMING(w, INTERVAL_SLEEP_UNCILK); + + // Check if we should exit this scheduling function. + if (rts->terminate) { + return NULL; + } + + // Start the new Cilkified region using the last worker that finished a + // Cilkified region. This approach ensures that the new Cilkified + // region starts on an available worker with the worker state that was + // updated by any operations that occurred outside of Cilkified regions. + // Such operations, for example might have updated the left-most view of + // a reducer. + if (!atomic_load_explicit(&rts->done, memory_order_acquire)) { + worker_scheduler(w); + } + + // At this point, some worker will have finished the Cilkified region, + // meaning it recordied its ID in g->exiting_worker and set g->done = 1. + // That worker's state accurately reflects the execution of the + // Cilkified region, including all updates to reducers. Wait for that + // worker to exit the work-stealing loop, and use it to wake-up the + // original Cilkifying thread. + if (self == rts->exiting_worker) { + // Mark the computation as no longer cilkified, to signal the thread + // that originally cilkified the execution. + CILK_EXIT_WORKER_TIMING(rts); + CILK_START_TIMING(w, INTERVAL_SLEEP_UNCILK); + signal_uncilkified(rts); +#if BOSS_THIEF + unsigned int fail = 0; + while (fail++ < 2048 && + !atomic_load_explicit(&rts->disengaged_thieves_futex, + memory_order_acquire)) { +#ifdef __SSE__ + __builtin_ia32_pause(); +#endif +#ifdef __aarch64__ + __builtin_arm_yield(); +#endif + } +#endif // BOSS_THIEF + } else { + CILK_START_TIMING(w, INTERVAL_SLEEP_UNCILK); + // Busy-wait for a while to amortize the cost of syscalls to put + // thief threads to sleep. + unsigned int fail = 0; + while (fail++ < 2048 && + !atomic_load_explicit(&rts->disengaged_thieves_futex, + memory_order_acquire)) { +#ifdef __SSE__ + __builtin_ia32_pause(); +#endif +#ifdef __aarch64__ + __builtin_arm_yield(); +#endif + } + } + } while (true); } diff --git a/runtime/scheduler.h b/runtime/scheduler.h index 4e3575c5..ab362118 100644 --- a/runtime/scheduler.h +++ b/runtime/scheduler.h @@ -9,8 +9,7 @@ #define EXCEPTION_INFINITY (__cilkrts_stack_frame **)(-1LL) -/* This is part of the ABI */ -CHEETAH_API __cilkrts_worker *__cilkrts_get_tls_worker(); +CHEETAH_INTERNAL void do_what_it_says_boss(__cilkrts_worker *w, Closure *t); CHEETAH_INTERNAL void __cilkrts_init_tls_variables(); CHEETAH_INTERNAL void __cilkrts_set_tls_worker(__cilkrts_worker *w); @@ -18,11 +17,12 @@ CHEETAH_INTERNAL void __cilkrts_set_tls_worker(__cilkrts_worker *w); CHEETAH_INTERNAL int Cilk_sync(__cilkrts_worker *const ws, __cilkrts_stack_frame *frame); -CHEETAH_INTERNAL void Cilk_set_return(__cilkrts_worker *const ws); -CHEETAH_INTERNAL void Cilk_exception_handler(char *exn); +void Cilk_set_return(__cilkrts_worker *const ws); +void Cilk_exception_handler(char *exn); CHEETAH_INTERNAL_NORETURN void longjmp_to_runtime(__cilkrts_worker *w); -CHEETAH_INTERNAL void worker_scheduler(__cilkrts_worker *ws, Closure *t); +CHEETAH_INTERNAL void worker_scheduler(__cilkrts_worker *ws); +CHEETAH_INTERNAL void *scheduler_thread_proc(void *arg); CHEETAH_INTERNAL void promote_own_deque(__cilkrts_worker *w); diff --git a/runtime/types.h b/runtime/types.h index d1d2cfba..d8c35ecc 100644 --- a/runtime/types.h +++ b/runtime/types.h @@ -12,4 +12,7 @@ typedef struct cilkred_map cilkred_map; #define NO_WORKER 0xffffffffu /* type worker_id */ +// Constant representing invalid worker. +#define INVALID (__cilkrts_worker *)0xbfbfbfbfbf + #endif /* _CILK_TYPES_H */ diff --git a/runtime/worker_coord.h b/runtime/worker_coord.h new file mode 100644 index 00000000..1421d0b8 --- /dev/null +++ b/runtime/worker_coord.h @@ -0,0 +1,451 @@ +#ifndef _WORKER_COORD_H +#define _WORKER_COORD_H + +// Routines for coordinating workers, specifically, putting workers to sleep and +// waking workers when execution enters and leaves cilkified regions. + +#include + +#ifdef __linux__ +#include +#include +#include +#include +#endif + +#include "global.h" + +#define USER_USE_FUTEX 1 +#ifdef __linux__ +#define USE_FUTEX USER_USE_FUTEX +#else +#define USE_FUTEX 0 +#endif + +#if USE_FUTEX +//========================================================= +// Primitive futex operations. +//========================================================= +#define errExit(msg) \ + do { \ + perror(msg); \ + exit(EXIT_FAILURE); \ + } while (false) + +// Convenience wrapper for futex syscall. +static inline long futex(_Atomic uint32_t *uaddr, int futex_op, uint32_t val, + const struct timespec *timeout, uint32_t *uaddr2, + uint32_t val3) { + return syscall(SYS_futex, uaddr, futex_op, val, timeout, uaddr2, val3); +} + +// Wait for the futex pointed to by `futexp` to become 1. +static inline void fwait(_Atomic uint32_t *futexp) { + // We don't worry about spurious wakeups here, since we ensure that all + // calls to fwait are contained in their own loops that effectively check + // for spurious wakeups. + long s = futex(futexp, FUTEX_WAIT_PRIVATE, 0, NULL, NULL, 0); + if (__builtin_expect(s == -1 && errno != EAGAIN, false)) + errExit("futex-FUTEX_WAIT"); +} + +// Set the futex pointed to by `futexp` to 1, and wake up 1 thread waiting on +// that futex. +static inline void fpost(_Atomic uint32_t *futexp) { + atomic_store_explicit(futexp, 1, memory_order_release); + long s = futex(futexp, FUTEX_WAKE_PRIVATE, 1, NULL, NULL, 0); + if (s == -1) + errExit("futex-FUTEX_WAKE"); +} + +// Set the futex pointed to by `futexp` to 1, and wake up all threads waiting on +// that futex. +static inline void fbroadcast(_Atomic uint32_t *futexp) { + atomic_store_explicit(futexp, 1, memory_order_release); + long s = futex(futexp, FUTEX_WAKE_PRIVATE, INT_MAX, NULL, NULL, 0); + if (s == -1) + errExit("futex-FUTEX_WAKE"); +} + +//========================================================= +// Operations to control worker behavior using futexes and corresponding flags. +//========================================================= + +// Called by a worker thread. Causes the worker thread to wait on the given +// flag-futex pair. +static inline void worker_wait(volatile atomic_bool *flag, + _Atomic uint32_t *flag_futex) { + while (!atomic_load_explicit(flag, memory_order_acquire)) { + fwait(flag_futex); + } +} + +// Start all workers waiting on the given flag-futex pair. +static inline void worker_start_broadcast(volatile atomic_bool *flag, + _Atomic uint32_t *flag_futex) { + atomic_store_explicit(flag, 1, memory_order_release); + fbroadcast(flag_futex); +} + +// Reset the given flag-futex pair, so that workers will eventually resume +// waiting on that flag-futex pair. +static inline void worker_clear_start(volatile atomic_bool *flag, + _Atomic uint32_t *flag_futex) { + atomic_store_explicit(flag, 0, memory_order_relaxed); + atomic_store_explicit(flag_futex, 0, memory_order_relaxed); +} +#else +//========================================================= +// Operations to control worker behavior using pthread condition variables and +// corresponding flags. +//========================================================= + +// Called by a worker thread. Causes the worker thread to wait on the given +// flag and associated mutex and condition variable. +static inline void worker_wait(volatile atomic_bool *flag, + pthread_mutex_t *flag_lock, + pthread_cond_t *flag_cond_var) { + pthread_mutex_lock(flag_lock); + while (!atomic_load_explicit(flag, memory_order_acquire)) { + pthread_cond_wait(flag_cond_var, flag_lock); + } + pthread_mutex_unlock(flag_lock); +} + +// Start all workers waiting on the given flag and associated mutex and +// condition variable. +static inline void worker_start_broadcast(volatile atomic_bool *flag, + pthread_mutex_t *flag_lock, + pthread_cond_t *flag_cond_var) { + pthread_mutex_lock(flag_lock); + atomic_store_explicit(flag, 1, memory_order_release); + pthread_cond_broadcast(flag_cond_var); + pthread_mutex_unlock(flag_lock); +} + +// Reset given flag, so that workers will eventually resume waiting on that +// flag. +static inline void worker_clear_start(volatile atomic_bool *start) { + atomic_store_explicit(start, 0, memory_order_relaxed); +} +#endif + +//========================================================= +// Common internal interface for managing execution of workers. +//========================================================= + +// Called by a root-worker thread, that is, the worker w where w->self == +// g->exiting_worker. Causes the root-worker thread to wait for a signal to +// start work-stealing. +static inline void root_worker_wait(global_state *g, const uint32_t id) { + _Atomic uint32_t *root_worker_p = &g->start_root_worker; +/* unsigned int fail = 0; */ +/* while (fail++ < 2048) { */ +/* if (id != atomic_load_explicit(root_worker_p, memory_order_acquire)) { */ +/* return; */ +/* } */ +/* #ifdef __SSE__ */ +/* __builtin_ia32_pause(); */ +/* #endif */ +/* #ifdef __aarch64__ */ +/* __builtin_arm_yield(); */ +/* #endif */ +/* } */ +#if USE_FUTEX + while (id == atomic_load_explicit(root_worker_p, memory_order_acquire)) { + long s = futex(root_worker_p, FUTEX_WAIT_PRIVATE, id, NULL, NULL, 0); + if (__builtin_expect(s == -1 && errno != EAGAIN, false)) + errExit("futex-FUTEX_WAIT"); + } +#else + pthread_mutex_t *root_worker_lock = &g->start_root_worker_lock; + pthread_mutex_lock(root_worker_lock); + while (id == atomic_load_explicit(root_worker_p, memory_order_acquire)) { + pthread_cond_wait(&g->start_root_worker_cond_var, root_worker_lock); + } + pthread_mutex_unlock(root_worker_lock); +#endif +} + +// Signal the root-worker thread to start work-stealing (or terminate, if +// g->terminate == 1). +static inline void wake_root_worker(global_state *g, uint32_t val) { + _Atomic uint32_t *root_worker_p = &g->start_root_worker; +#if USE_FUTEX + atomic_store_explicit(root_worker_p, val, memory_order_release); + long s = futex(root_worker_p, FUTEX_WAKE_PRIVATE, 1, NULL, NULL, 0); + if (s == -1) + errExit("futex-FUTEX_WAKE"); +#else + pthread_mutex_t *root_worker_lock = &g->start_root_worker_lock; + pthread_mutex_lock(root_worker_lock); + atomic_store_explicit(root_worker_p, val, memory_order_release); + pthread_cond_signal(&g->start_root_worker_cond_var); + pthread_mutex_unlock(root_worker_lock); +#endif +} + +// Try to signal the root-worker thread to start work-stealing (or terminate, if +// g->terminate == 1). If the current root-worker value is *old_val, then wake +// up the root worker. Otherwise, just exit; in this latter case, another +// worker must have woken up the root worker already. +static inline void try_wake_root_worker(global_state *g, uint32_t *old_val, + uint32_t new_val) { + _Atomic uint32_t *root_worker_p = &g->start_root_worker; +#if USE_FUTEX + if (atomic_compare_exchange_strong_explicit(root_worker_p, old_val, new_val, + memory_order_release, + memory_order_acquire)) { + long s = futex(root_worker_p, FUTEX_WAKE_PRIVATE, 1, NULL, NULL, 0); + if (s == -1) + errExit("futex-FUTEX_WAKE"); + } +#else + pthread_mutex_t *root_worker_lock = &g->start_root_worker_lock; + pthread_mutex_lock(root_worker_lock); + if (*old_val == atomic_load_explicit(root_worker_p, memory_order_acquire)) { + atomic_store_explicit(root_worker_p, new_val, memory_order_release); + pthread_cond_signal(&g->start_root_worker_cond_var); + } + pthread_mutex_unlock(root_worker_lock); +#endif +} + +// Routines to update global flags to prevent workers from re-entering the +// work-stealing loop. Note that we don't wait for the workers to exit the +// work-stealing loop, since its more efficient to allow that to happen +// eventually. + +// Routines to control the cilkified state. + +static inline void set_cilkified(global_state *g) { + // Set g->cilkified = 1, indicating that the execution is now cilkified. + atomic_store_explicit(&g->cilkified, 1, memory_order_release); +#if USE_FUTEX + atomic_store_explicit(&g->cilkified_futex, 0, memory_order_release); +#endif +} + +// Mark the computation as no longer cilkified and signal the thread that +// originally cilkified the execution. +static inline void signal_uncilkified(global_state *g) { +#if USE_FUTEX + atomic_store_explicit(&g->cilkified, 0, memory_order_release); + fpost(&g->cilkified_futex); +#else + pthread_mutex_lock(&(g->cilkified_lock)); + atomic_store_explicit(&g->cilkified, 0, memory_order_release); + pthread_cond_signal(&g->cilkified_cond_var); + pthread_mutex_unlock(&(g->cilkified_lock)); +#endif +} + +// Wait on g->cilkified to be set to 0, indicating the end of the Cilkified +// region. +static inline void wait_while_cilkified(global_state *g) { + unsigned int fail = 0; + while (fail++ < 2048) { + if (!atomic_load_explicit(&g->cilkified, memory_order_acquire)) { + return; + } +#ifdef __SSE__ + __builtin_ia32_pause(); +#endif +#ifdef __aarch64__ + __builtin_arm_yield(); +#endif + } +#if USE_FUTEX + while (atomic_load_explicit(&g->cilkified, memory_order_acquire)) { + fwait(&g->cilkified_futex); + } +#else + // TODO: Convert pthread_mutex_lock, pthread_mutex_unlock, and + // pthread_cond_wait to cilk_* equivalents. + pthread_mutex_lock(&(g->cilkified_lock)); + + // There may be a *very unlikely* scenario where the Cilk computation has + // already been completed before even starting to wait. In that case, do + // not wait and continue directly. Also handle spurious wakeups with a + // 'while' instead of an 'if'. + while (atomic_load_explicit(&g->cilkified, memory_order_acquire)) { + pthread_cond_wait(&(g->cilkified_cond_var), &(g->cilkified_lock)); + } + + pthread_mutex_unlock(&(g->cilkified_lock)); +#endif +} + +//========================================================= +// Operations to disengage and reengage workers within the work-stealing loop. +//========================================================= + +// Reset the shared variable for disengaging thief threads. +static inline void reset_disengaged_var(global_state *g) { +#if !USE_FUTEX + pthread_mutex_lock(&g->disengaged_lock); +#endif + atomic_store_explicit(&g->disengaged_thieves_futex, 0, + memory_order_release); +#if !USE_FUTEX + pthread_mutex_unlock(&g->disengaged_lock); +#endif +} + +// Request to reengage `count` thief threads. +static inline void request_more_thieves(global_state *g, uint32_t count) { + CILK_ASSERT_G(count > 0); + +#if USE_FUTEX + // This step synchronizes with concurrent calls to request_more_thieves and + // concurrent calls to try_to_disengage_thief. + while (true) { + uint32_t disengaged_thieves_futex = atomic_load_explicit( + &g->disengaged_thieves_futex, memory_order_acquire); + + // Don't allow this routine increment the futex beyond half the number + // of workers on the system. This bounds how many successful steals can + // possibly keep thieves engaged unnecessarily in the future, when there + // may not be as much parallelism. + int32_t max_to_wake = + (int32_t)(g->nworkers / 2) - disengaged_thieves_futex; + if (max_to_wake <= 0) + return; + uint64_t to_wake = max_to_wake < (int32_t)count ? max_to_wake : count; + + if (atomic_compare_exchange_strong_explicit( + &g->disengaged_thieves_futex, &disengaged_thieves_futex, + disengaged_thieves_futex + to_wake, memory_order_release, + memory_order_acquire)) { + // We successfully updated the futex. Wake the thief threads + // waiting on this futex. + long s = futex(&g->disengaged_thieves_futex, FUTEX_WAKE_PRIVATE, + to_wake, NULL, NULL, 0); + if (s == -1) + errExit("futex-FUTEX_WAKE"); + return; + } + } +#else + pthread_mutex_lock(&g->disengaged_lock); + uint32_t disengaged_thieves_futex = atomic_load_explicit( + &g->disengaged_thieves_futex, memory_order_acquire); + + // Don't allow this routine increment the futex beyond half the number + // of workers on the system. This bounds how many successful steals can + // possibly keep thieves engaged unnecessarily in the future, when there + // may not be as much parallelism. + int32_t max_to_wake = (int32_t)(g->nworkers / 2) - disengaged_thieves_futex; + if (max_to_wake <= 0) { + pthread_mutex_unlock(&g->disengaged_lock); + return; + } + uint32_t to_wake = max_to_wake < (int32_t)count ? max_to_wake : count; + atomic_store_explicit(&g->disengaged_thieves_futex, + disengaged_thieves_futex + to_wake, + memory_order_release); + while (to_wake-- > 0) { + pthread_cond_signal(&g->disengaged_cond_var); + } + pthread_mutex_unlock(&g->disengaged_lock); +#endif +} + +#if USE_FUTEX +static inline void thief_disengage_futex(_Atomic uint32_t *futexp) { + // This step synchronizes with calls to request_more_thieves. + while (true) { + // Decrement the futex when woken up. The loop and compare-exchange are + // designed to handle cases where multiple threads waiting on the futex + // were woken up and where there may be spurious wakeups. + uint32_t val; + while ((val = atomic_load_explicit(futexp, memory_order_relaxed)) > 0) { + if (atomic_compare_exchange_strong_explicit(futexp, &val, val - 1, + memory_order_release, + memory_order_acquire)) { + return; + } + } + + // Wait on the futex. + long s = futex(futexp, FUTEX_WAIT_PRIVATE, 0, NULL, NULL, 0); + if (__builtin_expect(s == -1 && errno != EAGAIN, false)) + errExit("futex-FUTEX_WAIT"); + } +} +#else +static inline void thief_disengage_cond_var(_Atomic uint32_t *count, + pthread_mutex_t *lock, + pthread_cond_t *cond_var) { + // This step synchronizes with calls to request_more_thieves. + pthread_mutex_lock(lock); + while (true) { + uint32_t val = atomic_load_explicit(count, memory_order_acquire); + if (val > 0) { + atomic_store_explicit(count, val - 1, memory_order_release); + pthread_mutex_unlock(lock); + return; + } + pthread_cond_wait(cond_var, lock); + } +} +#endif +static inline void thief_disengage(global_state *g) { +#if USE_FUTEX + thief_disengage_futex(&g->disengaged_thieves_futex); +#else + thief_disengage_cond_var(&g->disengaged_thieves_futex, &g->disengaged_lock, + &g->disengaged_cond_var); +#endif +} + +// Signal to all disengaged thief threads to resume work-stealing. +static inline void wake_all_disengaged(global_state *g) { +#if USE_FUTEX + atomic_store_explicit(&g->disengaged_thieves_futex, INT_MAX, + memory_order_release); + long s = futex(&g->disengaged_thieves_futex, FUTEX_WAKE_PRIVATE, INT_MAX, + NULL, NULL, 0); + if (s == -1) + errExit("futex-FUTEX_WAKE"); +#else + pthread_mutex_lock(&g->disengaged_lock); + atomic_store_explicit(&g->disengaged_thieves_futex, INT_MAX, + memory_order_release); + pthread_cond_broadcast(&g->disengaged_cond_var); + pthread_mutex_unlock(&g->disengaged_lock); +#endif +} + +// Reset global state to make thief threads sleep for signal to start +// work-stealing again. +static inline void sleep_thieves(global_state *g) { + reset_disengaged_var(g); +} + +// Called by a thief thread. Causes the thief thread to wait for a signal to +// start work-stealing. +static inline void thief_wait(global_state *g) { + thief_disengage(g); +} + +// Signal the thief threads to start work-stealing (or terminate, if +// g->terminate == 1). +static inline void wake_thieves(global_state *g) { +#if USE_FUTEX + atomic_store_explicit(&g->disengaged_thieves_futex, g->nworkers - 1, + memory_order_release); + long s = futex(&g->disengaged_thieves_futex, FUTEX_WAKE_PRIVATE, INT_MAX, + NULL, NULL, 0); + if (s == -1) + errExit("futex-FUTEX_WAKE"); +#else + pthread_mutex_lock(&g->disengaged_lock); + atomic_store_explicit(&g->disengaged_thieves_futex, g->nworkers - 1, + memory_order_release); + pthread_cond_broadcast(&g->disengaged_cond_var); + pthread_mutex_unlock(&g->disengaged_lock); +#endif +} + +#endif /* _WORKER_COORD_H */